PageSourceSearch

https://iguales.cl/wp-content/themes/uncode/library/js/plugins.js?ver=1064322736

js iguales.cl collected 2026-09-24 18:43:45 UTC 1,310,099 bytes, 37,845 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: 11,709 bytes, lines 910-1323
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
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: 22,800 bytes, lines 1973-2719
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) {
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: 36,979 bytes, lines 5838-7319
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() {
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
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 space
8960s
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) {
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)$/.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.parents('.isotope-filters').length ) {
12370						if ( $sub.parents('.text-right').eq(0).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.4.0 | January 29th 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        closable: true,
16435        swipeToClose: true,
16436        closeOnTap: true,
16437        showCloseIcon: true,
16438        showMaximizeIcon: false,
16439        loop: true,
16440        escKey: true,
16441        keyPress: true,
16442        controls: true,
16443        slideEndAnimation: true,
16444        hideControlOnEnd: false,
16445        mousewheel: false,
16446        getCaptionFromTitleOrAlt: true,
16447        appendSubHtmlTo: '.lg-sub-html',
16448        subHtmlSelectorRelative: false,
16449        preload: 2,
16450        numberOfSlideItemsInDom: 10,
16451        selector: '',
16452        selectWithin: '',
16453        nextHtml: '',
16454        prevHtml: '',
16455        index: 0,
16456        iframeWidth: '100%',
16457        iframeHeight: '100%',
16458        iframeMaxWidth: '100%',
16459        iframeMaxHeight: '100%',
16460        download: true,
16461        counter: true,
16462        appendCounterTo: '.lg-toolbar',
16463        swipeThreshold: 50,
16464        enableSwipe: true,
16465        enableDrag: true,
vendor: 59,996 bytes, lines 16466-17818
16466        dynamic: false,
16467        dynamicEl: [],
16468        extraProps: [],
16469        exThumbImage: '',
16470        isMobile: undefined,
16471        mobileSettings: {
16472            controls: false,
16473            showCloseIcon: false,
16474            download: false,
16475        },
16476        plugins: [],
16477        strings: {
16478            closeGallery: 'Close gallery',
16479            toggleMaximize: 'Toggle maximize',
16480            previousSlide: 'Previous slide',
16481            nextSlide: 'Next slide',
16482            download: 'Download',
16483            playVideo: 'Play video',
16484        },
16485    };
16486
16487    function initLgPolyfills() {
16488        (function () {
16489            if (typeof window.CustomEvent === 'function')
16490                return false;
16491            function CustomEvent(event, params) {
16492                params = params || {
16493                    bubbles: false,
16494                    cancelable: false,
16495                    detail: null,
16496                };
16497                var evt = document.createEvent('CustomEvent');
16498                evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
16499                return evt;
16500            }
16501            window.CustomEvent = CustomEvent;
16502        })();
16503        (function () {
16504            if (!Element.prototype.matches) {
16505                Element.prototype.matches =
16506                    Element.prototype.msMatchesSelector ||
16507                        Element.prototype.webkitMatchesSelector;
16508            }
16509        })();
16510    }
16511    var lgQuery = /** @class */ (function () {
16512        function lgQuery(selector) {
16513            this.cssVenderPrefixes = [
16514                'TransitionDuration',
16515                'TransitionTimingFunction',
16516                'Transform',
16517                'Transition',
16518            ];
16519            this.selector = this._getSelector(selector);
16520            this.firstElement = this._getFirstEl();
16521            return this;
16522        }
16523        lgQuery.generateUUID = function () {
16524            return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
16525                var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
16526                return v.toString(16);
16527            });
16528        };
16529        lgQuery.prototype._getSelector = function (selector, context) {
16530            if (context === void 0) { context = document; }
16531            if ( typeof selector === 'object' ) {
16532                return selector;
16533            } else {
16534	            if (typeof selector !== 'string') {
16535	                return selector;
16536	            }
16537	        }
16538            context = context || document;
16539            var fl = selector.substring(0, 1);
16540            if (fl === '#') {
16541                return context.querySelector(selector);
16542            }
16543            else {
16544                return context.querySelectorAll(selector);
16545            }
16546        };
16547        lgQuery.prototype._each = function (func) {
16548            if (!this.selector) {
16549                return this;
16550            }
16551            if (this.selector.length !== undefined) {
16552                [].forEach.call(this.selector, func);
16553            }
16554            else {
16555                func(this.selector, 0);
16556            }
16557            return this;
16558        };
16559        lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
16560            // prettier-ignore
16561            var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
16562                return group1.toUpperCase();
16563            });
16564            if (this.cssVenderPrefixes.indexOf(property) !== -1) {
16565                el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
16566                el.style['webkit' + property] = value;
16567                el.style['moz' + property] = value;
16568                el.style['ms' + property] = value;
16569                el.style['o' + property] = value;
16570            }
16571            else {
16572                el.style[property] = value;
16573            }
16574        };
16575        lgQuery.prototype._getFirstEl = function () {
16576            if (this.selector && this.selector.length !== undefined) {
16577                return this.selector[0];
16578            }
16579            else {
16580                return this.selector;
16581            }
16582        };
16583        lgQuery.prototype.isEventMatched = function (event, eventName) {
16584            var eventNamespace = eventName.split('.');
16585            return event
16586                .split('.')
16587                .filter(function (e) { return e; })
16588                .every(function (e) {
16589                return eventNamespace.indexOf(e) !== -1;
16590            });
16591        };
16592        lgQuery.prototype.attr = function (attr, value) {
16593            if (value === undefined) {
16594                if (!this.firstElement) {
16595                    return '';
16596                }
16597                return this.firstElement.getAttribute(attr);
16598            }
16599            this._each(function (el) {
16600                el.setAttribute(attr, value);
16601            });
16602            return this;
16603        };
16604        lgQuery.prototype.find = function (selector) {
16605            return $LG(this._getSelector(selector, this.selector));
16606        };
16607        lgQuery.prototype.first = function () {
16608            if (this.selector && this.selector.length !== undefined) {
16609                return $LG(this.selector[0]);
16610            }
16611            else {
16612                return $LG(this.selector);
16613            }
16614        };
16615        lgQuery.prototype.eq = function (index) {
16616            return $LG(this.selector[index]);
16617        };
16618        lgQuery.prototype.parent = function () {
16619            return $LG(this.selector.parentElement);
16620        };
16621        lgQuery.prototype.get = function () {
16622            return this._getFirstEl();
16623        };
16624        lgQuery.prototype.removeAttr = function (attributes) {
16625            var attrs = attributes.split(' ');
16626            this._each(function (el) {
16627                attrs.forEach(function (attr) { return el.removeAttribute(attr); });
16628            });
16629            return this;
16630        };
16631        lgQuery.prototype.wrap = function (className) {
16632            if (!this.firstElement) {
16633                return this;
16634            }
16635            var wrapper = document.createElement('div');
16636            wrapper.className = className;
16637            this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
16638            this.firstElement.parentNode.removeChild(this.firstElement);
16639            wrapper.appendChild(this.firstElement);
16640            return this;
16641        };
16642        lgQuery.prototype.addClass = function (classNames) {
16643            if (classNames === void 0) { classNames = ''; }
16644            this._each(function (el) {
16645                // IE doesn't support multiple arguments
16646                classNames.split(' ').forEach(function (className) {
16647                    if (className) {
16648                        el.classList.add(className);
16649                    }
16650                });
16651            });
16652            return this;
16653        };
16654        lgQuery.prototype.removeClass = function (classNames) {
16655            this._each(function (el) {
16656                // IE doesn't support multiple arguments
16657                classNames.split(' ').forEach(function (className) {
16658                    if (className) {
16659                        el.classList.remove(className);
16660                    }
16661                });
16662            });
16663            return this;
16664        };
16665        lgQuery.prototype.hasClass = function (className) {
16666            if (!this.firstElement) {
16667                return false;
16668            }
16669            return this.firstElement.classList.contains(className);
16670        };
16671        lgQuery.prototype.hasAttribute = function (attribute) {
16672            if (!this.firstElement) {
16673                return false;
16674            }
16675            return this.firstElement.hasAttribute(attribute);
16676        };
16677        lgQuery.prototype.toggleClass = function (className) {
16678            if (!this.firstElement) {
16679                return this;
16680            }
16681            if (this.hasClass(className)) {
16682                this.removeClass(className);
16683            }
16684            else {
16685                this.addClass(className);
16686            }
16687            return this;
16688        };
16689        lgQuery.prototype.css = function (property, value) {
16690            var _this = this;
16691            this._each(function (el) {
16692                _this._setCssVendorPrefix(el, property, value);
16693            });
16694            return this;
16695        };
16696        // Need to pass separate namespaces for separate elements
16697        lgQuery.prototype.on = function (events, listener) {
16698            var _this = this;
16699            if (!this.selector) {
16700                return this;
16701            }
16702            events.split(' ').forEach(function (event) {
16703                if (!Array.isArray(lgQuery.eventListeners[event])) {
16704                    lgQuery.eventListeners[event] = [];
16705                }
16706                lgQuery.eventListeners[event].push(listener);
16707                _this.selector.addEventListener(event.split('.')[0], listener);
16708            });
16709            return this;
16710        };
16711        // @todo - test this
16712        lgQuery.prototype.once = function (event, listener) {
16713            var _this = this;
16714            this.on(event, function () {
16715                _this.off(event);
16716                listener(event);
16717            });
16718            return this;
16719        };
16720        lgQuery.prototype.off = function (event) {
16721            var _this = this;
16722            if (!this.selector) {
16723                return this;
16724            }
16725            Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
16726                if (_this.isEventMatched(event, eventName)) {
16727                    lgQuery.eventListeners[eventName].forEach(function (listener) {
16728                        _this.selector.removeEventListener(eventName.split('.')[0], listener);
16729                    });
16730                    lgQuery.eventListeners[eventName] = [];
16731                }
16732            });
16733            return this;
16734        };
16735        lgQuery.prototype.trigger = function (event, detail) {
16736            if (!this.firstElement) {
16737                return this;
16738            }
16739            var customEvent = new CustomEvent(event.split('.')[0], {
16740                detail: detail || null,
16741            });
16742            this.firstElement.dispatchEvent(customEvent);
16743            return this;
16744        };
16745        // Does not support IE
16746        lgQuery.prototype.load = function (url) {
16747            var _this = this;
16748            fetch(url)
16749                .then(function (res) { return res.text(); })
16750                .then(function (html) {
16751                _this.selector.innerHTML = html;
16752            });
16753            return this;
16754        };
16755        lgQuery.prototype.html = function (html) {
16756            if (html === undefined) {
16757                if (!this.firstElement) {
16758                    return '';
16759                }
16760                return this.firstElement.innerHTML;
16761            }
16762            this._each(function (el) {
16763                el.innerHTML = html;
16764            });
16765            return this;
16766        };
16767        lgQuery.prototype.append = function (html) {
16768            this._each(function (el) {
16769                if (typeof html === 'string') {
16770                    el.insertAdjacentHTML('beforeend', html);
16771                }
16772                else {
16773                    el.appendChild(html);
16774                }
16775            });
16776            return this;
16777        };
16778        lgQuery.prototype.prepend = function (html) {
16779            this._each(function (el) {
16780                el.insertAdjacentHTML('afterbegin', html);
16781            });
16782            return this;
16783        };
16784        lgQuery.prototype.remove = function () {
16785            this._each(function (el) {
16786                el.parentNode.removeChild(el);
16787            });
16788            return this;
16789        };
16790        lgQuery.prototype.empty = function () {
16791            this._each(function (el) {
16792                el.innerHTML = '';
16793            });
16794            return this;
16795        };
16796        lgQuery.prototype.scrollTop = function (scrollTop) {
16797            if (scrollTop !== undefined) {
16798                document.body.scrollTop = scrollTop;
16799                document.documentElement.scrollTop = scrollTop;
16800                return this;
16801            }
16802            else {
16803                return (window.pageYOffset ||
16804                    document.documentElement.scrollTop ||
16805                    document.body.scrollTop ||
16806                    0);
16807            }
16808        };
16809        lgQuery.prototype.scrollLeft = function (scrollLeft) {
16810            if (scrollLeft !== undefined) {
16811                document.body.scrollLeft = scrollLeft;
16812                document.documentElement.scrollLeft = scrollLeft;
16813                return this;
16814            }
16815            else {
16816                return (window.pageXOffset ||
16817                    document.documentElement.scrollLeft ||
16818                    document.body.scrollLeft ||
16819                    0);
16820            }
16821        };
16822        lgQuery.prototype.offset = function () {
16823            if (!this.firstElement) {
16824                return {
16825                    left: 0,
16826                    top: 0,
16827                };
16828            }
16829            var rect = this.firstElement.getBoundingClientRect();
16830            var bodyMarginLeft = $LG('body').style().marginLeft;
16831            // Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
16832            return {
16833                left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
16834                top: rect.top + this.scrollTop(),
16835            };
16836        };
16837        lgQuery.prototype.style = function () {
16838            if (!this.firstElement) {
16839                return {};
16840            }
16841            return (this.firstElement.currentStyle ||
16842                window.getComputedStyle(this.firstElement));
16843        };
16844        // Width without padding and border even if box-sizing is used.
16845        lgQuery.prototype.width = function () {
16846            var style = this.style();
16847            return (this.firstElement.clientWidth -
16848                parseFloat(style.paddingLeft) -
16849                parseFloat(style.paddingRight));
16850        };
16851        // Height without padding and border even if box-sizing is used.
16852        lgQuery.prototype.height = function () {
16853            var style = this.style();
16854            return (this.firstElement.clientHeight -
16855                parseFloat(style.paddingTop) -
16856                parseFloat(style.paddingBottom));
16857        };
16858        lgQuery.eventListeners = {};
16859        return lgQuery;
16860    }());
16861    function $LG(selector) {
16862        initLgPolyfills();
16863        return new lgQuery(selector);
16864    }
16865
16866    var defaultDynamicOptions = [
16867        'src',
16868        'sources',
16869        'subHtml',
16870        'subHtmlUrl',
16871        'html',
16872        'video',
16873        'poster',
16874        'slideName',
16875        'responsive',
16876        'srcset',
16877        'sizes',
16878        'iframe',
16879        'downloadUrl',
16880        'download',
16881        'width',
16882        'facebookShareUrl',
16883        'tweetText',
16884        'iframeTitle',
16885        'twitterShareUrl',
16886        'pinterestShareUrl',
16887        'pinterestText',
16888        'fbHtml',
16889        'disqusIdentifier',
16890        'disqusUrl',
16891    ];
16892    // Convert html data-attribute to camalcase
16893    function convertToData(attr) {
16894        // FInd a way for lgsize
16895        if (attr === 'href') {
16896            return 'src';
16897        }
16898        attr = attr.replace('data-', '');
16899        attr = attr.charAt(0).toLowerCase() + attr.slice(1);
16900        attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
16901        return attr;
16902    }
16903    var utils = {
16904        /**
16905         * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
16906         */
16907        //Uncode edit ##START##
16908        getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
16909        // getSize: function (el, container, spacing, defaultLgSize) {
16910        //Uncode edit ##END##
16911            if (spacing === void 0) { spacing = 0; }
16912            var LGel = $LG(el);
16913            var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
16914	        //Uncode edit ##START##
16915            if ( typeof galleryItem.size && galleryItem.size != null ) {
16916            	lgSize = galleryItem.size;
16917            }
16918	        //Uncode edit ##END##
16919            if (!lgSize) {
16920                return;
16921            }
16922            var isResponsiveSizes = lgSize.split(',');
16923            // if at-least two viewport sizes are available
16924            if (isResponsiveSizes[1]) {
16925                var wWidth = window.innerWidth;
16926                for (var i = 0; i < isResponsiveSizes.length; i++) {
16927                    var size_1 = isResponsiveSizes[i];
16928                    var responsiveWidth = parseInt(size_1.split('-')[2], 10);
16929                    if (responsiveWidth > wWidth) {
16930                        lgSize = size_1;
16931                        break;
16932                    }
16933                    // take last item as last option
16934                    if (i === isResponsiveSizes.length - 1) {
16935                        lgSize = size_1;
16936                    }
16937                }
16938            }
16939            var size = lgSize.split('-');
16940            var width = parseInt(size[0], 10);
16941            var height = parseInt(size[1], 10);
16942            var cWidth = container.width();
16943            var cHeight = container.height() - spacing;
16944            var maxWidth = Math.min(cWidth, width);
16945            var maxHeight = Math.min(cHeight, height);
16946            var ratio = Math.min(maxWidth / width, maxHeight / height);
16947            return { width: width * ratio, height: height * ratio };
16948        },
16949        /**
16950         * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
16951         * @param {jQuery Element}
16952         * @returns {String} Transform CSS string
16953         */
16954        getTransform: function (el, container, top, bottom, imageSize) {
16955            if (!imageSize) {
16956                return;
16957            }
16958            var LGel = $LG(el).find('img').first();
16959            if (!LGel.get()) {
16960                return;
16961            }
16962            var containerRect = container.get().getBoundingClientRect();
16963            var wWidth = containerRect.width;
16964            // using innerWidth to include mobile safari bottom bar
16965            var wHeight = container.height() - (top + bottom);
16966            var elWidth = LGel.width();
16967            var elHeight = LGel.height();
16968            var elStyle = LGel.style();
16969            var x = (wWidth - elWidth) / 2 -
16970                LGel.offset().left +
16971                (parseFloat(elStyle.paddingLeft) || 0) +
16972                (parseFloat(elStyle.borderLeft) || 0) +
16973                $LG(window).scrollLeft() +
16974                containerRect.left;
16975            var y = (wHeight - elHeight) / 2 -
16976                LGel.offset().top +
16977                (parseFloat(elStyle.paddingTop) || 0) +
16978                (parseFloat(elStyle.borderTop) || 0) +
16979                $LG(window).scrollTop() +
16980                top;
16981            var scX = elWidth / imageSize.width;
16982            var scY = elHeight / imageSize.height;
16983            var transform = 'translate3d(' +
16984                (x *= -1) +
16985                'px, ' +
16986                (y *= -1) +
16987                'px, 0) scale3d(' +
16988                scX +
16989                ', ' +
16990                scY +
16991                ', 1)';
16992            return transform;
16993        },
16994        getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
16995            var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
16996            return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" + iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
16997        },
16998        getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
16999            var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
17000            var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17001            var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17002            var sourceTag = '';
17003            if (sources) {
17004                var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17005                sourceTag = sourceObj.map(function (source) {
17006                    var attrs = '';
17007                    Object.keys(source).forEach(function (key) {
17008                        // Do not remove the first space as it is required to separate the attributes
17009                        attrs += " " + key + "=\"" + source[key] + "\"";
17010                    });
17011                    return "<source " + attrs + "></source>";
17012                });
17013            }
17014            return "" + sourceTag + imgMarkup;
17015        },
17016        // Get src from responsive src
17017        getResponsiveSrc: function (srcItms) {
17018            var rsWidth = [];
17019            var rsSrc = [];
17020            var src = '';
17021            for (var i = 0; i < srcItms.length; i++) {
17022                var _src = srcItms[i].split(' ');
17023                // Manage empty space
17024                if (_src[0] === '') {
17025                    _src.splice(0, 1);
17026                }
17027                rsSrc.push(_src[0]);
17028                rsWidth.push(_src[1]);
17029            }
17030            var wWidth = window.innerWidth;
17031            for (var j = 0; j < rsWidth.length; j++) {
17032                if (parseInt(rsWidth[j], 10) > wWidth) {
17033                    src = rsSrc[j];
17034                    break;
17035                }
17036            }
17037            return src;
17038        },
17039        isImageLoaded: function (img) {
17040            if (!img)
17041                return false;
17042            // During the onload event, IE correctly identifies any images that
17043            // weren’t downloaded as not complete. Others should too. Gecko-based
17044            // browsers act like NS4 in that they report this incorrectly.
17045            if (!img.complete) {
17046                return false;
17047            }
17048            // However, they do have two very useful properties: naturalWidth and
17049            // naturalHeight. These give the true size of the image. If it failed
17050            // to load, either of these should be zero.
17051            if (img.naturalWidth === 0) {
17052                return false;
17053            }
17054            // No other way of checking: assume it’s ok.
17055            return true;
17056        },
17057        getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17058            var videoClass = '';
17059            if (_isVideo && _isVideo.youtube) {
17060                videoClass = 'lg-has-youtube';
17061            }
17062            else if (_isVideo && _isVideo.vimeo) {
17063                videoClass = 'lg-has-vimeo';
17064            }
17065            else {
17066                videoClass = 'lg-has-html5';
17067            }
17068            return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">\n                <svg\n                    viewBox=\"0 0 20 20\"\n                    preserveAspectRatio=\"xMidYMid\"\n                    focusable=\"false\"\n                    aria-labelledby=\"" + playVideoString + "\"\n                    role=\"img\"\n                    class=\"lg-video-play-icon\"\n                >\n                    <title>" + playVideoString + "</title>\n                    <polygon class=\"lg-video-play-icon-inner\" points=\"1,0 20,10 1,20\"></polygon>\n                </svg>\n                <svg class=\"lg-video-play-icon-bg\" viewBox=\"0 0 50 50\" focusable=\"false\">\n                    <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle></svg>\n                <svg class=\"lg-video-play-icon-circle\" viewBox=\"0 0 50 50\" focusable=\"false\">\n                    <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle>\n                </svg>\n            </div>\n            " + (dummyImg || '') + "\n            <img class=\"lg-object lg-video-poster\" src=\"" + _poster + "\" />\n        </div>";
17069        },
17070        /**
17071         * @desc Create dynamic elements array from gallery items when dynamic option is false
17072         * It helps to avoid frequent DOM interaction
17073         * and avoid multiple checks for dynamic elments
17074         *
17075         * @returns {Array} dynamicEl
17076         */
17077        getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17078            var dynamicElements = [];
17079            var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17080            [].forEach.call(items, function (item) {
17081                var dynamicEl = {};
17082                for (var i = 0; i < item.attributes.length; i++) {
17083                    var attr = item.attributes[i];
17084                    if (attr.specified) {
17085                        var dynamicAttr = convertToData(attr.name);
17086                        var label = '';
17087                        if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17088                            label = dynamicAttr;
17089                        }
17090                        if (label) {
17091                            dynamicEl[label] = attr.value;
17092                        }
17093                    }
17094                }
17095                var currentItem = $LG(item);
17096                var alt = currentItem.find('img').first().attr('alt');
17097                var title = currentItem.attr('title');
17098                //Uncode edit ##START##
17099                // var thumb = exThumbImage
17100                var thumb = exThumbImage && currentItem.attr(exThumbImage)
17101                //Uncode edit ##END##
17102                    ? currentItem.attr(exThumbImage)
17103                    : currentItem.find('img').first().attr('src');
17104                dynamicEl.thumb = thumb;
17105                //Uncode edit ##START##
17106                if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17107                    // dynamicEl.subHtml = title || alt || '';
17108                    dynamicEl.subHtml = title || '';
17109                }
17110                // dynamicEl.alt = alt || title || '';
17111                dynamicEl.alt = title || '';
17112                var inlineType = currentItem.attr('data-type');
17113                dynamicEl.type = inlineType;
17114                //Uncode edit ##END##
17115                dynamicElements.push(dynamicEl);
17116            });
17117            return dynamicElements;
17118        },
17119        isMobile: function () {
17120            return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17121        },
17122        /**
17123         * @desc Check the given src is video
17124         * @param {String} src
17125         * @return {Object} video type
17126         * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17127         *
17128         * @todo - this information can be moved to dynamicEl to avoid frequent calls
17129         */
17130        isVideo: function (src, isHTML5VIdeo, index) {
17131            if (!src) {
17132                if (isHTML5VIdeo) {
17133                    return {
17134                        html5: true,
17135                    };
17136                }
17137                else {
17138                    console.warn('lightGallery :- data-src is not provided on slide item ' +
17139                        (index + 1) +
17140                        '. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17141                    return;
17142                }
17143            }
17144            var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17145            var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17146            var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17147            if (youtube) {
17148                return {
17149                    youtube: youtube,
17150                };
17151            }
17152            else if (vimeo) {
17153                return {
17154                    vimeo: vimeo,
17155                };
17156            }
17157            else if (wistia) {
17158                return {
17159                    wistia: wistia,
17160                };
17161            }
17162        },
17163    };
17164
17165    // @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17166    // @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17167    // Unique id for each gallery
17168    var lgId = 0;
17169    var LightGallery = /** @class */ (function () {
17170        function LightGallery(element, options) {
17171            this.lgOpened = false;
17172            this.index = 0;
17173            // lightGallery modules
17174            this.plugins = [];
17175            // false when lightGallery load first slide content;
17176            this.lGalleryOn = false;
17177            // True when a slide animation is in progress
17178            this.lgBusy = false;
17179            this.currentItemsInDom = [];
17180            // Scroll top value before lightGallery is opened
17181            this.prevScrollTop = 0;
17182            this.isDummyImageRemoved = false;
17183            this.dragOrSwipeEnabled = false;
17184            this.mediaContainerPosition = {
17185                top: 0,
17186                bottom: 0,
17187            };
17188            if (!element) {
17189                return this;
17190            }
17191            lgId++;
17192            this.lgId = lgId;
17193            this.el = element;
17194            this.LGel = $LG(element);
17195            this.generateSettings(options);
17196            this.buildModules();
17197            // When using dynamic mode, ensure dynamicEl is an array
17198            if (this.settings.dynamic &&
17199                this.settings.dynamicEl !== undefined &&
17200                !Array.isArray(this.settings.dynamicEl)) {
17201                throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17202            }
17203            this.galleryItems = this.getItems();
17204            this.normalizeSettings();
17205            // Gallery items
17206            this.init();
17207	        //Uncode edit ##START##
17208            // this.validateLicense();
17209	        //Uncode edit ##END##
17210            return this;
17211        }
17212        LightGallery.prototype.generateSettings = function (options) {
17213            // lightGallery settings
17214            this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17215            if (this.settings.isMobile &&
17216                typeof this.settings.isMobile === 'function'
17217                ? this.settings.isMobile()
17218                : utils.isMobile()) {
17219                var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17220                this.settings = __assign(__assign({}, this.settings), mobileSettings);
17221            }
17222        };
17223        LightGallery.prototype.normalizeSettings = function () {
17224            if (this.settings.slideEndAnimation) {
17225                this.settings.hideControlOnEnd = false;
17226            }
17227            if (!this.settings.closable) {
17228                this.settings.swipeToClose = false;
17229            }
17230            // And reset it on close to get the correct value next time
17231            this.zoomFromOrigin = this.settings.zoomFromOrigin;
17232            // At the moment, Zoom from image doesn't support dynamic options
17233            // @todo add zoomFromOrigin support for dynamic images
17234            if (this.settings.dynamic) {
17235                this.zoomFromOrigin = false;
17236            }
17237            if (!this.settings.container) {
17238                this.settings.container = document.body;
17239            }
17240            // settings.preload should not be grater than $item.length
17241            this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17242        };
17243        LightGallery.prototype.init = function () {
17244            var _this = this;
17245            this.addSlideVideoInfo(this.galleryItems);
17246            this.buildStructure();
17247            this.LGel.trigger(lGEvents.init, {
17248                instance: this,
17249            });
17250            if (this.settings.keyPress) {
17251                this.keyPress();
17252            }
17253            setTimeout(function () {
17254                _this.enableDrag();
17255                _this.enableSwipe();
17256                _this.triggerPosterClick();
17257            }, 50);
17258            this.arrow();
17259            if (this.settings.mousewheel) {
17260                this.mousewheel();
17261            }
17262            if (!this.settings.dynamic) {
17263                this.openGalleryOnItemClick();
17264            }
17265        };
17266        LightGallery.prototype.openGalleryOnItemClick = function () {
17267            var _this = this;
17268            var _loop_1 = function (index) {
17269                var element = this_1.items[index];
17270                var $element = $LG(element);
17271                // Using different namespace for click because click event should not unbind if selector is same object('this')
17272                // @todo manage all event listners - should have namespace that represent element
17273                var uuid = lgQuery.generateUUID();
17274                $element
17275                    .attr('data-lg-id', uuid)
17276                    .on("click.lgcustom-item-" + uuid, function (e) {
17277                    e.preventDefault();
17278                    var currentItemIndex = _this.settings.index || index;
17279                    _this.openGallery(currentItemIndex, element);
17280                });
17281            };
17282            var this_1 = this;
17283            // Using for loop instead of using bubbling as the items can be any html element.
17284            for (var index = 0; index < this.items.length; index++) {
17285                _loop_1(index);
17286            }
17287        };
17288        /**
17289         * Module constructor
17290         * Modules are build incrementally.
17291         * Gallery should be opened only once all the modules are initialized.
17292         * use moduleBuildTimeout to make sure this
17293         */
17294        LightGallery.prototype.buildModules = function () {
17295            var _this = this;
17296            this.settings.plugins.forEach(function (plugin) {
17297                _this.plugins.push(new plugin(_this, $LG));
17298            });
17299        };
17300        LightGallery.prototype.validateLicense = function () {
17301            if (!this.settings.licenseKey) {
17302                console.warn('Please provide a valid license key');
17303            }
17304            else if (this.settings.licenseKey === '0000-0000-000-0000') {
17305                console.warn("lightGallery: " + this.settings.licenseKey + " license key is not valid for production use");
17306            }
17307        };
17308        LightGallery.prototype.getSlideItem = function (index) {
17309            return $LG(this.getSlideItemId(index));
17310        };
17311        LightGallery.prototype.getSlideItemId = function (index) {
17312            return "#lg-item-" + this.lgId + "-" + index;
17313        };
17314        LightGallery.prototype.getIdName = function (id) {
17315            return id + "-" + this.lgId;
17316        };
17317        LightGallery.prototype.getElementById = function (id) {
17318            return $LG("#" + this.getIdName(id));
17319        };
17320        LightGallery.prototype.manageSingleSlideClassName = function () {
17321            if (this.galleryItems.length < 2) {
17322                this.outer.addClass('lg-single-item');
17323            }
17324            else {
17325                this.outer.removeClass('lg-single-item');
17326            }
17327        };
17328        LightGallery.prototype.buildStructure = function () {
17329            var _this = this;
17330            var container = this.$container && this.$container.get();
17331            if (container) {
17332                return;
17333            }
17334            var controls = '';
17335            var subHtmlCont = '';
17336            // Create controls
17337            if (this.settings.controls) {
17338                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>";
17339            }
17340            if (this.settings.appendSubHtmlTo !== '.lg-item') {
17341                subHtmlCont =
17342                    '<div class="lg-sub-html" role="status" aria-live="polite"></div>';
17343            }
17344            var addClasses = '';
17345            if (this.settings.allowMediaOverlap) {
17346                // Do not remove space before last single quote
17347                addClasses += 'lg-media-overlap ';
17348            }
17349            var ariaLabelledby = this.settings.ariaLabelledby
17350                ? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
17351                : '';
17352            var ariaDescribedby = this.settings.ariaDescribedby
17353                ? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
17354                : '';
17355            var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
17356            var closeIcon = this.settings.closable && this.settings.showCloseIcon
17357                ? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
17358                : '';
17359            var maximizeIcon = this.settings.showMaximizeIcon
17360                ? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
17361                : '';
17362            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'
17363                ? subHtmlCont
17364                : '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
17365                ? subHtmlCont
17366                : '') + "\n                </div>\n            </div>\n        </div>\n        ";
17367            $LG(this.settings.container).append(template);
17368            if (document.body !== this.settings.container) {
17369                $LG(this.settings.container).css('position', 'relative');
17370            }
17371            this.outer = this.getElementById('lg-outer');
17372            this.$lgComponents = this.getElementById('lg-components');
17373            this.$backdrop = this.getElementById('lg-backdrop');
17374            this.$container = this.getElementById('lg-container');
17375            this.$inner = this.getElementById('lg-inner');
17376            this.$content = this.getElementById('lg-content');
17377            this.$toolbar = this.getElementById('lg-toolbar');
17378            this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
17379            var outerClassNames = this.settings.mode + " ";
17380            this.manageSingleSlideClassName();
17381            if (this.settings.enableDrag) {
17382                outerClassNames += 'lg-grab ';
17383            }
17384            this.outer.addClass(outerClassNames);
17385            this.$inner.css('transition-timing-function', this.settings.easing);
17386            this.$inner.css('transition-duration', this.settings.speed + 'ms');
17387            if (this.settings.download) {
17388                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>");
17389            }
17390            this.counter();
17391            $LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
17392                _this.refreshOnResize();
17393            });
17394            this.hideBars();
17395            this.manageCloseGallery();
17396            this.toggleMaximize();
17397            this.initModules();
17398        };
17399        LightGallery.prototype.refreshOnResize = function () {
17400            if (this.lgOpened) {
17401                var currentGalleryItem = this.galleryItems[this.index];
17402                var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
17403                this.mediaContainerPosition = this.getMediaContainerPosition();
17404                var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
17405		        //Uncode edit ##START##
17406                this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
17407                // this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
17408		        //Uncode edit ##END##
17409                if (__slideVideoInfo) {
17410                    this.resizeVideoSlide(this.index, this.currentImageSize);
17411                }
17412                if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
17413                    var imgStyle = this.getDummyImgStyles(this.currentImageSize);
17414                    this.outer
17415                        .find('.lg-current .lg-dummy-img')
17416                        .first()
17417                        .attr('style', imgStyle);
17418                }
17419                this.LGel.trigger(lGEvents.containerResize);
17420            }
17421        };
17422        LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
17423            var lgVideoStyle = this.getVideoContStyle(imageSize);
17424            var currentSlide = this.getSlideItem(index);
17425            currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
17426        };
17427        /**
17428         * Update slides dynamically.
17429         * Add, edit or delete slides dynamically when lightGallery is opened.
17430         * Modify the current gallery items and pass it via updateSlides method
17431         * @note
17432         * - Do not mutate existing lightGallery items directly.
17433         * - Always pass new list of gallery items
17434         * - You need to take care of thumbnails outside the gallery if any
17435         * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
17436         * @param items Gallery items
17437         * @param index After the update operation, which slide gallery should navigate to
17438         * @category lGPublicMethods
17439         * @example
17440         * const plugin = lightGallery();
17441         *
17442         * // Adding slides dynamically
17443         * let galleryItems = [
17444         * // Access existing lightGallery items
17445         * // galleryItems are automatically generated internally from the gallery HTML markup
17446         * // or directly from galleryItems when dynamic gallery is used
17447         *   ...plugin.galleryItems,
17448         *     ...[
17449         *       {
17450         *         src: 'img/img-1.png',
17451         *           thumb: 'img/thumb1.png',
17452         *         },
17453         *     ],
17454         *   ];
17455         *   plugin.updateSlides(
17456         *     galleryItems,
17457         *     plugin.index,
17458         *   );
17459         *
17460         *
17461         * // Remove slides dynamically
17462         * galleryItems = JSON.parse(
17463         *   JSON.stringify(updateSlideInstance.galleryItems),
17464         * );
17465         * galleryItems.shift();
17466         * updateSlideInstance.updateSlides(galleryItems, 1);
17467         * @see <a href="/demos/update-slides/">Demo</a>
17468         */
17469        LightGallery.prototype.updateSlides = function (items, index) {
17470            if (this.index > items.length - 1) {
17471                this.index = items.length - 1;
17472            }
17473            if (items.length === 1) {
17474                this.index = 0;
17475            }
17476            if (!items.length) {
17477                this.closeGallery();
17478                return;
17479            }
17480            var currentSrc = this.galleryItems[index].src;
17481            this.galleryItems = items;
17482            this.updateControls();
17483            this.$inner.empty();
17484            this.currentItemsInDom = [];
17485            var _index = 0;
17486            // Find the current index based on source value of the slide
17487            this.galleryItems.some(function (galleryItem, itemIndex) {
17488                if (galleryItem.src === currentSrc) {
17489                    _index = itemIndex;
17490                    return true;
17491                }
17492                return false;
17493            });
17494            this.currentItemsInDom = this.organizeSlideItems(_index, -1);
17495            this.loadContent(_index, true);
17496            this.getSlideItem(_index).addClass('lg-current');
17497            this.index = _index;
17498            this.updateCurrentCounter(_index);
17499            this.LGel.trigger(lGEvents.updateSlides);
17500        };
17501        // Get gallery items based on multiple conditions
17502        LightGallery.prototype.getItems = function () {
17503            // Gallery items
17504            this.items = [];
17505            if (!this.settings.dynamic) {
17506                if (this.settings.selector === 'this') {
17507                    this.items.push(this.el);
17508                }
17509                else if (this.settings.selector) {
17510                    if (typeof this.settings.selector === 'string') {
17511                        if (this.settings.selectWithin) {
17512                            var selectWithin = $LG(this.settings.selectWithin);
17513                            this.items = selectWithin
17514                                .find(this.settings.selector)
17515                                .get();
17516                        }
17517                        else {
17518                            this.items = this.el.querySelectorAll(this.settings.selector);
17519                        }
17520                    }
17521                    else {
17522                        this.items = this.settings.selector;
17523                    }
17524                }
17525                else {
17526                    this.items = this.el.children;
17527                }
17528                return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
17529            }
17530            else {
17531                return this.settings.dynamicEl || [];
17532            }
17533        };
17534        /**
17535         * Open lightGallery.
17536         * Open gallery with specific slide by passing index of the slide as parameter.
17537         * @category lGPublicMethods
17538         * @param {Number} index  - index of the slide
17539         * @param {HTMLElement} element - Which image lightGallery should zoom from
17540         *
17541         * @example
17542         * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
17543         * const dynamicGallery = lightGallery($dynamicGallery, {
17544         *     dynamic: true,
17545         *     dynamicEl: [
17546         *         {
17547         *              src: 'img/1.jpg',
17548         *              thumb: 'img/thumb-1.jpg',
17549         *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
17550         *         },
17551         *         ...
17552         *     ],
17553         * });
17554         * $dynamicGallery.addEventListener('click', function () {
17555         *     // Starts with third item.(Optional).
17556         *     // This is useful if you want use dynamic mode with
17557         *     // custom thumbnails (thumbnails outside gallery),
17558         *     dynamicGallery.openGallery(2);
17559         * });
17560         *
17561         */
17562        LightGallery.prototype.openGallery = function (index, element) {
17563            var _this = this;
17564            if (index === void 0) { index = this.settings.index; }
17565            // prevent accidental double execution
17566            if (this.lgOpened)
17567                return;
17568            this.lgOpened = true;
17569            this.outer.get().focus();
17570            this.outer.removeClass('lg-hide-items');
17571            // Add display block, but still has opacity 0
17572            this.$container.addClass('lg-show');
17573            var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
17574            this.currentItemsInDom = itemsToBeInsertedToDom;
17575            var items = '';
17576            itemsToBeInsertedToDom.forEach(function (item) {
17577                items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
17578            });
17579            this.$inner.append(items);
17580            this.addHtml(index);
17581            var transform = '';
17582            this.mediaContainerPosition = this.getMediaContainerPosition();
17583            var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
17584            if (!this.settings.allowMediaOverlap) {
17585                this.setMediaContainerPosition(top, bottom);
17586            }
17587            var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
17588            if (this.zoomFromOrigin && element) {
17589		        //Uncode edit ##START##
17590                this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
17591                // this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
17592		        //Uncode edit ##END##
17593                transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
17594            }
17595            if (!this.zoomFromOrigin || !transform) {
17596                this.outer.addClass(this.settings.startClass);
17597                this.getSlideItem(index).removeClass('lg-complete');
17598            }
17599            var timeout = this.settings.zoomFromOrigin
17600                ? 100
17601                : this.settings.backdropDuration;
17602            setTimeout(function () {
17603                _this.outer.addClass('lg-components-open');
17604            }, timeout);
17605            this.index = index;
17606            //Uncode edit ##START##
17607            // this.LGel.trigger(lGEvents.beforeOpen);
17608            this.LGel.trigger(lGEvents.beforeOpen, {
17609            	galleryItems: this.galleryItems,
17610                items: this.items,
17611                outer: this.outer,
17612            });
17613            //Uncode edit ##END##
17614            // add class lg-current to remove initial transition
17615            this.getSlideItem(index).addClass('lg-current');
17616            this.lGalleryOn = false;
17617            // Store the current scroll top value to scroll back after closing the gallery..
17618            this.prevScrollTop = $LG(window).scrollTop();
17619            setTimeout(function () {
17620                // Need to check both zoomFromOrigin and transform values as we need to set set the
17621                // default opening animation if user missed to add the lg-size attribute
17622                if (_this.zoomFromOrigin && transform) {
17623                    var currentSlide_1 = _this.getSlideItem(index);
17624                    currentSlide_1.css('transform', transform);
17625                    setTimeout(function () {
17626                        currentSlide_1
17627                            .addClass('lg-start-progress lg-start-end-progress')
17628                            .css('transition-duration', _this.settings.startAnimationDuration + 'ms');
17629                        _this.outer.addClass('lg-zoom-from-image');
17630                    });
17631                    setTimeout(function () {
17632                        currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
17633                    }, 100);
17634                }
17635                setTimeout(function () {
17636                    _this.$backdrop.addClass('in');
17637                    _this.$container.addClass('lg-show-in');
17638                }, 10);
17639                // lg-visible class resets gallery opacity to 1
17640                if (!_this.zoomFromOrigin || !transform) {
17641                    setTimeout(function () {
17642                        _this.outer.addClass('lg-visible');
17643                    }, _this.settings.backdropDuration);
17644                }
17645                // initiate slide function
17646                _this.slide(index, false, false, false);
17647                _this.LGel.trigger(lGEvents.afterOpen);
17648            });
17649            if (document.body === this.settings.container) {
17650                $LG('html').addClass('lg-on');
17651            }
17652        };
17653        /**
17654         * Note - Changing the position of the media on every slide transition creates a flickering effect.
17655         * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
17656         * if you have dynamic captions for each media,
17657         * you can provide an appropriate height for the captions via allowMediaOverlap option
17658         */
17659        LightGallery.prototype.getMediaContainerPosition = function () {
17660            if (this.settings.allowMediaOverlap) {
17661                return {
17662                    top: 0,
17663                    bottom: 0,
17664                };
17665            }
17666            var top = this.$toolbar.get().clientHeight || 0;
17667            var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
17668            var captionHeight = this.settings.defaultCaptionHeight ||
17669                (subHtml && subHtml.clientHeight) ||
17670                0;
17671            var thumbContainer = this.outer.find('.lg-thumb-outer').get();
17672            var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
17673            var bottom = thumbHeight + captionHeight;
17674            //Uncode edit ##START##
17675            bottom = bottom < 55 ? 55 : bottom;
17676            //Uncode edit ##END##
17677            return {
17678                top: top,
17679                bottom: bottom,
17680            };
17681        };
17682        LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
17683            if (top === void 0) { top = 0; }
17684            if (bottom === void 0) { bottom = 0; }
17685            this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
17686        };
17687        LightGallery.prototype.hideBars = function () {
17688            var _this = this;
17689            // Hide controllers if mouse doesn't move for some period
17690            setTimeout(function () {
17691                _this.outer.removeClass('lg-hide-items');
17692                if (_this.settings.hideBarsDelay > 0) {
17693                    _this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
17694                        _this.outer.removeClass('lg-hide-items');
17695                        clearTimeout(_this.hideBarTimeout);
17696                        // Timeout will be cleared on each slide movement also
17697                        _this.hideBarTimeout = setTimeout(function () {
17698                            _this.outer.addClass('lg-hide-items');
17699                        }, _this.settings.hideBarsDelay);
17700                    });
17701                    _this.outer.trigger('mousemove.lg');
17702                }
17703            }, this.settings.showBarsAfter);
17704        };
17705        LightGallery.prototype.initPictureFill = function ($img) {
17706            if (this.settings.supportLegacyBrowser) {
17707                try {
17708                    picturefill({
17709                        elements: [$img.get()],
17710                    });
17711                }
17712                catch (e) {
17713                    console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
17714                }
17715            }
17716        };
17717        /**
17718         *  @desc Create image counter
17719         *  Ex: 1/10
17720         */
17721        LightGallery.prototype.counter = function () {
17722            if (this.settings.counter) {
17723                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>";
17724                this.outer.find(this.settings.appendCounterTo).append(counterHtml);
17725            }
17726        };
17727        /**
17728         *  @desc add sub-html into the slide
17729         *  @param {Number} index - index of the slide
17730         */
17731        LightGallery.prototype.addHtml = function (index) {
17732            var subHtml;
17733            var subHtmlUrl;
17734            if (this.galleryItems[index].subHtmlUrl) {
17735                subHtmlUrl = this.galleryItems[index].subHtmlUrl;
17736            }
17737            else {
17738                subHtml = this.galleryItems[index].subHtml;
17739            }
17740            if (!subHtmlUrl) {
17741                if (subHtml) {
17742                    // get first letter of sub-html
17743                    // if first letter starts with . or # get the html form the jQuery object
17744                    var fL = subHtml.substring(0, 1);
17745                    if (fL === '.' || fL === '#') {
17746                        if (this.settings.subHtmlSelectorRelative &&
17747                            !this.settings.dynamic) {
17748                            subHtml = $LG(this.items)
17749                                .eq(index)
17750                                .find(subHtml)
17751                                .first()
17752                                .html();
17753                        }
17754                        else {
17755                            subHtml = $LG(subHtml).first().html();
17756                        }
17757                    }
17758                }
17759                else {
17760                    subHtml = '';
17761                }
17762            }
17763            if (this.settings.appendSubHtmlTo !== '.lg-item') {
17764                if (subHtmlUrl) {
17765                    this.outer.find('.lg-sub-html').load(subHtmlUrl);
17766                }
17767                else {
17768                    this.outer.find('.lg-sub-html').html(subHtml);
17769                }
17770            }
17771            else {
17772                var currentSlide = $LG(this.getSlideItemId(index));
17773                if (subHtmlUrl) {
17774                    currentSlide.load(subHtmlUrl);
17775                }
17776                else {
17777                    currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
17778                }
17779            }
17780            // Add lg-empty-html class if title doesn't exist
17781            if (typeof subHtml !== 'undefined' && subHtml !== null) {
17782                if (subHtml === '') {
17783                    this.outer
17784                        .find(this.settings.appendSubHtmlTo)
17785                        .addClass('lg-empty-html');
17786                }
17787                else {
17788                    this.outer
17789                        .find(this.settings.appendSubHtmlTo)
17790                        .removeClass('lg-empty-html');
17791                }
17792            }
17793            this.LGel.trigger(lGEvents.afterAppendSubHtml, {
17794                index: index,
17795            });
17796        };
17797        /**
17798         *  @desc Preload slides
17799         *  @param {Number} index - index of the slide
17800         * @todo preload not working for the first slide, Also, should work for the first and last slide as well
17801         */
17802        LightGallery.prototype.preload = function (index) {
17803            for (var i = 1; i <= this.settings.preload; i++) {
17804                if (i >= this.galleryItems.length - index) {
17805                    break;
17806                }
17807                this.loadContent(index + i, false);
17808            }
17809            for (var j = 1; j <= this.settings.preload; j++) {
17810                if (index - j < 0) {
17811                    break;
17812                }
17813                this.loadContent(index - j, false);
17814            }
17815        };
17816        LightGallery.prototype.getDummyImgStyles = function (imageSize) {
17817            if (!imageSize)
17818                return '';
17819            return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
17820        };
17821        LightGallery.prototype.getVideoContStyle = function (imageSize) {
17822            if (!imageSize)
17823                return '';
17824            return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
17825        };
17826        LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
17827            var $currentItem;
17828            if (!this.settings.dynamic) {
17829                $currentItem = $LG(this.items).eq(index);
17830            }
17831            if ($currentItem) {
17832                var _dummyImgSrc = void 0;
17833                if (!this.settings.exThumbImage) {
17834                    _dummyImgSrc = $currentItem.find('img').first().attr('src');
17835                }
17836                else {
17837                    _dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
17838                }
17839                if (!_dummyImgSrc)
17840                    return '';
17841                var imgStyle = this.getDummyImgStyles(this.currentImageSize);
17842                var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
17843                $currentSlide.addClass('lg-first-slide');
17844                this.outer.addClass('lg-first-slide-loading');
17845                return dummyImgContent;
17846            }
17847            return '';
17848        };
17849        LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
17850            var currentGalleryItem = this.galleryItems[index];
17851            var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
17852            // Use the thumbnail as dummy image which will be resized to actual image size and
17853            // displayed on top of actual image
17854            var imgContent = '';
17855            var altAttr = alt ? 'alt="' + alt + '"' : '';
17856            if (this.isFirstSlideWithZoomAnimation()) {
17857                imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
17858            }
17859            else {
17860                imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
17861            }
17862            var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
17863            $currentSlide.prepend(imgMarkup);
17864        };
17865        LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
17866            var mediaObject = $slide.find('.lg-object').first();
17867            if (utils.isImageLoaded(mediaObject.get()) ||
17868                isHTML5VideoWithoutPoster) {
17869                onLoad();
17870            }
17871            else {
17872                mediaObject.on('load.lg error.lg', function () {
17873                    onLoad && onLoad();
17874                });
17875                mediaObject.on('error.lg', function () {
17876                    onError && onError();
17877                });
17878            }
17879        };
17880        /**
17881         *
17882         * @param $el Current slide item
17883         * @param index
17884         * @param delay Delay is 0 except first time
17885         * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
17886         * @param isFirstSlide
17887         */
17888        LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
17889            var _this = this;
17890            //Uncode edit ##START##
17891            var $item = _this.galleryItems[index],
17892            	type = $item.type;
17893
17894            if ( typeof $item.src !== 'undefined' ) {
17895            	var inline_id = $item.src.replace('#', ''),
17896	            	$inline = document.getElementById(inline_id),
17897	            	inline_html;
17898
17899	            if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
17900	            	inline_html = $inline.innerHTML;
17901		        } else {
17902	            	inline_html = '';
17903		        }
17904		    }
17905            //Uncode edit ##END##
17906            this.onSlideObjectLoad(currentSlide, isHTML5VideoWithoutPoster, function () {
17907                _this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
17908            }, function () {
17909                currentSlide.addClass('lg-complete lg-complete_');
17910	            //Uncode edit ##START##
17911                // currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
17912	            if ( inline_html !== '' ) {
17913	                currentSlide.html(inline_html);
17914	            } else {
17915	                currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
17916	            }
17917	            //Uncode edit ##END##
17918            });
17919        };
17920        LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
17921            var _this = this;
17922            var currentGalleryItem = this.galleryItems[index];
17923            // Adding delay for video slides without poster for better performance and user experience
17924            // Videos should start playing once once the gallery is completely loaded
17925            var _speed = isFirstSlide &&
vendor: 49,644 bytes, lines 17926-18972
17926                this.getSlideType(currentGalleryItem) === 'video' &&
17927                !currentGalleryItem.poster
17928                ? speed
17929                : 0;
17930            setTimeout(function () {
17931                $currentSlide.addClass('lg-complete lg-complete_');
17932                _this.LGel.trigger(lGEvents.slideItemLoad, {
17933                    index: index,
17934                    delay: delay || 0,
17935                    isFirstSlide: isFirstSlide,
17936                });
17937            }, _speed);
17938        };
17939        LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
17940            return !!(!this.lGalleryOn &&
17941                this.zoomFromOrigin &&
17942                this.currentImageSize);
17943        };
17944        // Add video slideInfo
17945        LightGallery.prototype.addSlideVideoInfo = function (items) {
17946            var _this = this;
17947            items.forEach(function (element, index) {
17948                element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
17949                if (element.__slideVideoInfo &&
17950                    _this.settings.loadYouTubePoster &&
17951                    !element.poster &&
17952                    element.__slideVideoInfo.youtube) {
17953                    element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
17954                }
17955            });
17956        };
17957        /**
17958         *  Load slide content into slide.
17959         *  This is used to load content into slides that is not visible too
17960         *  @param {Number} index - index of the slide.
17961         *  @param {Boolean} rec - if true call loadcontent() function again.
17962         */
17963        LightGallery.prototype.loadContent = function (index, rec) {
17964            var _this = this;
17965            var currentGalleryItem = this.galleryItems[index];
17966            var $currentSlide = $LG(this.getSlideItemId(index));
17967            var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
17968            var src = currentGalleryItem.src;
17969            var video = currentGalleryItem.video;
17970            var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
17971            if (currentGalleryItem.responsive) {
17972                var srcDyItms = currentGalleryItem.responsive.split(',');
17973                src = utils.getResponsiveSrc(srcDyItms) || src;
17974            }
17975            var videoInfo = currentGalleryItem.__slideVideoInfo;
17976            var lgVideoStyle = '';
17977            var iframe = !!currentGalleryItem.iframe;
17978            var isFirstSlide = !this.lGalleryOn;
17979            // delay for adding complete class. it is 0 except first time.
17980            var delay = 0;
17981            if (isFirstSlide) {
17982                if (this.zoomFromOrigin && this.currentImageSize) {
17983                    delay = this.settings.startAnimationDuration + 10;
17984                }
17985                else {
17986                    delay = this.settings.backdropDuration + 10;
17987                }
17988            }
17989            if (!$currentSlide.hasClass('lg-loaded')) {
17990                if (videoInfo) {
17991                    var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
17992			        //Uncode edit ##START##
17993                    var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
17994                    // var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
17995			        //Uncode edit ##END##
17996                    lgVideoStyle = this.getVideoContStyle(videoSize);
17997                }
17998                if (iframe) {
17999                    var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18000                    $currentSlide.prepend(markup);
18001                }
18002                else if (poster) {
18003                    var dummyImg = '';
18004                    var hasStartAnimation = isFirstSlide &&
18005                        this.zoomFromOrigin &&
18006                        this.currentImageSize;
18007                    if (hasStartAnimation) {
18008                        dummyImg = this.getDummyImageContent($currentSlide, index, '');
18009                    }
18010                    var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18011                    $currentSlide.prepend(markup);
18012                }
18013                //Uncode edit ##START##
18014                // else if (videoInfo) {
18015                else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18016	                if (! _html5Video) {
18017	                    var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18018	                }
18019	                //Uncode edit ##END##
18020                    $currentSlide.prepend(markup);
18021                }
18022                else {
18023                    this.setImgMarkup(src, $currentSlide, index);
18024                    if (srcset || sources) {
18025                        var $img = $currentSlide.find('.lg-object');
18026                        this.initPictureFill($img);
18027                    }
18028                }
18029                if (poster || videoInfo) {
18030                    this.LGel.trigger(lGEvents.hasVideo, {
18031                        index: index,
18032                        src: src,
18033                        html5Video: _html5Video,
18034                        hasPoster: !!poster,
18035                    });
18036                }
18037                this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18038                if (this.lGalleryOn &&
18039                    this.settings.appendSubHtmlTo === '.lg-item') {
18040                    this.addHtml(index);
18041                }
18042            }
18043            // For first time add some delay for displaying the start animation.
18044            var _speed = 0;
18045            // Do not change the delay value because it is required for zoom plugin.
18046            // If gallery opened from direct url (hash) speed value should be 0
18047            if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18048                _speed = delay;
18049            }
18050            // Only for first slide and zoomFromOrigin is enabled
18051            if (this.isFirstSlideWithZoomAnimation()) {
18052                setTimeout(function () {
18053                    $currentSlide
18054                        .removeClass('lg-start-end-progress lg-start-progress')
18055                        .removeAttr('style');
18056                }, this.settings.startAnimationDuration + 100);
18057                if (!$currentSlide.hasClass('lg-loaded')) {
18058                    setTimeout(function () {
18059                        if (_this.getSlideType(currentGalleryItem) === 'image') {
18060                            $currentSlide
18061                                .find('.lg-img-wrap')
18062                                .append(utils.getImgMarkup(index, src, '', srcset, sizes, currentGalleryItem.sources));
18063                            if (srcset || sources) {
18064                                var $img = $currentSlide.find('.lg-object');
18065                                _this.initPictureFill($img);
18066                            }
18067                        }
18068                        if (_this.getSlideType(currentGalleryItem) === 'image' ||
18069                            (_this.getSlideType(currentGalleryItem) === 'video' &&
18070                                poster)) {
18071                            _this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18072                            // load remaining slides once the slide is completely loaded
18073                            _this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18074                                _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18075                            }, function () {
18076                                _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18077                            });
18078                        }
18079                    }, this.settings.startAnimationDuration + 100);
18080                }
18081            }
18082            // SLide content has been added to dom
18083            $currentSlide.addClass('lg-loaded');
18084            if (!this.isFirstSlideWithZoomAnimation() ||
18085                (this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18086                //Uncode edit ##START##
18087                // this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18088                this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.getSlideType(currentGalleryItem) === 'audio'));
18089                //Uncode edit ##END##
18090            }
18091            // When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18092            if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18093                $currentSlide.hasClass('lg-complete_') &&
18094                !this.lGalleryOn) {
18095                setTimeout(function () {
18096                    $currentSlide.addClass('lg-complete');
18097                }, this.settings.backdropDuration);
18098            }
18099            // Content loaded
18100            // Need to set lGalleryOn before calling preload function
18101            this.lGalleryOn = true;
18102            if (rec === true) {
18103                if (!$currentSlide.hasClass('lg-complete_')) {
18104                    $currentSlide
18105                        .find('.lg-object')
18106                        .first()
18107                        .on('load.lg error.lg', function () {
18108                        _this.preload(index);
18109                    });
18110                }
18111                else {
18112                    this.preload(index);
18113                }
18114            }
18115        };
18116        /**
18117         * @desc Remove dummy image content and load next slides
18118         * Called only for the first time if zoomFromOrigin animation is enabled
18119         * @param index
18120         * @param $currentSlide
18121         * @param speed
18122         */
18123        LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18124            var _this = this;
18125            setTimeout(function () {
18126                $currentSlide.find('.lg-dummy-img').remove();
18127                $currentSlide.removeClass('lg-first-slide');
18128                _this.outer.removeClass('lg-first-slide-loading');
18129                _this.isDummyImageRemoved = true;
18130                _this.preload(index);
18131            }, speed + 300);
18132        };
18133        LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18134            var _this = this;
18135            if (numberOfItems === void 0) { numberOfItems = 0; }
18136            var itemsToBeInsertedToDom = [];
18137            // Minimum 2 items should be there
18138            var possibleNumberOfItems = Math.max(numberOfItems, 3);
18139            possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18140            var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18141            if (this.galleryItems.length <= 3) {
18142                this.galleryItems.forEach(function (_element, index) {
18143                    itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18144                });
18145                return itemsToBeInsertedToDom;
18146            }
18147            if (index < (this.galleryItems.length - 1) / 2) {
18148                for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18149                    itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18150                }
18151                var numberOfExistingItems = itemsToBeInsertedToDom.length;
18152                for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18153                    itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18154                }
18155            }
18156            else {
18157                for (var idx = index; idx <= this.galleryItems.length - 1 &&
18158                    idx < index + possibleNumberOfItems / 2; idx++) {
18159                    itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18160                }
18161                var numberOfExistingItems = itemsToBeInsertedToDom.length;
18162                for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18163                    itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18164                }
18165            }
18166            if (this.settings.loop) {
18167                if (index === this.galleryItems.length - 1) {
18168                    itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18169                }
18170                else if (index === 0) {
18171                    itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18172                }
18173            }
18174            if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18175                itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18176            }
18177            return itemsToBeInsertedToDom;
18178        };
18179        LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18180            var _this = this;
18181            var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18182            itemsToBeInsertedToDom.forEach(function (item) {
18183                if (_this.currentItemsInDom.indexOf(item) === -1) {
18184                    _this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18185                }
18186            });
18187            this.currentItemsInDom.forEach(function (item) {
18188                if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18189                    $LG("#" + item).remove();
18190                }
18191            });
18192            return itemsToBeInsertedToDom;
18193        };
18194        /**
18195         * Get previous index of the slide
18196         */
18197        LightGallery.prototype.getPreviousSlideIndex = function () {
18198            var prevIndex = 0;
18199            try {
18200                var currentItemId = this.outer
18201                    .find('.lg-current')
18202                    .first()
18203                    .attr('id');
18204                prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18205            }
18206            catch (error) {
18207                prevIndex = 0;
18208            }
18209            return prevIndex;
18210        };
18211        LightGallery.prototype.setDownloadValue = function (index) {
18212            if (this.settings.download) {
18213                var currentGalleryItem = this.galleryItems[index];
18214                var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18215                    currentGalleryItem.downloadUrl === 'false';
18216                if (hideDownloadBtn) {
18217                    this.outer.addClass('lg-hide-download');
18218                }
18219                else {
18220                    var $download = this.getElementById('lg-download');
18221                    this.outer.removeClass('lg-hide-download');
18222                    $download.attr('href', currentGalleryItem.downloadUrl ||
18223                        currentGalleryItem.src);
18224                    if (currentGalleryItem.download) {
18225		            	//Uncode edit ##START##
18226		                var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
18227		                	download_name = download_url.substring(download_url.lastIndexOf('/')+1);
18228		                $download.attr('download', download_name);
18229                        // $download.attr('download', currentGalleryItem.download);
18230		                //Uncode edit ##END##
18231                    }
18232                }
18233            }
18234        };
18235        LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
18236            var _this = this;
18237            if (this.lGalleryOn) {
18238                previousSlideItem.addClass('lg-slide-progress');
18239            }
18240            setTimeout(function () {
18241                // remove all transitions
18242                _this.outer.addClass('lg-no-trans');
18243                _this.outer
18244                    .find('.lg-item')
18245                    .removeClass('lg-prev-slide lg-next-slide');
18246                if (direction === 'prev') {
18247                    //prevslide
18248                    currentSlideItem.addClass('lg-prev-slide');
18249                    previousSlideItem.addClass('lg-next-slide');
18250                }
18251                else {
18252                    // next slide
18253                    currentSlideItem.addClass('lg-next-slide');
18254                    previousSlideItem.addClass('lg-prev-slide');
18255                }
18256                // give 50 ms for browser to add/remove class
18257                setTimeout(function () {
18258                    _this.outer.find('.lg-item').removeClass('lg-current');
18259                    currentSlideItem.addClass('lg-current');
18260                    // reset all transitions
18261                    _this.outer.removeClass('lg-no-trans');
18262                }, 50);
18263            }, this.lGalleryOn ? this.settings.slideDelay : 0);
18264        };
18265        /**
18266         * Goto a specific slide.
18267         * @param {Number} index - index of the slide
18268         * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
18269         * @param {Boolean} fromThumb - true if slide function called via thumbnail click
18270         * @param {String} direction - Direction of the slide(next/prev)
18271         * @category lGPublicMethods
18272         * @example
18273         *  const plugin = lightGallery();
18274         *  // to go to 3rd slide
18275         *  plugin.slide(2);
18276         *
18277         */
18278        LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
18279            var _this = this;
18280            var prevIndex = this.getPreviousSlideIndex();
18281            this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
18282            // Prevent multiple call, Required for hsh plugin
18283            if (this.lGalleryOn && prevIndex === index) {
18284                return;
18285            }
18286            var numberOfGalleryItems = this.galleryItems.length;
18287            if (!this.lgBusy) {
18288                if (this.settings.counter) {
18289                    this.updateCurrentCounter(index);
18290                }
18291                var currentSlideItem = this.getSlideItem(index);
18292                var previousSlideItem_1 = this.getSlideItem(prevIndex);
18293                var currentGalleryItem = this.galleryItems[index];
18294                var videoInfo = currentGalleryItem.__slideVideoInfo;
18295                this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
18296                this.setDownloadValue(index);
18297                if (videoInfo) {
18298                    var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
18299                    //Uncode edit ##START##
18300                    var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18301                    // var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
18302                    //Uncode edit ##END##
18303                    this.resizeVideoSlide(index, videoSize);
18304                }
18305                this.LGel.trigger(lGEvents.beforeSlide, {
18306                    prevIndex: prevIndex,
18307                    index: index,
18308                    fromTouch: !!fromTouch,
18309                    fromThumb: !!fromThumb,
18310                    //Uncode edit ##START##
18311                    currentSlide: currentSlideItem,
18312                    previousSlide: previousSlideItem_1,
18313                    info: currentGalleryItem,
18314                    item: this.items[index]
18315                    //Uncode edit ##END##
18316                });
18317                this.lgBusy = true;
18318                clearTimeout(this.hideBarTimeout);
18319                this.arrowDisable(index);
18320                if (!direction) {
18321                    if (index < prevIndex) {
18322                        direction = 'prev';
18323                    }
18324                    else if (index > prevIndex) {
18325                        direction = 'next';
18326                    }
18327                }
18328                if (!fromTouch) {
18329                    this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
18330                }
18331                else {
18332                    this.outer
18333                        .find('.lg-item')
18334                        .removeClass('lg-prev-slide lg-current lg-next-slide');
18335                    var touchPrev = void 0;
18336                    var touchNext = void 0;
18337                    if (numberOfGalleryItems > 2) {
18338                        touchPrev = index - 1;
18339                        touchNext = index + 1;
18340                        if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
18341                            // next slide
18342                            touchNext = 0;
18343                            touchPrev = numberOfGalleryItems - 1;
18344                        }
18345                        else if (index === numberOfGalleryItems - 1 &&
18346                            prevIndex === 0) {
18347                            // prev slide
18348                            touchNext = 0;
18349                            touchPrev = numberOfGalleryItems - 1;
18350                        }
18351                    }
18352                    else {
18353                        touchPrev = 0;
18354                        touchNext = 1;
18355                    }
18356                    if (direction === 'prev') {
18357                        this.getSlideItem(touchNext).addClass('lg-next-slide');
18358                    }
18359                    else {
18360                        this.getSlideItem(touchPrev).addClass('lg-prev-slide');
18361                    }
18362                    currentSlideItem.addClass('lg-current');
18363                }
18364                // Do not put load content in set timeout as it needs to load immediately when the gallery is opened
18365                if (!this.lGalleryOn) {
18366                    this.loadContent(index, true);
18367                }
18368                else {
18369                    setTimeout(function () {
18370                        _this.loadContent(index, true);
18371                        // Add title if this.settings.appendSubHtmlTo === lg-sub-html
18372                        if (_this.settings.appendSubHtmlTo !== '.lg-item') {
18373                            _this.addHtml(index);
18374                        }
18375                    }, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
18376                }
18377                setTimeout(function () {
18378                    _this.lgBusy = false;
18379                    previousSlideItem_1.removeClass('lg-slide-progress');
18380                    _this.LGel.trigger(lGEvents.afterSlide, {
18381                        prevIndex: prevIndex,
18382                        index: index,
18383                        fromTouch: fromTouch,
18384                        fromThumb: fromThumb,
18385                    });
18386                }, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
18387            }
18388            this.index = index;
18389        };
18390        LightGallery.prototype.updateCurrentCounter = function (index) {
18391            this.getElementById('lg-counter-current').html(index + 1 + '');
18392        };
18393        LightGallery.prototype.updateCounterTotal = function () {
18394            this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
18395        };
18396        LightGallery.prototype.getSlideType = function (item) {
18397            if (item.__slideVideoInfo) {
18398                return 'video';
18399            }
18400            else if (item.iframe) {
18401                return 'iframe';
18402            }
18403            //Uncode edit ##START##
18404            else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
18405                return 'audio';
18406            }
18407            //Uncode edit ##END##
18408            else {
18409                return 'image';
18410            }
18411        };
18412        LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
18413            var distanceX = endCoords.pageX - startCoords.pageX;
18414            var distanceY = endCoords.pageY - startCoords.pageY;
18415            var allowSwipe = false;
18416            if (this.swipeDirection) {
18417                allowSwipe = true;
18418            }
18419            else {
18420                if (Math.abs(distanceX) > 15) {
18421                    this.swipeDirection = 'horizontal';
18422                    allowSwipe = true;
18423                }
18424                else if (Math.abs(distanceY) > 15) {
18425                    this.swipeDirection = 'vertical';
18426                    allowSwipe = true;
18427                }
18428            }
18429            if (!allowSwipe) {
18430                return;
18431            }
18432            var $currentSlide = this.getSlideItem(this.index);
18433            if (this.swipeDirection === 'horizontal') {
18434                e === null || e === void 0 ? void 0 : e.preventDefault();
18435                // reset opacity and transition duration
18436                this.outer.addClass('lg-dragging');
18437                // move current slide
18438                this.setTranslate($currentSlide, distanceX, 0);
18439                // move next and prev slide with current slide
18440                var width = $currentSlide.get().offsetWidth;
18441                var slideWidthAmount = (width * 15) / 100;
18442                var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
18443                this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
18444                this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
18445            }
18446            else if (this.swipeDirection === 'vertical') {
18447                if (this.settings.swipeToClose) {
18448                    e === null || e === void 0 ? void 0 : e.preventDefault();
18449                    this.$container.addClass('lg-dragging-vertical');
18450                    var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
18451                    this.$backdrop.css('opacity', opacity);
18452                    var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
18453                    this.setTranslate($currentSlide, 0, distanceY, scale, scale);
18454                    if (Math.abs(distanceY) > 100) {
18455                        this.outer
18456                            .addClass('lg-hide-items')
18457                            .removeClass('lg-components-open');
18458                    }
18459                }
18460            }
18461        };
18462        LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
18463            var _this = this;
18464            var distance;
18465            // keep slide animation for any mode while dragg/swipe
18466            if (this.settings.mode !== 'lg-slide') {
18467                this.outer.addClass('lg-slide');
18468            }
18469            // set transition duration
18470            setTimeout(function () {
18471                _this.$container.removeClass('lg-dragging-vertical');
18472                _this.outer
18473                    .removeClass('lg-dragging lg-hide-items')
18474                    .addClass('lg-components-open');
18475                var triggerClick = true;
18476                if (_this.swipeDirection === 'horizontal') {
18477                    distance = endCoords.pageX - startCoords.pageX;
18478                    var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
18479                    if (distance < 0 &&
18480                        distanceAbs > _this.settings.swipeThreshold) {
18481                        _this.goToNextSlide(true);
18482                        triggerClick = false;
18483                    }
18484                    else if (distance > 0 &&
18485                        distanceAbs > _this.settings.swipeThreshold) {
18486                        _this.goToPrevSlide(true);
18487                        triggerClick = false;
18488                    }
18489                }
18490                else if (_this.swipeDirection === 'vertical') {
18491                    distance = Math.abs(endCoords.pageY - startCoords.pageY);
18492                    if (_this.settings.closable &&
18493                        _this.settings.swipeToClose &&
18494                        distance > 100) {
18495                        _this.closeGallery();
18496                        return;
18497                    }
18498                    else {
18499                        _this.$backdrop.css('opacity', 1);
18500                    }
18501                }
18502                _this.outer.find('.lg-item').removeAttr('style');
18503                if (triggerClick &&
18504                    Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
18505                    // Trigger click if distance is less than 5 pix
18506                    var target = $LG(event.target);
18507                    if (_this.isPosterElement(target)) {
18508                        _this.LGel.trigger(lGEvents.posterClick);
18509                    }
18510                }
18511                _this.swipeDirection = undefined;
18512            });
18513            // remove slide class once drag/swipe is completed if mode is not slide
18514            setTimeout(function () {
18515                if (!_this.outer.hasClass('lg-dragging') &&
18516                    _this.settings.mode !== 'lg-slide') {
18517                    _this.outer.removeClass('lg-slide');
18518                }
18519            }, this.settings.speed + 100);
18520        };
18521        LightGallery.prototype.enableSwipe = function () {
18522            var _this = this;
18523            var startCoords = {};
18524            var endCoords = {};
18525            var isMoved = false;
18526            var isSwiping = false;
18527            if (this.settings.enableSwipe) {
18528                this.$inner.on('touchstart.lg', function (e) {
18529                    _this.dragOrSwipeEnabled = true;
18530                    var $item = _this.getSlideItem(_this.index);
18531                    if (($LG(e.target).hasClass('lg-item') ||
18532                        $item.get().contains(e.target)) &&
18533                        !_this.outer.hasClass('lg-zoomed') &&
18534                        !_this.lgBusy &&
18535                        e.targetTouches.length === 1) {
18536                        isSwiping = true;
18537                        _this.touchAction = 'swipe';
18538                        _this.manageSwipeClass();
18539                        startCoords = {
18540                            pageX: e.targetTouches[0].pageX,
18541                            pageY: e.targetTouches[0].pageY,
18542                        };
18543                    }
18544                });
18545                this.$inner.on('touchmove.lg', function (e) {
18546                    if (isSwiping &&
18547                        _this.touchAction === 'swipe' &&
18548                        e.targetTouches.length === 1) {
18549                        endCoords = {
18550                            pageX: e.targetTouches[0].pageX,
18551                            pageY: e.targetTouches[0].pageY,
18552                        };
18553                        _this.touchMove(startCoords, endCoords, e);
18554                        isMoved = true;
18555                    }
18556                });
18557                this.$inner.on('touchend.lg', function (event) {
18558                    if (_this.touchAction === 'swipe') {
18559                        if (isMoved) {
18560                            isMoved = false;
18561                            _this.touchEnd(endCoords, startCoords, event);
18562                        }
18563                        else if (isSwiping) {
18564                            var target = $LG(event.target);
18565                            if (_this.isPosterElement(target)) {
18566                                _this.LGel.trigger(lGEvents.posterClick);
18567                            }
18568                        }
18569                        _this.touchAction = undefined;
18570                        isSwiping = false;
18571                    }
18572                });
18573            }
18574        };
18575        LightGallery.prototype.enableDrag = function () {
18576            var _this = this;
18577            var startCoords = {};
18578            var endCoords = {};
18579            var isDraging = false;
18580            var isMoved = false;
18581            if (this.settings.enableDrag) {
18582                this.outer.on('mousedown.lg', function (e) {
18583                    _this.dragOrSwipeEnabled = true;
18584                    var $item = _this.getSlideItem(_this.index);
18585                    if ($LG(e.target).hasClass('lg-item') ||
18586                        $item.get().contains(e.target)) {
18587                        if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
18588                            e.preventDefault();
18589                            if (!_this.lgBusy) {
18590                                _this.manageSwipeClass();
18591                                startCoords = {
18592                                    pageX: e.pageX,
18593                                    pageY: e.pageY,
18594                                };
18595                                isDraging = true;
18596                                // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
18597                                _this.outer.get().scrollLeft += 1;
18598                                _this.outer.get().scrollLeft -= 1;
18599                                // *
18600                                _this.outer
18601                                    .removeClass('lg-grab')
18602                                    .addClass('lg-grabbing');
18603                                _this.LGel.trigger(lGEvents.dragStart);
18604                            }
18605                        }
18606                    }
18607                });
18608                $LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
18609                    if (isDraging && _this.lgOpened) {
18610                        isMoved = true;
18611                        endCoords = {
18612                            pageX: e.pageX,
18613                            pageY: e.pageY,
18614                        };
18615                        _this.touchMove(startCoords, endCoords);
18616                        _this.LGel.trigger(lGEvents.dragMove);
18617                    }
18618                });
18619                $LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
18620                    if (!_this.lgOpened) {
18621                        return;
18622                    }
18623                    var target = $LG(event.target);
18624                    if (isMoved) {
18625                        isMoved = false;
18626                        _this.touchEnd(endCoords, startCoords, event);
18627                        _this.LGel.trigger(lGEvents.dragEnd);
18628                    }
18629                    else if (_this.isPosterElement(target)) {
18630                        _this.LGel.trigger(lGEvents.posterClick);
18631                    }
18632                    // Prevent execution on click
18633                    if (isDraging) {
18634                        isDraging = false;
18635                        _this.outer.removeClass('lg-grabbing').addClass('lg-grab');
18636                    }
18637                });
18638            }
18639        };
18640        LightGallery.prototype.triggerPosterClick = function () {
18641            var _this = this;
18642            this.$inner.on('click.lg', function (event) {
18643                if (!_this.dragOrSwipeEnabled &&
18644                    _this.isPosterElement($LG(event.target))) {
18645                    _this.LGel.trigger(lGEvents.posterClick);
18646                }
18647            });
18648        };
18649        LightGallery.prototype.manageSwipeClass = function () {
18650            var _touchNext = this.index + 1;
18651            var _touchPrev = this.index - 1;
18652            if (this.settings.loop && this.galleryItems.length > 2) {
18653                if (this.index === 0) {
18654                    _touchPrev = this.galleryItems.length - 1;
18655                }
18656                else if (this.index === this.galleryItems.length - 1) {
18657                    _touchNext = 0;
18658                }
18659            }
18660            this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
18661            if (_touchPrev > -1) {
18662                this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
18663            }
18664            this.getSlideItem(_touchNext).addClass('lg-next-slide');
18665        };
18666        /**
18667         * Go to next slide
18668         * @param {Boolean} fromTouch - true if slide function called via touch event
18669         * @category lGPublicMethods
18670         * @example
18671         *  const plugin = lightGallery();
18672         *  plugin.goToNextSlide();
18673         * @see <a href="/demos/methods/">Demo</a>
18674         */
18675        LightGallery.prototype.goToNextSlide = function (fromTouch) {
18676            var _this = this;
18677            var _loop = this.settings.loop;
18678            if (fromTouch && this.galleryItems.length < 3) {
18679                _loop = false;
18680            }
18681            if (!this.lgBusy) {
18682                if (this.index + 1 < this.galleryItems.length) {
18683                    this.index++;
18684                    this.LGel.trigger(lGEvents.beforeNextSlide, {
18685                        index: this.index,
18686                    });
18687                    this.slide(this.index, !!fromTouch, false, 'next');
18688                }
18689                else {
18690                    if (_loop) {
18691                        this.index = 0;
18692                        this.LGel.trigger(lGEvents.beforeNextSlide, {
18693                            index: this.index,
18694                        });
18695                        this.slide(this.index, !!fromTouch, false, 'next');
18696                    }
18697                    else if (this.settings.slideEndAnimation && !fromTouch) {
18698                        this.outer.addClass('lg-right-end');
18699                        setTimeout(function () {
18700                            _this.outer.removeClass('lg-right-end');
18701                        }, 400);
18702                    }
18703                }
18704            }
18705        };
18706        /**
18707         * Go to previous slides
18708         * @param {Boolean} fromTouch - true if slide function called via touch event
18709         * @category lGPublicMethods
18710         * @example
18711         *  const plugin = lightGallery({});
18712         *  plugin.goToPrevSlide();
18713         * @see <a href="/demos/methods/">Demo</a>
18714         *
18715         */
18716        LightGallery.prototype.goToPrevSlide = function (fromTouch) {
18717            var _this = this;
18718            var _loop = this.settings.loop;
18719            if (fromTouch && this.galleryItems.length < 3) {
18720                _loop = false;
18721            }
18722            if (!this.lgBusy) {
18723                if (this.index > 0) {
18724                    this.index--;
18725                    this.LGel.trigger(lGEvents.beforePrevSlide, {
18726                        index: this.index,
18727                        fromTouch: fromTouch,
18728                    });
18729                    this.slide(this.index, !!fromTouch, false, 'prev');
18730                }
18731                else {
18732                    if (_loop) {
18733                        this.index = this.galleryItems.length - 1;
18734                        this.LGel.trigger(lGEvents.beforePrevSlide, {
18735                            index: this.index,
18736                            fromTouch: fromTouch,
18737                        });
18738                        this.slide(this.index, !!fromTouch, false, 'prev');
18739                    }
18740                    else if (this.settings.slideEndAnimation && !fromTouch) {
18741                        this.outer.addClass('lg-left-end');
18742                        setTimeout(function () {
18743                            _this.outer.removeClass('lg-left-end');
18744                        }, 400);
18745                    }
18746                }
18747            }
18748        };
18749        LightGallery.prototype.keyPress = function () {
18750            var _this = this;
18751            $LG(window).on("keydown.lg.global" + this.lgId, function (e) {
18752                if (_this.lgOpened &&
18753                    _this.settings.escKey === true &&
18754                    e.keyCode === 27) {
18755                    e.preventDefault();
18756                    if (_this.settings.allowMediaOverlap &&
18757                        _this.outer.hasClass('lg-can-toggle') &&
18758                        _this.outer.hasClass('lg-components-open')) {
18759                        _this.outer.removeClass('lg-components-open');
18760                    }
18761                    else {
18762                        _this.closeGallery();
18763                    }
18764                }
18765                if (_this.lgOpened && _this.galleryItems.length > 1) {
18766                    if (e.keyCode === 37) {
18767                        e.preventDefault();
18768                        _this.goToPrevSlide();
18769                    }
18770                    if (e.keyCode === 39) {
18771                        e.preventDefault();
18772                        _this.goToNextSlide();
18773                    }
18774                }
18775            });
18776        };
18777        LightGallery.prototype.arrow = function () {
18778            var _this = this;
18779            this.getElementById('lg-prev').on('click.lg', function () {
18780                _this.goToPrevSlide();
18781            });
18782            this.getElementById('lg-next').on('click.lg', function () {
18783                _this.goToNextSlide();
18784            });
18785        };
18786        LightGallery.prototype.arrowDisable = function (index) {
18787            // Disable arrows if settings.hideControlOnEnd is true
18788            if (!this.settings.loop && this.settings.hideControlOnEnd) {
18789                var $prev = this.getElementById('lg-prev');
18790                var $next = this.getElementById('lg-next');
18791                if (index + 1 === this.galleryItems.length) {
18792                    $next.attr('disabled', 'disabled').addClass('disabled');
18793                }
18794                else {
18795                    $next.removeAttr('disabled').removeClass('disabled');
18796                }
18797                if (index === 0) {
18798                    $prev.attr('disabled', 'disabled').addClass('disabled');
18799                }
18800                else {
18801                    $prev.removeAttr('disabled').removeClass('disabled');
18802                }
18803            }
18804        };
18805        LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
18806            if (scaleX === void 0) { scaleX = 1; }
18807            if (scaleY === void 0) { scaleY = 1; }
18808            $el.css('transform', 'translate3d(' +
18809                xValue +
18810                'px, ' +
18811                yValue +
18812                'px, 0px) scale3d(' +
18813                scaleX +
18814                ', ' +
18815                scaleY +
18816                ', 1)');
18817        };
18818        LightGallery.prototype.mousewheel = function () {
18819            var _this = this;
18820            var lastCall = 0;
18821            this.outer.on('wheel.lg', function (e) {
18822                if (!e.deltaY || _this.galleryItems.length < 2) {
18823                    return;
18824                }
18825                e.preventDefault();
18826                var now = new Date().getTime();
18827                if (now - lastCall < 1000) {
18828                    return;
18829                }
18830                lastCall = now;
18831                if (e.deltaY > 0) {
18832                    _this.goToNextSlide();
18833                }
18834                else if (e.deltaY < 0) {
18835                    _this.goToPrevSlide();
18836                }
18837            });
18838        };
18839        LightGallery.prototype.isSlideElement = function (target) {
18840            return (target.hasClass('lg-outer') ||
18841                target.hasClass('lg-item') ||
18842                target.hasClass('lg-img-wrap'));
18843        };
18844        LightGallery.prototype.isPosterElement = function (target) {
18845            var playButton = this.getSlideItem(this.index)
18846                .find('.lg-video-play-button')
18847                .get();
18848            return (target.hasClass('lg-video-poster') ||
18849                target.hasClass('lg-video-play-button') ||
18850                (playButton && playButton.contains(target.get())));
18851        };
18852        /**
18853         * Maximize minimize inline gallery.
18854         * @category lGPublicMethods
18855         */
18856        LightGallery.prototype.toggleMaximize = function () {
18857            var _this = this;
18858            this.getElementById('lg-maximize').on('click.lg', function () {
18859                _this.$container.toggleClass('lg-inline');
18860                _this.refreshOnResize();
18861            });
18862        };
18863        LightGallery.prototype.invalidateItems = function () {
18864            for (var index = 0; index < this.items.length; index++) {
18865                var element = this.items[index];
18866                var $element = $LG(element);
18867                $element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
18868            }
18869        };
18870        LightGallery.prototype.manageCloseGallery = function () {
18871            var _this = this;
18872            if (!this.settings.closable)
18873                return;
18874            var mousedown = false;
18875            this.getElementById('lg-close').on('click.lg', function () {
18876                _this.closeGallery();
18877            });
18878            if (this.settings.closeOnTap) {
18879                // If you drag the slide and release outside gallery gets close on chrome
18880                // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
18881                this.outer.on('mousedown.lg', function (e) {
18882                    var target = $LG(e.target);
18883                    if (_this.isSlideElement(target)) {
18884                        mousedown = true;
18885                    }
18886                    else {
18887                        mousedown = false;
18888                    }
18889                });
18890                this.outer.on('mousemove.lg', function () {
18891                    mousedown = false;
18892                });
18893                this.outer.on('mouseup.lg', function (e) {
18894                    var target = $LG(e.target);
18895                    if (_this.isSlideElement(target) && mousedown) {
18896                        if (!_this.outer.hasClass('lg-dragging')) {
18897                            _this.closeGallery();
18898                        }
18899                    }
18900                });
18901            }
18902        };
18903        /**
18904         * Close lightGallery if it is opened.
18905         *
18906         * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
18907         * @return returns the estimated time to close gallery completely including the close animation duration
18908         * @category lGPublicMethods
18909         * @example
18910         *  const plugin = lightGallery();
18911         *  plugin.closeGallery();
18912         *
18913         */
18914        LightGallery.prototype.closeGallery = function (force) {
18915            var _this = this;
18916            if (!this.lgOpened || (!this.settings.closable && !force)) {
18917                return 0;
18918            }
18919            this.LGel.trigger(lGEvents.beforeClose);
18920            $LG(window).scrollTop(this.prevScrollTop);
18921            var currentItem = this.items[this.index];
18922            var transform;
18923            if (this.zoomFromOrigin && currentItem) {
18924                var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
18925                var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
18926                //Uncode edit ##START##
18927                var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
18928                // var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
18929                //Uncode edit ##END##
18930                transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
18931            }
18932            if (this.zoomFromOrigin && transform) {
18933                this.outer.addClass('lg-closing lg-zoom-from-image');
18934                this.getSlideItem(this.index)
18935                    .addClass('lg-start-end-progress')
18936                    .css('transition-duration', this.settings.startAnimationDuration + 'ms')
18937                    .css('transform', transform);
18938            }
18939            else {
18940                this.outer.addClass('lg-hide-items');
18941                // lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
18942                // If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
18943                this.outer.removeClass('lg-zoom-from-image');
18944            }
18945            // Unbind all events added by lightGallery
18946            // @todo
18947            //this.$el.off('.lg.tm');
18948            this.destroyModules();
18949            this.lGalleryOn = false;
18950            this.isDummyImageRemoved = false;
18951            this.zoomFromOrigin = this.settings.zoomFromOrigin;
18952            clearTimeout(this.hideBarTimeout);
18953            this.hideBarTimeout = false;
18954            $LG('html').removeClass('lg-on');
18955            this.outer.removeClass('lg-visible lg-components-open');
18956            // Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
18957            this.$backdrop.removeClass('in').css('opacity', 0);
18958            var removeTimeout = this.zoomFromOrigin && transform
18959                ? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
18960                : this.settings.backdropDuration;
18961            this.$container.removeClass('lg-show-in');
18962            // Once the closign animation is completed and gallery is invisible
18963            setTimeout(function () {
18964                if (_this.zoomFromOrigin && transform) {
18965                    _this.outer.removeClass('lg-zoom-from-image');
18966                }
18967                _this.$container.removeClass('lg-show');
18968                // Need to remove inline opacity as it is used in the stylesheet as well
18969                _this.$backdrop
18970                    .removeAttr('style')
18971                    .css('transition-duration', _this.settings.backdropDuration + 'ms');
18972                _this.outer.removeClass("lg-closing " + _this.settings.startClass);
18973                _this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
18974                _this.$inner.empty();
18975                if (_this.lgOpened) {
18976                    _this.LGel.trigger(lGEvents.afterClose, {
18977                        instance: _this,
18978                    });
18979                }
18980                if (_this.outer.get()) {
18981                    _this.outer.get().blur();
18982                }
18983                _this.lgOpened = false;
18984            }, removeTimeout + 100);
18985            return removeTimeout + 100;
18986        };
18987        LightGallery.prototype.initModules = function () {
18988            this.plugins.forEach(function (module) {
18989                try {
18990                    module.init();
18991                }
18992                catch (err) {
18993                    console.warn("lightGallery:- make sure lightGallery module is properly initiated");
18994                }
18995            });
18996        };
18997        LightGallery.prototype.destroyModules = function (destroy) {
18998            this.plugins.forEach(function (module) {
18999                try {
19000                    if (destroy) {
19001                        module.destroy();
19002                    }
19003                    else {
19004                        module.closeGallery && module.closeGallery();
19005                    }
19006                }
19007                catch (err) {
19008                    console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19009                }
19010            });
19011        };
19012        /**
19013         * Refresh lightGallery with new set of children.
19014         *
19015         * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19016         *
19017         * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19018         * @see <a href="/demos/dynamic-mode/">Demo</a>
19019         * @category lGPublicMethods
19020         * @example
19021         *  const plugin = lightGallery();
19022         *  // Delete or add children, then call
19023         *  plugin.refresh();
19024         *
19025         */
19026        LightGallery.prototype.refresh = function (galleryItems) {
19027            if (!this.settings.dynamic) {
19028                this.invalidateItems();
19029            }
19030            if (galleryItems) {
19031                this.galleryItems = galleryItems;
19032            }
19033            else {
19034                this.galleryItems = this.getItems();
19035            }
19036            this.updateControls();
19037            this.openGalleryOnItemClick();
19038            this.LGel.trigger(lGEvents.updateSlides);
19039        };
19040        LightGallery.prototype.updateControls = function () {
19041            this.addSlideVideoInfo(this.galleryItems);
19042            this.updateCounterTotal();
19043            this.manageSingleSlideClassName();
19044        };
19045        /**
19046         * Destroy lightGallery.
19047         * Destroy lightGallery and its plugin instances completely
19048         *
19049         * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19050         * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19051         * You can use refresh method most of the times.
19052         * @category lGPublicMethods
19053         * @example
19054         *  const plugin = lightGallery();
19055         *  plugin.destroy();
19056         *
19057         */
19058        LightGallery.prototype.destroy = function () {
19059            var _this = this;
19060            var closeTimeout = this.closeGallery(true);
19061            setTimeout(function () {
19062                _this.destroyModules(true);
19063                if (!_this.settings.dynamic) {
19064                    _this.invalidateItems();
19065                }
19066                $LG(window).off(".lg.global" + _this.lgId);
19067                _this.LGel.off('.lg');
19068                _this.$container.remove();
19069            }, closeTimeout);
19070            return closeTimeout;
19071        };
19072        return LightGallery;
19073    }());
19074
19075    function lightGallery(el, options) {
19076        return new LightGallery(el, options);
19077    }
19078
19079    return lightGallery;
19080
19081})));
19082//# sourceMappingURL=lightgallery.umd.js.map
19083
19084/*!
19085 * lightgallery | 2.4.0 | January 29th 2022
19086 * http://www.lightgalleryjs.com/
19087 * Copyright (c) 2020 Sachin Neravath;
19088 * @license GPLv3
19089 */
19090
19091(function (global, factory) {
19092    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19093    typeof define === 'function' && define.amd ? define(factory) :
19094    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19095}(this, (function () { 'use strict';
19096
19097    /*! *****************************************************************************
19098    Copyright (c) Microsoft Corporation.
19099
19100    Permission to use, copy, modify, and/or distribute this software for any
19101    purpose with or without fee is hereby granted.
19102
19103    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19104    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19105    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19106    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19107    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19108    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19109    PERFORMANCE OF THIS SOFTWARE.
19110    ***************************************************************************** */
19111
19112    var __assign = function() {
19113        __assign = Object.assign || function __assign(t) {
19114            for (var s, i = 1, n = arguments.length; i < n; i++) {
19115                s = arguments[i];
19116                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19117            }
19118            return t;
19119        };
19120        return __assign.apply(this, arguments);
19121    };
19122
19123    var zoomSettings = {
19124        scale: 1,
19125        zoom: true,
19126        actualSize: true,
19127        showZoomInOutIcons: false,
19128        actualSizeIcons: {
19129            zoomIn: 'lg-zoom-in',
19130            zoomOut: 'lg-zoom-out',
19131        },
19132        enableZoomAfter: 300,
19133        zoomPluginStrings: {
19134            zoomIn: 'Zoom in',
19135            zoomOut: 'Zoom out',
19136            viewActualSize: 'View actual size',
19137        },
19138    };
19139
19140    /**
19141     * List of lightGallery events
19142     * All events should be documented here
19143     * Below interfaces are used to build the website documentations
19144     * */
19145    var lGEvents = {
19146        afterAppendSlide: 'lgAfterAppendSlide',
19147        init: 'lgInit',
19148        hasVideo: 'lgHasVideo',
19149        containerResize: 'lgContainerResize',
19150        updateSlides: 'lgUpdateSlides',
19151        afterAppendSubHtml: 'lgAfterAppendSubHtml',
19152        beforeOpen: 'lgBeforeOpen',
19153        afterOpen: 'lgAfterOpen',
19154        slideItemLoad: 'lgSlideItemLoad',
19155        beforeSlide: 'lgBeforeSlide',
19156        afterSlide: 'lgAfterSlide',
19157        posterClick: 'lgPosterClick',
19158        dragStart: 'lgDragStart',
19159        dragMove: 'lgDragMove',
19160        dragEnd: 'lgDragEnd',
19161        beforeNextSlide: 'lgBeforeNextSlide',
19162        beforePrevSlide: 'lgBeforePrevSlide',
19163        beforeClose: 'lgBeforeClose',
19164        afterClose: 'lgAfterClose',
19165        rotateLeft: 'lgRotateLeft',
19166        rotateRight: 'lgRotateRight',
19167        flipHorizontal: 'lgFlipHorizontal',
19168        flipVertical: 'lgFlipVertical',
19169        autoplay: 'lgAutoplay',
19170        autoplayStart: 'lgAutoplayStart',
19171        autoplayStop: 'lgAutoplayStop',
19172    };
19173
19174    var Zoom = /** @class */ (function () {
19175        function Zoom(instance, $LG) {
19176            // get lightGallery core plugin instance
19177            this.core = instance;
19178            this.$LG = $LG;
19179            this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19180            return this;
19181        }
19182        // Append Zoom controls. Actual size, Zoom-in, Zoom-out
19183        Zoom.prototype.buildTemplates = function () {
19184            var zoomIcons = this.settings.showZoomInOutIcons
19185                ? "<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>"
19186                : '';
19187            if (this.settings.actualSize) {
19188                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>";
19189            }
19190            this.core.outer.addClass('lg-use-transition-for-zoom');
19191            this.core.$toolbar.first().append(zoomIcons);
19192        };
19193        /**
19194         * @desc Enable zoom option only once the image is completely loaded
19195         * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
19196         *
19197         * Zoom styles are defined under lg-zoomable CSS class.
19198         */
19199        Zoom.prototype.enableZoom = function (event) {
19200            var _this = this;
19201            // delay will be 0 except first time
19202            var _speed = this.settings.enableZoomAfter + event.detail.delay;
19203            // set _speed value 0 if gallery opened from direct url and if it is first slide
19204            if (this.$LG('body').first().hasClass('lg-from-hash') &&
19205                event.detail.delay) {
19206                // will execute only once
19207                _speed = 0;
19208            }
19209            else {
19210                // Remove lg-from-hash to enable starting animation.
19211                this.$LG('body').first().removeClass('lg-from-hash');
19212            }
19213            this.zoomableTimeout = setTimeout(function () {
19214                if (!_this.isImageSlide()) {
19215                    return;
19216                }
19217                _this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
19218                if (event.detail.index === _this.core.index) {
19219                    _this.setZoomEssentials();
19220                }
19221            }, _speed + 30);
19222        };
19223        Zoom.prototype.enableZoomOnSlideItemLoad = function () {
19224            // Add zoomable class
19225            this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
19226        };
19227        Zoom.prototype.getModifier = function (rotateValue, axis, el) {
19228            var originalRotate = rotateValue;
19229            rotateValue = Math.abs(rotateValue);
19230            var transformValues = this.getCurrentTransform(el);
19231            if (!transformValues) {
19232                return 1;
19233            }
19234            var modifier = 1;
19235            if (axis === 'X') {
19236                var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
19237                if (rotateValue === 0 || rotateValue === 180) {
19238                    modifier = 1;
19239                }
19240                else if (rotateValue === 90) {
19241                    if ((originalRotate === -90 && flipHorizontalValue === 1) ||
19242                        (originalRotate === 90 && flipHorizontalValue === -1)) {
19243                        modifier = -1;
19244                    }
19245                    else {
19246                        modifier = 1;
19247                    }
19248                }
19249                modifier = modifier * flipHorizontalValue;
19250            }
19251            else {
19252                var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
19253                if (rotateValue === 0 || rotateValue === 180) {
19254                    modifier = 1;
19255                }
19256                else if (rotateValue === 90) {
19257                    var sinX = parseFloat(transformValues[1]);
19258                    var sinMinusX = parseFloat(transformValues[2]);
19259                    modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
19260                }
19261                modifier = modifier * flipVerticalValue;
19262            }
19263            return modifier;
19264        };
19265        Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
19266            var imageSizes = {
19267                y: 'offsetHeight',
19268                x: 'offsetWidth',
19269            };
19270            if (Math.abs(rotateValue) === 90) {
19271                // Swap axis
19272                if (axis === 'x') {
19273                    axis = 'y';
19274                }
19275                else {
19276                    axis = 'x';
19277                }
19278            }
19279            return $image[imageSizes[axis]];
19280        };
19281        Zoom.prototype.getDragCords = function (e, rotateValue) {
19282            if (rotateValue === 90) {
19283                return {
19284                    x: e.pageY,
19285                    y: e.pageX,
19286                };
19287            }
19288            else {
19289                return {
19290                    x: e.pageX,
19291                    y: e.pageY,
19292                };
19293            }
19294        };
19295        Zoom.prototype.getSwipeCords = function (e, rotateValue) {
19296            var x = e.targetTouches[0].pageX;
19297            var y = e.targetTouches[0].pageY;
19298            if (rotateValue === 90) {
19299                return {
19300                    x: y,
19301                    y: x,
19302                };
19303            }
19304            else {
19305                return {
19306                    x: x,
19307                    y: y,
19308                };
19309            }
19310        };
19311        Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
19312            scale = scale || this.scale || 1;
19313            var allowY = this.imageYSize * scale > this.containerRect.height;
19314            var allowX = this.imageXSize * scale > this.containerRect.width;
19315            if (rotateValue === 90) {
19316                return {
19317                    allowX: allowY,
19318                    allowY: allowX,
19319                };
19320            }
19321            else {
19322                return {
19323                    allowX: allowX,
19324                    allowY: allowY,
19325                };
19326            }
19327        };
19328        /**
19329         *
19330         * @param {Element} el
19331         * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
19332         * Get the current transform value
19333         */
19334        Zoom.prototype.getCurrentTransform = function (el) {
19335            if (!el) {
19336                return;
19337            }
19338            var st = window.getComputedStyle(el, null);
19339            var tm = st.getPropertyValue('-webkit-transform') ||
19340                st.getPropertyValue('-moz-transform') ||
19341                st.getPropertyValue('-ms-transform') ||
19342                st.getPropertyValue('-o-transform') ||
19343                st.getPropertyValue('transform') ||
19344                'none';
19345            if (tm !== 'none') {
19346                return tm.split('(')[1].split(')')[0].split(',');
19347            }
19348            return;
19349        };
19350        Zoom.prototype.getCurrentRotation = function (el) {
19351            if (!el) {
19352                return 0;
19353            }
19354            var values = this.getCurrentTransform(el);
19355            if (values) {
19356                return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
19357                    (180 / Math.PI));
19358                // If you want rotate in 360
19359                //return (angle < 0 ? angle + 360 : angle);
19360            }
19361            return 0;
19362        };
19363        Zoom.prototype.setZoomEssentials = function () {
19364            var $image = this.core
19365                .getSlideItem(this.core.index)
19366                .find('.lg-image')
19367                .first();
19368            var rotateEl = this.core
19369                .getSlideItem(this.core.index)
19370                .find('.lg-img-rotate')
19371                .first()
19372                .get();
19373            this.rotateValue = this.getCurrentRotation(rotateEl);
19374            this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
19375            this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
19376            this.containerRect = this.core.outer.get().getBoundingClientRect();
19377            this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
19378            this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
19379        };
19380        /**
19381         * @desc Image zoom
19382         * Translate the wrap and scale the image to get better user experience
19383         *
19384         * @param {String} scale - Zoom decrement/increment value
19385         */
19386        Zoom.prototype.zoomImage = function (scale) {
19387            // Find offset manually to avoid issue after zoom
19388            var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
19389                this.containerRect.left;
19390            var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
19391            var topBottomSpacing = Math.abs(top - bottom) / 2;
19392            var offsetY = (this.containerRect.height -
19393                this.imageYSize -
19394                topBottomSpacing * this.modifierX) /
19395                2 +
19396                this.scrollTop +
19397                this.containerRect.top;
19398            var originalX;
19399            var originalY;
19400            if (scale === 1) {
19401                this.positionChanged = false;
19402            }
19403            var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
19404            var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
19405            if (this.positionChanged) {
19406                originalX = this.left / (this.scale - 1);
19407                originalY = this.top / (this.scale - 1);
19408                this.pageX = Math.abs(originalX) + offsetX;
19409                this.pageY = Math.abs(originalY) + offsetY;
19410                this.positionChanged = false;
19411            }
19412            var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
19413            var _x = offsetX - this.pageX;
19414            var _y = offsetY - this.pageY;
19415            var x = (scale - 1) * _x;
19416            var y = (scale - 1) * _y;
19417            if (allowX) {
19418                if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
19419                    x = possibleSwipeCords.minX;
19420                }
19421                else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
19422                    x = possibleSwipeCords.maxX;
19423                }
19424            }
19425            else {
19426                if (scale > 1) {
19427                    if (x < possibleSwipeCords.minX) {
19428                        x = possibleSwipeCords.minX;
19429                    }
19430                    else if (x > possibleSwipeCords.maxX) {
19431                        x = possibleSwipeCords.maxX;
19432                    }
19433                }
19434            }
19435            if (allowY) {
19436                if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
19437                    y = possibleSwipeCords.minY;
19438                }
19439                else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
19440                    y = possibleSwipeCords.maxY;
19441                }
19442            }
19443            else {
19444                // If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
19445                if (scale > 1) {
19446                    //If image goes beyond viewport top, use the minim possible translate value
19447                    if (y < possibleSwipeCords.minY) {
19448                        y = possibleSwipeCords.minY;
19449                    }
19450                    else if (y > possibleSwipeCords.maxY) {
19451                        y = possibleSwipeCords.maxY;
19452                    }
19453                }
19454            }
19455            this.setZoomStyles({
19456                x: x,
19457                y: y,
19458                scale: scale,
19459            });
19460        };
19461        /**
19462         * @desc apply scale3d to image and translate to image wrap
19463         * @param {style} X,Y and scale
19464         */
19465        Zoom.prototype.setZoomStyles = function (style) {
19466            var $image = this.core
19467                .getSlideItem(this.core.index)
19468                .find('.lg-image')
19469                .first();
19470            var $dummyImage = this.core.outer
19471                .find('.lg-current .lg-dummy-img')
19472                .first();
19473            var $imageWrap = $image.parent();
19474            this.scale = style.scale;
19475            $image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
19476            $dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
19477            var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
19478            $imageWrap.css('transform', transform);
19479            this.left = style.x;
19480            this.top = style.y;
19481        };
19482        /**
19483         * @param index - Index of the current slide
19484         * @param event - event will be available only if the function is called on clicking/taping the imags
19485         */
19486        Zoom.prototype.setActualSize = function (index, event) {
19487            var _this = this;
19488            // Allow zoom only on image
19489            if (!this.isImageSlide() ||
19490                this.core.outer.hasClass('lg-first-slide-loading')) {
19491                return;
19492            }
19493            var scale = this.getCurrentImageActualSizeScale();
19494            if (this.core.outer.hasClass('lg-zoomed')) {
19495                this.scale = 1;
19496            }
19497            else {
19498                this.scale = this.getScale(scale);
19499            }
19500            this.setPageCords(event);
19501            this.beginZoom(this.scale);
19502            this.zoomImage(this.scale);
19503            setTimeout(function () {
19504                _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
19505            }, 10);
19506        };
19507        Zoom.prototype.getNaturalWidth = function (index) {
19508            var $image = this.core.getSlideItem(index).find('.lg-image').first();
19509            var naturalWidth = this.core.galleryItems[index].width;
19510            return naturalWidth
19511                ? parseFloat(naturalWidth)
19512                : $image.get().naturalWidth;
19513        };
19514        Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
19515            var _scale;
19516            var scale;
19517            if (naturalWidth > width) {
19518                _scale = naturalWidth / width;
19519                scale = _scale || 2;
19520            }
19521            else {
19522                scale = 1;
19523            }
19524            return scale;
19525        };
19526        Zoom.prototype.getCurrentImageActualSizeScale = function () {
19527            var $image = this.core
19528                .getSlideItem(this.core.index)
19529                .find('.lg-image')
19530                .first();
19531            var width = $image.get().offsetWidth;
19532            var naturalWidth = this.getNaturalWidth(this.core.index) || width;
19533            return this.getActualSizeScale(naturalWidth, width);
19534        };
19535        Zoom.prototype.getPageCords = function (event) {
19536            var cords = {};
19537            if (event) {
19538                cords.x = event.pageX || event.targetTouches[0].pageX;
19539                cords.y = event.pageY || event.targetTouches[0].pageY;
19540            }
19541            else {
19542                var containerRect = this.core.outer.get().getBoundingClientRect();
19543                cords.x = containerRect.width / 2 + containerRect.left;
19544                cords.y =
19545                    containerRect.height / 2 + this.scrollTop + containerRect.top;
19546            }
19547            return cords;
19548        };
19549        Zoom.prototype.setPageCords = function (event) {
19550            var pageCords = this.getPageCords(event);
19551            this.pageX = pageCords.x;
19552            this.pageY = pageCords.y;
19553        };
19554        // If true, zoomed - in else zoomed out
19555        Zoom.prototype.beginZoom = function (scale) {
19556            this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
19557            if (scale > 1) {
19558                this.core.outer.addClass('lg-zoomed');
19559                var $actualSize = this.core.getElementById('lg-actual-size');
19560                $actualSize
19561                    .removeClass(this.settings.actualSizeIcons.zoomIn)
19562                    .addClass(this.settings.actualSizeIcons.zoomOut);
19563            }
19564            else {
19565                this.resetZoom();
19566            }
19567            return scale > 1;
19568        };
19569        Zoom.prototype.getScale = function (scale) {
19570            var actualSizeScale = this.getCurrentImageActualSizeScale();
19571            if (scale < 1) {
19572                scale = 1;
19573            }
19574            else if (scale > actualSizeScale) {
19575                scale = actualSizeScale;
19576            }
19577            return scale;
19578        };
19579        Zoom.prototype.init = function () {
19580            var _this = this;
19581            if (!this.settings.zoom) {
19582                return;
19583            }
19584            this.buildTemplates();
19585            this.enableZoomOnSlideItemLoad();
19586            var tapped = null;
19587            this.core.outer.on('dblclick.lg', function (event) {
19588                if (!_this.$LG(event.target).hasClass('lg-image')) {
19589                    return;
19590                }
19591                _this.setActualSize(_this.core.index, event);
19592            });
19593            this.core.outer.on('touchstart.lg', function (event) {
19594                var $target = _this.$LG(event.target);
19595                if (event.targetTouches.length === 1 &&
19596                    $target.hasClass('lg-image')) {
19597                    if (!tapped) {
19598                        tapped = setTimeout(function () {
19599                            tapped = null;
19600                        }, 300);
19601                    }
19602                    else {
19603                        clearTimeout(tapped);
19604                        tapped = null;
19605                        event.preventDefault();
19606                        _this.setActualSize(_this.core.index, event);
19607                    }
19608                }
19609            });
19610            // Update zoom on resize and orientationchange
19611            this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
19612                if (!_this.core.lgOpened || !_this.isImageSlide())
19613                    return;
19614                _this.setPageCords();
19615                _this.setZoomEssentials();
19616                _this.zoomImage(_this.scale);
19617            });
19618            // Update zoom on resize and orientationchange
19619            this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
19620                if (!_this.core.lgOpened)
19621                    return;
19622                _this.scrollTop = _this.$LG(window).scrollTop();
19623            });
19624            this.core.getElementById('lg-zoom-out').on('click.lg', function () {
19625                if (_this.core.outer.find('.lg-current .lg-image').get()) {
19626                    _this.scale -= _this.settings.scale;
19627                    _this.scale = _this.getScale(_this.scale);
19628                    _this.beginZoom(_this.scale);
19629                    _this.zoomImage(_this.scale);
19630                }
19631            });
19632            this.core.getElementById('lg-zoom-in').on('click.lg', function () {
19633                _this.zoomIn();
19634            });
19635            this.core.getElementById('lg-actual-size').on('click.lg', function () {
19636                _this.setActualSize(_this.core.index);
19637            });
19638            this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
19639                _this.core.outer.find('.lg-item').removeClass('lg-zoomable');
19640            });
19641            this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
19642                _this.scrollTop = _this.$LG(window).scrollTop();
19643                // Set the initial value center
19644                _this.pageX = _this.core.outer.width() / 2;
19645                _this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
19646                _this.scale = 1;
19647            });
19648            // Reset zoom on slide change
19649            this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
19650                var prevIndex = event.detail.prevIndex;
19651                _this.scale = 1;
19652                _this.positionChanged = false;
19653                _this.resetZoom(prevIndex);
19654                if (_this.isImageSlide()) {
19655                    _this.setZoomEssentials();
19656                }
19657            });
19658            // Drag option after zoom
19659            this.zoomDrag();
19660            this.pinchZoom();
19661            this.zoomSwipe();
19662            // Store the zoomable timeout value just to clear it while closing
19663            this.zoomableTimeout = false;
19664            this.positionChanged = false;
19665        };
19666        Zoom.prototype.zoomIn = function (scale) {
19667            // Allow zoom only on image
19668            if (!this.isImageSlide()) {
19669                return;
19670            }
19671            if (scale) {
19672                this.scale = scale;
19673            }
19674            else {
19675                this.scale += this.settings.scale;
19676            }
19677            this.scale = this.getScale(this.scale);
19678            this.beginZoom(this.scale);
19679            this.zoomImage(this.scale);
19680        };
19681        // Reset zoom effect
19682        Zoom.prototype.resetZoom = function (index) {
19683            this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
19684            var $actualSize = this.core.getElementById('lg-actual-size');
19685            var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
19686            $actualSize
19687                .removeClass(this.settings.actualSizeIcons.zoomOut)
19688                .addClass(this.settings.actualSizeIcons.zoomIn);
19689            $item.find('.lg-img-wrap').first().removeAttr('style');
19690            $item.find('.lg-image').first().removeAttr('style');
19691            this.scale = 1;
19692            this.left = 0;
19693            this.top = 0;
19694            // Reset pagx pagy values to center
19695            this.setPageCords();
19696        };
19697        Zoom.prototype.getTouchDistance = function (e) {
19698            return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
19699                (e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
19700                (e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
19701                    (e.targetTouches[0].pageY - e.targetTouches[1].pageY));
19702        };
19703        Zoom.prototype.pinchZoom = function () {
19704            var _this = this;
19705            var startDist = 0;
19706            var pinchStarted = false;
19707            var initScale = 1;
19708            var $item = this.core.getSlideItem(this.core.index);
19709            this.core.$inner.on('touchstart.lg', function (e) {
19710                $item = _this.core.getSlideItem(_this.core.index);
19711                if (!_this.isImageSlide()) {
19712                    return;
19713                }
19714                if (e.targetTouches.length === 2 &&
19715                    !_this.core.outer.hasClass('lg-first-slide-loading') &&
19716                    (_this.$LG(e.target).hasClass('lg-item') ||
19717                        $item.get().contains(e.target))) {
19718                    initScale = _this.scale || 1;
19719                    _this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
19720                    _this.core.touchAction = 'pinch';
19721                    startDist = _this.getTouchDistance(e);
19722                }
19723            });
19724            this.core.$inner.on('touchmove.lg', function (e) {
19725                if (e.targetTouches.length === 2 &&
19726                    _this.core.touchAction === 'pinch' &&
19727                    (_this.$LG(e.target).hasClass('lg-item') ||
19728                        $item.get().contains(e.target))) {
19729                    e.preventDefault();
19730                    var endDist = _this.getTouchDistance(e);
19731                    var distance = startDist - endDist;
19732                    if (!pinchStarted && Math.abs(distance) > 5) {
19733                        pinchStarted = true;
19734                    }
19735                    if (pinchStarted) {
19736                        _this.scale = Math.max(1, initScale + -distance * 0.008);
19737                        _this.zoomImage(_this.scale);
19738                    }
19739                }
19740            });
19741            this.core.$inner.on('touchend.lg', function (e) {
19742                if (_this.core.touchAction === 'pinch' &&
19743                    (_this.$LG(e.target).hasClass('lg-item') ||
19744                        $item.get().contains(e.target))) {
19745                    pinchStarted = false;
19746                    startDist = 0;
19747                    if (_this.scale <= 1) {
19748                        _this.resetZoom();
19749                    }
19750                    else {
19751                        _this.scale = _this.getScale(_this.scale);
19752                        _this.zoomImage(_this.scale);
19753                        _this.core.outer.addClass('lg-zoomed');
19754                    }
19755                    _this.core.touchAction = undefined;
19756                }
19757            });
19758        };
19759        Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
19760            var distanceXnew = endCoords.x - startCoords.x;
19761            var distanceYnew = endCoords.y - startCoords.y;
19762            var speedX = Math.abs(distanceXnew) / touchDuration + 1;
19763            var speedY = Math.abs(distanceYnew) / touchDuration + 1;
19764            if (speedX > 2) {
19765                speedX += 1;
19766            }
19767            if (speedY > 2) {
19768                speedY += 1;
19769            }
19770            distanceXnew = distanceXnew * speedX;
19771            distanceYnew = distanceYnew * speedY;
19772            var _LGel = this.core
19773                .getSlideItem(this.core.index)
19774                .find('.lg-img-wrap')
19775                .first();
19776            var distance = {};
19777            distance.x = this.left + distanceXnew * this.modifierX;
19778            distance.y = this.top + distanceYnew * this.modifierY;
19779            var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
19780            if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
19781                if (allowY) {
19782                    if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
19783                        distance.y = possibleSwipeCords.minY;
19784                    }
19785                    else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
19786                        distance.y = possibleSwipeCords.maxY;
19787                    }
19788                }
19789                if (allowX) {
19790                    if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
19791                        distance.x = possibleSwipeCords.minX;
19792                    }
19793                    else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
19794                        distance.x = possibleSwipeCords.maxX;
19795                    }
19796                }
19797                if (allowY) {
19798                    this.top = distance.y;
19799                }
19800                else {
19801                    distance.y = this.top;
19802                }
19803                if (allowX) {
19804                    this.left = distance.x;
19805                }
19806                else {
19807                    distance.x = this.left;
19808                }
19809                this.setZoomSwipeStyles(_LGel, distance);
19810                this.positionChanged = true;
19811            }
19812        };
19813        Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
19814            var distance = {};
19815            if (allowY) {
19816                distance.y =
19817                    this.top + (endCoords.y - startCoords.y) * this.modifierY;
19818                if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
19819                    var diffMinY = possibleSwipeCords.minY - distance.y;
19820                    distance.y = possibleSwipeCords.minY - diffMinY / 6;
19821                }
19822                else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
19823                    var diffMaxY = distance.y - possibleSwipeCords.maxY;
19824                    distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
19825                }
19826            }
19827            else {
19828                distance.y = this.top;
19829            }
19830            if (allowX) {
19831                distance.x =
19832                    this.left + (endCoords.x - startCoords.x) * this.modifierX;
19833                if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
19834                    var diffMinX = possibleSwipeCords.minX - distance.x;
19835                    distance.x = possibleSwipeCords.minX - diffMinX / 6;
19836                }
19837                else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
19838                    var difMaxX = distance.x - possibleSwipeCords.maxX;
19839                    distance.x = possibleSwipeCords.maxX + difMaxX / 6;
19840                }
19841            }
19842            else {
19843                distance.x = this.left;
19844            }
19845            return distance;
19846        };
19847        Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
19848            return x >= minX;
19849        };
19850        Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
19851            return x <= maxX;
19852        };
19853        Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
19854            return y >= minY;
19855        };
19856        Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
19857            return y <= maxY;
19858        };
19859        Zoom.prototype.isImageSlide = function () {
19860            var currentItem = this.core.galleryItems[this.core.index];
19861            return this.core.getSlideType(currentItem) === 'image';
19862        };
19863        Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
19864            var dataScale = scale || this.scale || 1;
19865            var elDataScale = Math.abs(dataScale);
19866            var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
19867            var topBottomSpacing = Math.abs(top - bottom) / 2;
19868            var minY = (this.imageYSize - this.containerRect.height) / 2 +
19869                topBottomSpacing * this.modifierX;
19870            var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
19871            var minX = (this.imageXSize - this.containerRect.width) / 2;
19872            var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
19873            var possibleSwipeCords = {
19874                minY: minY,
19875                maxY: maxY,
19876                minX: minX,
19877                maxX: maxX,
19878            };
19879            if (Math.abs(rotateValue) === 90) {
19880                possibleSwipeCords = {
19881                    minY: minX,
19882                    maxY: maxX,
19883                    minX: minY,
19884                    maxX: maxY,
19885                };
19886            }
19887            return possibleSwipeCords;
19888        };
19889        Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
19890            LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
19891        };
19892        Zoom.prototype.zoomSwipe = function () {
19893            var _this = this;
19894            var startCoords = {};
19895            var endCoords = {};
19896            var isMoved = false;
19897            // Allow x direction drag
19898            var allowX = false;
19899            // Allow Y direction drag
19900            var allowY = false;
19901            var startTime = new Date();
19902            var endTime = new Date();
19903            var possibleSwipeCords;
19904            var _LGel;
19905            var $item = this.core.getSlideItem(this.core.index);
19906            this.core.$inner.on('touchstart.lg', function (e) {
19907                // Allow zoom only on image
19908                if (!_this.isImageSlide()) {
19909                    return;
19910                }
19911                $item = _this.core.getSlideItem(_this.core.index);
19912                if ((_this.$LG(e.target).hasClass('lg-item') ||
19913                    $item.get().contains(e.target)) &&
19914                    e.targetTouches.length === 1 &&
19915                    _this.core.outer.hasClass('lg-zoomed')) {
19916                    e.preventDefault();
19917                    startTime = new Date();
19918                    _this.core.touchAction = 'zoomSwipe';
19919                    _LGel = _this.core
19920                        .getSlideItem(_this.core.index)
19921                        .find('.lg-img-wrap')
19922                        .first();
19923                    var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
19924                    allowY = dragAllowedAxises.allowY;
19925                    allowX = dragAllowedAxises.allowX;
19926                    if (allowX || allowY) {
19927                        startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
19928                    }
19929                    possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
19930                    // reset opacity and transition duration
19931                    _this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
19932                }
19933            });
19934            this.core.$inner.on('touchmove.lg', function (e) {
19935                if (e.targetTouches.length === 1 &&
19936                    _this.core.touchAction === 'zoomSwipe' &&
19937                    (_this.$LG(e.target).hasClass('lg-item') ||
19938                        $item.get().contains(e.target))) {
19939                    e.preventDefault();
19940                    _this.core.touchAction = 'zoomSwipe';
19941                    endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
19942                    var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
19943                    if (Math.abs(endCoords.x - startCoords.x) > 15 ||
19944                        Math.abs(endCoords.y - startCoords.y) > 15) {
19945                        isMoved = true;
19946                        _this.setZoomSwipeStyles(_LGel, distance);
19947                    }
19948                }
19949            });
19950            this.core.$inner.on('touchend.lg', function (e) {
19951                if (_this.core.touchAction === 'zoomSwipe' &&
19952                    (_this.$LG(e.target).hasClass('lg-item') ||
19953                        $item.get().contains(e.target))) {
19954                    _this.core.touchAction = undefined;
19955                    _this.core.outer.removeClass('lg-zoom-dragging');
19956                    if (!isMoved) {
19957                        return;
19958                    }
19959                    isMoved = false;
19960                    endTime = new Date();
19961                    var touchDuration = endTime.valueOf() - startTime.valueOf();
19962                    _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
19963                }
19964            });
19965        };
19966        Zoom.prototype.zoomDrag = function () {
19967            var _this = this;
19968            var startCoords = {};
19969            var endCoords = {};
19970            var isDragging = false;
19971            var isMoved = false;
19972            // Allow x direction drag
19973            var allowX = false;
19974            // Allow Y direction drag
19975            var allowY = false;
19976            var startTime;
19977            var endTime;
19978            var possibleSwipeCords;
19979            var _LGel;
19980            this.core.outer.on('mousedown.lg.zoom', function (e) {
19981                // Allow zoom only on image
19982                if (!_this.isImageSlide()) {
19983                    return;
19984                }
19985                var $item = _this.core.getSlideItem(_this.core.index);
19986                if (_this.$LG(e.target).hasClass('lg-item') ||
19987                    $item.get().contains(e.target)) {
19988                    startTime = new Date();
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 (_this.core.outer.hasClass('lg-zoomed')) {
19997                        if (_this.$LG(e.target).hasClass('lg-object') &&
19998                            (allowX || allowY)) {
19999                            e.preventDefault();
20000                            startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20001                            possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20002                            isDragging = true;
20003                            // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20004                            _this.core.outer.get().scrollLeft += 1;
20005                            _this.core.outer.get().scrollLeft -= 1;
20006                            _this.core.outer
20007                                .removeClass('lg-grab')
20008                                .addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20009                            // reset opacity and transition duration
20010                        }
20011                    }
20012                }
20013            });
20014            this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20015                if (isDragging) {
20016                    isMoved = true;
20017                    endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20018                    var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20019                    _this.setZoomSwipeStyles(_LGel, distance);
20020                }
20021            });
20022            this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20023                if (isDragging) {
20024                    endTime = new Date();
20025                    isDragging = false;
20026                    _this.core.outer.removeClass('lg-zoom-dragging');
20027                    // Fix for chrome mouse move on click
20028                    if (isMoved &&
20029                        (startCoords.x !== endCoords.x ||
20030                            startCoords.y !== endCoords.y)) {
20031                        endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20032                        var touchDuration = endTime.valueOf() - startTime.valueOf();
20033                        _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20034                    }
20035                    isMoved = false;
20036                }
20037                _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20038            });
20039        };
20040        Zoom.prototype.closeGallery = function () {
20041            this.resetZoom();
20042        };
20043        Zoom.prototype.destroy = function () {
20044            // Unbind all events added by lightGallery zoom plugin
20045            this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20046            this.core.LGel.off('.lg.zoom');
20047            this.core.LGel.off('.zoom');
20048            clearTimeout(this.zoomableTimeout);
20049            this.zoomableTimeout = false;
20050        };
20051        return Zoom;
20052    }());
20053
20054    return Zoom;
20055
20056})));
20057//# sourceMappingURL=lg-zoom.umd.js.map
20058
20059/*!
20060 * lightgallery | 2.4.0 | January 29th 2022
20061 * http://www.lightgalleryjs.com/
20062 * Copyright (c) 2020 Sachin Neravath;
20063 * @license GPLv3
20064 */
20065
20066(function (global, factory) {
20067    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20068    typeof define === 'function' && define.amd ? define(factory) :
20069    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20070}(this, (function () { 'use strict';
20071
20072    /*! *****************************************************************************
20073    Copyright (c) Microsoft Corporation.
20074
20075    Permission to use, copy, modify, and/or distribute this software for any
20076    purpose with or without fee is hereby granted.
20077
20078    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20079    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20080    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20081    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20082    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20083    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20084    PERFORMANCE OF THIS SOFTWARE.
20085    ***************************************************************************** */
20086
20087    var __assign = function() {
20088        __assign = Object.assign || function __assign(t) {
20089            for (var s, i = 1, n = arguments.length; i < n; i++) {
20090                s = arguments[i];
20091                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20092            }
20093            return t;
20094        };
20095        return __assign.apply(this, arguments);
20096    };
20097
20098    var fullscreenSettings = {
20099        fullScreen: true,
20100        fullscreenPluginStrings: {
20101            toggleFullscreen: 'Toggle Fullscreen',
20102        },
20103    };
20104
20105    var FullScreen = /** @class */ (function () {
20106        function FullScreen(instance, $LG) {
20107            // get lightGallery core plugin instance
20108            this.core = instance;
20109            this.$LG = $LG;
20110            // extend module default settings with lightGallery core settings
20111            this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20112            return this;
20113        }
20114        FullScreen.prototype.init = function () {
20115            var fullScreen = '';
20116            if (this.settings.fullScreen) {
20117                // check for fullscreen browser support
20118                if (!document.fullscreenEnabled &&
20119                    !document.webkitFullscreenEnabled &&
20120                    !document.mozFullScreenEnabled &&
20121                    !document.msFullscreenEnabled) {
20122                    return;
20123                }
20124                else {
20125                    fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20126                    this.core.$toolbar.append(fullScreen);
20127                    this.fullScreen();
20128                }
20129            }
20130        };
20131        FullScreen.prototype.isFullScreen = function () {
20132            return (document.fullscreenElement ||
20133                document.mozFullScreenElement ||
20134                document.webkitFullscreenElement ||
20135                document.msFullscreenElement);
20136        };
20137        FullScreen.prototype.requestFullscreen = function () {
20138            var el = document.documentElement;
20139            if (el.requestFullscreen) {
20140                el.requestFullscreen();
20141            }
20142            else if (el.msRequestFullscreen) {
20143                el.msRequestFullscreen();
20144            }
20145            else if (el.mozRequestFullScreen) {
20146                el.mozRequestFullScreen();
20147            }
20148            else if (el.webkitRequestFullscreen) {
20149                el.webkitRequestFullscreen();
20150            }
20151        };
20152        FullScreen.prototype.exitFullscreen = function () {
20153            if (document.exitFullscreen) {
20154                document.exitFullscreen();
20155            }
20156            else if (document.msExitFullscreen) {
20157                document.msExitFullscreen();
20158            }
20159            else if (document.mozCancelFullScreen) {
20160                document.mozCancelFullScreen();
20161            }
20162            else if (document.webkitExitFullscreen) {
20163                document.webkitExitFullscreen();
20164            }
20165        };
20166        // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20167        FullScreen.prototype.fullScreen = function () {
20168            var _this = this;
20169            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 () {
20170                if (!_this.core.lgOpened)
20171                    return;
20172                _this.core.outer.toggleClass('lg-fullscreen-on');
20173            });
20174            this.core.outer
20175                .find('.lg-fullscreen')
20176                .first()
20177                .on('click.lg', function () {
20178                if (_this.isFullScreen()) {
20179                    _this.exitFullscreen();
20180                }
20181                else {
20182                    _this.requestFullscreen();
20183                }
20184            });
20185        };
20186        FullScreen.prototype.closeGallery = function () {
20187            // exit from fullscreen if activated
20188            if (this.isFullScreen()) {
20189                this.exitFullscreen();
20190            }
20191        };
20192        FullScreen.prototype.destroy = function () {
20193            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);
20194        };
20195        return FullScreen;
20196    }());
20197
20198    return FullScreen;
20199
20200})));
20201//# sourceMappingURL=lg-fullscreen.umd.js.map
20202
20203/*!
20204 * lightgallery | 2.4.0 | January 29th 2022
20205 * http://www.lightgalleryjs.com/
20206 * Copyright (c) 2020 Sachin Neravath;
20207 * @license GPLv3
20208 */
20209
20210(function (global, factory) {
20211    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20212    typeof define === 'function' && define.amd ? define(factory) :
20213    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
20214}(this, (function () { 'use strict';
20215
20216    /*! *****************************************************************************
20217    Copyright (c) Microsoft Corporation.
20218
20219    Permission to use, copy, modify, and/or distribute this software for any
20220    purpose with or without fee is hereby granted.
20221
20222    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20223    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20224    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20225    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20226    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20227    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20228    PERFORMANCE OF THIS SOFTWARE.
20229    ***************************************************************************** */
20230
20231    var __assign = function() {
20232        __assign = Object.assign || function __assign(t) {
20233            for (var s, i = 1, n = arguments.length; i < n; i++) {
20234                s = arguments[i];
20235                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20236            }
20237            return t;
20238        };
20239        return __assign.apply(this, arguments);
20240    };
20241
20242    /**
20243     * List of lightGallery events
20244     * All events should be documented here
20245     * Below interfaces are used to build the website documentations
20246     * */
20247    var lGEvents = {
20248        afterAppendSlide: 'lgAfterAppendSlide',
20249        init: 'lgInit',
20250        hasVideo: 'lgHasVideo',
20251        containerResize: 'lgContainerResize',
20252        updateSlides: 'lgUpdateSlides',
20253        afterAppendSubHtml: 'lgAfterAppendSubHtml',
20254        beforeOpen: 'lgBeforeOpen',
20255        afterOpen: 'lgAfterOpen',
20256        slideItemLoad: 'lgSlideItemLoad',
20257        beforeSlide: 'lgBeforeSlide',
20258        afterSlide: 'lgAfterSlide',
20259        posterClick: 'lgPosterClick',
20260        dragStart: 'lgDragStart',
20261        dragMove: 'lgDragMove',
20262        dragEnd: 'lgDragEnd',
20263        beforeNextSlide: 'lgBeforeNextSlide',
20264        beforePrevSlide: 'lgBeforePrevSlide',
20265        beforeClose: 'lgBeforeClose',
20266        afterClose: 'lgAfterClose',
20267        rotateLeft: 'lgRotateLeft',
20268        rotateRight: 'lgRotateRight',
20269        flipHorizontal: 'lgFlipHorizontal',
20270        flipVertical: 'lgFlipVertical',
20271        autoplay: 'lgAutoplay',
20272        autoplayStart: 'lgAutoplayStart',
20273        autoplayStop: 'lgAutoplayStop',
20274    };
20275
20276    var hashSettings = {
20277        hash: true,
20278        galleryId: '1',
20279        customSlideName: false,
20280    };
20281
20282    var Hash = /** @class */ (function () {
20283        function Hash(instance, $LG) {
20284            // get lightGallery core plugin instance
20285            this.core = instance;
20286            this.$LG = $LG;
20287            // extend module default settings with lightGallery core settings
20288            this.settings = __assign(__assign({}, hashSettings), this.core.settings);
20289            return this;
20290        }
20291        Hash.prototype.init = function () {
20292            var _this = this;
20293            if (!this.settings.hash) {
20294                return;
20295            }
20296            this.oldHash = window.location.hash;
20297            setTimeout(function () {
20298                _this.buildFromHash();
20299            }, 100);
20300            // Change hash value on after each slide transition
20301            this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
20302            this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
20303            // Listen hash change and change the slide according to slide value
20304            this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
20305        };
20306        Hash.prototype.onAfterSlide = function (event) {
20307            var slideName = this.core.galleryItems[event.detail.index].slideName;
20308            slideName = this.settings.customSlideName
20309                ? slideName || event.detail.index
20310                : event.detail.index;
20311            if (history.replaceState) {
20312                history.replaceState(null, '', window.location.pathname +
20313                    window.location.search +
20314                    '#lg=' +
20315                    this.settings.galleryId +
20316                    '&slide=' +
20317                    slideName);
20318            }
20319            else {
20320                window.location.hash =
20321                    'lg=' + this.settings.galleryId + '&slide=' + slideName;
20322            }
20323        };
20324        /**
20325         * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
20326         * @param {String} hash
20327         * @returns {Number} Index of the slide.
20328         */
20329        Hash.prototype.getIndexFromUrl = function (hash) {
20330            if (hash === void 0) { hash = window.location.hash; }
20331            var slideName = hash.split('&slide=')[1];
20332            var _idx = 0;
20333            if (this.settings.customSlideName) {
20334                for (var index = 0; index < this.core.galleryItems.length; index++) {
20335                    var dynamicEl = this.core.galleryItems[index];
20336                    if (dynamicEl.slideName === slideName) {
20337                        _idx = index;
20338                        break;
20339                    }
20340                }
20341            }
20342            else {
20343                _idx = parseInt(slideName, 10);
20344            }
20345            return isNaN(_idx) ? 0 : _idx;
20346        };
20347        // Build Gallery if gallery id exist in the URL
20348        Hash.prototype.buildFromHash = function () {
20349            // if dynamic option is enabled execute immediately
20350            var _hash = window.location.hash;
20351	        //Uncode edit ##START##
20352            // if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
20353            if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
20354	        //Uncode edit ##END##
20355                // This class is used to remove the initial animation if galleryId present in the URL
20356                this.$LG(document.body).addClass('lg-from-hash');
20357                var index = this.getIndexFromUrl(_hash);
20358                this.core.openGallery(index);
20359                return true;
20360            }
20361        };
20362        Hash.prototype.onCloseAfter = function () {
20363            // Reset to old hash value
20364            if (this.oldHash &&
20365                this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
20366                if (history.replaceState) {
20367                    history.replaceState(null, '', this.oldHash);
20368                }
20369                else {
20370                    window.location.hash = this.oldHash;
20371                }
20372            }
20373            else {
20374                if (history.replaceState) {
20375                    history.replaceState(null, document.title, window.location.pathname + window.location.search);
20376                }
20377                else {
20378                    window.location.hash = '';
20379                }
20380            }
20381        };
20382        Hash.prototype.onHashchange = function () {
20383            if (!this.core.lgOpened)
20384                return;
20385            var _hash = window.location.hash;
20386            var index = this.getIndexFromUrl(_hash);
20387            // it galleryId doesn't exist in the url close the gallery
20388            if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
20389                this.core.slide(index, false, false);
20390            }
20391            else if (this.core.lGalleryOn) {
20392                this.core.closeGallery();
20393            }
20394        };
20395        Hash.prototype.closeGallery = function () {
20396            if (this.settings.hash) {
20397                this.$LG(document.body).removeClass('lg-from-hash');
20398            }
20399        };
20400        Hash.prototype.destroy = function () {
20401            this.core.LGel.off('.lg.hash');
20402            this.core.LGel.off('.hash');
20403            this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
20404        };
20405        return Hash;
20406    }());
20407
20408    return Hash;
20409
20410})));
20411//# sourceMappingURL=lg-hash.umd.js.map
20412
20413/*!
20414 * lightgallery | 2.4.0 | January 29th 2022
20415 * http://www.lightgalleryjs.com/
20416 * Copyright (c) 2020 Sachin Neravath;
20417 * @license GPLv3
20418 */
20419
20420(function (global, factory) {
20421    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20422    typeof define === 'function' && define.amd ? define(factory) :
20423    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
20424}(this, (function () { 'use strict';
20425
20426    /*! *****************************************************************************
20427    Copyright (c) Microsoft Corporation.
20428
20429    Permission to use, copy, modify, and/or distribute this software for any
20430    purpose with or without fee is hereby granted.
20431
20432    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20433    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20434    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20435    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20436    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20437    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20438    PERFORMANCE OF THIS SOFTWARE.
20439    ***************************************************************************** */
20440
20441    var __assign = function() {
20442        __assign = Object.assign || function __assign(t) {
20443            for (var s, i = 1, n = arguments.length; i < n; i++) {
20444                s = arguments[i];
20445                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20446            }
20447            return t;
20448        };
20449        return __assign.apply(this, arguments);
20450    };
20451
20452    function __spreadArrays() {
20453        for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
20454        for (var r = Array(s), k = 0, i = 0; i < il; i++)
20455            for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
20456                r[k] = a[j];
20457        return r;
20458    }
20459
20460    var shareSettings = {
20461        share: true,
20462        facebook: true,
20463        facebookDropdownText: 'Facebook',
20464        twitter: true,
20465        twitterDropdownText: 'Twitter',
20466        pinterest: true,
20467        pinterestDropdownText: 'Pinterest',
20468        additionalShareOptions: [],
20469        sharePluginStrings: { share: 'Share' },
20470    };
20471
20472    function getFacebookShareLink(galleryItem) {
20473        var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
20474        return (facebookBaseUrl +
20475            encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
20476    }
20477
20478    function getTwitterShareLink(galleryItem) {
20479        var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
20480        var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
20481        var text = galleryItem.tweetText;
20482        return twitterBaseUrl + text + '&url=' + url;
20483    }
20484
20485    function getPinterestShareLink(galleryItem) {
20486        var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
20487        var description = galleryItem.pinterestText;
20488        var media = encodeURIComponent(galleryItem.src);
20489        var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
20490        return (pinterestBaseUrl +
20491            url +
20492            '&media=' +
20493            media +
20494            '&description=' +
20495            description);
20496    }
20497
20498    /**
20499     * List of lightGallery events
20500     * All events should be documented here
20501     * Below interfaces are used to build the website documentations
20502     * */
20503    var lGEvents = {
20504        afterAppendSlide: 'lgAfterAppendSlide',
20505        init: 'lgInit',
20506        hasVideo: 'lgHasVideo',
20507        containerResize: 'lgContainerResize',
20508        updateSlides: 'lgUpdateSlides',
20509        afterAppendSubHtml: 'lgAfterAppendSubHtml',
20510        beforeOpen: 'lgBeforeOpen',
20511        afterOpen: 'lgAfterOpen',
20512        slideItemLoad: 'lgSlideItemLoad',
20513        beforeSlide: 'lgBeforeSlide',
20514        afterSlide: 'lgAfterSlide',
20515        posterClick: 'lgPosterClick',
20516        dragStart: 'lgDragStart',
20517        dragMove: 'lgDragMove',
20518        dragEnd: 'lgDragEnd',
20519        beforeNextSlide: 'lgBeforeNextSlide',
20520        beforePrevSlide: 'lgBeforePrevSlide',
20521        beforeClose: 'lgBeforeClose',
20522        afterClose: 'lgAfterClose',
20523        rotateLeft: 'lgRotateLeft',
20524        rotateRight: 'lgRotateRight',
20525        flipHorizontal: 'lgFlipHorizontal',
20526        flipVertical: 'lgFlipVertical',
20527        autoplay: 'lgAutoplay',
20528        autoplayStart: 'lgAutoplayStart',
20529        autoplayStop: 'lgAutoplayStop',
20530    };
20531
20532    var Share = /** @class */ (function () {
20533        function Share(instance) {
20534            this.shareOptions = [];
20535            // get lightGallery core plugin instance
20536            this.core = instance;
20537            // extend module default settings with lightGallery core settings
20538            this.settings = __assign(__assign({}, shareSettings), this.core.settings);
20539            return this;
20540        }
20541        Share.prototype.init = function () {
20542            if (!this.settings.share) {
20543                return;
20544            }
20545            this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
20546            this.setLgShareMarkup();
20547            this.core.outer
20548                .find('.lg-share .lg-dropdown')
20549                .append(this.getShareListHtml());
20550            this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
20551        };
20552        Share.prototype.getShareListHtml = function () {
20553            var shareHtml = '';
20554            this.shareOptions.forEach(function (shareOption) {
20555                shareHtml += shareOption.dropdownHTML;
20556            });
20557            return shareHtml;
20558        };
20559        Share.prototype.setLgShareMarkup = function () {
20560            var _this = this;
20561            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>");
20562            this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
20563            var $shareButton = this.core.outer.find('.lg-share');
20564            $shareButton.first().on('click.lg', function () {
20565                _this.core.outer.toggleClass('lg-dropdown-active');
20566                if (_this.core.outer.hasClass('lg-dropdown-active')) {
20567                    _this.core.outer.attr('aria-expanded', true);
20568                }
20569                else {
20570                    _this.core.outer.attr('aria-expanded', false);
20571                }
20572            });
20573            this.core.outer
20574                .find('.lg-dropdown-overlay')
20575                .first()
20576                .on('click.lg', function () {
20577                _this.core.outer.removeClass('lg-dropdown-active');
20578                _this.core.outer.attr('aria-expanded', false);
20579            });
20580        };
20581        Share.prototype.onAfterSlide = function (event) {
20582            var _this = this;
20583            var index = event.detail.index;
20584            var currentItem = this.core.galleryItems[index];
20585            setTimeout(function () {
20586                _this.shareOptions.forEach(function (shareOption) {
20587                    var selector = shareOption.selector;
20588                    _this.core.outer
20589                        .find(selector)
20590                        .attr('href', shareOption.generateLink(currentItem));
20591                });
20592            }, 100);
20593        };
20594        Share.prototype.getShareListItemHTML = function (type, text) {
20595            return "<li><a class=\"lg-share-" + type + "\" rel=\"noopener\" target=\"_blank\"><span class=\"lg-icon\"></span><span class=\"lg-dropdown-text\">
20595" + text + "</span></a></li>";
20596        };
20597        Share.prototype.getDefaultShareOptions = function () {
20598            return __spreadArrays((this.settings.facebook
20599                ? [
20600                    {
20601                        type: 'facebook',
20602                        generateLink: getFacebookShareLink,
20603                        dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
20604                        selector: '.lg-share-facebook',
20605                    },
20606                ]
20607                : []), (this.settings.twitter
20608                ? [
20609                    {
20610                        type: 'twitter',
20611                        generateLink: getTwitterShareLink,
20612                        dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
20613                        selector: '.lg-share-twitter',
20614                    },
20615                ]
20616                : []), (this.settings.pinterest
20617                ? [
20618                    {
20619                        type: 'pinterest',
20620                        generateLink: getPinterestShareLink,
20621                        dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
20622                        selector: '.lg-share-pinterest',
20623                    },
20624                ]
20625                : []));
20626        };
20627        Share.prototype.destroy = function () {
20628            this.core.outer.find('.lg-dropdown-overlay').remove();
20629            this.core.outer.find('.lg-share').remove();
20630            this.core.LGel.off('.lg.share');
20631            this.core.LGel.off('.share');
20632        };
20633        return Share;
20634    }());
20635
20636    return Share;
20637
20638})));
20639//# sourceMappingURL=lg-share.umd.js.map
20640
20641/*!
20642 * lightgallery | 2.4.0 | January 29th 2022
20643 * http://www.lightgalleryjs.com/
20644 * Copyright (c) 2020 Sachin Neravath;
20645 * @license GPLv3
20646 */
20647
20648(function (global, factory) {
20649    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20650    typeof define === 'function' && define.amd ? define(factory) :
20651    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
20652}(this, (function () { 'use strict';
20653
20654    /*! *****************************************************************************
20655    Copyright (c) Microsoft Corporation.
20656
20657    Permission to use, copy, modify, and/or distribute this software for any
20658    purpose with or without fee is hereby granted.
20659
20660    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20661    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20662    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20663    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20664    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20665    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20666    PERFORMANCE OF THIS SOFTWARE.
20667    ***************************************************************************** */
20668
20669    var __assign = function() {
20670        __assign = Object.assign || function __assign(t) {
20671            for (var s, i = 1, n = arguments.length; i < n; i++) {
20672                s = arguments[i];
20673                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20674            }
20675            return t;
20676        };
20677        return __assign.apply(this, arguments);
20678    };
20679
20680    var thumbnailsSettings = {
20681        thumbnail: true,
20682        animateThumb: true,
20683        currentPagerPosition: 'middle',
20684        alignThumbnails: 'middle',
20685        thumbWidth: 100,
20686        thumbHeight: '80px',
20687        thumbMargin: 5,
20688        appendThumbnailsTo: '.lg-components',
20689        toggleThumb: false,
20690        enableThumbDrag: true,
20691        enableThumbSwipe: true,
20692        thumbnailSwipeThreshold: 10,
20693        loadYouTubeThumbnail: true,
20694        youTubeThumbSize: 1,
20695        thumbnailPluginStrings: {
20696            toggleThumbnails: 'Toggle thumbnails',
20697        },
20698    };
20699
20700    /**
20701     * List of lightGallery events
20702     * All events should be documented here
20703     * Below interfaces are used to build the website documentations
20704     * */
20705    var lGEvents = {
20706        afterAppendSlide: 'lgAfterAppendSlide',
20707        init: 'lgInit',
20708        hasVideo: 'lgHasVideo',
20709        containerResize: 'lgContainerResize',
20710        updateSlides: 'lgUpdateSlides',
20711        afterAppendSubHtml: 'lgAfterAppendSubHtml',
20712        beforeOpen: 'lgBeforeOpen',
20713        afterOpen: 'lgAfterOpen',
20714        slideItemLoad: 'lgSlideItemLoad',
20715        beforeSlide: 'lgBeforeSlide',
20716        afterSlide: 'lgAfterSlide',
20717        posterClick: 'lgPosterClick',
20718        dragStart: 'lgDragStart',
20719        dragMove: 'lgDragMove',
20720        dragEnd: 'lgDragEnd',
20721        beforeNextSlide: 'lgBeforeNextSlide',
20722        beforePrevSlide: 'lgBeforePrevSlide',
20723        beforeClose: 'lgBeforeClose',
20724        afterClose: 'lgAfterClose',
20725        rotateLeft: 'lgRotateLeft',
20726        rotateRight: 'lgRotateRight',
20727        flipHorizontal: 'lgFlipHorizontal',
20728        flipVertical: 'lgFlipVertical',
20729        autoplay: 'lgAutoplay',
20730        autoplayStart: 'lgAutoplayStart',
20731        autoplayStop: 'lgAutoplayStop',
20732    };
20733
20734    var Thumbnail = /** @class */ (function () {
20735        function Thumbnail(instance, $LG) {
20736            this.thumbOuterWidth = 0;
20737            this.thumbTotalWidth = 0;
20738            this.translateX = 0;
20739            this.thumbClickable = false;
20740            // get lightGallery core plugin instance
20741            this.core = instance;
20742            this.$LG = $LG;
20743            return this;
20744        }
20745        Thumbnail.prototype.init = function () {
20746            // extend module default settings with lightGallery core settings
20747            this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
20748            this.thumbOuterWidth = 0;
20749            this.thumbTotalWidth =
20750                this.core.galleryItems.length *
20751                    (this.settings.thumbWidth + this.settings.thumbMargin);
20752            // Thumbnail animation value
20753            this.translateX = 0;
20754            this.setAnimateThumbStyles();
20755            if (!this.core.settings.allowMediaOverlap) {
20756                this.settings.toggleThumb = false;
20757            }
20758            if (this.settings.thumbnail) {
20759                this.build();
20760                if (this.settings.animateThumb) {
20761                    if (this.settings.enableThumbDrag) {
20762                        this.enableThumbDrag();
20763                    }
20764                    if (this.settings.enableThumbSwipe) {
20765                        this.enableThumbSwipe();
20766                    }
20767                    this.thumbClickable = false;
20768                }
20769                else {
20770                    this.thumbClickable = true;
20771                }
20772                this.toggleThumbBar();
20773                this.thumbKeyPress();
20774            }
20775        };
20776        Thumbnail.prototype.build = function () {
20777            var _this = this;
20778            this.setThumbMarkup();
20779            this.manageActiveClassOnSlideChange();
20780            this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
20781                var $target = _this.$LG(e.target);
20782                if (!$target.hasAttribute('data-lg-item-id')) {
20783                    return;
20784                }
20785                setTimeout(function () {
20786                    // In IE9 and bellow touch does not support
20787                    // Go to slide if browser does not support css transitions
20788                    if (_this.thumbClickable && !_this.core.lgBusy) {
20789                        var index = parseInt($target.attr('data-lg-item-id'));
20790                        _this.core.slide(index, false, true, false);
20791                    }
20792                }, 50);
20793            });
20794            //Uncode edit ##START##
20795            // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
20796            this.core.LGel.on(lGEvents.beforeSlide, function (event) {
20797            //Uncode edit ##END##
20798                var index = event.detail.index;
20799                _this.animateThumb(index);
20800            });
20801            //Uncode edit ##START##
20802            // this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
20803            this.core.LGel.on(lGEvents.beforeOpen, function () {
20804            //Uncode edit ##END##
20805                _this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
20806            });
20807            //Uncode edit ##START##
20808            // this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
20809            this.core.LGel.on(lGEvents.updateSlides, function () {
20810            //Uncode edit ##END##
20811                _this.rebuildThumbnails();
20812            });
20813            //Uncode edit ##START##
20814            // this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
20815            this.core.LGel.on(lGEvents.containerResize, function () {
20816            //Uncode edit ##END##
20817                if (!_this.core.lgOpened)
20818                    return;
20819                setTimeout(function () {
20820                    _this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
20821                    _this.animateThumb(_this.core.index);
20822                    _this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
20823                }, 50);
20824            });
20825        };
20826        Thumbnail.prototype.setThumbMarkup = function () {
20827            var thumbOuterClassNames = 'lg-thumb-outer ';
20828            if (this.settings.alignThumbnails) {
20829                thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
20830            }
20831            var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
20832            this.core.outer.addClass('lg-has-thumb');
20833            if (this.settings.appendThumbnailsTo === '.lg-components') {
20834                this.core.$lgComponents.append(html);
20835            }
20836            else {
20837                this.core.outer.append(html);
20838            }
20839            this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
20840            this.$lgThumb = this.core.outer.find('.lg-thumb').first();
20841            if (this.settings.animateThumb) {
20842                this.core.outer
20843                    .find('.lg-thumb')
20844                    .css('transition-duration', this.core.settings.speed + 'ms')
20845                    .css('width', this.thumbTotalWidth + 'px')
20846                    .css('position', 'relative');
20847            }
20848            this.setThumbItemHtml(this.core.galleryItems);
20849        };
20850        Thumbnail.prototype.enableThumbDrag = function () {
20851            var _this = this;
20852            var thumbDragUtils = {
20853                cords: {
20854                    startX: 0,
20855                    endX: 0,
20856                },
20857                isMoved: false,
20858                newTranslateX: 0,
20859                startTime: new Date(),
20860                endTime: new Date(),
20861                touchMoveTime: 0,
20862            };
20863            var isDragging = false;
20864            this.$thumbOuter.addClass('lg-grab');
20865            this.core.outer
20866                .find('.lg-thumb')
20867                .first()
20868                .on('mousedown.lg.thumb', function (e) {
20869                if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
20870                    // execute only on .lg-object
20871                    e.preventDefault();
20872                    thumbDragUtils.cords.startX = e.pageX;
20873                    thumbDragUtils.startTime = new Date();
20874                    _this.thumbClickable = false;
20875                    isDragging = true;
20876                    // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20877                    _this.core.outer.get().scrollLeft += 1;
20878                    _this.core.outer.get().scrollLeft -= 1;
20879                    // *
20880                    _this.$thumbOuter
20881                        .removeClass('lg-grab')
20882                        .addClass('lg-grabbing');
20883                }
20884            });
20885            this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
20886                if (!_this.core.lgOpened)
20887                    return;
20888                if (isDragging) {
20889                    thumbDragUtils.cords.endX = e.pageX;
20890                    thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
20891                }
20892            });
20893            this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
20894                if (!_this.core.lgOpened)
20895                    return;
20896                if (thumbDragUtils.isMoved) {
20897                    thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
20898                }
20899                else {
20900                    _this.thumbClickable = true;
20901                }
20902                if (isDragging) {
20903                    isDragging = false;
20904                    _this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
20905                }
20906            });
20907        };
20908        Thumbnail.prototype.enableThumbSwipe = function () {
20909            var _this = this;
20910            var thumbDragUtils = {
20911                cords: {
20912                    startX: 0,
20913                    endX: 0,
20914                },
20915                isMoved: false,
20916                newTranslateX: 0,
20917                startTime: new Date(),
20918                endTime: new Date(),
20919                touchMoveTime: 0,
20920            };
20921            this.$lgThumb.on('touchstart.lg', function (e) {
20922                if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
20923                    e.preventDefault();
20924                    thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
20925                    _this.thumbClickable = false;
20926                    thumbDragUtils.startTime = new Date();
20927                }
20928            });
20929            this.$lgThumb.on('touchmove.lg', function (e) {
20930                if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
20931                    e.preventDefault();
20932                    thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
20933                    thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
20934                }
20935            });
20936            this.$lgThumb.on('touchend.lg', function () {
20937                if (thumbDragUtils.isMoved) {
20938                    thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
20939                }
20940                else {
20941                    _this.thumbClickable = true;
20942                }
20943            });
20944        };
20945        // Rebuild thumbnails
20946        Thumbnail.prototype.rebuildThumbnails = function () {
20947            var _this = this;
20948            // Remove transitions
20949            this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
20950            setTimeout(function () {
20951                _this.thumbTotalWidth =
20952                    _this.core.galleryItems.length *
20953                        (_this.settings.thumbWidth + _this.settings.thumbMargin);
20954                _this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
20955                _this.$lgThumb.empty();
20956                _this.setThumbItemHtml(_this.core.galleryItems);
20957                _this.animateThumb(_this.core.index);
20958            }, 50);
20959            setTimeout(function () {
20960                _this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
20961            }, 200);
20962        };
20963        // @ts-check
20964        Thumbnail.prototype.setTranslate = function (value) {
20965            this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
20966        };
20967        Thumbnail.prototype.getPossibleTransformX = function (left) {
20968            if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
20969                left = this.thumbTotalWidth - this.thumbOuterWidth;
20970            }
20971            if (left < 0) {
20972                left = 0;
20973            }
20974            return left;
20975        };
20976        Thumbnail.prototype.animateThumb = function (index) {
20977            this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
20978            if (this.settings.animateThumb) {
20979                var position = 0;
20980                switch (this.settings.currentPagerPosition) {
20981                    case 'left':
20982                        position = 0;
20983                        break;
20984                    case 'middle':
20985                        position =
20986                            this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
20987                        break;
20988                    case 'right':
20989                        position = this.thumbOuterWidth - this.settings.thumbWidth;
20990                }
20991                this.translateX =
20992                    (this.settings.thumbWidth + this.settings.thumbMargin) * index -
20993                        1 -
20994                        position;
20995                if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
20996                    this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
20997                }
20998                if (this.translateX < 0) {
20999                    this.translateX = 0;
21000                }
21001                this.setTranslate(this.translateX);
21002            }
21003        };
21004        Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21005            thumbDragUtils.newTranslateX = this.translateX;
21006            thumbDragUtils.isMoved = true;
21007            thumbDragUtils.touchMoveTime = new Date().valueOf();
21008            thumbDragUtils.newTranslateX -=
21009                thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21010            thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21011            // move current slide
21012            this.setTranslate(thumbDragUtils.newTranslateX);
21013            this.$thumbOuter.addClass('lg-dragging');
21014            return thumbDragUtils;
21015        };
21016        Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21017            thumbDragUtils.isMoved = false;
21018            thumbDragUtils.endTime = new Date();
21019            this.$thumbOuter.removeClass('lg-dragging');
21020            var touchDuration = thumbDragUtils.endTime.valueOf() -
21021                thumbDragUtils.startTime.valueOf();
21022            var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21023            var speedX = Math.abs(distanceXnew) / touchDuration;
21024            // Some magical numbers
21025            // Can be improved
21026            if (speedX > 0.15 &&
21027                thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21028                speedX += 1;
21029                if (speedX > 2) {
21030                    speedX += 1;
21031                }
21032                speedX =
21033                    speedX +
21034                        speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21035                this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21036                distanceXnew = distanceXnew * speedX;
21037                this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21038                this.setTranslate(this.translateX);
21039            }
21040            else {
21041                this.translateX = thumbDragUtils.newTranslateX;
21042            }
21043            if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21044                this.settings.thumbnailSwipeThreshold) {
21045                this.thumbClickable = true;
21046            }
21047            return thumbDragUtils;
21048        };
21049        Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21050            var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21051            var thumbImg;
21052            if (slideVideoInfo.youtube) {
21053                if (this.settings.loadYouTubeThumbnail) {
21054                    thumbImg =
21055                        '//img.youtube.com/vi/' +
21056                            slideVideoInfo.youtube[1] +
21057                            '/' +
21058                            this.settings.youTubeThumbSize +
21059                            '.jpg';
21060                }
21061                else {
21062                    thumbImg = thumb;
21063                }
21064            }
21065            else {
21066                thumbImg = thumb;
21067            }
21068            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>";
21069        };
21070        Thumbnail.prototype.getThumbItemHtml = function (items) {
21071            var thumbList = '';
21072            for (var i = 0; i < items.length; i++) {
21073                thumbList += this.getThumbHtml(items[i].thumb, i);
21074            }
21075            return thumbList;
21076        };
21077        Thumbnail.prototype.setThumbItemHtml = function (items) {
21078            var thumbList = this.getThumbItemHtml(items);
21079            this.$lgThumb.html(thumbList);
21080        };
21081        Thumbnail.prototype.setAnimateThumbStyles = function () {
21082            if (this.settings.animateThumb) {
21083                this.core.outer.addClass('lg-animate-thumb');
21084            }
21085        };
21086        // Manage thumbnail active calss
21087        Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21088            var _this = this;
21089            // manage active class for thumbnail
21090            //Uncode edit ##START##
21091            // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21092            this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21093            //Uncode edit ##END##
21094                var $thumb = _this.core.outer.find('.lg-thumb-item');
21095                var index = event.detail.index;
21096                $thumb.removeClass('active');
21097                $thumb.eq(index).addClass('active');
21098            });
21099        };
21100        // Toggle thumbnail bar
21101        Thumbnail.prototype.toggleThumbBar = function () {
21102            var _this = this;
21103            if (this.settings.toggleThumb) {
21104                this.core.outer.addClass('lg-can-toggle');
21105                this.core.$toolbar.append('<button type="button" aria-label="' +
21106                    this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21107                    '" class="lg-toggle-thumb lg-icon"></button>');
21108                this.core.outer
21109                    .find('.lg-toggle-thumb')
21110                    .first()
21111                    .on('click.lg', function () {
21112                    _this.core.outer.toggleClass('lg-components-open');
21113                });
21114            }
21115        };
21116        Thumbnail.prototype.thumbKeyPress = function () {
21117            var _this = this;
21118            this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21119                if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21120                    return;
21121                if (e.keyCode === 38) {
21122                    e.preventDefault();
21123                    _this.core.outer.addClass('lg-components-open');
21124                }
21125                else if (e.keyCode === 40) {
21126                    e.preventDefault();
21127                    _this.core.outer.removeClass('lg-components-open');
21128                }
21129            });
21130        };
21131        Thumbnail.prototype.destroy = function () {
21132            if (this.settings.thumbnail) {
21133                this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21134                this.core.LGel.off('.lg.thumb');
21135                this.core.LGel.off('.thumb');
21136                this.$thumbOuter.remove();
21137                this.core.outer.removeClass('lg-has-thumb');
21138            }
21139        };
21140        return Thumbnail;
21141    }());
21142
21143    return Thumbnail;
21144
21145})));
21146//# sourceMappingURL=lg-thumbnail.umd.js.map
21147
21148/*!
21149 * lightgallery | 2.4.0 | January 29th 2022
21150 * http://www.lightgalleryjs.com/
21151 * Copyright (c) 2020 Sachin Neravath;
21152 * @license GPLv3
21153 */
21154
21155(function (global, factory) {
21156    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21157    typeof define === 'function' && define.amd ? define(factory) :
21158    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21159}(this, (function () { 'use strict';
21160
21161    /*! *****************************************************************************
21162    Copyright (c) Microsoft Corporation.
21163
21164    Permission to use, copy, modify, and/or distribute this software for any
21165    purpose with or without fee is hereby granted.
21166
21167    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21168    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21169    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21170    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21171    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21172    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21173    PERFORMANCE OF THIS SOFTWARE.
21174    ***************************************************************************** */
21175
21176    var __assign = function() {
21177        __assign = Object.assign || function __assign(t) {
21178            for (var s, i = 1, n = arguments.length; i < n; i++) {
21179                s = arguments[i];
21180                for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21181            }
21182            return t;
21183        };
21184        return __assign.apply(this, arguments);
21185    };
21186
21187    var videoSettings = {
21188        autoplayFirstVideo: true,
21189        youTubePlayerParams: false,
21190        vimeoPlayerParams: false,
21191        wistiaPlayerParams: false,
21192        gotoNextSlideOnVideoEnd: true,
21193        autoplayVideoOnSlide: false,
21194        videojs: false,
21195        videojsOptions: {},
21196    };
21197
21198    /**
21199     * List of lightGallery events
21200     * All events should be documented here
21201     * Below interfaces are used to build the website documentations
21202     * */
21203    var lGEvents = {
21204        afterAppendSlide: 'lgAfterAppendSlide',
21205        init: 'lgInit',
21206        hasVideo: 'lgHasVideo',
21207        containerResize: 'lgContainerResize',
21208        updateSlides: 'lgUpdateSlides',
21209        afterAppendSubHtml: 'lgAfterAppendSubHtml',
21210        beforeOpen: 'lgBeforeOpen',
21211        afterOpen: 'lgAfterOpen',
21212        slideItemLoad: 'lgSlideItemLoad',
21213        beforeSlide: 'lgBeforeSlide',
21214        afterSlide: 'lgAfterSlide',
21215        posterClick: 'lgPosterClick',
21216        dragStart: 'lgDragStart',
21217        dragMove: 'lgDragMove',
21218        dragEnd: 'lgDragEnd',
21219        beforeNextSlide: 'lgBeforeNextSlide',
21220        beforePrevSlide: 'lgBeforePrevSlide',
21221        beforeClose: 'lgBeforeClose',
21222        afterClose: 'lgAfterClose',
21223        rotateLeft: 'lgRotateLeft',
21224        rotateRight: 'lgRotateRight',
21225        flipHorizontal: 'lgFlipHorizontal',
21226        flipVertical: 'lgFlipVertical',
21227        autoplay: 'lgAutoplay',
21228        autoplayStart: 'lgAutoplayStart',
21229        autoplayStop: 'lgAutoplayStop',
21230    };
21231
21232    var param = function (obj) {
21233        return Object.keys(obj)
21234            .map(function (k) {
21235            return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
21236        })
21237            .join('&');
21238    };
21239    var getVimeoURLParams = function (defaultParams, videoInfo) {
21240        if (!videoInfo || !videoInfo.vimeo)
21241            return '';
21242        var urlParams = videoInfo.vimeo[2] || '';
21243        urlParams =
21244            urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
21245        var defaultPlayerParams = defaultParams
21246            ? '&' + param(defaultParams)
21247            : '';
21248        // For vimeo last parms gets priority if duplicates found
21249        var vimeoPlayerParams = "?autoplay=0&muted=1" + defaultPlayerParams + urlParams;
21250        return vimeoPlayerParams;
21251    };
21252
21253    /**
21254     * Video module for lightGallery
21255     * Supports HTML5, YouTube, Vimeo, wistia videos
21256     *
21257     *
21258     * @ref Wistia
21259     * https://wistia.com/support/integrations/wordpress(How to get url)
21260     * https://wistia.com/support/developers/embed-options#using-embed-options
21261     * https://wistia.com/support/developers/player-api
21262     * https://wistia.com/support/developers/construct-an-embed-code
21263     * http://jsfiddle.net/xvnm7xLm/
21264     * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
21265     * https://wistia.com/support/embed-and-share/sharing-videos
21266     * https://private-sharing.wistia.com/medias/mwhrulrucj
21267     *
21268     * @ref Youtube
21269     * https://developers.google.com/youtube/player_parameters#enablejsapi
21270     * https://developers.google.com/youtube/iframe_api_reference
21271     * https://developer.chrome.com/blog/autoplay/#iframe-delegation
21272     *
21273     * @ref Vimeo
21274     * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
21275     * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
21276     * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
21277     */
21278    var Video = /** @class */ (function () {
21279        function Video(instance) {
21280            // get lightGallery core plugin instance
21281            this.core = instance;
21282            this.settings = __assign(__assign({}, videoSettings), this.core.settings);
21283            return this;
21284        }
21285        Video.prototype.init = function () {
21286            var _this = this;
21287            /**
21288             * Event triggered when video url found without poster
21289             * Append video HTML
21290             * Play if autoplayFirstVideo is true
21291             */
21292            this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
21293            this.core.LGel.on(lGEvents.posterClick + ".video", function () {
21294                var $el = _this.core.getSlideItem(_this.core.index);
21295                _this.loadVideoOnPosterClick($el);
21296            });
21297            this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
21298            // @desc fired immediately before each slide transition.
21299            this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
21300            // @desc fired immediately after each slide transition.
21301            this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
21302        };
21303        /**
21304         * @desc Event triggered when a slide is completely loaded
21305         *
21306         * @param {Event} event - lightGalley custom event
21307         */
21308        Video.prototype.onSlideItemLoad = function (event) {
21309            var _this = this;
21310            var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
21311            // Should check the active slide as well as user may have moved to different slide before the first slide is loaded
21312            if (this.settings.autoplayFirstVideo &&
21313                isFirstSlide &&
21314                index === this.core.index) {
21315                // Delay is just for the transition effect on video load
21316                setTimeout(function () {
21317                    _this.loadAndPlayVideo(index);
21318                }, 200);
21319            }
21320            // Should not call on first slide. should check only if the slide is active
21321            if (!isFirstSlide &&
21322                this.settings.autoplayVideoOnSlide &&
21323                index === this.core.index) {
21324                this.loadAndPlayVideo(index);
21325            }
21326        };
21327        /**
21328         * @desc Event triggered when video url or poster found
21329         * Append video HTML is poster is not given
21330         * Play if autoplayFirstVideo is true
21331         *
21332         * @param {Event} event - Javascript Event object.
21333         */
21334        Video.prototype.onHasVideo = function (event) {
21335            var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
21336            if (!hasPoster) {
21337                // All functions are called separately if poster exist in loadVideoOnPosterClick function
21338                this.appendVideos(this.core.getSlideItem(index), {
21339                    src: src,
21340                    addClass: 'lg-object',
21341                    index: index,
21342                    html5Video: html5Video,
21343                });
21344                // Automatically navigate to next slide once video reaches the end.
21345                this.gotoNextSlideOnVideoEnd(src, index);
21346            }
21347        };
21348        /**
21349         * @desc fired immediately before each slide transition.
21350         * Pause the previous video
21351         * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
21352         *
21353         * @param {Event} event - Javascript Event object.
21354         * @param {number} prevIndex - Previous index of the slide.
21355         * @param {number} index - Current index of the slide
21356         */
21357        Video.prototype.onBeforeSlide = function (event) {
21358            if (this.core.lGalleryOn) {
21359                var prevIndex = event.detail.prevIndex;
21360                this.pauseVideo(prevIndex);
21361            }
21362            // Uncode edit ##START##
21363            var _a = event.detail, index = _a.index, src = _a.info.src;
21364            if ( typeof src !== 'undefined' && src.indexOf("autoplay") > -1 ) {
21365                this.loadAndPlayVideo(index);
21366
21367	            var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
21368	            	$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
21369                if (videoInfo.vimeo) {
21370		            var vimeoPlayer = new Vimeo.Player($videoElement.get());
21371                    vimeoPlayer.on('play', function () {
21372                        vimeoPlayer.setCurrentTime(0);
21373                    });
21374                } else if ( videoInfo.youtube ) {
21375	                try {
21376			            $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
21377	                }
21378	                catch (e) {
21379	                    console.warn(e);
21380	                }
21381                }
21382            }
21383            // Uncode edit ##END##
21384        };
21385        /**
21386         * @desc fired immediately after each slide transition.
21387         * Play video if autoplayVideoOnSlide option is enabled.
21388         *
21389         * @param {Event} event - Javascript Event object.
21390         * @param {number} prevIndex - Previous index of the slide.
21391         * @param {number} index - Current index of the slide
21392         * @todo should check on onSlideLoad as well if video is not loaded on after slide
21393         */
21394        Video.prototype.onAfterSlide = function (event) {
21395            var _this = this;
21396            var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
21397            // Do not call on first slide
21398            var $slide = this.core.getSlideItem(index);
21399            if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
21400                if ($slide.hasClass('lg-complete')) {
21401                    setTimeout(function () {
21402                        _this.loadAndPlayVideo(index);
21403                    }, 100);
21404                }
21405            }
21406        };
21407        Video.prototype.loadAndPlayVideo = function (index) {
21408            var $slide = this.core.getSlideItem(index);
21409            var currentGalleryItem = this.core.galleryItems[index];
21410            if (currentGalleryItem.poster) {
21411                this.loadVideoOnPosterClick($slide, true);
21412            }
21413            else {
21414	            //Uncode edit ##START##
21415                // this.playVideo(index);
21416	            var src = currentGalleryItem.src;
21417	            if ( typeof src !== 'undefined' && src.indexOf("autoplay") > -1) {
21418	                if ( this.core.index == index ) {
21419		                this.playVideo(index);
21420	                } else {
21421		                this.pauseVideo(index);
21422	                }
21423	            }
21424	            //Uncode edit ##END##
21425            }
21426        };
21427        /**
21428         * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
21429         * @param {number} index - Index of the slide
21430         */
21431        Video.prototype.playVideo = function (index) {
21432            this.controlVideo(index, 'play');
21433        };
21434        /**
21435         * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
21436         * @param {number} index - Index of the slide
21437         */
21438        Video.prototype.pauseVideo = function (index) {
21439            this.controlVideo(index, 'pause');
21440        };
21441        Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
21442            var video = '';
21443            var videoInfo = this.core.galleryItems[index]
21444                .__slideVideoInfo || {};
21445            var currentGalleryItem = this.core.galleryItems[index];
21446            var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
21447            videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
21448            var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
21449            if (videoInfo.youtube) {
21450                var videoId = 'lg-youtube' + index;
21451                var slideUrlParams = videoInfo.youtube[2]
21452                    ? videoInfo.youtube[2] + '&'
21453                    : '';
21454                // For youtube first parms gets priority if duplicates found
21455                var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
21456                var playerParams = youTubePlayerParams +
21457                    (this.settings.youTubePlayerParams
21458                        ? '&' + param(this.settings.youTubePlayerParams)
21459                        : '');
21460                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>";
21461            }
21462            else if (videoInfo.vimeo) {
21463                var videoId = 'lg-vimeo' + index;
21464                var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
21465                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>";
21466            }
21467            else if (videoInfo.wistia) {
21468                var wistiaId = 'lg-wistia' + index;
21469                var playerParams = param(this.settings.wistiaPlayerParams);
21470                playerParams = playerParams ? '?' + playerParams : '';
21471                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>";
21472            }
21473            else if (videoInfo.html5) {
21474                var html5VideoMarkup = '';
21475                for (var i = 0; i < html5Video.source.length; i++) {
21476                    html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
21477                }
21478                if (html5Video.tracks) {
21479                    var _loop_1 = function (i) {
21480                        var trackAttributes = '';
21481                        var track = html5Video.tracks[i];
21482                        Object.keys(track || {}
21482).forEach(function (key) {
21483                            trackAttributes += key + "=\"" + track[key] + "\" ";
21484                        });
21485                        html5VideoMarkup += "<track " + trackAttributes + ">";
21486                    };
21487                    for (var i = 0; i < html5Video.tracks.length; i++) {
21488                        _loop_1(i);
21489                    }
21490                }
21491                var html5VideoAttrs_1 = '';
21492                var videoAttributes_1 = html5Video.attributes || {};
21493                Object.keys(videoAttributes_1 || {}).forEach(function (key) {
21494                    html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
21495                });
21496                video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs ? 'video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
21497            }
21498            return video;
21499        };
21500        /**
21501         * @desc - Append videos to the slide
21502         *
21503         * @param {HTMLElement} el - slide element
21504         * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
21505         */
21506        Video.prototype.appendVideos = function (el, videoParams) {
21507            var _a;
21508            var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
21509            el.find('.lg-video-cont').append(videoHtml);
21510            var $videoElement = el.find('.lg-video-object').first();
21511            if (videoParams.html5Video) {
21512                $videoElement.on('mousedown.lg.video', function (e) {
21513                    e.stopPropagation();
21514                });
21515            }
21516            if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
21517                try {
21518                    return videojs($videoElement.get(), this.settings.videojsOptions);
21519                }
21520                catch (e) {
21521                    console.warn('lightGallery:- Make sure you have included videojs');
21522                }
21523            }
21524        };
21525        Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
21526            var _this = this;
21527            var $videoElement = this.core
21528                .getSlideItem(index)
21529                .find('.lg-video-object')
21530                .first();
21531            var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21532            if (this.settings.gotoNextSlideOnVideoEnd) {
21533                if (videoInfo.html5) {
21534                    $videoElement.on('ended', function () {
21535                        _this.core.goToNextSlide();
21536                    });
21537                }
21538                else if (videoInfo.vimeo) {
21539                    try {
21540                        // https://github.com/vimeo/player.js/#ended
21541                        new Vimeo.Player($videoElement.get()).on('ended', function () {
21542                            _this.core.goToNextSlide();
21543                        });
21544                    }
21545                    catch (e) {
21546                        console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
21547                    }
21548                }
21549                else if (videoInfo.wistia) {
21550                    try {
21551                        window._wq = window._wq || [];
21552                        // @todo Event is gettign triggered multiple times
21553                        window._wq.push({
21554                            id: $videoElement.attr('id'),
21555                            onReady: function (video) {
21556                                video.bind('end', function () {
21557                                    _this.core.goToNextSlide();
21558                                });
21559                            },
21560                        });
21561                    }
21562                    catch (e) {
21563                        console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
21564                    }
21565                }
21566            }
21567        };
21568        Video.prototype.controlVideo = function (index, action) {
21569            var $videoElement = this.core
21570                .getSlideItem(index)
21571                .find('.lg-video-object')
21572                .first();
21573            var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21574            if (!$videoElement.get())
21575                return;
21576            if (videoInfo.youtube) {
21577                try {
21578                    $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
21579                }
21580                catch (e) {
21581                    console.warn("lightGallery:- " + e);
21582                }
21583            }
21584            else if (videoInfo.vimeo) {
21585                try {
21586                    new Vimeo.Player($videoElement.get())[action]();
21587                }
21588                catch (e) {
21589                    console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
21590                }
21591            }
21592            else if (videoInfo.html5) {
21593                if (this.settings.videojs) {
21594                    try {
21595                        videojs($videoElement.get())[action]();
21596                    }
21597                    catch (e) {
21598                        console.warn('lightGallery:- Make sure you have included videojs');
21599                    }
21600                }
21601                else {
21602                    $videoElement.get()[action]();
21603                }
21604            }
21605            else if (videoInfo.wistia) {
21606                try {
21607                    window._wq = window._wq || [];
21608                    // @todo Find a way to destroy wistia player instance
21609                    window._wq.push({
21610                        id: $videoElement.attr('id'),
21611                        onReady: function (video) {
21612                            video[action]();
21613                        },
21614                    });
21615                }
21616                catch (e) {
21617                    console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
21618                }
21619            }
21620        };
21621        Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
21622            var _this = this;
21623            // check slide has poster
21624            if (!$el.hasClass('lg-video-loaded')) {
21625                // check already video element present
21626                if (!$el.hasClass('lg-has-video')) {
21627                    $el.addClass('lg-has-video');
21628                    var _html = void 0;
21629                    var _src = this.core.galleryItems[this.core.index].src;
21630                    var video = this.core.galleryItems[this.core.index].video;
21631                    if (video) {
21632                        _html =
21633                            typeof video === 'string' ? JSON.parse(video) : video;
21634                    }
21635                    var videoJsPlayer_1 = this.appendVideos($el, {
21636                        src: _src,
21637                        addClass: '',
21638                        index: this.core.index,
21639                        html5Video: _html,
21640                    });
21641                    this.gotoNextSlideOnVideoEnd(_src, this.core.index);
21642                    var $tempImg = $el.find('.lg-object').first().get();
21643                    // @todo make sure it is working
21644                    $el.find('.lg-video-cont').first().append($tempImg);
21645                    $el.addClass('lg-video-loading');
21646                    videoJsPlayer_1 &&
21647                        videoJsPlayer_1.ready(function () {
21648                            videoJsPlayer_1.on('loadedmetadata', function () {
21649                                _this.onVideoLoadAfterPosterClick($el, _this.core.index);
21650                            });
21651                        });
21652                    $el.find('.lg-video-object')
21653                        .first()
21654                        .on('load.lg error.lg loadedmetadata.lg', function () {
21655                        setTimeout(function () {
21656                            _this.onVideoLoadAfterPosterClick($el, _this.core.index);
21657                        }, 50);
21658                    });
21659                }
21660                else {
21661                    this.playVideo(this.core.index);
21662                }
21663            }
21664            else if (forcePlay) {
21665                this.playVideo(this.core.index);
21666            }
21667        };
21668        Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
21669            $el.addClass('lg-video-loaded');
21670            this.playVideo(index);
21671        };
21672        Video.prototype.destroy = function () {
21673            this.core.LGel.off('.lg.video');
21674            this.core.LGel.off('.video');
21675        };
21676        return Video;
21677    }());
21678
21679    return Video;
21680
21681})));
21682//# sourceMappingURL=lg-video.umd.js.map
21683
21684
21685/*! @vimeo/player v2.16.3 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
21686!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 l(e){return/^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(e)}function u(e){var t=0<arguments.length&&void 0!==e?e:{},n=t.id,e=t.url,t=n||e;if(!t)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(e=t,!isNaN(parseFloat(e))&&isFinite(e)&&Math.floor(e)==e)return"https://vimeo.com/".concat(t);if(l(t))return t.replace("http:","https:");if(n)throw new TypeError("“".concat(n,"” is not a valid video id."));throw new TypeError("“".concat(t,"” is not a vimeo.com url."))}var t=void 0!==Array.prototype.indexOf,Player="undefined"!=typeof window&&void 0!==window.postMessage;if(!(e||t&&Player))throw new Error("Sorry, the Vimeo Player API is not available in this browser.");var n,o,a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function c(){if(void 0===this)throw new TypeError("Constructor WeakMap requires 'new'");if(o(this,"_id","_WeakMap_"+f()+"."+f()),0<arguments.length)throw new TypeError("WeakMap iterable is not supported")}function s(e,t){if(!d(e)||!n.call(e,"_id"))throw new TypeError(t+" method called on incompatible receiver "+typeof e)}function f(){return Math.random().toString().substring(2)}function d(e){return Object(e)===e}(Player="undefined"!=typeof self?self:"undefined"!=typeof window?window:a).WeakMap||(n=Object.prototype.hasOwnProperty,Player.WeakMap=((o=function(e,t,n){Object.defineProperty?Object.defineProperty(e,t,{configurable:!0,writable:!0,value:n}):e[t]=n})(c.prototype,"delete",function(e){if(s(this,"delete"),!d(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)&&(delete e[this._id],!0)}),o(c.prototype,"get",function(e){if(s(this,"get"),d(e)){var t=e[this._id];return t&&t[0]===e?t[1]:void 0}}),o(c.prototype,"has",function(e){if(s(this,"has"),!d(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)}),o(c.prototype,"set",function(e,t){if(s(this,"set"),!d(e))throw new TypeError("Invalid value used as weak map key");var n=e[this._id];return n&&n[0]===e?n[1]=t:o(e,this._id,[e,t]),this}),o(c,"_polyfill",!0),c));var h,m=(function(e){var t,n,r;r=function(){var t,n,r,o,i,e=Object.prototype.toString,a="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 u(e,t){this.fn=e,this.self=t,this.next=void 0}function l(e,t){y.add(e,t),n=n||a(y.drain)}function c(e){var t,n=typeof e;return"function"==typeof(t=null!=e&&("object"==n||"function"==n)?e.then:t)&&t}function s(){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=c(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 f(e){var n,r=this;if(!r.triggered){r.triggered=!0,r.def&&(r=r.def);try{(n=c(e))?l(function(){var t=new m(r);try{n.call(e,function(){f.apply(t,arguments)},function(){d.apply(t,arguments)})}catch(e){d.call(t,e)}}):(r.msg=e,r.state=1,0<r.chain.length&&l(s,r))}catch(e){d.call(new m(r),e)}}}function d(e){var t=this;t.triggered||(t.triggered=!0,(t=t.def?t.def:t).msg=e,t.state=2,0<t.chain.length&&l(s,t))}function h(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 v(e){this.promise=e,this.state=0,this.triggered=!1,this.chain=[],this.msg=void 0}function p(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 v(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&&l(s,r),n.promise},this.catch=function(e){return this.then(void 0,e)};try{e.call(void 0,function(e){f.call(r,e)},function(e){d.call(r,e)})}catch(e){d.call(r,e)}}var y={add:function(e,t){i=new u(e,t),o?o.next=i:r=i,o=i,i=void 0},drain:function(){var e=r;
vendor: 14,752 bytes, lines 21686-21689
21686for(r=o=n=void 0;e;)e.fn.call(e.self),e=e.next}},g=t({},"constructor",p,!1);return t(p.prototype=g,"__NPO__",0,!1),t(p,"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(p,"reject",function(n){return new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");t(n)})}),t(p,"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;h(a,t,function(e,t){o[e]=t,++i===r&&n(o)},e)})}),t(p,"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");h(r,t,function(e,t){n(t)},e)})}),p},(n=a)[t="Promise"]=n[t]||r(),e.exports&&(e.exports=n[t])}(h={exports:{}}),h.exports),v=new WeakMap;function p(e,t,n){var r=v.get(e.element)||{};t in r||(r[t]=[]),r[t].push(n),v.set(e.element,r)}function y(e,t){return(v.get(e.element)||{})[t]||[]}function g(e,t,n){var r=v.get(e.element)||{};if(!r[t])return!0;if(!n)return r[t]=[],v.set(e.element,r),!0;n=r[t].indexOf(n);return-1!==n&&r[t].splice(n,1),v.set(e.element,r),r[t]&&0===r[t].length}var w=["autopause","autoplay","background","byline","color","controls","dnt","height","id","interactiveparams","keyboard","loop","maxheight","maxwidth","muted","playsinline","portrait","responsive","speed","texttrack","title","transparent","url","width"];function b(r,e){return w.reduce(function(e,t){var n=r.getAttribute("data-vimeo-".concat(t));return!n&&""!==n||(e[t]=""===n?1:n),e},1<arguments.length&&void 0!==e?e:{})}function k(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");e=document.createElement("div");return e.innerHTML=n,t.appendChild(e.firstChild),t.setAttribute("data-vimeo-initialized","true"),t.querySelector("iframe")}function E(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(!l(i))throw new TypeError("“".concat(i,"” is not a vimeo.com url."));var e,r="https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(i));for(e in a)a.hasOwnProperty(e)&&(r+="&".concat(e,"=").concat(encodeURIComponent(a[e])));var o=new("XDomainRequest"in window?XDomainRequest:XMLHttpRequest);o.open("GET",r,!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 k(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()})}function T(e){function n(e){"console"in window&&console.warn&&console.warn("There was an error creating an embed: ".concat(e))}e=0<arguments.length&&void 0!==e?e:document,e=[].slice.call(e.querySelectorAll("[data-vimeo-id], [data-vimeo-url]"));e.forEach(function(t){try{if(null!==t.getAttribute("data-vimeo-defer"))return;var e=b(t);E(u(e),e,t).then(function(e){return k(e,t)}).catch(n)}catch(e){n(e)}})}function P(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){return console.warn(e),{}}return e}function _(e,t,n){e.element.contentWindow&&e.element.contentWindow.postMessage&&(t={method:t},void 0!==n&&(t.value=n),8<=(n=parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/,"$1")))&&n<10&&(t=JSON.stringify(t)),e.element.contentWindow.postMessage(t,e.origin))}function M(n,r){var t,e,o,i,a=[];(r=P(r)).event?("error"===r.event&&y(n,r.data.method).forEach(function(e){var t=new Error(r.data.message);t.name=r.data.name,e.reject(t),g(n,r.data.method,e)}),a=y(n,"event:".concat(r.event)),t=r.data):r.method&&(e=n,o=r.method,(i=!((i=y(e,o)).length<1)&&(i=i.shift(),g(e,o,i),i))&&(a.push(i),t=r.value)),a.forEach(function(e){try{if("function"==typeof e)return void e.call(n,t);e.resolve(t)}catch(e){}})}var N,F,x,C=new WeakMap,j=new WeakMap,A={},Player=function(){function Player(i){var e,a=this,t=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&&i instanceof jQuery&&(1<i.length&&window.console&&console.warn&&console.warn("A jQuery object with multiple elements was passed, using the first element."),i=i[0]),"undefined"!=typeof document&&"string"==typeof i&&(i=document.getElementById(i)),e=i,!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"===i.nodeName||(r=i.querySelector("iframe"))&&(i=r),"IFRAME"===i.nodeName&&!l(i.getAttribute("src")||""))throw new Error("The player element passed isn’t a Vimeo embed.");if(C.has(i))return C.get(i);this._window=i.ownerDocument.defaultView,this.element=i,this.origin="*";var n,r=new m(function(r,o){var e;a._onMessage=function(e){if(l(e.origin)&&a.element.contentWindow===e.source){"*"===a.origin&&(a.origin=e.origin);var t=P(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 o(n)}e=t&&"ready"===t.event,n=t&&"ping"===t.method;if(e||n)return a.element.setAttribute("data-ready","true"),void r();M(a,t)}},a._window.addEventListener("message",a._onMessage),"IFRAME"!==a.element.nodeName&&E(u(e=b(i,t)),e,i).then(function(e){var t,n,r=k(e,i);return a.element=r,a._originalElement=i,t=i,n=r,r=v.get(t),v.set(n,r),v.delete(t),C.set(a.element,a),e}).catch(o)});return j.set(this,r),C.set(this.element,this),"IFRAME"===this.element.nodeName&&_(this,"ping"),A.isEnabled&&(n=function(){return A.exit()},this.fullscreenchangeHandler=function(){(A.isFullscreen?p:g)(a,"event:exitFullscreen",n),a.ready().then(function(){_(a,"fullscreenchange",A.isFullscreen)})},A.on("fullscreenchange",this.fullscreenchangeHandler)),this}var e,t,n;return e=Player,(t=[{key:"callMethod",value:function(n){var r=this,o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};return new m(function(e,t){return r.ready().then(function(){p(r,n,{resolve:e,reject:t}),_(r,n,o)}).catch(t)})}},{key:"get",value:function(n){var r=this;return new m(function(e,t){return n=i(n,"get"),r.ready().then(function(){p(r,n,{resolve:e,reject:t}),_(r,n)}).catch(t)})}},{key:"set",value:function(n,r){var o=this;return new m(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(){p(o,n,{resolve:e,reject: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===y(this,"event:".concat(e)).length&&this.callMethod("addEventListener",e).catch(function(){}),p(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.");g(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=j.get(this)||new m(function(e,t){t(new Error("Unknown player. Probably unloaded."))});return m.resolve(e)}},{key:"addCuePoint",value:function(e){return this.callMethod("addCuePoint",{time:e,data:1<arguments.length&&void 0!==arguments[1]?arguments[1]:{}})}},{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 A.isEnabled?A.request(this.element):this.callMethod("requestFullscreen")}},{key:"exitFullscreen",value:function(){return A.isEnabled?A.exit():this.callMethod("exitFullscreen")}},{key:"getFullscreen",value:function(){return A.isEnabled?m.resolve(A.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 m(function(e){var t;j.delete(n),C.delete(n.element),n._originalElement&&(C.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),A.isEnabled&&A.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)}},{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||(N=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}(),F={fullscreenchange:N.fullscreenchange,fullscreenerror:N.fullscreenerror},x={request:function(o){return new Promise(function(e,t){function n(){x.off("fullscreenchange",n),e()}x.on("fullscreenchange",n);var r=(o=o||document.documentElement)[N.requestFullscreen]();r instanceof Promise&&r.then(n).catch(t)})},exit:function(){return new Promise(function(t,e){var n,r;x.isFullscreen?(n=function e(){x.off("fullscreenchange",e),t()},x.on("fullscreenchange",n),(r=document[N.exitFullscreen]())instanceof Promise&&r.then(n).catch(e)):t()})},on:function(e,t){e=F[e];e&&document.addEventListener(e,t)},off:function(e,t){e=F[e];e&&document.removeEventListener(e,t)}},Object.defineProperties(x,{isFullscreen:{get:function(){return Boolean(document[N.fullscreenElement])}},element:{enumerable:!0,get:function(){return document[N.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(document[N.fullscreenEnabled])}}}),A=x,T(),function(e){var r=0<arguments.length&&void 0!==e?e:document;window.VimeoPlayerResizeEmbeds_||(window.VimeoPlayerResizeEmbeds_=!0,window.addEventListener("message",function(e){if(l(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}}))}()),Player});
21687
21688/**
21689 * Owl carousel
vendor: 31,483 bytes, lines 21690-22893
21690 * @version 2.0.0-beta.3
21691 * @author Bartosz Wojciechowski
21692 * @license The MIT License (MIT)
21693 * @todo Lazy Load Icon
21694 * @todo prevent animationend bubling
21695 * @todo itemsScaleUp
21696 * @todo Test Zepto
21697 * @todo stagePadding calculate wrong active classes
21698 */
21699;(function($, window, document, undefined) {
21700
21701	/**
21702	 * Creates a carousel.
21703	 * @class The Owl Carousel.
21704	 * @public
21705	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
21706	 * @param {Object} [options] - The options
21707	 */
21708	function Owl(element, options) {
21709
21710		/**
21711		 * Current settings for the carousel.
21712		 * @public
21713		 */
21714		this.settings = null;
21715
21716		/**
21717		 * Current options set by the caller including defaults.
21718		 * @public
21719		 */
21720		this.options = $.extend({}, Owl.Defaults, options);
21721
21722		/**
21723		 * Plugin element.
21724		 * @public
21725		 */
21726		this.$element = $(element);
21727
21728		/**
21729		 * Proxied event handlers.
21730		 * @protected
21731		 */
21732		this._handlers = {};
21733
21734		/**
21735		 * References to the running plugins of this carousel.
21736		 * @protected
21737		 */
21738		this._plugins = {};
21739
21740		/**
21741		 * Currently suppressed events to prevent them from beeing retriggered.
21742		 * @protected
21743		 */
21744		this._supress = {};
21745
21746		/**
21747		 * Absolute current position.
21748		 * @protected
21749		 */
21750		this._current = null;
21751
21752		/**
21753		 * Animation speed in milliseconds.
21754		 * @protected
21755		 */
21756		this._speed = null;
21757
21758		/**
21759		 * Coordinates of all items in pixel.
21760		 * @todo The name of this member is missleading.
21761		 * @protected
21762		 */
21763		this._coordinates = [];
21764
21765		/**
21766		 * Current breakpoint.
21767		 * @todo Real media queries would be nice.
21768		 * @protected
21769		 */
21770		this._breakpoint = null;
21771
21772		/**
21773		 * Current width of the plugin element.
21774		 */
21775		this._width = null;
21776
21777		/**
21778		 * All real items.
21779		 * @protected
21780		 */
21781		this._items = [];
21782
21783		/**
21784		 * All cloned items.
21785		 * @protected
21786		 */
21787		this._clones = [];
21788
21789		/**
21790		 * Merge values of all items.
21791		 * @todo Maybe this could be part of a plugin.
21792		 * @protected
21793		 */
21794		this._mergers = [];
21795
21796		/**
21797		 * Widths of all items.
21798		 */
21799		this._widths = [];
21800
21801		/**
21802		 * Invalidated parts within the update process.
21803		 * @protected
21804		 */
21805		this._invalidated = {};
21806
21807		/**
21808		 * Ordered list of workers for the update process.
21809		 * @protected
21810		 */
21811		this._pipe = [];
21812
21813		/**
21814		 * Current state information for the drag operation.
21815		 * @todo #261
21816		 * @protected
21817		 */
21818		this._drag = {
21819			time: null,
21820			target: null,
21821			pointer: null,
21822			stage: {
21823				start: null,
21824				current: null
21825			},
21826			direction: null
21827		};
21828
21829		/**
21830		 * Current state information and their tags.
21831		 * @type {Object}
21832		 * @protected
21833		 */
21834		this._states = {
21835			current: {},
21836			tags: {
21837				'initializing': [ 'busy' ],
21838				'animating': [ 'busy' ],
21839				'dragging': [ 'interacting' ]
21840			}
21841		};
21842
21843		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
21844			this._handlers[handler] = $.proxy(this[handler], this);
21845		}, this));
21846
21847		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
21848			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
21849				= new plugin(this);
21850		}, this));
21851
21852		$.each(Owl.Workers, $.proxy(function(priority, worker) {
21853			this._pipe.push({
21854				'filter': worker.filter,
21855				'run': $.proxy(worker.run, this)
21856			});
21857		}, this));
21858
21859		this.setup();
21860		this.initialize();
21861	}
21862
21863	/**
21864	 * Default options for the carousel.
21865	 * @public
21866	 */
21867	Owl.Defaults = {
21868		items: 3,
21869		loop: false,
21870		center: false,
21871		rewind: false,
21872
21873		mouseDrag: true,
21874		touchDrag: true,
21875		pullDrag: true,
21876		freeDrag: false,
21877
21878		margin: 0,
21879		stagePadding: 0,
21880
21881		merge: false,
21882		mergeFit: true,
21883		autoWidth: false,
21884
21885		startPosition: 0,
21886		rtl: false,
21887
21888		smartSpeed: 250,
21889		fluidSpeed: false,
21890		dragEndSpeed: false,
21891
21892		responsive: {},
21893		responsiveRefreshRate: 200,
21894		responsiveBaseElement: window,
21895
21896		fallbackEasing: 'swing',
21897
21898		info: false,
21899
21900		nestedItemSelector: false,
21901		itemElement: 'div',
21902		stageElement: 'div',
21903
21904		refreshClass: 'owl-refresh',
21905		loadedClass: 'owl-loaded',
21906		loadingClass: 'owl-loading',
21907		rtlClass: 'owl-rtl',
21908		responsiveClass: 'owl-responsive',
21909		dragClass: 'owl-drag',
21910		itemClass: 'owl-item',
21911		stageClass: 'owl-stage',
21912		stageOuterClass: 'owl-stage-outer',
21913		grabClass: 'owl-grab'
21914	};
21915
21916	/**
21917	 * Enumeration for width.
21918	 * @public
21919	 * @readonly
21920	 * @enum {String}
21921	 */
21922	Owl.Width = {
21923		Default: 'default',
21924		Inner: 'inner',
21925		Outer: 'outer'
21926	};
21927
21928	/**
21929	 * Enumeration for types.
21930	 * @public
21931	 * @readonly
21932	 * @enum {String}
21933	 */
21934	Owl.Type = {
21935		Event: 'event',
21936		State: 'state'
21937	};
21938
21939	/**
21940	 * Contains all registered plugins.
21941	 * @public
21942	 */
21943	Owl.Plugins = {};
21944
21945	/**
21946	 * List of workers involved in the update process.
21947	 */
21948	Owl.Workers = [ {
21949		filter: [ 'width', 'settings' ],
21950		run: function() {
21951			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
21952			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
21953		}
21954	}, {
21955		filter: [ 'width', 'items', 'settings' ],
21956		run: function(cache) {
21957			cache.current = this._items && this._items[this.relative(this._current)];
21958		}
21959	}, {
21960		filter: [ 'items', 'settings' ],
21961		run: function() {
21962			this.$stage.children('.cloned').remove();
21963		}
21964	}, {
21965		filter: [ 'width', 'items', 'settings' ],
21966		run: function(cache) {
21967			var margin = this.settings.margin || '',
21968				grid = !this.settings.autoWidth,
21969				rtl = this.settings.rtl,
21970				css = {
21971					'width': 'auto',
21972					'margin-left': rtl ? margin : '',
21973					'margin-right': rtl ? '' : margin
21974				};
21975
21976			!grid && this.$stage.children().css(css);
21977
21978			cache.css = css;
21979		}
21980	}, {
21981		filter: [ 'width', 'items', 'settings' ],
21982		run: function(cache) {
21983			//UNCODE edit to fix Chrome stage padding issue
21984			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
21985				merge = null,
21986				iterator = this._items.length,
21987				grid = !this.settings.autoWidth,
21988				widths = [];
21989
21990			cache.items = {
21991				merge: false,
21992				width: width
21993			};
21994
21995			while (iterator--) {
21996				merge = this._mergers[iterator];
21997				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
21998
21999				cache.items.merge = merge > 1 || cache.items.merge;
22000
22001				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22002			}
22003
22004			this._widths = widths;
22005		}
22006	}, {
22007		filter: [ 'items', 'settings' ],
22008		run: function() {
22009			var clones = [],
22010				items = this._items,
22011				settings = this.settings,
22012				view = Math.max(settings.items * 2, 4),
22013				size = Math.ceil(items.length / 2) * 2,
22014				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22015				append = '',
22016				prepend = '';
22017
22018			repeat /= 2;
22019
22020			while (repeat--) {
22021				clones.push(this.normalize(clones.length / 2, true));
22022				append = append + items[clones[clones.length - 1]][0].outerHTML;
22023				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22024				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22025			}
22026
22027			this._clones = clones;
22028
22029			// var appendVideo = $(append).find('.uncode-video-container');
22030			// if (appendVideo.length) {
22031			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22032			// }
22033			// var prependVideo = $(prepend).find('.uncode-video-container');
22034			// if (prependVideo.length) {
22035			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22036			// }
22037			$(append).addClass('cloned').appendTo(this.$stage);
22038			$(prepend).addClass('cloned').prependTo(this.$stage);
22039		}
22040	}, {
22041		filter: [ 'width', 'items', 'settings' ],
22042		run: function() {
22043			var rtl = this.settings.rtl ? 1 : -1,
22044				size = this._clones.length + this._items.length,
22045				iterator = -1,
22046				previous = 0,
22047				current = 0,
22048				coordinates = [];
22049
22050			while (++iterator < size) {
22051				previous = coordinates[iterator - 1] || 0;
22052				current = this._widths[this.relative(iterator)] + this.settings.margin;
22053				coordinates.push(previous + current * rtl);
22054			}
22055
22056			this._coordinates = coordinates;
22057		}
22058	}, {
22059		filter: [ 'width', 'items', 'settings' ],
22060		run: function() {
22061			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22062				padding = stagePadding,
22063				coordinates = this._coordinates,
22064				css = {
22065					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22066					'padding-left': padding || '',
22067					'padding-right': padding || ''
22068				};
22069
22070			this.$stage.css(css);
22071		}
22072	}, {
22073		filter: [ 'width', 'items', 'settings' ],
22074		run: function(cache) {
22075			var iterator = this._coordinates.length,
22076				grid = !this.settings.autoWidth,
22077				items = this.$stage.children();
22078
22079			if (grid && cache.items.merge) {
22080				while (iterator--) {
22081					cache.css.width = this._widths[this.relative(iterator)];
22082					items.eq(iterator).css(cache.css);
22083				}
22084			} else if (grid) {
22085				cache.css.width = cache.items.width;
22086				items.css(cache.css);
22087			}
22088		}
22089	}, {
22090		filter: [ 'items' ],
22091		run: function() {
22092			this._coordinates.length < 1 && this.$stage.removeAttr('style');
22093		}
22094	}, {
22095		filter: [ 'width', 'items', 'settings' ],
22096		run: function(cache) {
22097			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
22098			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
22099			this.reset(cache.current);
22100		}
22101	}, {
22102		filter: [ 'position' ],
22103		run: function() {
22104			this.animate(this.coordinates(this._current));
22105		}
22106	}, {
22107		filter: [ 'width', 'position', 'items', 'settings' ],
22108		run: function() {
22109			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22110				rtl = this.settings.rtl ? 1 : -1,
22111				padding = this.settings.stagePadding * 2,
22112				begin = this.coordinates(this.current()) + padding,
22113				end = begin + this.width() * rtl,
22114				inner, outer, matches = [], i, n;
22115
22116			for (i = 0, n = this._coordinates.length; i < n; i++) {
22117				inner = this._coordinates[i - 1] || 0;
22118				outer = Math.abs(this._coordinates[i]) + padding * rtl;
22119
22120				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
22121					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
22122					matches.push(i);
22123				}
22124			}
22125
22126			this.$stage.children('.active').removeClass('active');
22127			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
22128
22129			if (this.settings.center) {
22130				this.$stage.children('.center').removeClass('center');
22131				this.$stage.children().eq(this.current()).addClass('center');
22132			}
22133		}
22134	} ];
22135
22136	/**
22137	 * Initializes the carousel.
22138	 * @protected
22139	 */
22140	Owl.prototype.initialize = function() {
22141		this.enter('initializing');
22142		this.trigger('initialize');
22143
22144		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
22145
22146		if (this.settings.autoWidth && !this.is('pre-loading')) {
22147			var imgs, nestedSelector, width;
22148			imgs = this.$element.find('img');
22149			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
22150			width = this.$element.children(nestedSelector).width();
22151
22152			if (imgs.length && width <= 0) {
22153				this.preloadAutoWidthImages(imgs);
22154			}
22155		}
22156
22157		this.$element.addClass(this.options.loadingClass);
22158
22159		// create stage
22160		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
22161			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
22162
22163		// append stage
22164		this.$element.append(this.$stage.parent());
22165
22166		// append content
22167		this.replace(this.$element.children().not(this.$stage.parent()));
22168
22169		// check visibility
22170		if (this.$element.is(':visible')) {
22171			// update view
22172			this.refresh();
22173		} else {
22174			// invalidate width
22175			this.invalidate('width');
22176		}
22177
22178		this.$element
22179			.removeClass(this.options.loadingClass)
22180			.addClass(this.options.loadedClass);
22181
22182		// register event handlers
22183		this.registerEventHandlers();
22184
22185		this.leave('initializing');
22186		this.trigger('initialized');
22187	};
22188
22189	/**
22190	 * Setups the current settings.
22191	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
22192	 * @todo Support for media queries by using `matchMedia` would be nice.
22193	 * @public
22194	 */
22195	Owl.prototype.setup = function() {
22196		var viewport = this.viewport(),
22197			overwrites = this.options.responsive,
22198			match = -1,
22199			settings = null;
22200
22201		if (!overwrites) {
22202			settings = $.extend({}, this.options);
22203		} else {
22204			$.each(overwrites, function(breakpoint) {
22205				if (breakpoint <= viewport && breakpoint > match) {
22206					match = Number(breakpoint);
22207				}
22208			});
22209
22210			settings = $.extend({}, this.options, overwrites[match]);
22211			delete settings.responsive;
22212
22213			// responsive class
22214			if (settings.responsiveClass) {
22215				this.$element.attr('class',
22216					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
22217				);
22218			}
22219		}
22220
22221		if (this.settings === null || this._breakpoint !== match) {
22222			this.trigger('change', { property: { name: 'settings', value: settings } });
22223			this._breakpoint = match;
22224			this.settings = settings;
22225			this.invalidate('settings');
22226			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
22227		}
22228	};
22229
22230	/**
22231	 * Updates option logic if necessery.
22232	 * @protected
22233	 */
22234	Owl.prototype.optionsLogic = function() {
22235		if (this.settings.autoWidth) {
22236			this.settings.stagePadding = false;
22237			this.settings.merge = false;
22238		}
22239	};
22240
22241	/**
22242	 * Prepares an item before add.
22243	 * @todo Rename event parameter `content` to `item`.
22244	 * @protected
22245	 * @returns {jQuery|HTMLElement} - The item container.
22246	 */
22247	Owl.prototype.prepare = function(item, index) {
22248		var event = this.trigger('prepare', { content: item });
22249		if (!event.data) {
22250			event.data = $('<' + this.settings.itemElement + '/>')
22251				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
22252		}
22253
22254		this.trigger('prepared', { content: event.data });
22255
22256		return event.data;
22257	};
22258
22259	/**
22260	 * Updates the view.
22261	 * @public
22262	 */
22263	Owl.prototype.update = function() {
22264		var i = 0,
22265			n = this._pipe.length,
22266			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
22267			cache = {};
22268
22269		while (i < n) {
22270			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
22271				this._pipe[i].run(cache);
22272			}
22273			i++;
22274		}
22275
22276		this._invalidated = {};
22277
22278		!this.is('valid') && this.enter('valid');
22279	};
22280
22281	/**
22282	 * Gets the width of the view.
22283	 * @public
22284	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
22285	 * @returns {Number} - The width of the view in pixel.
22286	 */
22287	Owl.prototype.width = function(dimension) {
22288		dimension = dimension || Owl.Width.Default;
22289		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
22290		switch (dimension) {
22291			case Owl.Width.Inner:
22292			case Owl.Width.Outer:
22293				return this._width;
22294			default:
22295				return this._width - stagePadding * 2 + this.settings.margin;
22296		}
22297	};
22298
22299	/**
22300	 * Refreshes the carousel primarily for adaptive purposes.
22301	 * @public
22302	 */
22303	Owl.prototype.refresh = function() {
22304		this.enter('refreshing');
22305		this.trigger('refresh');
22306
22307		this.setup();
22308
22309		this.optionsLogic();
22310
22311		this.$element.addClass(this.options.refreshClass);
22312
22313		this.update();
22314
22315		this.$element.removeClass(this.options.refreshClass);
22316
22317		this.leave('refreshing');
22318		this.trigger('refreshed');
22319	};
22320
22321	/**
22322	 * Checks window `resize` event.
22323	 * @protected
22324	 */
22325	Owl.prototype.onThrottledResize = function() {
22326		window.clearTimeout(this.resizeTimer);
22327		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
22328	};
22329
22330	/**
22331	 * Checks window `resize` event.
22332	 * @protected
22333	 */
22334	Owl.prototype.onResize = function() {
22335		if (!this._items.length) {
22336			return false;
22337		}
22338
22339		if (this._width === this.$element.width()) {
22340			return false;
22341		}
22342
22343		if (!this.$element.is(':visible')) {
22344			return false;
22345		}
22346
22347		this.enter('resizing');
22348
22349		if (this.trigger('resize').isDefaultPrevented()) {
22350			this.leave('resizing');
22351			return false;
22352		}
22353
22354		this.invalidate('width');
22355
22356		this.refresh();
22357
22358		this.leave('resizing');
22359		this.trigger('resized');
22360	};
22361
22362	/**
22363	 * Registers event handlers.
22364	 * @todo Check `msPointerEnabled`
22365	 * @todo #261
22366	 * @protected
22367	 */
22368	Owl.prototype.registerEventHandlers = function() {
22369		if ($.support.transition) {
22370			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
22371		}
22372
22373		if (this.settings.responsive !== false) {
22374			this.on(window, 'resize', this._handlers.onThrottledResize);
22375		}
22376
22377		if (this.settings.mouseDrag) {
22378			this.$element.addClass(this.options.dragClass);
22379			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
22380			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
22381		}
22382
22383		if (this.settings.touchDrag){
22384			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
22385			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
22386		}
22387	};
22388
22389	/**
22390	 * Handles `touchstart` and `mousedown` events.
22391	 * @todo Horizontal swipe threshold as option
22392	 * @todo #261
22393	 * @protected
22394	 * @param {Event} event - The event arguments.
22395	 */
22396	Owl.prototype.onDragStart = function(event) {
22397		var stage = null;
22398
22399		if (event.which === 3) {
22400			return;
22401		}
22402
22403		if ($.support.transform) {
22404			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
22405			stage = {
22406				x: stage[stage.length === 16 ? 12 : 4],
22407				y: stage[stage.length === 16 ? 13 : 5]
22408			};
22409		} else {
22410			stage = this.$stage.position();
22411			stage = {
22412				x: this.settings.rtl ?
22413					stage.left + this.$stage.width() - this.width() + this.settings.margin :
22414					stage.left,
22415				y: stage.top
22416			};
22417		}
22418
22419		if (this.is('animating')) {
22420			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
22421			this.invalidate('position');
22422		}
22423
22424		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
22425
22426		this.speed(0);
22427
22428		this._drag.time = new Date().getTime();
22429		this._drag.target = $(event.target);
22430		this._drag.stage.start = stage;
22431		this._drag.stage.current = stage;
22432		this._drag.pointer = this.pointer(event);
22433
22434		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
22435
22436		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
22437			var delta = this.difference(this._drag.pointer, this.pointer(event));
22438
22439			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
22440
22441			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
22442				return;
22443			}
22444
22445			event.preventDefault();
22446
22447			this.enter('dragging');
22448			this.trigger('drag');
22449		}, this));
22450	};
22451
22452	/**
22453	 * Handles the `touchmove` and `mousemove` events.
22454	 * @todo #261
22455	 * @protected
22456	 * @param {Event} event - The event arguments.
22457	 */
22458	Owl.prototype.onDragMove = function(event) {
22459		var minimum = null,
22460			maximum = null,
22461			pull = null,
22462			delta = this.difference(this._drag.pointer, this.pointer(event)),
22463			stage = this.difference(this._drag.stage.start, delta);
22464
22465		if (!this.is('dragging')) {
22466			return;
22467		}
22468
22469		event.preventDefault();
22470
22471		if (this.settings.loop) {
22472			minimum = this.coordinates(this.minimum());
22473			maximum = this.coordinates(this.maximum() + 1) - minimum;
22474			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
22475		} else {
22476			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
22477			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
22478			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
22479			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
22480		}
22481
22482		this._drag.stage.current = stage;
22483
22484		this.animate(stage.x);
22485	};
22486
22487	/**
22488	 * Handles the `touchend` and `mouseup` events.
22489	 * @todo #261
22490	 * @todo Threshold for click event
22491	 * @protected
22492	 * @param {Event} event - The event arguments.
22493	 */
22494	Owl.prototype.onDragEnd = function(event) {
22495		var delta = this.difference(this._drag.pointer, this.pointer(event)),
22496			stage = this._drag.stage.current,
22497			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
22498
22499		$(document).off('.owl.core');
22500
22501		this.$element.removeClass(this.options.grabClass);
22502
22503		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
22504			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
22505			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
22506			this.invalidate('position');
22507			this.update();
22508
22509			this._drag.direction = direction;
22510
22511			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
22512				this._drag.target.one('click.owl.core', function() { return false; });
22513			}
22514		}
22515
22516		if (!this.is('dragging')) {
22517			return;
22518		}
22519
22520		this.leave('dragging');
22521		this.trigger('dragged');
22522	};
22523
22524	/**
22525	 * Gets absolute position of the closest item for a coordinate.
22526	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
22527	 * @protected
22528	 * @param {Number} coordinate - The coordinate in pixel.
22529	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
22530	 * @return {Number} - The absolute position of the closest item.
22531	 */
22532	Owl.prototype.closest = function(coordinate, direction) {
22533		var position = -1,
22534			pull = 30,
22535			width = this.width(),
22536			coordinates = this.coordinates();
22537
22538		if (!this.settings.freeDrag) {
22539			// check closest item
22540			$.each(coordinates, $.proxy(function(index, value) {
22541				if (coordinate > value - pull && coordinate < value + pull) {
22542					position = index;
22543				} else if (this.op(coordinate, '<', value)
22544					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
22545					position = direction === 'left' ? index + 1 : index;
22546				}
22547				return position === -1;
22548			}, this));
22549		}
22550
22551		if (!this.settings.loop) {
22552			// non loop boundries
22553			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
22554				position = coordinate = this.minimum();
22555			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
22556				position = coordinate = this.maximum();
22557			}
22558		}
22559
22560		return position;
22561	};
22562
22563	/**
22564	 * Animates the stage.
22565	 * @todo #270
22566	 * @public
22567	 * @param {Number} coordinate - The coordinate in pixels.
22568	 */
22569	Owl.prototype.animate = function(coordinate) {
22570		var animate = this.speed() > 0;
22571
22572		this.is('animating') && this.onTransitionEnd();
22573
22574		if (animate) {
22575			this.enter('animating');
22576			this.trigger('translate');
22577		}
22578
22579		if ($.support.transform3d && $.support.transition) {
22580			this.$stage.css({
22581				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
22582				transition: (this.speed() / 1000) + 's'
22583			});
22584		} else if (animate) {
22585			this.$stage.animate({
22586				left: coordinate + 'px'
22587			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
22588		} else {
22589			this.$stage.css({
22590				left: coordinate + 'px'
22591			});
22592		}
22593	};
22594
22595	/**
22596	 * Checks whether the carousel is in a specific state or not.
22597	 * @param {String} state - The state to check.
22598	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
22599	 */
22600	Owl.prototype.is = function(state) {
22601		return this._states.current[state] && this._states.current[state] > 0;
22602	};
22603
22604	/**
22605	 * Sets the absolute position of the current item.
22606	 * @public
22607	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
22608	 * @returns {Number} - The absolute position of the current item.
22609	 */
22610	Owl.prototype.current = function(position) {
22611		if (position === undefined) {
22612			return this._current;
22613		}
22614
22615		if (this._items.length === 0) {
22616			return undefined;
22617		}
22618
22619		position = this.normalize(position);
22620
22621		if (this._current !== position) {
22622			var event = this.trigger('change', { property: { name: 'position', value: position } });
22623
22624			if (event.data !== undefined) {
22625				position = this.normalize(event.data);
22626			}
22627
22628			this._current = position;
22629
22630			this.invalidate('position');
22631
22632			this.trigger('changed', { property: { name: 'position', value: this._current } });
22633		}
22634
22635		return this._current;
22636	};
22637
22638	/**
22639	 * Invalidates the given part of the update routine.
22640	 * @param {String} [part] - The part to invalidate.
22641	 * @returns {Array.<String>} - The invalidated parts.
22642	 */
22643	Owl.prototype.invalidate = function(part) {
22644		if ($.type(part) === 'string') {
22645			this._invalidated[part] = true;
22646			this.is('valid') && this.leave('valid');
22647		}
22648		return $.map(this._invalidated, function(v, i) { return i });
22649	};
22650
22651	/**
22652	 * Resets the absolute position of the current item.
22653	 * @public
22654	 * @param {Number} position - The absolute position of the new item.
22655	 */
22656	Owl.prototype.reset = function(position) {
22657		position = this.normalize(position);
22658
22659		if (position === undefined) {
22660			return;
22661		}
22662
22663		this._speed = 0;
22664		this._current = position;
22665
22666		this.suppress([ 'translate', 'translated' ]);
22667
22668		this.animate(this.coordinates(position));
22669
22670		this.release([ 'translate', 'translated' ]);
22671	};
22672
22673	/**
22674	 * Normalizes an absolute or a relative position of an item.
22675	 * @public
22676	 * @param {Number} position - The absolute or relative position to normalize.
22677	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
22678	 * @returns {Number} - The normalized position.
22679	 */
22680	Owl.prototype.normalize = function(position, relative) {
22681		var n = this._items.length,
22682			m = relative ? 0 : this._clones.length;
22683
22684		if (!$.isNumeric(position) || n < 1) {
22685			position = undefined;
22686		} else if (position < 0 || position >= n + m) {
22687			position = ((position - m / 2) % n + n) % n + m / 2;
22688		}
22689
22690		return position;
22691	};
22692
22693	/**
22694	 * Converts an absolute position of an item into a relative one.
22695	 * @public
22696	 * @param {Number} position - The absolute position to convert.
22697	 * @returns {Number} - The converted position.
22698	 */
22699	Owl.prototype.relative = function(position) {
22700		position -= this._clones.length / 2;
22701		return this.normalize(position, true);
22702	};
22703
22704	/**
22705	 * Gets the maximum position for the current item.
22706	 * @public
22707	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
22708	 * @returns {Number}
22709	 */
22710	Owl.prototype.maximum = function(relative) {
22711		var settings = this.settings,
22712			maximum = this._coordinates.length,
22713			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
22714			i = -1, j;
22715
22716		if (settings.loop) {
22717			maximum = this._clones.length / 2 + this._items.length - 1;
22718		} else if (settings.autoWidth || settings.merge) {
22719			// binary search
22720			while (maximum - i > 1) {
22721				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
22722					? i = j : maximum = j;
22723			}
22724		} else if (settings.center) {
22725			maximum = this._items.length - 1;
22726		} else {
22727			maximum = this._items.length - settings.items;
22728		}
22729
22730		if (relative) {
22731			maximum -= this._clones.length / 2;
22732		}
22733
22734		return Math.max(maximum, 0);
22735	};
22736
22737	/**
22738	 * Gets the minimum position for the current item.
22739	 * @public
22740	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
22741	 * @returns {Number}
22742	 */
22743	Owl.prototype.minimum = function(relative) {
22744		return relative ? 0 : this._clones.length / 2;
22745	};
22746
22747	/**
22748	 * Gets an item at the specified relative position.
22749	 * @public
22750	 * @param {Number} [position] - The relative position of the item.
22751	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
22752	 */
22753	Owl.prototype.items = function(position) {
22754		if (position === undefined) {
22755			return this._items.slice();
22756		}
22757
22758		position = this.normalize(position, true);
22759		return this._items[position];
22760	};
22761
22762	/**
22763	 * Gets an item at the specified relative position.
22764	 * @public
22765	 * @param {Number} [position] - The relative position of the item.
22766	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
22767	 */
22768	Owl.prototype.mergers = function(position) {
22769		if (position === undefined) {
22770			return this._mergers.slice();
22771		}
22772
22773		position = this.normalize(position, true);
22774		return this._mergers[position];
22775	};
22776
22777	/**
22778	 * Gets the absolute positions of clones for an item.
22779	 * @public
22780	 * @param {Number} [position] - The relative position of the item.
22781	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
22782	 */
22783	Owl.prototype.clones = function(position) {
22784		var odd = this._clones.length / 2,
22785			even = odd + this._items.length,
22786			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
22787
22788		if (position === undefined) {
22789			return $.map(this._clones, function(v, i) { return map(i) });
22790		}
22791
22792		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
22793	};
22794
22795	/**
22796	 * Sets the current animation speed.
22797	 * @public
22798	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
22799	 * @returns {Number} - The current animation speed in milliseconds.
22800	 */
22801	Owl.prototype.speed = function(speed) {
22802		if (speed !== undefined) {
22803			this._speed = speed;
22804		}
22805
22806		return this._speed;
22807	};
22808
22809	/**
22810	 * Gets the coordinate of an item.
22811	 * @todo The name of this method is missleanding.
22812	 * @public
22813	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
22814	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
22815	 */
22816	Owl.prototype.coordinates = function(position) {
22817		var coordinate = null;
22818
22819		if (position === undefined) {
22820			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
22821				return this.coordinates(index);
22822			}, this));
22823		}
22824
22825		if (this.settings.center) {
22826			coordinate = this._coordinates[position];
22827			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
22828		} else {
22829			coordinate = this._coordinates[position - 1] || 0;
22830		}
22831
22832		return coordinate;
22833	};
22834
22835	/**
22836	 * Calculates the speed for a translation.
22837	 * @protected
22838	 * @param {Number} from - The absolute position of the start item.
22839	 * @param {Number} to - The absolute position of the target item.
22840	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
22841	 * @returns {Number} - The time in milliseconds for the translation.
22842	 */
22843	Owl.prototype.duration = function(from, to, factor) {
22844		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
22845	};
22846
22847	/**
22848	 * Slides to the specified item.
22849	 * @public
22850	 * @param {Number} position - The position of the item.
22851	 * @param {Number} [speed] - The time in milliseconds for the transition.
22852	 */
22853	Owl.prototype.to = function(position, speed) {
22854		var current = this.current(),
22855			revert = null,
22856			distance = position - this.relative(current),
22857			direction = (distance > 0) - (distance < 0),
22858			items = this._items.length,
22859			minimum = this.minimum(),
22860			maximum = this.maximum();
22861
22862		if (this.settings.loop) {
22863			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
22864				distance += direction * -1 * items;
22865			}
22866
22867			position = current + distance;
22868			revert = ((position - minimum) % items + items) % items + minimum;
22869
22870			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
22871				current = revert - distance;
22872				position = revert;
22873				this.reset(current);
22874			}
22875		} else if (this.settings.rewind) {
22876			maximum += 1;
22877			position = (position % maximum + maximum) % maximum;
22878		} else {
22879			position = Math.max(minimum, Math.min(maximum, position));
22880		}
22881
22882		this.speed(this.duration(current, position, speed));
22883		this.current(position);
22884
22885		if (this.$element.is(':visible')) {
22886			this.update();
22887		}
22888	};
22889
22890	/**
22891	 * Slides to the next item.
22892	 * @public
22893	 * @param {Number}
vendor: 4,086 bytes, lines 22893-23029
22893 [speed] - The time in milliseconds for the transition.
22894	 */
22895	Owl.prototype.next = function(speed) {
22896		speed = speed || false;
22897		this.to(this.relative(this.current()) + 1, speed);
22898	};
22899
22900	/**
22901	 * Slides to the previous item.
22902	 * @public
22903	 * @param {Number} [speed] - The time in milliseconds for the transition.
22904	 */
22905	Owl.prototype.prev = function(speed) {
22906		speed = speed || false;
22907		this.to(this.relative(this.current()) - 1, speed);
22908	};
22909
22910	/**
22911	 * Handles the end of an animation.
22912	 * @protected
22913	 * @param {Event} event - The event arguments.
22914	 */
22915	Owl.prototype.onTransitionEnd = function(event) {
22916
22917		// if css2 animation then event object is undefined
22918		if (event !== undefined) {
22919			event.stopPropagation();
22920
22921			// Catch only owl-stage transitionEnd event
22922			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
22923				return false;
22924			}
22925		}
22926
22927		this.leave('animating');
22928		this.trigger('translated');
22929	};
22930
22931	/**
22932	 * Gets viewport width.
22933	 * @protected
22934	 * @return {Number} - The width in pixel.
22935	 */
22936	Owl.prototype.viewport = function() {
22937		var width;
22938		if (this.options.responsiveBaseElement !== window) {
22939			width = $(this.options.responsiveBaseElement).width();
22940		} else if (window.innerWidth) {
22941			width = window.innerWidth;
22942		} else if (document.documentElement && document.documentElement.clientWidth) {
22943			width = document.documentElement.clientWidth;
22944		} else {
22945			throw 'Can not detect viewport width.';
22946		}
22947
22948		return width;
22949	};
22950
22951	/**
22952	 * Replaces the current content.
22953	 * @public
22954	 * @param {HTMLElement|jQuery|String} content - The new content.
22955	 */
22956	Owl.prototype.replace = function(content) {
22957		this.$stage.empty();
22958		this._items = [];
22959
22960		if (content) {
22961			content = (content instanceof jQuery) ? content : $(content);
22962		}
22963
22964		if (this.settings.nestedItemSelector) {
22965			content = content.find('.' + this.settings.nestedItemSelector);
22966		}
22967
22968		content.filter(function() {
22969			return this.nodeType === 1;
22970		}).each($.proxy(function(index, item) {
22971			item = this.prepare(item, index);
22972			this.$stage.append(item);
22973			this._items.push(item);
22974			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
22975		}, this));
22976
22977		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
22978
22979		this.invalidate('items');
22980	};
22981
22982	/**
22983	 * Adds an item.
22984	 * @todo Use `item` instead of `content` for the event arguments.
22985	 * @public
22986	 * @param {HTMLElement|jQuery|String} content - The item content to add.
22987	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
22988	 */
22989	Owl.prototype.add = function(content, position) {
22990		var current = this.relative(this._current);
22991
22992		position = position === undefined ? this._items.length : this.normalize(position, true);
22993		content = content instanceof jQuery ? content : $(content);
22994
22995		this.trigger('add', { content: content, position: position });
22996
22997		content = this.prepare(content, this._items[current].index());
22998
22999		if (this._items.length === 0 || position === this._items.length) {
23000			this._items.length === 0 && this.$stage.append(content);
23001			this._items.length !== 0 && this._items[position - 1].after(content);
23002			this._items.push(content);
23003			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23004		} else {
23005			this._items[position].before(content);
23006			this._items.splice(position, 0, content);
23007			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23008		}
23009
23010		this._items[current] && this.reset(this._items[current].index());
23011
23012		this.invalidate('items');
23013
23014		this.trigger('added', { content: content, position: position });
23015	};
23016
23017	/**
23018	 * Removes an item by its position.
23019	 * @todo Use `item` instead of `content` for the event arguments.
23020	 * @public
23021	 * @param {Number} position - The relative position of the item to remove.
23022	 */
23023	Owl.prototype.remove = function(position) {
23024		position = this.normalize(position, true);
23025
23026		if (position === undefined) {
23027			return;
23028		}
23029
vendor: 40,414 bytes, lines 23030-24596
23030		this.trigger('remove', { content: this._items[position], position: position });
23031
23032		this._items[position].remove();
23033		this._items.splice(position, 1);
23034		this._mergers.splice(position, 1);
23035
23036		this.invalidate('items');
23037
23038		this.trigger('removed', { content: null, position: position });
23039	};
23040
23041	/**
23042	 * Preloads images with auto width.
23043	 * @todo Replace by a more generic approach
23044	 * @protected
23045	 */
23046	Owl.prototype.preloadAutoWidthImages = function(images) {
23047		images.each($.proxy(function(i, element) {
23048			this.enter('pre-loading');
23049			element = $(element);
23050			$(new Image()).one('load', $.proxy(function(e) {
23051				element.attr('src', e.target.src);
23052				element.css('opacity', 1);
23053				this.leave('pre-loading');
23054				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23055			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23056		}, this));
23057	};
23058
23059	/**
23060	 * Destroys the carousel.
23061	 * @public
23062	 */
23063	Owl.prototype.destroy = function() {
23064
23065		this.$element.off('.owl.core');
23066		this.$stage.off('.owl.core');
23067		$(document).off('.owl.core');
23068
23069		if (this.settings.responsive !== false) {
23070			window.clearTimeout(this.resizeTimer);
23071			this.off(window, 'resize', this._handlers.onThrottledResize);
23072		}
23073
23074		for (var i in this._plugins) {
23075			this._plugins[i].destroy();
23076		}
23077
23078		this.$stage.children('.cloned').remove();
23079
23080		this.$stage.unwrap();
23081		this.$stage.children().contents().unwrap();
23082		this.$stage.children().unwrap();
23083
23084		this.$element
23085			.removeClass(this.options.refreshClass)
23086			.removeClass(this.options.loadingClass)
23087			.removeClass(this.options.loadedClass)
23088			.removeClass(this.options.rtlClass)
23089			.removeClass(this.options.dragClass)
23090			.removeClass(this.options.grabClass)
23091			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
23092			.removeData('owl.carousel');
23093	};
23094
23095	/**
23096	 * Operators to calculate right-to-left and left-to-right.
23097	 * @protected
23098	 * @param {Number} [a] - The left side operand.
23099	 * @param {String} [o] - The operator.
23100	 * @param {Number} [b] - The right side operand.
23101	 */
23102	Owl.prototype.op = function(a, o, b) {
23103		var rtl = this.settings.rtl;
23104		switch (o) {
23105			case '<':
23106				return rtl ? a > b : a < b;
23107			case '>':
23108				return rtl ? a < b : a > b;
23109			case '>=':
23110				return rtl ? a <= b : a >= b;
23111			case '<=':
23112				return rtl ? a >= b : a <= b;
23113			default:
23114				break;
23115		}
23116	};
23117
23118	/**
23119	 * Attaches to an internal event.
23120	 * @protected
23121	 * @param {HTMLElement} element - The event source.
23122	 * @param {String} event - The event name.
23123	 * @param {Function} listener - The event handler to attach.
23124	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
23125	 */
23126	Owl.prototype.on = function(element, event, listener, capture) {
23127		if (element.addEventListener) {
23128			element.addEventListener(event, listener, capture);
23129		} else if (element.attachEvent) {
23130			element.attachEvent('on' + event, listener);
23131		}
23132	};
23133
23134	/**
23135	 * Detaches from an internal event.
23136	 * @protected
23137	 * @param {HTMLElement} element - The event source.
23138	 * @param {String} event - The event name.
23139	 * @param {Function} listener - The attached event handler to detach.
23140	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
23141	 */
23142	Owl.prototype.off = function(element, event, listener, capture) {
23143		if (element.removeEventListener) {
23144			element.removeEventListener(event, listener, capture);
23145		} else if (element.detachEvent) {
23146			element.detachEvent('on' + event, listener);
23147		}
23148	};
23149
23150	/**
23151	 * Triggers a public event.
23152	 * @todo Remove `status`, `relatedTarget` should be used instead.
23153	 * @protected
23154	 * @param {String} name - The event name.
23155	 * @param {*} [data=null] - The event data.
23156	 * @param {String} [namespace=carousel] - The event namespace.
23157	 * @param {String} [state] - The state which is associated with the event.
23158	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
23159	 * @returns {Event} - The event arguments.
23160	 */
23161	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
23162		var status = {
23163			item: { count: this._items.length, index: this.current() }
23164		}, handler = $.camelCase(
23165			$.grep([ 'on', name, namespace ], function(v) { return v })
23166				.join('-').toLowerCase()
23167		), event = $.Event(
23168			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
23169			$.extend({ relatedTarget: this }, status, data)
23170		);
23171
23172		if (!this._supress[name]) {
23173			$.each(this._plugins, function(name, plugin) {
23174				if (plugin.onTrigger) {
23175					plugin.onTrigger(event);
23176				}
23177			});
23178
23179			this.register({ type: Owl.Type.Event, name: name });
23180			this.$element.trigger(event);
23181
23182			if (this.settings && typeof this.settings[handler] === 'function') {
23183				this.settings[handler].call(this, event);
23184			}
23185		}
23186
23187		return event;
23188	};
23189
23190	/**
23191	 * Enters a state.
23192	 * @param name - The state name.
23193	 */
23194	Owl.prototype.enter = function(name) {
23195		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
23196			if (this._states.current[name] === undefined) {
23197				this._states.current[name] = 0;
23198			}
23199
23200			this._states.current[name]++;
23201		}, this));
23202	};
23203
23204	/**
23205	 * Leaves a state.
23206	 * @param name - The state name.
23207	 */
23208	Owl.prototype.leave = function(name) {
23209		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
23210			this._states.current[name]--;
23211		}, this));
23212	};
23213
23214	/**
23215	 * Registers an event or state.
23216	 * @public
23217	 * @param {Object} object - The event or state to register.
23218	 */
23219	Owl.prototype.register = function(object) {
23220		if (object.type === Owl.Type.Event) {
23221			if (!$.event.special[object.name]) {
23222				$.event.special[object.name] = {};
23223			}
23224
23225			if (!$.event.special[object.name].owl) {
23226				var _default = $.event.special[object.name]._default;
23227				$.event.special[object.name]._default = function(e) {
23228					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
23229						return _default.apply(this, arguments);
23230					}
23231					return e.namespace && e.namespace.indexOf('owl') > -1;
23232				};
23233				$.event.special[object.name].owl = true;
23234			}
23235		} else if (object.type === Owl.Type.State) {
23236			if (!this._states.tags[object.name]) {
23237				this._states.tags[object.name] = object.tags;
23238			} else {
23239				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
23240			}
23241
23242			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
23243				return $.inArray(tag, this._states.tags[object.name]) === i;
23244			}, this));
23245		}
23246	};
23247
23248	/**
23249	 * Suppresses events.
23250	 * @protected
23251	 * @param {Array.<String>} events - The events to suppress.
23252	 */
23253	Owl.prototype.suppress = function(events) {
23254		$.each(events, $.proxy(function(index, event) {
23255			this._supress[event] = true;
23256		}, this));
23257	};
23258
23259	/**
23260	 * Releases suppressed events.
23261	 * @protected
23262	 * @param {Array.<String>} events - The events to release.
23263	 */
23264	Owl.prototype.release = function(events) {
23265		$.each(events, $.proxy(function(index, event) {
23266			delete this._supress[event];
23267		}, this));
23268	};
23269
23270	/**
23271	 * Gets unified pointer coordinates from event.
23272	 * @todo #261
23273	 * @protected
23274	 * @param {Event} - The `mousedown` or `touchstart` event.
23275	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
23276	 */
23277	Owl.prototype.pointer = function(event) {
23278		var result = { x: null, y: null };
23279
23280		event = event.originalEvent || event || window.event;
23281
23282		event = event.touches && event.touches.length ?
23283			event.touches[0] : event.changedTouches && event.changedTouches.length ?
23284				event.changedTouches[0] : event;
23285
23286		if (event.pageX) {
23287			result.x = event.pageX;
23288			result.y = event.pageY;
23289		} else {
23290			result.x = event.clientX;
23291			result.y = event.clientY;
23292		}
23293
23294		return result;
23295	};
23296
23297	/**
23298	 * Gets the difference of two vectors.
23299	 * @todo #261
23300	 * @protected
23301	 * @param {Object} - The first vector.
23302	 * @param {Object} - The second vector.
23303	 * @returns {Object} - The difference.
23304	 */
23305	Owl.prototype.difference = function(first, second) {
23306		return {
23307			x: first.x - second.x,
23308			y: first.y - second.y
23309		};
23310	};
23311
23312	/**
23313	 * The jQuery Plugin for the Owl Carousel
23314	 * @todo Navigation plugin `next` and `prev`
23315	 * @public
23316	 */
23317	$.fn.owlCarousel = function(option) {
23318		var args = Array.prototype.slice.call(arguments, 1);
23319
23320		return this.each(function() {
23321			var $this = $(this),
23322				data = $this.data('owl.carousel');
23323
23324			if (!data) {
23325				data = new Owl(this, typeof option == 'object' && option);
23326				$this.data('owl.carousel', data);
23327
23328				$.each([
23329					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
23330				], function(i, event) {
23331					data.register({ type: Owl.Type.Event, name: event });
23332					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
23333						if (e.namespace && e.relatedTarget !== this) {
23334							this.suppress([ event ]);
23335							data[event].apply(this, [].slice.call(arguments, 1));
23336							this.release([ event ]);
23337						}
23338					}, data));
23339				});
23340			}
23341
23342			if (typeof option == 'string' && option.charAt(0) !== '_') {
23343				data[option].apply(data, args);
23344			}
23345		});
23346	};
23347
23348	/**
23349	 * The constructor for the jQuery Plugin
23350	 * @public
23351	 */
23352	$.fn.owlCarousel.Constructor = Owl;
23353
23354})(window.Zepto || window.jQuery, window, document);
23355
23356/**
23357 * AutoRefresh Plugin
23358 * @version 2.0.0-beta.3
23359 * @author Artus Kolanowski
23360 * @license The MIT License (MIT)
23361 */
23362;(function($, window, document, undefined) {
23363
23364	/**
23365	 * Creates the auto refresh plugin.
23366	 * @class The Auto Refresh Plugin
23367	 * @param {Owl} carousel - The Owl Carousel
23368	 */
23369	var AutoRefresh = function(carousel) {
23370		/**
23371		 * Reference to the core.
23372		 * @protected
23373		 * @type {Owl}
23374		 */
23375		this._core = carousel;
23376
23377		/**
23378		 * Refresh interval.
23379		 * @protected
23380		 * @type {number}
23381		 */
23382		this._interval = null;
23383
23384		/**
23385		 * Whether the element is currently visible or not.
23386		 * @protected
23387		 * @type {Boolean}
23388		 */
23389		this._visible = null;
23390
23391		/**
23392		 * All event handlers.
23393		 * @protected
23394		 * @type {Object}
23395		 */
23396		this._handlers = {
23397			'initialized.owl.carousel': $.proxy(function(e) {
23398				if (e.namespace && this._core.settings.autoRefresh) {
23399					this.watch();
23400				}
23401			}, this)
23402		};
23403
23404		// set default options
23405		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
23406
23407		// register event handlers
23408		this._core.$element.on(this._handlers);
23409	};
23410
23411	/**
23412	 * Default options.
23413	 * @public
23414	 */
23415	AutoRefresh.Defaults = {
23416		autoRefresh: true,
23417		autoRefreshInterval: 500
23418	};
23419
23420	/**
23421	 * Watches the element.
23422	 */
23423	AutoRefresh.prototype.watch = function() {
23424		if (this._interval) {
23425			return;
23426		}
23427
23428		this._visible = this._core.$element.is(':visible');
23429		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
23430	};
23431
23432	/**
23433	 * Refreshes the element.
23434	 */
23435	AutoRefresh.prototype.refresh = function() {
23436		if (this._core.$element.is(':visible') === this._visible) {
23437			return;
23438		}
23439
23440		this._visible = !this._visible;
23441
23442		this._core.$element.toggleClass('owl-hidden', !this._visible);
23443
23444		this._visible && (this._core.invalidate('width') && this._core.refresh());
23445	};
23446
23447	/**
23448	 * Destroys the plugin.
23449	 */
23450	AutoRefresh.prototype.destroy = function() {
23451		var handler, property;
23452
23453		window.clearInterval(this._interval);
23454
23455		for (handler in this._handlers) {
23456			this._core.$element.off(handler, this._handlers[handler]);
23457		}
23458		for (property in Object.getOwnPropertyNames(this)) {
23459			typeof this[property] != 'function' && (this[property] = null);
23460		}
23461	};
23462
23463	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
23464
23465})(window.Zepto || window.jQuery, window, document);
23466
23467/**
23468 * Lazy Plugin
23469 * @version 2.0.0-beta.3
23470 * @author Bartosz Wojciechowski
23471 * @license The MIT License (MIT)
23472 */
23473;(function($, window, document, undefined) {
23474
23475	/**
23476	 * Creates the lazy plugin.
23477	 * @class The Lazy Plugin
23478	 * @param {Owl} carousel - The Owl Carousel
23479	 */
23480	var Lazy = function(carousel) {
23481
23482		/**
23483		 * Reference to the core.
23484		 * @protected
23485		 * @type {Owl}
23486		 */
23487		this._core = carousel;
23488
23489		/**
23490		 * Already loaded items.
23491		 * @protected
23492		 * @type {Array.<jQuery>}
23493		 */
23494		this._loaded = [];
23495
23496		/**
23497		 * Event handlers.
23498		 * @protected
23499		 * @type {Object}
23500		 */
23501		this._handlers = {
23502			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
23503				if (!e.namespace) {
23504					return;
23505				}
23506
23507				if (!this._core.settings || !this._core.settings.lazyLoad) {
23508					return;
23509				}
23510
23511				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
23512					var settings = this._core.settings,
23513						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
23514						i = ((settings.center && n * -1) || 0),
23515						position = ((e.property && e.property.value) || this._core.current()) + i,
23516						clones = this._core.clones().length,
23517						load = $.proxy(function(i, v) { this.load(v) }, this);
23518
23519					while (i++ < n) {
23520						this.load(clones / 2 + this._core.relative(position));
23521						clones && $.each(this._core.clones(this._core.relative(position)), load);
23522						position++;
23523					}
23524				}
23525			}, this)
23526		};
23527
23528		// set the default options
23529		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
23530
23531		// register event handler
23532		this._core.$element.on(this._handlers);
23533	}
23534
23535	/**
23536	 * Default options.
23537	 * @public
23538	 */
23539	Lazy.Defaults = {
23540		lazyLoad: false
23541	}
23542
23543	/**
23544	 * Loads all resources of an item at the specified position.
23545	 * @param {Number} position - The absolute position of the item.
23546	 * @protected
23547	 */
23548	Lazy.prototype.load = function(position) {
23549		var $item = this._core.$stage.children().eq(position),
23550			$elements = $item && $item.find('.owl-lazy');
23551
23552		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
23553			return;
23554		}
23555
23556		$elements.each($.proxy(function(index, element) {
23557			var $element = $(element), image,
23558				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
23559
23560			this._core.trigger('load', { element: $element, url: url }, 'lazy');
23561
23562			if ($element.is('img')) {
23563				$element.one('load.owl.lazy', $.proxy(function() {
23564					$element.css('opacity', 1);
23565					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
23566				}, this)).attr('src', url);
23567			} else {
23568				image = new Image();
23569				image.onload = $.proxy(function() {
23570					$element.css({
23571						'background-image': 'url(' + url + ')',
23572						'opacity': '1'
23573					});
23574					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
23575				}, this);
23576				image.src = url;
23577			}
23578		}, this));
23579
23580		this._loaded.push($item.get(0));
23581	}
23582
23583	/**
23584	 * Destroys the plugin.
23585	 * @public
23586	 */
23587	Lazy.prototype.destroy = function() {
23588		var handler, property;
23589
23590		for (handler in this.handlers) {
23591			this._core.$element.off(handler, this.handlers[handler]);
23592		}
23593		for (property in Object.getOwnPropertyNames(this)) {
23594			typeof this[property] != 'function' && (this[property] = null);
23595		}
23596	};
23597
23598	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
23599
23600})(window.Zepto || window.jQuery, window, document);
23601
23602/**
23603 * AutoHeight Plugin
23604 * @version 2.0.0-beta.3
23605 * @author Bartosz Wojciechowski
23606 * @license The MIT License (MIT)
23607 */
23608;(function($, window, document, undefined) {
23609
23610	/**
23611	 * Creates the auto height plugin.
23612	 * @class The Auto Height Plugin
23613	 * @param {Owl} carousel - The Owl Carousel
23614	 */
23615	var AutoHeight = function(carousel) {
23616		/**
23617		 * Reference to the core.
23618		 * @protected
23619		 * @type {Owl}
23620		 */
23621		this._core = carousel;
23622
23623		/**
23624		 * All event handlers.
23625		 * @protected
23626		 * @type {Object}
23627		 */
23628		this._handlers = {
23629			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
23630				if (e.namespace && this._core.settings.autoHeight) {
23631					this.update();
23632				}
23633			}, this),
23634			'changed.owl.carousel': $.proxy(function(e) {
23635				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
23636					this.update();
23637				}
23638			}, this),
23639			'loaded.owl.lazy': $.proxy(function(e) {
23640				if (e.namespace && this._core.settings.autoHeight
23641					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
23642					this.update();
23643				}
23644			}, this)
23645		};
23646
23647		// set default options
23648		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
23649
23650		// register event handlers
23651		this._core.$element.on(this._handlers);
23652	};
23653
23654	/**
23655	 * Default options.
23656	 * @public
23657	 */
23658	AutoHeight.Defaults = {
23659		autoHeight: false,
23660		autoHeightClass: 'owl-height'
23661	};
23662
23663	/**
23664	 * Updates the view.
23665	 */
23666	AutoHeight.prototype.update = function() {
23667		var start = this._core._current,
23668			end = start + this._core.settings.items,
23669			visible = this._core.$stage.children().toArray().slice(start, end);
23670			heights = [],
23671			maxheight = 0;
23672
23673		$.each(visible, function(index, item) {
23674			heights.push($(item).height());
23675		});
23676
23677		maxheight = Math.max.apply(null, heights);
23678
23679		this._core.$stage.parent()
23680			.height(maxheight)
23681			.addClass(this._core.settings.autoHeightClass);
23682	};
23683
23684	AutoHeight.prototype.destroy = function() {
23685		var handler, property;
23686
23687		for (handler in this._handlers) {
23688			this._core.$element.off(handler, this._handlers[handler]);
23689		}
23690		for (property in Object.getOwnPropertyNames(this)) {
23691			typeof this[property] != 'function' && (this[property] = null);
23692		}
23693	};
23694
23695	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
23696
23697})(window.Zepto || window.jQuery, window, document);
23698
23699/**
23700 * Video Plugin
23701 * @version 2.0.0-beta.3
23702 * @author Bartosz Wojciechowski
23703 * @license The MIT License (MIT)
23704 */
23705;(function($, window, document, undefined) {
23706
23707	/**
23708	 * Creates the video plugin.
23709	 * @class The Video Plugin
23710	 * @param {Owl} carousel - The Owl Carousel
23711	 */
23712	var Video = function(carousel) {
23713		/**
23714		 * Reference to the core.
23715		 * @protected
23716		 * @type {Owl}
23717		 */
23718		this._core = carousel;
23719
23720		/**
23721		 * Cache all video URLs.
23722		 * @protected
23723		 * @type {Object}
23724		 */
23725		this._videos = {};
23726
23727		/**
23728		 * Current playing item.
23729		 * @protected
23730		 * @type {jQuery}
23731		 */
23732		this._playing = null;
23733
23734		/**
23735		 * All event handlers.
23736		 * @todo The cloned content removale is too late
23737		 * @protected
23738		 * @type {Object}
23739		 */
23740		this._handlers = {
23741			'initialized.owl.carousel': $.proxy(function(e) {
23742				if (e.namespace) {
23743					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
23744				}
23745			}, this),
23746			'resize.owl.carousel': $.proxy(function(e) {
23747				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
23748					e.preventDefault();
23749				}
23750			}, this),
23751			'refreshed.owl.carousel': $.proxy(function(e) {
23752				if (e.namespace && this._core.is('resizing')) {
23753					this._core.$stage.find('.cloned .owl-video-frame').remove();
23754				}
23755			}, this),
23756			'changed.owl.carousel': $.proxy(function(e) {
23757				if (e.namespace && e.property.name === 'position' && this._playing) {
23758					this.stop();
23759				}
23760			}, this),
23761			'prepared.owl.carousel': $.proxy(function(e) {
23762				if (!e.namespace) {
23763					return;
23764				}
23765
23766				var $element = $(e.content).find('.owl-video');
23767
23768				if ($element.length) {
23769					$element.css('display', 'none');
23770					this.fetch($element, $(e.content));
23771				}
23772			}, this)
23773		};
23774
23775		// set default options
23776		this._core.options = $.extend({}, Video.Defaults, this._core.options);
23777
23778		// register event handlers
23779		this._core.$element.on(this._handlers);
23780
23781		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
23782			this.play(e);
23783		}, this));
23784	};
23785
23786	/**
23787	 * Default options.
23788	 * @public
23789	 */
23790	Video.Defaults = {
23791		video: false,
23792		videoHeight: false,
23793		videoWidth: false
23794	};
23795
23796	/**
23797	 * Gets the video ID and the type (YouTube/Vimeo only).
23798	 * @protected
23799	 * @param {jQuery} target - The target containing the video data.
23800	 * @param {jQuery} item - The item containing the video.
23801	 */
23802	Video.prototype.fetch = function(target, item) {
23803		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
23804			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
23805			width = target.attr('data-width') || this._core.settings.videoWidth,
23806			height = target.attr('data-height') || this._core.settings.videoHeight,
23807			url = target.attr('href');
23808
23809		if (url) {
23810			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+)?/);
23811
23812			if (id[3].indexOf('youtu') > -1) {
23813				type = 'youtube';
23814			} else if (id[3].indexOf('vimeo') > -1) {
23815				type = 'vimeo';
23816			} else {
23817				throw new Error('Video URL not supported.');
23818			}
23819			id = id[6];
23820		} else {
23821			throw new Error('Missing video URL.');
23822		}
23823
23824		this._videos[url] = {
23825			type: type,
23826			id: id,
23827			width: width,
23828			height: height
23829		};
23830
23831		item.attr('data-video', url);
23832
23833		this.thumbnail(target, this._videos[url]);
23834	};
23835
23836	/**
23837	 * Creates video thumbnail.
23838	 * @protected
23839	 * @param {jQuery} target - The target containing the video data.
23840	 * @param {Object} info - The video info object.
23841	 * @see `fetch`
23842	 */
23843	Video.prototype.thumbnail = function(target, video) {
23844		var tnLink,
23845			icon,
23846			path,
23847			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
23848			customTn = target.find('img'),
23849			srcType = 'src',
23850			lazyClass = '',
23851			settings = this._core.settings,
23852			create = function(path) {
23853				icon = '<div class="owl-video-play-icon"></div>';
23854
23855				if (settings.lazyLoad) {
23856					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
23857				} else {
23858					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
23859				}
23860				target.after(tnLink);
23861				target.after(icon);
23862			};
23863
23864		// wrap video content into owl-video-wrapper div
23865		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
23866
23867		if (this._core.settings.lazyLoad) {
23868			srcType = 'data-src';
23869			lazyClass = 'owl-lazy';
23870		}
23871
23872		// custom thumbnail
23873		if (customTn.length) {
23874			create(customTn.attr(srcType));
23875			customTn.remove();
23876			return false;
23877		}
23878
23879		if (video.type === 'youtube') {
23880			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
23881			create(path);
23882		} else if (video.type === 'vimeo') {
23883			$.ajax({
23884				type: 'GET',
23885				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
23886				jsonp: 'callback',
23887				dataType: 'jsonp',
23888				success: function(data) {
23889					path = data[0].thumbnail_large;
23890					create(path);
23891				}
23892			});
23893		}
23894	};
23895
23896	/**
23897	 * Stops the current video.
23898	 * @public
23899	 */
23900	Video.prototype.stop = function() {
23901		this._core.trigger('stop', null, 'video');
23902		this._playing.find('.owl-video-frame').remove();
23903		this._playing.removeClass('owl-video-playing');
23904		this._playing = null;
23905		this._core.leave('playing');
23906		this._core.trigger('stopped', null, 'video');
23907	};
23908
23909	/**
23910	 * Starts the current video.
23911	 * @public
23912	 * @param {Event} event - The event arguments.
23913	 */
23914	Video.prototype.play = function(event) {
23915		var target = $(event.target),
23916			item = target.closest('.' + this._core.settings.itemClass),
23917			video = this._videos[item.attr('data-video')],
23918			width = video.width || '100%',
23919			height = video.height || this._core.$stage.height(),
23920			html;
23921
23922		if (this._playing) {
23923			return;
23924		}
23925
23926		this._core.enter('playing');
23927		this._core.trigger('play', null, 'video');
23928
23929		item = this._core.items(this._core.relative(item.index()));
23930
23931		this._core.reset(item.index());
23932
23933		if (video.type === 'youtube') {
23934			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
23935				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
23936		} else if (video.type === 'vimeo') {
23937			html = '<iframe src="//player.vimeo.com/video/' + video.id +
23938				'?autoplay=1" width="' + width + '" height="' + height +
23939				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
23940		}
23941
23942		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
23943
23944		this._playing = item.addClass('owl-video-playing');
23945	};
23946
23947	/**
23948	 * Checks whether an video is currently in full screen mode or not.
23949	 * @todo Bad style because looks like a readonly method but changes members.
23950	 * @protected
23951	 * @returns {Boolean}
23952	 */
23953	Video.prototype.isInFullScreen = function() {
23954		var element = document.fullscreenElement || document.mozFullScreenElement ||
23955				document.webkitFullscreenElement;
23956
23957		return element && $(element).parent().hasClass('owl-video-frame');
23958	};
23959
23960	/**
23961	 * Destroys the plugin.
23962	 */
23963	Video.prototype.destroy = function() {
23964		var handler, property;
23965
23966		this._core.$element.off('click.owl.video');
23967
23968		for (handler in this._handlers) {
23969			this._core.$element.off(handler, this._handlers[handler]);
23970		}
23971		for (property in Object.getOwnPropertyNames(this)) {
23972			typeof this[property] != 'function' && (this[property] = null);
23973		}
23974	};
23975
23976	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
23977
23978})(window.Zepto || window.jQuery, window, document);
23979
23980/**
23981 * Animate Plugin
23982 * @version 2.0.0-beta.3
23983 * @author Bartosz Wojciechowski
23984 * @license The MIT License (MIT)
23985 */
23986;(function($, window, document, undefined) {
23987
23988	/**
23989	 * Creates the animate plugin.
23990	 * @class The Navigation Plugin
23991	 * @param {Owl} scope - The Owl Carousel
23992	 */
23993	var Animate = function(scope) {
23994		this.core = scope;
23995		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
23996		this.swapping = true;
23997		this.previous = undefined;
23998		this.next = undefined;
23999
24000		this.handlers = {
24001			'change.owl.carousel': $.proxy(function(e) {
24002				if (e.namespace && e.property.name == 'position') {
24003					this.previous = this.core.current();
24004					this.next = e.property.value;
24005				}
24006			}, this),
24007			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24008				if (e.namespace) {
24009					this.swapping = e.type == 'translated';
24010				}
24011			}, this),
24012			'translate.owl.carousel': $.proxy(function(e) {
24013				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24014					this.swap();
24015				}
24016			}, this)
24017		};
24018
24019		this.core.$element.on(this.handlers);
24020	};
24021
24022	/**
24023	 * Default options.
24024	 * @public
24025	 */
24026	Animate.Defaults = {
24027		animateOut: false,
24028		animateIn: false
24029	};
24030
24031	/**
24032	 * Toggles the animation classes whenever an translations starts.
24033	 * @protected
24034	 * @returns {Boolean|undefined}
24035	 */
24036	Animate.prototype.swap = function() {
24037
24038		if (this.core.settings.items !== 1) {
24039			return;
24040		}
24041
24042		if (!$.support.animation || !$.support.transition) {
24043			return;
24044		}
24045
24046		this.core.speed(0);
24047
24048		var left,
24049			clear = $.proxy(this.clear, this),
24050			previous = this.core.$stage.children().eq(this.previous),
24051			next = this.core.$stage.children().eq(this.next),
24052			incoming = this.core.settings.animateIn,
24053			outgoing = this.core.settings.animateOut;
24054
24055		if (this.core.current() === this.previous) {
24056			return;
24057		}
24058
24059		if (outgoing) {
24060			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24061			previous.css( { 'left': left + 'px' } )
24062				.addClass('animated owl-animated-out')
24063				.addClass(outgoing)
24064				.on($.support.animation.end, clear);
24065		}
24066
24067		if (incoming) {
24068			next.addClass('animated owl-animated-in')
24069				.addClass(incoming)
24070				.on($.support.animation.end, clear);
24071		}
24072	};
24073
24074	Animate.prototype.clear = function(e) {
24075		if ($(e.target).hasClass('animated')) {
24076			$(e.target).css( { 'left': '' } )
24077				.removeClass('animated owl-animated-out owl-animated-in')
24078				.removeClass(this.core.settings.animateIn)
24079				.removeClass(this.core.settings.animateOut);
24080			this.core.onTransitionEnd();
24081		}
24082	};
24083
24084	/**
24085	 * Destroys the plugin.
24086	 * @public
24087	 */
24088	Animate.prototype.destroy = function() {
24089		var handler, property;
24090
24091		for (handler in this.handlers) {
24092			this.core.$element.off(handler, this.handlers[handler]);
24093		}
24094		for (property in Object.getOwnPropertyNames(this)) {
24095			typeof this[property] != 'function' && (this[property] = null);
24096		}
24097	};
24098
24099	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
24100
24101})(window.Zepto || window.jQuery, window, document);
24102
24103/**
24104 * Autoplay Plugin
24105 * @version 2.0.0-beta.3
24106 * @author Bartosz Wojciechowski
24107 * @author Artus Kolanowski
24108 * @license The MIT License (MIT)
24109 */
24110;(function($, window, document, undefined) {
24111
24112	/**
24113	 * Creates the autoplay plugin.
24114	 * @class The Autoplay Plugin
24115	 * @param {Owl} scope - The Owl Carousel
24116	 */
24117	var Autoplay = function(carousel) {
24118		/**
24119		 * Reference to the core.
24120		 * @protected
24121		 * @type {Owl}
24122		 */
24123		this._core = carousel;
24124
24125		/**
24126		 * The autoplay interval.
24127		 * @type {Number}
24128		 */
24129		this._interval = null;
24130
24131		/**
24132		 * Indicates whenever the autoplay is paused.
24133		 * @type {Boolean}
24134		 */
24135		this._paused = false;
24136
24137		/**
24138		 * All event handlers.
24139		 * @protected
24140		 * @type {Object}
24141		 */
24142		this._handlers = {
24143			'changed.owl.carousel': $.proxy(function(e) {
24144				if (e.namespace && e.property.name === 'settings') {
24145					if (this._core.settings.autoplay) {
24146						this.play();
24147					} else {
24148						this.stop();
24149					}
24150				}
24151			}, this),
24152			'initialized.owl.carousel': $.proxy(function(e) {
24153				if (e.namespace && this._core.settings.autoplay) {
24154					this.play();
24155				}
24156			}, this),
24157			'play.owl.autoplay': $.proxy(function(e, t, s) {
24158				if (e.namespace) {
24159					this.play(t, s);
24160				}
24161			}, this),
24162			'stop.owl.autoplay': $.proxy(function(e) {
24163				if (e.namespace) {
24164					this.stop();
24165				}
24166			}, this),
24167			'mouseover.owl.autoplay': $.proxy(function() {
24168				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
24169					this.pause();
24170				}
24171			}, this),
24172			'mouseleave.owl.autoplay': $.proxy(function() {
24173				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
24174					this.play();
24175				}
24176			}, this)
24177		};
24178
24179		// register event handlers
24180		this._core.$element.on(this._handlers);
24181
24182		// set default options
24183		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
24184	};
24185
24186	/**
24187	 * Default options.
24188	 * @public
24189	 */
24190	Autoplay.Defaults = {
24191		autoplay: false,
24192		autoplayTimeout: 5000,
24193		autoplayHoverPause: false,
24194		autoplaySpeed: false
24195	};
24196
24197	/**
24198	 * Starts the autoplay.
24199	 * @public
24200	 * @param {Number} [timeout] - The interval before the next animation starts.
24201	 * @param {Number} [speed] - The animation speed for the animations.
24202	 */
24203	Autoplay.prototype.play = function(timeout, speed) {
24204		this._paused = false;
24205
24206		if (this._core.is('rotating')) {
24207			return;
24208		}
24209
24210		this._core.enter('rotating');
24211
24212		this._interval = window.setInterval($.proxy(function() {
24213			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
24214				return;
24215			}
24216			this._core.next(speed || this._core.settings.autoplaySpeed);
24217		}, this), timeout || this._core.settings.autoplayTimeout);
24218	};
24219
24220	/**
24221	 * Stops the autoplay.
24222	 * @public
24223	 */
24224	Autoplay.prototype.stop = function() {
24225		if (!this._core.is('rotating')) {
24226			return;
24227		}
24228
24229		window.clearInterval(this._interval);
24230		this._core.leave('rotating');
24231	};
24232
24233	/**
24234	 * Stops the autoplay.
24235	 * @public
24236	 */
24237	Autoplay.prototype.pause = function() {
24238		if (!this._core.is('rotating')) {
24239			return;
24240		}
24241
24242		this._paused = true;
24243	};
24244
24245	/**
24246	 * Destroys the plugin.
24247	 */
24248	Autoplay.prototype.destroy = function() {
24249		var handler, property;
24250
24251		this.stop();
24252
24253		for (handler in this._handlers) {
24254			this._core.$element.off(handler, this._handlers[handler]);
24255		}
24256		for (property in Object.getOwnPropertyNames(this)) {
24257			typeof this[property] != 'function' && (this[property] = null);
24258		}
24259	};
24260
24261	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
24262
24263})(window.Zepto || window.jQuery, window, document);
24264
24265/**
24266 * Navigation Plugin
24267 * @version 2.0.0-beta.3
24268 * @author Artus Kolanowski
24269 * @license The MIT License (MIT)
24270 */
24271;(function($, window, document, undefined) {
24272	'use strict';
24273
24274	/**
24275	 * Creates the navigation plugin.
24276	 * @class The Navigation Plugin
24277	 * @param {Owl} carousel - The Owl Carousel.
24278	 */
24279	var Navigation = function(carousel) {
24280		/**
24281		 * Reference to the core.
24282		 * @protected
24283		 * @type {Owl}
24284		 */
24285		this._core = carousel;
24286
24287		/**
24288		 * Indicates whether the plugin is initialized or not.
24289		 * @protected
24290		 * @type {Boolean}
24291		 */
24292		this._initialized = false;
24293
24294		/**
24295		 * The current paging indexes.
24296		 * @protected
24297		 * @type {Array}
24298		 */
24299		this._pages = [];
24300
24301		/**
24302		 * All DOM elements of the user interface.
24303		 * @protected
24304		 * @type {Object}
24305		 */
24306		this._controls = {};
24307
24308		/**
24309		 * Markup for an indicator.
24310		 * @protected
24311		 * @type {Array.<String>}
24312		 */
24313		this._templates = [];
24314
24315		/**
24316		 * The carousel element.
24317		 * @type {jQuery}
24318		 */
24319		this.$element = this._core.$element;
24320
24321		/**
24322		 * Overridden methods of the carousel.
24323		 * @protected
24324		 * @type {Object}
24325		 */
24326		this._overrides = {
24327			next: this._core.next,
24328			prev: this._core.prev,
24329			to: this._core.to
24330		};
24331
24332		/**
24333		 * All event handlers.
24334		 * @protected
24335		 * @type {Object}
24336		 */
24337		this._handlers = {
24338			'prepared.owl.carousel': $.proxy(function(e) {
24339				if (e.namespace && this._core.settings.dotsData) {
24340					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
24341						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
24342				}
24343			}, this),
24344			'added.owl.carousel': $.proxy(function(e) {
24345				if (e.namespace && this._core.settings.dotsData) {
24346					this._templates.splice(e.position, 0, this._templates.pop());
24347				}
24348			}, this),
24349			'remove.owl.carousel': $.proxy(function(e) {
24350				if (e.namespace && this._core.settings.dotsData) {
24351					this._templates.splice(e.position, 1);
24352				}
24353			}, this),
24354			'changed.owl.carousel': $.proxy(function(e) {
24355				if (e.namespace && e.property.name == 'position') {
24356					this.draw();
24357				}
24358			}, this),
24359			'initialized.owl.carousel': $.proxy(function(e) {
24360				if (e.namespace && !this._initialized) {
24361					this._core.trigger('initialize', null, 'navigation');
24362					this.initialize();
24363					this.update();
24364					this.draw();
24365					this._initialized = true;
24366					this._core.trigger('initialized', null, 'navigation');
24367				}
24368			}, this),
24369			'refreshed.owl.carousel': $.proxy(function(e) {
24370				if (e.namespace && this._initialized) {
24371					this._core.trigger('refresh', null, 'navigation');
24372					this.update();
24373					this.draw();
24374					this._core.trigger('refreshed', null, 'navigation');
24375				}
24376			}, this)
24377		};
24378
24379		// set default options
24380		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
24381
24382		// register event handlers
24383		this.$element.on(this._handlers);
24384	};
24385
24386	/**
24387	 * Default options.
24388	 * @public
24389	 * @todo Rename `slideBy` to `navBy`
24390	 */
24391	Navigation.Defaults = {
24392		nav: false,
24393		navText: [ 'prev', 'next' ],
24394		navSpeed: false,
24395		navElement: 'div',
24396		navContainer: false,
24397		navContainerClass: 'owl-nav',
24398		navClass: [ 'owl-prev', 'owl-next' ],
24399		slideBy: 1,
24400		dotClass: 'owl-dot',
24401		dotsClass: 'owl-dots',
24402		dots: true,
24403		dotsEach: false,
24404		dotsData: false,
24405		dotsSpeed: false,
24406		dotsContainer: false
24407	};
24408
24409	/**
24410	 * Initializes the layout of the plugin and extends the carousel.
24411	 * @protected
24412	 */
24413	Navigation.prototype.initialize = function() {
24414		var override,
24415			settings = this._core.settings;
24416
24417		// create DOM structure for relative navigation
24418		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
24419			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
24420
24421		this._controls.$previous = $('<' + settings.navElement + '>')
24422			.addClass(settings.navClass[0])
24423			.html(settings.navText[0])
24424			.prependTo(this._controls.$relative)
24425			.on('click', $.proxy(function(e) {
24426				this.prev(settings.navSpeed);
24427			}, this));
24428		this._controls.$next = $('<' + settings.navElement + '>')
24429			.addClass(settings.navClass[1])
24430			.html(settings.navText[1])
24431			.appendTo(this._controls.$relative)
24432			.on('click', $.proxy(function(e) {
24433				this.next(settings.navSpeed);
24434			}, this));
24435
24436		// create DOM structure for absolute navigation
24437		if (!settings.dotsData) {
24438			this._templates = [ $('<div>')
24439				.addClass(settings.dotClass)
24440				.append($('<span>'))
24441				.prop('outerHTML') ];
24442		}
24443
24444		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
24445			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
24446
24447		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
24448			var index = $(e.target).parent().is(this._controls.$absolute)
24449				? $(e.target).index() : $(e.target).parent().index();
24450
24451			e.preventDefault();
24452
24453			this.to(index, settings.dotsSpeed);
24454		}, this));
24455
24456		// override public methods of the carousel
24457		for (override in this._overrides) {
24458			this._core[override] = $.proxy(this[override], this);
24459		}
24460	};
24461
24462	/**
24463	 * Destroys the plugin.
24464	 * @protected
24465	 */
24466	Navigation.prototype.destroy = function() {
24467		var handler, control, property, override;
24468
24469		for (handler in this._handlers) {
24470			this.$element.off(handler, this._handlers[handler]);
24471		}
24472		for (control in this._controls) {
24473			this._controls[control].remove();
24474		}
24475		for (override in this.overides) {
24476			this._core[override] = this._overrides[override];
24477		}
24478		for (property in Object.getOwnPropertyNames(this)) {
24479			typeof this[property] != 'function' && (this[property] = null);
24480		}
24481	};
24482
24483	/**
24484	 * Updates the internal state.
24485	 * @protected
24486	 */
24487	Navigation.prototype.update = function() {
24488		var i, j, k,
24489			lower = this._core.clones().length / 2,
24490			upper = lower + this._core.items().length,
24491			maximum = this._core.maximum(true),
24492			settings = this._core.settings,
24493			size = settings.center || settings.autoWidth || settings.dotsData
24494				? 1 : settings.dotsEach || settings.items;
24495
24496		if (settings.slideBy !== 'page') {
24497			settings.slideBy = Math.min(settings.slideBy, settings.items);
24498		}
24499
24500		if (settings.dots || settings.slideBy == 'page') {
24501			this._pages = [];
24502
24503			for (i = lower, j = 0, k = 0; i < upper; i++) {
24504				if (j >= size || j === 0) {
24505					this._pages.push({
24506						start: Math.min(maximum, i - lower),
24507						end: i - lower + size - 1
24508					});
24509					if (Math.min(maximum, i - lower) === maximum) {
24510						break;
24511					}
24512					j = 0, ++k;
24513				}
24514				j += this._core.mergers(this._core.relative(i));
24515			}
24516		}
24517	};
24518
24519	/**
24520	 * Draws the user interface.
24521	 * @todo The option `dotsData` wont work.
24522	 * @protected
24523	 */
24524	Navigation.prototype.draw = function() {
24525		var difference,
24526			settings = this._core.settings,
24527			disabled = this._core.items().length <= settings.items,
24528			index = this._core.relative(this._core.current()),
24529			loop = settings.loop || settings.rewind;
24530
24531		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
24532
24533		if (settings.nav) {
24534			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
24535			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
24536		}
24537
24538		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
24539
24540		if (settings.dots) {
24541			difference = this._pages.length - this._controls.$absolute.children().length;
24542
24543			if (settings.dotsData && difference !== 0) {
24544				this._controls.$absolute.html(this._templates.join(''));
24545			} else if (difference > 0) {
24546				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
24547			} else if (difference < 0) {
24548				this._controls.$absolute.children().slice(difference).remove();
24549			}
24550
24551			this._controls.$absolute.find('.active').removeClass('active');
24552			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
24553		}
24554	};
24555
24556	/**
24557	 * Extends event data.
24558	 * @protected
24559	 * @param {Event} event - The event object which gets thrown.
24560	 */
24561	Navigation.prototype.onTrigger = function(event) {
24562		var settings = this._core.settings;
24563
24564		event.page = {
24565			index: $.inArray(this.current(), this._pages),
24566			count: this._pages.length,
24567			size: settings && (settings.center || settings.autoWidth || settings.dotsData
24568				? 1 : settings.dotsEach || settings.items)
24569		};
24570	};
24571
24572	/**
24573	 * Gets the current page position of the carousel.
24574	 * @protected
24575	 * @returns {Number}
24576	 */
24577	Navigation.prototype.current = function() {
24578		var current = this._core.relative(this._core.current());
24579		return $.grep(this._pages, $.proxy(function(page, index) {
24580			return page.start <= current && page.end >= current;
24581		}, this)).pop();
24582	};
24583
24584	/**
24585	 * Gets the current succesor/predecessor position.
24586	 * @protected
24587	 * @returns {Number}
24588	 */
24589	Navigation.prototype.getPosition = function(successor) {
24590		var position, length,
24591			settings = this._core.settings;
24592
24593		if (settings.slideBy == 'page') {
24594			position = $.inArray(this.current(), this._pages);
24595			length = this._pages.length;
24596			successor ? ++position : --position;
vendor: 5,678 bytes, lines 24597-24821
24597			position = this._pages[((position % length) + length) % length].start;
24598		} else {
24599			position = this._core.relative(this._core.current());
24600			length = this._core.items().length;
24601			successor ? position += settings.slideBy : position -= settings.slideBy;
24602		}
24603
24604		return position;
24605	};
24606
24607	/**
24608	 * Slides to the next item or page.
24609	 * @public
24610	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
24611	 */
24612	Navigation.prototype.next = function(speed) {
24613		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
24614	};
24615
24616	/**
24617	 * Slides to the previous item or page.
24618	 * @public
24619	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
24620	 */
24621	Navigation.prototype.prev = function(speed) {
24622		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
24623	};
24624
24625	/**
24626	 * Slides to the specified item or page.
24627	 * @public
24628	 * @param {Number} position - The position of the item or page.
24629	 * @param {Number} [speed] - The time in milliseconds for the transition.
24630	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
24631	 */
24632	Navigation.prototype.to = function(position, speed, standard) {
24633		var length;
24634
24635		if (!standard) {
24636			length = this._pages.length;
24637			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
24638		} else {
24639			$.proxy(this._overrides.to, this._core)(position, speed);
24640		}
24641	};
24642
24643	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
24644
24645})(window.Zepto || window.jQuery, window, document);
24646
24647/**
24648 * Hash Plugin
24649 * @version 2.0.0-beta.3
24650 * @author Artus Kolanowski
24651 * @license The MIT License (MIT)
24652 */
24653;(function($, window, document, undefined) {
24654	'use strict';
24655
24656	/**
24657	 * Creates the hash plugin.
24658	 * @class The Hash Plugin
24659	 * @param {Owl} carousel - The Owl Carousel
24660	 */
24661	var Hash = function(carousel) {
24662		/**
24663		 * Reference to the core.
24664		 * @protected
24665		 * @type {Owl}
24666		 */
24667		this._core = carousel;
24668
24669		/**
24670		 * Hash index for the items.
24671		 * @protected
24672		 * @type {Object}
24673		 */
24674		this._hashes = {};
24675
24676		/**
24677		 * The carousel element.
24678		 * @type {jQuery}
24679		 */
24680		this.$element = this._core.$element;
24681
24682		/**
24683		 * All event handlers.
24684		 * @protected
24685		 * @type {Object}
24686		 */
24687		this._handlers = {
24688			/*'initialized.owl.carousel': $.proxy(function(e) {
24689				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
24690					$(window).trigger('hashchange.owl.navigation');
24691				}
24692			}, this),*/
24693			'prepared.owl.carousel': $.proxy(function(e) {
24694				if (e.namespace) {
24695					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
24696
24697					if (!hash) {
24698						return;
24699					}
24700
24701					this._hashes[hash] = e.content;
24702				}
24703			}, this),
24704			'changed.owl.carousel': $.proxy(function(e) {
24705				if (e.namespace && e.property.name === 'position') {
24706					var current = this._core.items(this._core.relative(this._core.current())),
24707						hash = $.map(this._hashes, function(item, hash) {
24708							return item === current ? hash : null;
24709						}).join();
24710
24711					if (!hash || window.location.hash.slice(1) === hash) {
24712						return;
24713					}
24714
24715					window.location.hash = hash;
24716				}
24717			}, this)
24718		};
24719
24720		// set default options
24721		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
24722
24723		// register the event handlers
24724		this.$element.on(this._handlers);
24725
24726		// register event listener for hash navigation
24727		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
24728			var hash = window.location.hash.substring(1),
24729				items = this._core.$stage.children(),
24730				position = this._hashes[hash] && items.index(this._hashes[hash]);
24731
24732			if (position === undefined || position === this._core.current()) {
24733				return;
24734			}
24735
24736			this._core.to(this._core.relative(position), false, true);
24737		}, this));*/
24738	};
24739
24740	/**
24741	 * Default options.
24742	 * @public
24743	 */
24744	Hash.Defaults = {
24745		URLhashListener: false
24746	};
24747
24748	/**
24749	 * Destroys the plugin.
24750	 * @public
24751	 */
24752	Hash.prototype.destroy = function() {
24753		var handler, property;
24754
24755		$(window).off('hashchange.owl.navigation');
24756
24757		for (handler in this._handlers) {
24758			this._core.$element.off(handler, this._handlers[handler]);
24759		}
24760		for (property in Object.getOwnPropertyNames(this)) {
24761			typeof this[property] != 'function' && (this[property] = null);
24762		}
24763	};
24764
24765	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
24766
24767})(window.Zepto || window.jQuery, window, document);
24768
24769/**
24770 * Support Plugin
24771 *
24772 * @version 2.0.0-beta.3
24773 * @author Vivid Planet Software GmbH
24774 * @author Artus Kolanowski
24775 * @license The MIT License (MIT)
24776 */
24777;(function($, window, document, undefined) {
24778
24779	var style = $('<support>').get(0).style,
24780		prefixes = 'Webkit Moz O ms'.split(' '),
24781		events = {
24782			transition: {
24783				end: {
24784					WebkitTransition: 'webkitTransitionEnd',
24785					MozTransition: 'transitionend',
24786					OTransition: 'oTransitionEnd',
24787					transition: 'transitionend'
24788				}
24789			},
24790			animation: {
24791				end: {
24792					WebkitAnimation: 'webkitAnimationEnd',
24793					MozAnimation: 'animationend',
24794					OAnimation: 'oAnimationEnd',
24795					animation: 'animationend'
24796				}
24797			}
24798		},
24799		tests = {
24800			csstransforms: function() {
24801				return !!test('transform');
24802			},
24803			csstransforms3d: function() {
24804				return !!test('perspective');
24805			},
24806			csstransitions: function() {
24807				return !!test('transition');
24808			},
24809			cssanimations: function() {
24810				return !!test('animation');
24811			}
24812		};
24813
24814	function test(property, prefixed) {
24815		var result = false,
24816			upper = property.charAt(0).toUpperCase() + property.slice(1);
24817
24818		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
24819			if (style[property] !== undefined) {
24820				result = prefixed ? property : true;
24821				return false;
24822			}
24823		});
24824
24825		return result;
24826	}
24827
24828	function prefixed(property) {
24829		return test(property, true);
24830	}
24831
24832	if (tests.csstransitions()) {
24833		/* jshint -W053 */
24834		$.support.transition = new String(prefixed('transition'))
24835		$.support.transition.end = events.transition.end[ $.support.transition ];
24836	}
24837
24838	if (tests.cssanimations()) {
24839		/* jshint -W053 */
24840		$.support.animation = new String(prefixed('animation'))
24841		$.support.animation.end = events.animation.end[ $.support.animation ];
24842	}
24843
24844	if (tests.csstransforms()) {
24845		/* jshint -W053 */
24846		$.support.transform = new String(prefixed('transform'));
24847		$.support.transform3d = tests.csstransforms3d();
24848	}
24849
24850})(window.Zepto || window.jQuery, window, document);
24851
24852(function(window, document, undefined) {
24853
24854	/**
24855	 * Find the absolute position of an element
24856	 */
24857	var absPos = function(element) {
24858		var offsetLeft, offsetTop;
24859		offsetLeft = offsetTop = 0;
24860		if (element.offsetParent) {
24861			do {
24862				offsetLeft += element.offsetLeft;
24863				offsetTop += element.offsetTop;
24864			} while (element = element.offsetParent);
24865		}
24866		return [offsetLeft, offsetTop];
24867	};
24868
24869	/**
24870	 * @constructor Progress Circle class
24871	 * @param params.canvas Canvas on which the circles will be drawn.
24872	 * @param params.minRadius Inner radius of the innermost circle, in px.
24873	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
24874	 * @param params.gapWidth Space between each circle.
24875	 * @param params.centerX X coordinate of the center of circles.
24876	 * @param params.centerY Y coordinate of the center of circles.
24877	 * @param params.infoLineBaseAngle Base angle of the info line.
24878	 * @param params.infoLineAngleInterval Angles between the info lines.
24879	 */
24880	var ProgressCircle = function(params) {
24881		this.canvas = params.canvas;
24882		this.minRadius = params.minRadius || 15;
24883		this.arcWidth = params.arcWidth || 5;
24884		this.gapWidth = params.gapWidth || 3;
24885		this.centerX = params.centerX || this.canvas.width / 2;
24886		this.centerY = params.centerY || this.canvas.height / 2;
24887		this.infoLineLength = params.infoLineLength || 60;
24888		this.horizLineLength = params.horizLineLength || 10;
24889		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
24890		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
24891
24892		this.context = this.canvas.getContext('2d');
24893
24894		this.width = this.canvas.width;
24895		this.height = this.canvas.height;
24896
24897		this.circles = [];
24898		this.runningCount = 0;
24899	};
24900
24901	ProgressCircle.prototype = {
24902		constructor: ProgressCircle,
24903
24904		/**
24905		 * @method Adds an progress monitor entry.
24906		 * @param params.fillColor Color to fill in the circle.
24907		 * @param params.outlineColor Color to outline the circle.
24908		 * @param params.progressListener Callback function to fetch the progress.
24909		 * @param params.infoListener Callback function to fetch the info.
24910		 * @returns this
24911		 */
24912		addEntry: function(params) {
24913			this.circles.push(new Circle({
24914				canvas: this.canvas,
24915				context: this.context,
24916				centerX: this.centerX,
24917				centerY: this.centerY,
24918				innerRadius: this.minRadius + this.circles.length *
24919					(this.gapWidth + this.arcWidth),
24920				arcWidth: this.arcWidth,
24921				infoLineLength: this.infoLineLength,
24922				horizLineLength: this.horizLineLength,
24923
24924				id: this.circles.length,
24925				fillColor: params.fillColor,
24926				outlineColor: params.outlineColor,
24927				progressListener: params.progressListener,
24928				infoListener: params.infoListener,
24929				infoLineAngle: this.infoLineBaseAngle +
24930					this.circles.length * this.infoLineAngleInterval,
24931			}));
24932
24933			return this;
24934		},
24935
24936		/**
24937		 * @method Starts the monitor and updates with the given interval.
24938		 * @param interval Interval between updates, in millisecond.
24939		 * @returns this
24940		 */
24941		start: function(interval) {
24942			var self = this;
24943			this.timer = setInterval(function() {
24944				self._update();
24945			}, interval || 33);
24946
24947			return this;
24948		},
24949
24950		/**
24951		 * @method Stop the animation.
24952		 */
24953		stop: function() {
24954			clearTimeout(this.timer);
24955		},
24956
24957		/**
24958		 * @private
24959		 * @method Call update on each circle and redraw them.
24960		 * @returns this
24961		 */
24962		_update: function() {
24963			this._clear();
24964			this.circles.forEach(function(circle, idx, array) {
24965				circle.update();
24966			});
24967
24968			return this;
24969		},
24970
24971		/**
24972		 * @private
24973		 * @method Clear the canvas.
24974		 * @returns this
24975		 */
24976		_clear: function() {
24977			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
24978
24979			return this;
24980		},
24981
24982	};
24983
24984	/**
24985	 * @private
24986	 * @class Individual progress circle.
24987	 * @param params.canvas Canvas on which the circle will be drawn.
24988	 * @param params.context Context of the canvas.
24989	 * @param params.innerRadius Inner radius of the circle, in px.
24990	 * @param params.arcWidth Width of each arc(circle).
24991	 * @param params.gapWidth Distance between each arc.
24992	 * @param params.centerX X coordinate of the center of circles.
24993	 * @param params.centerY Y coordinate of the center of circles.
24994	 * @param params.fillColor Color to fill in the circle.
24995	 * @param params.outlineColor Color to outline the circle.
24996	 * @param params.progressListener Callback function to fetch the progress.
24997	 * @param params.infoListener Callback function to fetch the info.
24998	 * @param params.infoLineAngle Angle of info line.
24999	 */
25000	var Circle = function(params) {
25001		this.id = params.id;
25002		this.canvas = params.canvas;
25003		this.context = params.context;
25004		this.centerX = params.centerX;
25005		this.centerY = params.centerY;
25006		this.arcWidth = params.arcWidth;
25007		this.innerRadius = params.innerRadius || 0;
25008		this.fillColor = params.fillColor || '#fff';
25009		this.outlineColor = params.outlineColor || this.fillColor;
25010		this.progressListener = params.progressListener;
25011		this.infoLineLength = params.infoLineLength || 250;
25012		this.horizLineLength = params.horizLineLength || 50;
25013		this.infoListener = params.infoListener;
25014		this.infoLineAngle = params.infoLineAngle;
25015
25016		this.outerRadius = this.innerRadius + this.arcWidth;
25017
25018		// If the info listener is not registered, then don't calculate
25019		// the related coordinates
25020		if (!this.infoListener) return;
25021
25022		// calculate the info-line turning points
25023		var angle = this.infoLineAngle,
25024			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25025
25026			sinA = Math.sin(angle),
25027			cosA = Math.cos(angle);
25028
25029		this.infoLineStartX = this.centerX + sinA * arcDistance;
25030		this.infoLineStartY = this.centerY - cosA * arcDistance;
25031
25032		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25033		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25034
25035		this.infoLineEndX = this.infoLineMidX +
25036			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25037		this.infoLineEndY = this.infoLineMidY;
25038
25039		var infoText = document.createElement('div'),
25040			style = infoText.style;
25041
25042		style.color = this.fillColor;
25043		style.position = 'absolute';
25044		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25045		// style.top will be calculated in the `drawInfo` method. Since
25046		// user may want to change the size of the font, so the top offset
25047		// must be updated in each loop.
25048		infoText.className = 'ProgressCircleInfo'; // For css styling
25049		infoText.id = 'progress_circle_info_' + this.id;
25050		document.body.appendChild(infoText);
25051		this.infoText = infoText;
25052	};
25053
25054	Circle.prototype = {
25055		constructor: Circle,
25056
25057		update: function() {
25058			this.progress = this.progressListener();
25059			this._draw();
25060
25061			if (this.infoListener) {
25062				this.info = this.infoListener();
25063				this._drawInfo();
25064			}
25065		},
25066
25067		/**
25068		 * @private
25069		 * @method Draw the circle on the canvas.
25070		 * @returns this
25071		 */
25072		_draw: function() {
25073			var ctx = this.context,
25074
25075				ANGLE_OFFSET = -Math.PI / 2,
25076
25077				startAngle = 0 + ANGLE_OFFSET,
25078				endAngle= startAngle + this.progress * Math.PI * 2,
25079
25080				x = this.centerX,
25081				y = this.centerY,
25082
25083				innerRadius = this.innerRadius - this.arcWidth - 1,
25084				outerRadius = this.outerRadius - this.arcWidth - 1;
25085
25086			if ( innerRadius < 0 )
25087				return;
25088
25089			ctx.fillStyle = this.fillColor;
25090			ctx.strokeStyle = this.outlineColor;
25091
25092			ctx.beginPath();
25093			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
25094			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
25095			ctx.closePath();
25096			ctx.stroke();
25097			ctx.fill();
25098
25099			return this;
25100		},
25101
25102		/**
25103		 * @private
25104		 * @method Draw the info lines and info text.
25105		 * @returns this
25106		 */
25107		_drawInfo: function() {
25108
25109			var pointList, lineHeight;
25110
25111			pointList = [
25112				[this.infoLineStartX, this.infoLineStartY],
25113				[this.infoLineMidX, this.infoLineMidY],
25114				[this.infoLineEndX, this.infoLineEndY],
25115			];
25116			this._drawSegments(pointList, false);
25117
25118			this.infoText.innerHTML = this.info;
25119
25120			lineHeight = this.infoText.offsetHeight;
25121			this.infoText.style.top = this.infoLineEndY +
25122				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
25123
25124			return this;
25125		},
25126
25127		/**
25128		 * @private
25129		 * @method Helper function to draw the segments
25130		 * @param pointList An array of points in the form of [x, y].
25131		 * @param close Whether to connect the first and last point.
25132		 */
25133		_drawSegments: function(pointList, close) {
25134			var ctx = this.context;
25135
25136			ctx.beginPath();
25137			ctx.moveTo(pointList[0][0], pointList[0][1]);
25138			for (var i = 1; i < pointList.length; ++i) {
25139				ctx.lineTo(pointList[i][0], pointList[i][1]);
25140			}
25141
25142			if (close) {
25143				ctx.closePath();
25144			}
25145			ctx.stroke();
25146		},
25147	};
25148
25149	window.ProgressCircle = ProgressCircle;
25150
25151})(window, document);
25152
25153
25154
25155
25156/* =========================================================
25157 * jquery.vc_chart.js v1.0
25158 * =========================================================
25159 * Copyright 2013 Wpbakery
25160 *
25161 * Jquery chart plugin for the Visual Composer.
25162 * ========================================================= */
25163(function($){
25164	/**
25165	 * Pie chart animated.
25166	 * @param element - DOM element
25167	 * @param options - settings object.
25168	 * @constructor
25169	 */
25170	var VcChart = function(element, options) {
25171		this.el = element;
25172		this.$el = $(this.el);
25173		var $this = this;
25174		$this.options = $.extend({
25175			color: 'wpb_button',
25176			units: '',
25177			width: '',
25178			label_selector: '.vc_pie_chart_value',
25179			back_selector: '.vc_pie_chart_back',
25180			responsive: true
25181		}, options);
25182		$this.init();
25183	};
25184	VcChart.prototype = {
25185		constructor: VcChart,
25186		_progress_v: 0,
25187		animated: false,
25188		colors: {
25189			'wpb_button': 'rgba(247, 247, 247, 1)',
25190			'btn-primary': 'rgba(0, 136, 204, 1)',
25191			'btn-info': 'rgba(88, 185, 218, 1)',
25192			'btn-success': 'rgba(106, 177, 101, 1)',
25193			'btn-warning': 'rgba(255, 153, 0, 1)',
25194			'btn-danger': 'rgba(255, 103, 91, 1)',
25195			'btn-inverse': 'rgba(85, 85, 85, 1)'
25196		},
25197		init: function() {
25198			this.setupColor();
25199			this.value = this.$el.data('pie-value')/100;
25200			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
25201			this.$wrapper = $('.vc_pie_wrapper', this.$el);
25202			this.$label = $(this.options.label_selector, this.$el);
25203			this.$back = $(this.options.back_selector, this.$el);
25204			this.$canvas = this.$el.find('canvas');
25205			this.arcWidth = this.$el.data('pie-width') * 2;
25206			this.draw();
25207			this.setWayPoint();
25208			if(this.options.responsive === true) this.setResponsive();
25209			if (UNCODE.isMobile) this._progress_v = this.value;
25210		},
25211		setupColor: function() {
25212			// if(typeof this.colors[this.options.color] !== 'undefined') {
25213			//     this.color = this.colors[this.options.color];
25214			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
25215			//     this.color = this.options.color;
25216			// } else {
25217			//     this.color = 'rgba(247, 247, 247, 0.2)';
25218			// }
25219			if(typeof this.options.color !== 'undefined') {
25220				this.color = this.options.color;
25221			} else this.color = 'rgba(247, 247, 247, 0.2)';
25222
25223		},
25224		setResponsive: function() {
25225			var that = this;
25226			if (!UNCODE.isMobile) {
25227				$(window).resize(function(){
25228					if(that.animated === true) that.circle.stop();
25229					that.draw(true);
25230				});
25231			}
25232		},
25233		draw: function(redraw) {
25234			var w = this.$el.addClass('vc_ready').width() * 2,
25235				border_w = this.arcWidth,
25236				radius;
25237			if(!w) w = this.$el.parents(':visible').first().width()-2;
25238			//w = Math.round(w/100*80);
25239			//if (w < 250) w = 250;
25240			radius = w/2;
25241			this.$wrapper.css({"width" : (w / 2) + "px"});
25242			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
25243			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
25244			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
25245			this.$el.addClass('vc_ready');
25246			this.circle = new ProgressCircle({
25247				canvas: this.$canvas.get(0),
25248				minRadius: radius,
25249				arcWidth: border_w
25250			});
25251			if(redraw === true && this.animated === true) {
25252				this._progress_v = this.value;
25253				this.circle.addEntry({
25254					fillColor: this.color,
25255					progressListener: $.proxy(this.setProgress, this)
25256				}).start();
25257			}
25258		},
25259		setProgress: function() {
25260			if (this._progress_v >= this.value) {
25261				this.circle.stop();
25262				this.animated = true;
25263				this.$label.html(this.label_value + this.options.units);
25264				return this._progress_v;
25265			}
25266			this._progress_v += 0.01;
25267			if (!isNaN(this.label_value)) {
25268				var label_value = this._progress_v/this.value*this.label_value;
25269				var val = Math.round(label_value) + this.options.units;
25270				this.$label.html(val);
25271			} else this.$label.html(this.label_value + this.options.units);
25272			return this._progress_v;
25273		},
25274		animate: function() {
25275			if(this.animated !== true) {
25276				this.circle.addEntry({
25277					fillColor: this.color,
25278					progressListener: $.proxy(this.setProgress, this)
25279				}).start(10);
25280			}
25281		},
25282		setWayPoint: function() {
25283			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
25284				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
25285			} else {
25286				this.animate();
25287			}
25288		}
25289	};
25290	/**
25291	 * jQuery plugin
25292	 * @param option - object with settings
25293	 * @return {*}
25294	 */
25295	$.fn.vcChat = function(option, value) {
25296		return this.each(function () {
25297			var $this = $(this),
25298				data = $this.data('vc_chart'),
25299				options = typeof option === 'object' ? option : {
25300					color: $this.data('pie-color'),
25301					units: $this.data('pie-units')
25302				};
25303			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
25304			if (typeof option == 'string') data[option](value);
25305		});
25306	};
25307	/**
25308	 * Allows users to rewrite function inside theme.
25309	 */
25310	if ( typeof window['vc_pieChart'] !== 'function' ) {
25311		window.vc_pieChart = function() {
25312			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
25313		}
25314	}
25315	$(document).ready(function(){
25316		!window.vc_iframe && vc_pieChart();
25317
25318		/**
25319		* Tab and collapse integration.
25320		*/
25321		$('.nav-tabs a').on('shown.bs.tab', function(e){
25322			var $cont = $(e.target).closest('.tab-container'),
25323				$active = $('.tab-pane.active', $cont);
25324			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
25325		});
25326
25327		$('.panel-collapse').on('shown.bs.collapse', function (e) {
25328			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
25329		})
25330	});
25331
25332})(window.jQuery);
25333
25334/* Progress bar
25335 ---------------------------------------------------------- */
25336function uncode_progress_bar() {
25337	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
25338		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
25339			return;
25340		}
25341		if (!UNCODE.isMobile) {
25342			new Waypoint({
25343				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
25344				element: val,
25345				handler: function() {
25346					var element = jQuery(this.element);
25347					element.find('.vc_single_bar').each(function(index) {
25348						var $this = jQuery(this),
25349							bar = $this.find('.vc_bar'),
25350							val = bar.data('percentage-value');
25351						setTimeout(function() {
25352							bar.css({
25353								"width": val + '%'
25354							});
25355						}, index * 200);
25356					});
25357				},
25358				offset: '80%'
25359			});
25360		} else {
25361			var element = jQuery(val);
25362			element.find('.vc_single_bar').each(function(index) {
25363				var $this = jQuery(this),
25364					bar = $this.find('.vc_bar'),
25365					val = bar.data('percentage-value');
25366				setTimeout(function() {
25367					bar.css({
25368						"width": val + '%'
25369					});
25370				}, index * 200);
25371			});
25372		}
25373	});
25374};
25375uncode_progress_bar();
25376
25377/*!
25378 * jquery.counterup.js 1.0
25379 *
25380 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
25381 * Released under the GPL v2 License
25382 *
25383 * Date: Nov 26, 2013
25384 */
25385(function($) {
25386	"use strict";
25387	$.fn.counterUp = function(options) {
25388		// Defaults
25389		var settings = $.extend({
25390			'time': 400,
25391			'delay': 10
25392		}, options);
25393		return this.each(function() {
25394			// Store the object
25395			var $this = $(this);
25396			var $settings = settings;
25397			var counterUpper = function() {
25398				var nums = [];
25399				var divisions = $settings.time / $settings.delay;
25400				var numReal = $this.attr('data-val'),
25401				num = numReal;
25402				var isComma = /[0-9]+,[0-9]+/.test(num);
25403				num = num.replace(/,/g, '');
25404				var isInt = /^[0-9]+$/.test(num);
25405				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
25406				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
25407				// Generate list of incremental numbers to display
25408				for (var i = divisions; i >= 1; i--) {
25409					// Preserve as int if input was int
25410					var newNum = parseInt(num / divisions * i);
25411					// Preserve float if input was float
25412					if (isFloat) {
25413						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
25414					}
25415					// Preserve commas if input had commas
25416					if (isComma) {
25417						while (/(\d+)(\d{3})/.test(newNum.toString())) {
25418							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
25419						}
25420					}
25421					nums.unshift(newNum);
25422				}
25423				nums.push(numReal);
25424				$this.data('counterup-nums', nums);
25425				$this.text('0');
25426				// Updates the number until we're done
25427				var f = function() {
25428					if ($this.data('counterup-nums') != null) {
25429						$this.text($this.data('counterup-nums').shift());
25430						if ($this.data('counterup-nums').length) {
25431							setTimeout($this.data('counterup-func'), $settings.delay);
25432						} else {
25433							delete $this.data('counterup-nums');
25434							$this.data('counterup-nums', null);
25435							$this.data('counterup-func', null);
25436						}
25437					}
25438				};
25439				$this.data('counterup-func', f);
25440				// Start the count up
25441				setTimeout($this.data('counterup-func'), $settings.delay);
25442			};
25443			// Perform counts when the element gets into view
25444			new Waypoint({
25445				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
25446				element: this,
25447				handler: function() {
25448					counterUpper();
25449					if (!UNCODE.isUnmodalOpen) {
25450						this.destroy();
25451					}
25452				},
25453				offset: '100%'
25454			});
25455		});
25456	};
25457})(jQuery);
25458
25459/*!
25460 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
25461 * Copyright (c) 2016 Edson Hilios
25462 *
25463 * Permission is hereby granted, free of charge, to any person obtaining a copy of
25464 * this software and associated documentation files (the "Software"), to deal in
25465 * the Software without restriction, including without limitation the rights to
25466 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
25467 * the Software, and to permit persons to whom the Software is furnished to do so,
25468 * subject to the following conditions:
25469 *
25470 * The above copyright notice and this permission notice shall be included in all
25471 * copies or substantial portions of the Software.
25472 *
25473 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25474 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
25475 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
25476 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25477 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25478 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25479 */
25480(function(factory) {
25481	"use strict";
25482	if (typeof define === "function" && define.amd) {
25483		define([ "jquery" ], factory);
25484	} else {
25485		factory(jQuery);
25486	}
25487})(function($) {
25488	"use strict";
25489	var instances = [], matchers = [], defaultOptions = {
25490		precision: 100,
25491		elapse: false,
25492		defer: false
25493	};
25494	matchers.push(/^[0-9]*$/.source);
25495	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
25496	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
25497	matchers = new RegExp(matchers.join("|"));
25498	function parseDateString(dateString) {
25499		if (dateString instanceof Date) {
25500			return dateString;
25501		}
25502		if (String(dateString).match(matchers)) {
25503			if (String(dateString).match(/^[0-9]*$/)) {
25504				dateString = Number(dateString);
25505			}
25506			if (String(dateString).match(/\-/)) {
25507				dateString = String(dateString).replace(/\-/g, "/");
25508			}
25509			return new Date(dateString);
25510		} else {
25511			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
25512		}
25513	}
25514	var DIRECTIVE_KEY_MAP = {
25515		Y: "years",
25516		m: "months",
25517		n: "daysToMonth",
25518		d: "daysToWeek",
25519		w: "weeks",
25520		W: "weeksToMonth",
25521		H: "hours",
25522		M: "minutes",
25523		S: "seconds",
25524		D: "totalDays",
25525		I: "totalHours",
25526		N: "totalMinutes",
25527		T: "totalSeconds"
25528	};
25529	function escapedRegExp(str) {
25530		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
25531		return new RegExp(sanitize);
25532	}
25533	function strftime(offsetObject) {
25534		return function(format) {
25535			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
25536			if (directives) {
25537				for (var i = 0, len = directives.length; i < len; ++i) {
25538					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
25539					directive = directive[2];
25540					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
25541						value = DIRECTIVE_KEY_MAP[directive];
25542						value = Number(offsetObject[value]);
25543					}
25544					if (value !== null) {
25545						if (modifier === "!") {
25546							value = pluralize(plural, value);
25547						}
25548						if (modifier === "") {
25549							if (value < 10) {
25550								value = "0" + value.toString();
25551							}
25552						}
25553						format = format.replace(regexp, value.toString());
25554					}
25555				}
25556			}
25557			format = format.replace(/%%/, "%");
25558			return format;
25559		};
25560	}
25561	function pluralize(format, count) {
25562		var plural = "s", singular = "";
25563		if (format) {
25564			format = format.rep
vendor: 8,618 bytes, lines 25564-25708
25564lace(/(:|;|\s)/gi, "").split(/\,/);
25565			if (format.length === 1) {
25566				plural = format[0];
25567			} else {
25568				singular = format[0];
25569				plural = format[1];
25570			}
25571		}
25572		if (Math.abs(count) > 1) {
25573			return plural;
25574		} else {
25575			return singular;
25576		}
25577	}
25578	var Countdown = function(el, finalDate, options) {
25579		this.el = el;
25580		this.$el = $(el);
25581		this.interval = null;
25582		this.offset = {};
25583		this.options = $.extend({}, defaultOptions);
25584		this.instanceNumber = instances.length;
25585		instances.push(this);
25586		this.$el.data("countdown-instance", this.instanceNumber);
25587		if (options) {
25588			if (typeof options === "function") {
25589				this.$el.on("update.countdown", options);
25590				this.$el.on("stoped.countdown", options);
25591				this.$el.on("finish.countdown", options);
25592			} else {
25593				this.options = $.extend({}, defaultOptions, options);
25594			}
25595		}
25596		this.setFinalDate(finalDate);
25597		if (this.options.defer === false) {
25598			this.start();
25599		}
25600	};
25601	$.extend(Countdown.prototype, {
25602		start: function() {
25603			if (this.interval !== null) {
25604				clearInterval(this.interval);
25605			}
25606			var self = this;
25607			this.update();
25608			this.interval = setInterval(function() {
25609				self.update.call(self);
25610			}, this.options.precision);
25611		},
25612		stop: function() {
25613			clearInterval(this.interval);
25614			this.interval = null;
25615			this.dispatchEvent("stoped");
25616		},
25617		toggle: function() {
25618			if (this.interval) {
25619				this.stop();
25620			} else {
25621				this.start();
25622			}
25623		},
25624		pause: function() {
25625			this.stop();
25626		},
25627		resume: function() {
25628			this.start();
25629		},
25630		remove: function() {
25631			this.stop.call(this);
25632			instances[this.instanceNumber] = null;
25633			delete this.$el.data().countdownInstance;
25634		},
25635		setFinalDate: function(value) {
25636			this.finalDate = parseDateString(value);
25637		},
25638		update: function() {
25639			if (this.$el.closest("html").length === 0) {
25640				this.remove();
25641				return;
25642			}
25643			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
25644			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
25645			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
25646			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
25647			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
25648				return;
25649			} else {
25650				this.totalSecsLeft = newTotalSecsLeft;
25651			}
25652			this.elapsed = now >= this.finalDate;
25653			this.offset = {
25654				seconds: this.totalSecsLeft % 60,
25655				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
25656				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
25657				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
25658				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
25659				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
25660				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
25661				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
25662				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
25663				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
25664				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
25665				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
25666				totalMinutes: Math.floor(this.totalSecsLeft / 60),
25667				totalSeconds: this.totalSecsLeft
25668			};
25669			if (!this.options.elapse && this.totalSecsLeft === 0) {
25670				this.stop();
25671				this.dispatchEvent("finish");
25672			} else {
25673				this.dispatchEvent("update");
25674			}
25675		},
25676		dispatchEvent: function(eventName) {
25677			var event = $.Event(eventName + ".countdown");
25678			event.finalDate = this.finalDate;
25679			event.elapsed = this.elapsed;
25680			event.offset = $.extend({}, this.offset);
25681			event.strftime = strftime(this.offset);
25682			this.$el.trigger(event);
25683		}
25684	});
25685	$.fn.countdown = function() {
25686		var argumentsArray = Array.prototype.slice.call(arguments, 0);
25687		return this.each(function() {
25688			var instanceNumber = $(this).data("countdown-instance");
25689			if (instanceNumber !== undefined) {
25690				var instance = instances[instanceNumber], method = argumentsArray[0];
25691				if (Countdown.prototype.hasOwnProperty(method)) {
25692					instance[method].apply(instance, argumentsArray.slice(1));
25693				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
25694					instance.setFinalDate.call(instance, method);
25695					instance.start();
25696				} else {
25697					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
25698				}
25699			} else {
25700				new Countdown(this, argumentsArray[0], argumentsArray[1]);
25701			}
25702		});
25703	};
25704});
25705
25706!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;
25707function getStyles(config){
25708  // 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;
25708left: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+"}"
25709};
25710  var ShareUtils;
25711
25712if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
25713  Object.defineProperty(HTMLElement.prototype, "classList", {
25714    get: function() {
25715      var ret, self, update;
25716      update = function(fn) {
25717        return function(value) {
25718          var classes, index;
25719          classes = self.className.split(/\s+/);
25720          index = classes.indexOf(value);
25721          fn(classes, index, value);
25722          self.className = classes.join(" ");
25723        };
25724      };
25725      self = this;
25726      ret = {
25727        add: update(function(classes, index, value) {
25728          ~index || classes.push(value);
25729        }),
25730        remove: update(function(classes, index) {
25731          ~index && classes.splice(index, 1);
25732        }),
25733        toggle: update(function(classes, index, value) {
25734          if (~index) {
25735            classes.splice(index, 1);
25736          } else {
25737            classes.push(value);
25738          }
25739        }),
25740        contains: function(value) {
25741          return !!~self.className.split(/\s+/).indexOf(value);
25742        },
25743        item: function(i) {
25744          return self.className.split(/\s+/)[i] || null;
25745        }
25746      };
25747      Object.defineProperty(ret, "length", {
25748        get: function() {
25749          return self.className.split(/\s+/).length;
25750        }
25751      });
25752      return ret;
25753    }
25754  });
25755}
25756
25757String.prototype.to_rfc3986 = function() {
25758  var tmp;
25759  tmp = encodeURIComponent(this);
25760  return tmp.replace(/[!'()*]/g, function(c) {
25761    return "%" + c.charCodeAt(0).toString(16);
25762  });
25763};
25764
25765ShareUtils = (function() {
25766  function ShareUtils() {}
25767
25768  ShareUtils.prototype.extend = function(to, from, overwrite) {
25769    var hasProp, prop;
25770    for (prop in from) {
25771      hasProp = to[prop] !== undefined;
25772      if (hasProp && typeof from[prop] === "object") {
25773        this.extend(to[prop], from[prop], overwrite);
25774      } else {
25775        if (overwrite || !hasProp) {
25776          to[prop] = from[prop];
25777        }
25778      }
25779    }
25780  };
25781
25782  ShareUtils.prototype.hide = function(el) {
25783    return el.style.display = "none";
25784  };
25785
25786  ShareUtils.prototype.show = function(el) {
25787    return el.style.display = "block";
25788  };
25789
25790  ShareUtils.prototype.has_class = function(el, class_name) {
25791    return el.classList.contains(class_name);
25792  };
25793
25794  ShareUtils.prototype.add_class = function(el, class_name) {
25795    return el.classList.add(class_name);
25796  };
25797
25798  ShareUtils.prototype.remove_class = function(el, class_name) {
25799    return el.classList.remove(class_name);
25800  };
25801
25802  ShareUtils.prototype.is_encoded = function(str) {
25803    str = str.to_rfc3986();
25804    return decodeURIComponent(str) !== str;
25805  };
25806
25807  ShareUtils.prototype.encode = function(str) {
25808    if (typeof str === "undefined" || this.is_encoded(str)) {
25809      return str;
25810    } else {
25811      return str.to_rfc3986();
25812    }
25813  };
25814
25815  ShareUtils.prototype.popup = function(url, params) {
25816    var k, popup, qs, v;
25817    if (params == null) {
25818      params = {};
25819    }
25820    popup = {
25821      width: 500,
25822      height: 350
25823    };
25824    popup.top = (screen.height / 2) - (popup.height / 2);
25825    popup.left = (screen.width / 2) - (popup.width / 2);
25826    qs = ((function() {
25827      var _results;
25828      _results = [];
25829      for (k in params) {
25830        v = params[k];
25831        _results.push("" + k + "=" + (this.encode(v)));
25832      }
25833      return _results;
25834    }).call(this)).join('&');
25835    if (qs) {
25836      qs = "?" + qs;
25837    }
25838    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=" 
25838+ popup.width + ",height=" + popup.height);
25839  };
25840
25841  return ShareUtils;
25842
25843})();
25844var Share,
25845  __hasProp = {}.hasOwnProperty,
25846  __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; };
25847
25848Share = (function(_super) {
25849  __extends(Share, _super);
25850
25851  function Share(element, options) {
25852    this.element = element;
25853    this.el = {
25854      head: document.getElementsByTagName('head')[0],
25855      body: document.getElementsByTagName('body')[0]
25856    };
25857    this.config = {
25858      enabled_networks: 0,
25859      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
25860      url: window.location.href.replace("&", "%26"),
25861      caption: null,
25862      title: this.default_title(),
25863      image: this.default_image(),
25864      description: this.default_description(),
25865      ui: {
25866        flyout: 'top center',
25867        button_text: 'Share',
25868        button_font: true,
25869        icon_font: true
25870      },
25871      networks: {
25872        twitter: {
25873          enabled: true,
25874          url: null,
25875          title: null,
25876          description: null
25877        },
25878        facebook: {
25879          enabled: true,
25880          load_sdk: true,
25881          url: null,
25882          app_id: null,
25883          title: null,
25884          caption: null,
25885          description: null,
25886          image: null
25887        },
25888        pinterest: {
25889          enabled: true,
25890          url: null,
25891          image: null,
25892          description: null
25893        },
25894        reddit: {
25895          enabled: true,
25896          url: null,
25897          title: null
25898        },
25899        linkedin: {
25900          enabled: true,
25901          url: null,
25902          title: null,
25903          description: null
25904        },
25905        xing: {
25906          enabled: true,
25907          url: null,
25908          title: null,
25909          image: null,
25910          description: null
25911        },
25912        whatsapp: {
25913          enabled: true,
25914          description: null,
25915          url: null
25916        },
25917        email: {
25918          enabled: true,
25919          title: null,
25920          description: null,
25921          url: null
25922        }
25923      }
25924    };
25925    this.setup(element, options);
25926    return this;
25927  }
25928
25929  Share.prototype.setup = function(element, opts) {
25930    var index, instance, instances, _i, _len;
25931    instances = document.querySelectorAll(element);
25932    this.extend(this.config, opts, true);
25933    this.set_global_configuration();
25934    this.normalize_network_configuration();
25935    if (this.config.ui.icon_font) {
25936      this.inject_icons();
25937    }
25938    if (this.config.ui.button_font) {
25939      this.inject_fonts();
25940    }
25941    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
25942      this.inject_facebook_sdk();
25943    }
25944    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
25945      instance = instances[index];
25946      this.setup_instance(element, index);
25947    }
25948  };
25949
25950  Share.prototype.setup_instance = function(element, index) {
25951    var button, instance, label, network, networks, _i, _len, _results,
25952      _this = this;
25953    instance = document.querySelectorAll(element)[index];
25954    this.hide(instance);
25955    this.add_class(instance, "sharer-" + index);
25956    instance = document.querySelectorAll(element)[index];
25957    this.inject_css(instance);
25958    this.inject_html(instance);
25959    this.show(instance);
25960    label = instance.getElementsByTagName("label")[0];
25961    button = instance.getElementsByClassName("social")[0];
25962    networks = instance.getElementsByTagName('li');
25963    this.add_class(button, "networks-" + this.config.enabled_networks);
25964    label.addEventListener("click", function() {
25965      return _this.event_toggle(button);
25966    });
25967    _this = this;
25968    _results = [];
25969    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
25970      network = networks[index];
25971      _results.push(network.addEventListener("click", function() {
25972        _this.event_network(instance, this);
25973        return _this.event_close(button);
25974      }));
25975    }
25976    return _results;
25977  };
25978
25979  Share.prototype.event_toggle = function(button) {
25980    if (this.has_class(button, "active")) {
25981      return this.event_close(button);
25982    } else {
25983      return this.event_open(button);
25984    }
25985  };
25986
25987  Share.prototype.event_open = function(button) {
25988    if (this.has_class(button, "load")) {
25989      this.remove_class(button, "load");
25990    }
25991    return this.add_class(button, "active");
25992  };
25993
25994  Share.prototype.event_close = function(button) {
25995    return this.remove_class(button, "active");
25996  };
25997
25998  Share.prototype.event_network = function(instance, network) {
25999    var name;
26000    name = network.getAttribute("data-network");
26001    this.hook("before", name, instance);
26002    this["network_" + name]();
26003    return this.hook("after", name, instance);
26004  };
26005
26006  Share.prototype.open = function() {
26007    return this["public"]("open");
26008  };
26009
26010  Share.prototype.close = function() {
26011    return this["public"]("close");
26012  };
26013
26014  Share.prototype.toggle = function() {
26015    return this["public"]("toggle");
26016  };
26017
26018  Share.prototype["public"] = function(action) {
26019    var button, index, instance, _i, _len, _ref, _results;
26020    _ref = document.querySelectorAll(this.element);
26021    _results = [];
26022    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26023      instance = _ref[index];
26024      button = instance.getElementsByClassName("social")[0];
26025      _results.push(this["event_" + action](button));
26026    }
26027    return _results;
26028  };
26029
26030  Share.prototype.network_facebook = function() {
26031    if (this.config.networks.facebook.load_sdk) {
26032      if (!window.FB) {
26033        return console.error("The Facebook JS SDK hasn't loaded yet.");
26034      }
26035      return FB.ui({
26036        method: 'feed',
26037        name: this.config.networks.facebook.title,
26038        link: this.config.networks.facebook.url,
26039        picture: this.config.networks.facebook.image,
26040        caption: this.config.networks.facebook.caption,
26041        description: this.config.networks.facebook.description
26042      });
26043    } else {
26044      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26045        u: this.config.networks.facebook.url
26046      });
26047    }
26048  };
26049
26050  Share.prototype.network_twitter = function() {
26051    return this.popup('https://twitter.com/intent/tweet', {
26052      text: this.config.networks.twitter.title,
26053      url: this.config.networks.twitter.url
26054    });
26055  };
26056
26057  Share.prototype.network_pinterest = function() {
26058    return this.popup('https://www.pinterest.com/pin/create/button', {
26059      url: this.config.networks.pinterest.url,
26060      media: this.config.networks.pinterest.image,
26061      description: this.config.networks.pinterest.description
26062    });
26063  };
26064
26065  Share.prototype.network_linkedin = function() {
26066    return this.popup('https://www.linkedin.com/shareArticle', {
26067      url: this.config.networks.linkedin.url,
26068      title: this.config.networks.linkedin.title,
26069      summary: this.config.networks.linkedin.description
26070    });
26071  }
26072
26073  Share.prototype.network_xing = function() {
26074    return this.popup('https://www.xing.com/spi/shares/new', {
26075      url: this.config.networks.xing.url,
26076      image: this.config.networks.xing.image,
26077      title: this.config.networks.xing.title,
26078      summary: this.config.networks.xing.description
26079    });
26080  }
26081
26082  Share.prototype.network_email = function() {
26083    return this.popup('mailto:', {
26084      subject: this.config.networks.email.title,
26085      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26086    });
26087  };
26088
26089  Share.prototype.inject_icons = function() {
26090  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
26091  };
26092
26093  Share.prototype.inject_fonts = function() {
26094   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
26095  };
26096
26097  Share.prototype.inject_stylesheet = function(url) {
26098    var link;
26099    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
26100      link = document.createElement("link");
26101      link.setAttribute("rel", "stylesheet");
26102      link.setAttribute("href", url);
26103      return this.el.head.appendChild(link);
26104    }
26105  };
26106
26107  Share.prototype.inject_css = function(instance) {
26108    var css, meta, selector, style;
26109    selector = "." + (instance.getAttribute('class').split(" ").join("."));
26110    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
26111      this.config.selector = selector;
26112      css = getStyles(this.config);
26113      style = document.createElement("style");
26114      style.type = "text/css";
26115      if (style.styleSheet) {
26116        style.styleSheet.cssText = css;
26117      } else {
26118        style.appendChild(document.createTextNode(css));
26119      }
26120      this.el.head.appendChild(style);
26121      delete this.config.selector;
26122      meta = document.createElement("meta");
26123      meta.setAttribute("name", "sharer" + selector);
26124      return this.el.head.appendChild(meta);
26125    }
26126  };
26127
26128  Share.prototype.inject_html = function(instance) {
26129    //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>";
26130    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>";
26131  };
26132
26133  Share.prototype.inject_facebook_sdk = function() {
26134    var fb_root, script;
26135    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
26136      script = document.createElement("script");
26137      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')";
26138      fb_root = document.createElement("div");
26139      fb_root.id = "fb-root";
26140      this.el.body.appendChild(fb_root);
26141      return this.el.body.appendChild(script);
26142    }
26143  };
26144
26145  Share.prototype.hook = function(type, network, instance) {
26146    var fn, opts;
26147    fn = this.config.networks[network][type];
26148    if (typeof fn === "function") {
26149      opts = fn.call(this.config.networks[network], instance);
26150      if (opts !== void 0) {
26151        opts = this.normalize_filter_config_updates(opts);
26152        this.extend(this.config.networks[network], opts, true);
26153        this.normalize_network_configuration();
26154      }
26155    }
26156  };
26157
26158  Share.prototype.default_title = function() {
26159    var content;
26160    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
26161      return encodeURIComponent(content.getAttribute('content'));
26162    } else if (content = document.querySelector('title')) {
26163      return encodeURIComponent(content.innerText);
26164    }
26165  };
26166
26167  Share.prototype.default_image = function() {
26168    var content;
26169    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
26170      return content.getAttribute('content');
26171    }
26172  };
26173
26174  Share.prototype.default_description = function() {
26175    var content;
26176    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
26177      return encodeURIComponent(content.getAttribute('content'));
26178    } else {
26179      return '';
26180    }
26181  };
26182
26183  Share.prototype.set_global_configuration = function() {
26184    var display, network, option, options, _ref, _results;
26185    _ref = this.config.networks;
26186    _results = [];
26187    for (network in _ref) {
26188      options = _ref[network];
26189      for (option in options) {
26190        if (this.config.networks[network][option] == null) {
26191          this.config.networks[network][option] = this.config[option];
26192        }
26193      }
26194      if (this.config.networks[network].enabled) {
26195        display = 'block';
26196        this.config.enabled_networks += 1;
26197      } else {
26198        display = 'none';
26199      }
26200      _results.push(this.config.networks[network].display = display);
26201    }
26202    return _results;
26203  };
26204
26205  Share.prototype.normalize_network_configuration = function() {
26206    if (!this.config.networks.facebook.app_id) {
26207      this.config.networks.facebook.load_sdk = false;
26208    }
26209    if (!this.is_encoded(this.config.networks.twitter.description)) {
26210      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
26211    }
26212    if (typeof this.config.networks.facebook.app_id === 'number') {
26213      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
26214    }
26215  };
26216
26217  Share.prototype.normalize_filter_config_updates = function(opts) {
26218    if (this.config.networks.facebook.app_id !== opts.app_id) {
26219      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.");
26220      delete opts.app_id;
26221    }
26222    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
26223      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.");
26224      delete opts.app_id;
26225    }
26226    return opts;
26227  };
26228
26229  return Share;
26230
26231})(ShareUtils);
26232 return Share;
26233});
26234
26235// Generated by CoffeeScript 1.9.2
26236
26237// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
26238
26239(function() {
26240  var $, win;
26241
26242  $ = this.jQuery || window.jQuery;
26243
26244  win = $(window);
26245
26246  $.fn.stick_in_parent = function(opts) {
26247    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
26248    if (opts == null) {
26249      opts = {};
26250    }
26251    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;
26252    if (offset_top == null) {
26253      offset_top = 0;
26254    }
26255    if (parent_selector == null) {
26256      parent_selector = void 0;
26257    }
26258    if (inner_scrolling == null) {
26259      inner_scrolling = true;
26260    }
26261    if (sticky_class == null) {
26262      sticky_class = "is_stuck";
26263    }
26264    doc = $(document);
26265    if (enable_bottoming == null) {
26266      enable_bottoming = true;
26267    }
26268    outer_width = function(el) {
26269      var _el, computed, w;
26270      if (window.getComputedStyle) {
26271        _el = el[0];
26272        computed = window.getComputedStyle(el[0]);
26273        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
26274        if (computed.getPropertyValue("box-sizing") !== "border-box") {
26275          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
26276        }
26277        return w;
26278      } else {
26279        return el.outerWidth(true);
26280      }
26281    };
26282    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
26283      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
26284      if (elm.data("sticky_kit")) {
26285        return;
26286      }
26287      elm.data("sticky_kit", true);
26288      last_scroll_height = doc.height();
26289      parent = elm.parent();
26290      if (parent_selector != null) {
26291        parent = parent.closest(parent_selector);
26292      }
26293      if (!parent.length) {
26294        throw "failed to find stick parent";
26295      }
26296      fixed = false;
26297      bottomed = false;
26298      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
26299      if (spacer) {
26300        spacer.css('position', elm.css('position'));
26301      }
26302      recalc = function() {
26303        var border_top, padding_top, restore;
26304        if (detached) {
26305          return;
26306        }
26307        last_scroll_height = doc.height();
26308        border_top = parseInt(parent.css("border-top-width"), 10);
26309        padding_top = parseInt(parent.css("padding-top"), 10);
26310        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
26311        parent_top = parent.offset().top + border_top + padding_top;
26312        parent_height = parent.height();
26313        if (fixed) {
26314          fixed = false;
vendor: 6,068 bytes, lines 26315-26509
26315          bottomed = false;
26316          if (manual_spacer == null) {
26317            elm.insertAfter(spacer);
26318            spacer.detach();
26319          }
26320          elm.css({
26321            position: "",
26322            top: "",
26323            width: "",
26324            bottom: ""
26325          }).removeClass(sticky_class);
26326          restore = true;
26327        }
26328        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
26329        height = elm.outerHeight(true);
26330        el_float = elm.css("float");
26331        if (spacer) {
26332          spacer.css({
26333            width: outer_width(elm),
26334            height: height,
26335            display: elm.css("display"),
26336            "vertical-align": elm.css("vertical-align"),
26337            "float": el_float
26338          });
26339        }
26340        if (restore) {
26341          return tick();
26342        }
26343      };
26344      recalc();
26345      if (height === parent_height) {
26346        return;
26347      }
26348      last_pos = void 0;
26349      offset = offset_top;
26350      recalc_counter = recalc_every;
26351      tick = function() {
26352        var css, delta, recalced, scroll, will_bottom, win_height;
26353        if (detached) {
26354          return;
26355        }
26356        recalced = false;
26357        if (recalc_counter != null) {
26358          recalc_counter -= 1;
26359          if (recalc_counter <= 0) {
26360            recalc_counter = recalc_every;
26361            recalc();
26362            recalced = true;
26363          }
26364        }
26365        if (!recalced && doc.height() !== last_scroll_height) {
26366          recalc();
26367          recalced = true;
26368        }
26369        scroll = win.scrollTop();
26370        if (last_pos != null) {
26371          delta = scroll - last_pos;
26372        }
26373        last_pos = scroll;
26374        if (fixed) {
26375          if (enable_bottoming) {
26376            will_bottom = scroll + height + offset > parent_height + parent_top;
26377            if (bottomed && !will_bottom) {
26378              bottomed = false;
26379              elm.css({
26380                position: "fixed",
26381                bottom: "",
26382                top: offset
26383              }).trigger("sticky_kit:unbottom");
26384            }
26385          }
26386          if (scroll < top) {
26387            fixed = false;
26388            offset = offset_top;
26389            if (manual_spacer == null) {
26390              if (el_float === "left" || el_float === "right") {
26391                elm.insertAfter(spacer);
26392              }
26393              spacer.detach();
26394            }
26395            css = {
26396              position: "",
26397              width: "",
26398              top: ""
26399            };
26400            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
26401          }
26402          if (inner_scrolling) {
26403            win_height = win.height();
26404            if (height + offset_top > win_height) {
26405              if (!bottomed) {
26406                offset -= delta;
26407                offset = Math.max(win_height - height, offset);
26408                offset = Math.min(offset_top, offset);
26409                if (fixed) {
26410                  elm.css({
26411                    top: offset + "px"
26412                  });
26413                }
26414              }
26415            }
26416          }
26417        } else {
26418          if (scroll > top) {
26419            fixed = true;
26420            css = {
26421              position: "fixed",
26422              top: offset
26423            };
26424            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
26425            elm.css(css).addClass(sticky_class);
26426            if (manual_spacer == null) {
26427              elm.after(spacer);
26428              if (el_float === "left" || el_float === "right") {
26429                spacer.append(elm);
26430              }
26431            }
26432            elm.trigger("sticky_kit:stick");
26433          }
26434        }
26435        if (fixed && enable_bottoming) {
26436          if (will_bottom == null) {
26437            will_bottom = scroll + height + offset > parent_height + parent_top;
26438          }
26439          if (!bottomed && will_bottom) {
26440            bottomed = true;
26441            if (parent.css("position") === "static") {
26442              parent.css({
26443                position: "relative"
26444              });
26445            }
26446            return elm.css({
26447              position: "absolute",
26448              bottom: padding_bottom,
26449              top: "auto"
26450            }).trigger("sticky_kit:bottom");
26451          }
26452        }
26453      };
26454      recalc_and_tick = function() {
26455        recalc();
26456        return tick();
26457      };
26458      detach = function() {
26459        detached = true;
26460        win.off("touchmove", tick);
26461        win.off("scroll", tick);
26462        win.off("resize", recalc_and_tick);
26463        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
26464        elm.off("sticky_kit:detach", detach);
26465        elm.removeData("sticky_kit");
26466        elm.css({
26467          position: "",
26468          bottom: "",
26469          top: "",
26470          width: ""
26471        });
26472        parent.position("position", "");
26473        if (fixed) {
26474          if (manual_spacer == null) {
26475            if (el_float === "left" || el_float === "right") {
26476              elm.insertAfter(spacer);
26477            }
26478            spacer.remove();
26479          }
26480          return elm.removeClass(sticky_class);
26481        }
26482      };
26483      win.on("touchmove", tick);
26484      win.on("scroll", tick);
26485      win.on("resize", recalc_and_tick);
26486      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
26487      elm.on("sticky_kit:detach", detach);
26488      return setTimeout(tick, 0);
26489    };
26490    for (i = 0, len = this.length; i < len; i++) {
26491      elm = this[i];
26492      fn($(elm));
26493    }
26494    return this;
26495  };
26496
26497}).call(this);
26498/* ==========================================================================
26499 * bootstrap-tab-history.js
26500 * Author: Michael Narayan <[email protected]>
26501 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
26502 * ==========================================================================
26503 * Licensed under the Apache License, Version 2.0 (the "License"); you may
26504 * not use this file except in compliance with the License. You may obtain a
26505 * copy of the License at
26506 *
26507 * http://www.apache.org/licenses/LICENSE-2.0
26508 *
26509 * Unless required by applicable law or agreed to in writing, softw
26509are
26510 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
26511 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26512 * License for the specific language governing permissions and limitations
26513 * under the License.
26514 * ========================================================================== */
26515
26516/* ========================================================================== */
26517/* JSHint directives                                                          */
26518/*                                                                            */
26519/* global BootstrapTabHistory: true                                           */
26520/*                                                                            */
26521/* global document                                                            */
26522/* global jQuery                                                              */
26523/* global history                                                             */
26524/* global window                                                              */
26525/* ========================================================================== */
26526
26527/**
26528 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
26529 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
26530 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
26531 *
26532 * See the README for additional information.
26533 *
26534 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
26535 */
26536
26537BootstrapTabHistory = {
26538  options: {
26539    /**
26540     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
26541     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
26542     *
26543     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
26544     *
26545     * @public
26546     * @type {?number}
26547     */
26548    defaultAnchorYOffset: 0,
26549    /**
26550     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
26551     *
26552     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
26553     *
26554     * @public
26555     * @type {string}
26556     */
26557    defaultChanger: 'replace',
26558    /**
26559     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
26560     * `null` is passed as the third parameter to these calls.
26561     *
26562     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
26563     *
26564     * @public
26565     * @type {boolean}
26566     */
26567    defaultUpdateURL: false,
26568    /**
26569     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
26570     * load.
26571     *
26572     * @public
26573     * @type {boolean}
26574     */
26575    showTabsBasedOnAnchor: true
26576  }
26577};
26578
26579(function () {
26580  'use strict';
26581
26582  jQuery(function () {
26583    if(history && history.pushState && history.replaceState) {
26584      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
26585
26586      if(bootstrapTabHistory) {
26587        showTabsBasedOnState(bootstrapTabHistory);
26588      } else {
26589        showTabsBasedOnAnchor();
26590      }
26591
26592      backfillHistoryState();
26593
26594      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
26595      jQuery(window).on('popstate', onPopState);
26596    } else {
26597      showTabsBasedOnAnchor();
26598    }
26599  });
26600
26601  /**
26602   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
26603   *
26604   * @type {boolean}
26605   */
26606  var showingTabsBasedOnState = false;
26607
26608  /**
26609   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
26610   * `history.back` handling when `data-tab-history-update-url` is true.
26611   */
26612  function backfillHistoryState() {
26613    var newState = null;
26614
26615    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
26616      var $activeTabElement = jQuery(this);
26617      var selector = getTabSelector($activeTabElement);
26618
26619      if(selector) {
26620        var tabGroup = getTabGroup($activeTabElement);
26621
26622        if(tabGroup) {
26623          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
26624        }
26625      }
26626    });
26627
26628    if(newState) {
26629      history.replaceState(newState, '', null);
26630    }
26631  }
26632
26633  /**
26634   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
26635   * said bootstrapTabHistory attribute.
26636   *
26637   * @param {?object} existingState
26638   * @param {!string} tabGroup
26639   * @param {!string} selector
26640   * @returns {!object}
26641   */
26642  function createNewHistoryState(existingState, tabGroup, selector) {
26643    // Clone history.state and ensure it has a bootstrapTabHistory entry.
26644    var newState = jQuery.extend(true, {}, existingState, {
26645      bootstrapTabHistory: {}
26646    });
26647
26648    newState.bootstrapTabHistory[tabGroup] = selector;
26649
26650    return newState;
26651  }
26652
26653  /**
26654   * @param {jQuery} $tab
26655   * @returns {?string}
26656   */
26657  function getTabGroup($tab) {
26658    return parseTruthyAttributeValue($tab.data('tab-history'));
26659  }
26660
26661  /**
26662   * @param {jQuery} $tab
26663   * @returns {?string}
26664   */
26665  function getTabSelector($tab) {
26666    return $tab.data('target') || $tab.attr('href');
26667  }
26668
26669  /**
26670   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
26671   *
26672   * @param {jQuery.Event} shownEvt
26673   */
26674  function onShownTab(shownEvt) {
26675    if(!showingTabsBasedOnState) {
26676      var $activatedTab = jQuery(shownEvt.target);
26677      if ( $activatedTab.hasClass('panel-collapse') )
26678        $activatedTab = $activatedTab.closest('.panel').find('a');
26679      var selector = getTabSelector($activatedTab);
26680
26681      if(selector) {
26682        var tabGroup = getTabGroup($activatedTab);
26683
26684        if(tabGroup) {
26685          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
26686          var newState = createNewHistoryState(history.state, tabGroup, selector);
26687          var updateURL = (function ($activatedTab) {
26688            if(selector[0] === '#') {
26689              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
26690
26691              if(elementUpdateURLOption === undefined) {
26692                return BootstrapTabHistory.options.defaultUpdateURL;
26693              } else {
26694                return elementUpdateURLOption;
26695              }
26696            } else {
26697              return false;
26698            }
26699          })($activatedTab);
26700
26701          switch(historyChanger) {
26702            case 'push':
26703              history.pushState(newState, '', updateURL ? selector : null);
26704              break;
26705            case 'replace':
26706              history.replaceState(newState, '', updateURL ? selector : null);
26707              break;
26708            default:
26709              throw new Error('Unknown tab-history-changer: ' + historyChanger);
26710          }
26711        }
26712      }
26713    }
26714  }
26715
26716  /**
26717   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
26718   */
26719  function onPopState() {
26720    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
26721
26722    if(bootstrapTabHistory) {
26723      showTabsBasedOnState(bootstrapTabHistory);
26724    }
26725  }
26726
26727  /**
26728   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
26729   *
26730   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
26731   *
26732   * @param {*} value
26733   * @returns {*}
26734   */
26735  function parseTruthyAttributeValue(value) {
26736    if(value) {
26737      return value;
26738    } else if(value === '') {
26739      return true;
26740    } else {
26741      return value;
26742    }
26743  }
26744
26745  /**
26746   * Show tabs based upon the anchor component of `window.location`.
26747   */
26748  function showTabsBasedOnAnchor() {
26749    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
26750      var anchor = window.location && window.location.hash;
26751
26752      if(anchor) {
26753        var $tabElement = showTabForSelector(anchor);
26754
26755        if($tabElement && window.addEventListener && window.removeEventListener) {
26756          var anchorYOffset = (function ($tabElement) {
26757            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
26758
26759            if(elementSetting === undefined) {
26760              return BootstrapTabHistory.options.defaultAnchorYOffset;
26761            } else {
26762              return elementSetting;
26763            }
26764          })($tabElement);
26765
26766          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
26767          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
26768          //   `history.state` object should have been used (unless the browser did not support the modern History API).
26769          if(anchorYOffset || anchorYOffset === 0) {
26770            var scrollListener = function resetAnchorScroll () {
26771              window.removeEventListener('scroll', scrollListener);
26772              window.scrollTo(0, anchorYOffset);
26773            };
26774
26775            window.addEventListener('scroll', scrollListener);
26776          }
26777        }
26778      }
26779    }
26780  }
26781
26782  /**
26783   * Show a tab which corresponds to the provided selector.
26784   *
26785   * @param {string} selector - A CSS selector.
26786   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
26787   */
26788  function showTabForSelector(selector) {
26789    var $tabElement = (function (selector) {
26790      var $ret = null;
26791
26792      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
26793        var $potentialTab = jQuery(this);
26794
26795        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
26796          $ret = $potentialTab;
26797          return false;
vendor: 43,417 bytes, lines 26798-28012
26798        } else {
26799         return null;
26800        }
26801      });
26802
26803      return $ret;
26804    })(selector);
26805
26806    if($tabElement) {
26807      $tabElement.trigger('click');
26808      //$tabElement.tab('show');
26809    }
26810
26811    return $tabElement;
26812  }
26813
26814  /**
26815   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
26816   *
26817   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
26818   */
26819  function showTabsBasedOnState(bootstrapTabHistory) {
26820    showingTabsBasedOnState = true;
26821
26822    try {
26823      for(var k in bootstrapTabHistory) {
26824        if(bootstrapTabHistory.hasOwnProperty(k)) {
26825          showTabForSelector(bootstrapTabHistory[k]);
26826        }
26827      }
26828    } finally {
26829      showingTabsBasedOnState = false;
26830    }
26831  }
26832})();
26833
26834/*!
26835 * justifiedGallery - v3.8.1
26836 * http://miromannino.github.io/Justified-Gallery/
26837 * Copyright (c) 2020 Miro Mannino
26838 * Licensed under the MIT license.
26839 */
26840(function (factory) {
26841  if (typeof define === 'function' && define.amd) {
26842    // AMD. Register as an anonymous module.
26843    define(['jquery'], factory);
26844  } else if (typeof module === 'object' && module.exports) {
26845    // Node/CommonJS
26846    module.exports = function (root, jQuery) {
26847      if (jQuery === undefined) {
26848        // require('jQuery') returns a factory that requires window to
26849        // build a jQuery instance, we normalize how we use modules
26850        // that require this pattern but the window provided is a noop
26851        // if it's defined (how jquery works)
26852        if (typeof window !== 'undefined') {
26853          jQuery = require('jquery');
26854        }
26855        else {
26856          jQuery = require('jquery')(root);
26857        }
26858      }
26859      factory(jQuery);
26860      return jQuery;
26861    };
26862  } else {
26863    // Browser globals
26864    factory(jQuery);
26865  }
26866}(function ($) {
26867
26868  /**
26869   * Justified Gallery controller constructor
26870   *
26871   * @param $gallery the gallery to build
26872   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
26873   * @constructor
26874   */
26875  var JustifiedGallery = function ($gallery, settings) {
26876
26877    this.settings = settings;
26878    this.checkSettings();
26879
26880    this.imgAnalyzerTimeout = null;
26881    this.entries = null;
26882    this.buildingRow = {
26883      entriesBuff: [],
26884      width: 0,
26885      height: 0,
26886      aspectRatio: 0
26887    };
26888    this.lastFetchedEntry = null;
26889    this.lastAnalyzedIndex = -1;
26890    this.yield = {
26891      every: 2, // do a flush every n flushes (must be greater than 1)
26892      flushed: 0 // flushed rows without a yield
26893    };
26894    this.border = settings.border >= 0 ? settings.border : settings.margins;
26895    this.maxRowHeight = this.retrieveMaxRowHeight();
26896    this.suffixRanges = this.retrieveSuffixRanges();
26897    this.offY = this.border;
26898    this.rows = 0;
26899    this.spinner = {
26900      phase: 0,
26901      timeSlot: 150,
26902      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
26903      intervalId: null
26904    };
26905    this.scrollBarOn = false;
26906    this.checkWidthIntervalId = null;
26907    this.galleryWidth = $gallery.width();
26908    this.$gallery = $gallery;
26909
26910  };
26911
26912  /** @returns {String} the best suffix given the width and the height */
26913  JustifiedGallery.prototype.getSuffix = function (width, height) {
26914    var longestSide, i;
26915    longestSide = (width > height) ? width : height;
26916    for (i = 0; i < this.suffixRanges.length; i++) {
26917      if (longestSide <= this.suffixRanges[i]) {
26918        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
26919      }
26920    }
26921    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
26922  };
26923
26924  /**
26925   * Remove the suffix from the string
26926   *
26927   * @returns {string} a new string without the suffix
26928   */
26929  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
26930    return str.substring(0, str.length - suffix.length);
26931  };
26932
26933  /**
26934   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
26935   */
26936  JustifiedGallery.prototype.endsWith = function (str, suffix) {
26937    return str.indexOf(suffix, str.length - suffix.length) !== -1;
26938  };
26939
26940  /**
26941   * Get the used suffix of a particular url
26942   *
26943   * @param str
26944   * @returns {String} return the used suffix
26945   */
26946  JustifiedGallery.prototype.getUsedSuffix = function (str) {
26947    for (var si in this.settings.sizeRangeSuffixes) {
26948      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
26949        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
26950        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
26951      }
26952    }
26953    return '';
26954  };
26955
26956  /**
26957   * Given an image src, with the width and the height, returns the new image src with the
26958   * best suffix to show the best quality thumbnail.
26959   *
26960   * @returns {String} the suffix to use
26961   */
26962  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
26963    var newImageSrc;
26964
26965    if (this.settings.thumbnailPath) {
26966      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
26967    } else {
26968      var matchRes = imageSrc.match(this.settings.extension);
26969      var ext = (matchRes !== null) ? matchRes[0] : '';
26970      newImageSrc = imageSrc.replace(this.settings.extension, '');
26971      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
26972      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
26973    }
26974
26975    return newImageSrc;
26976  };
26977
26978  /**
26979   * Shows the images that is in the given entry
26980   *
26981   * @param $entry the entry
26982   * @param callback the callback that is called when the show animation is finished
26983   */
26984  JustifiedGallery.prototype.showImg = function ($entry, callback) {
26985    if (this.settings.cssAnimation) {
26986      $entry.addClass('jg-entry-visible');
26987      if (callback) callback();
26988    } else {
26989      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
26990      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
26991    }
26992  };
26993
26994  /**
26995   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
26996   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
26997   *
26998   * @param $image the image to analyze
26999   * @returns {String} the extracted src
27000   */
27001  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27002    var imageSrc = $image.data('safe-src');
27003    var imageSrcLoc = 'data-safe-src';
27004    // Begin Uncode edit
27005    if (typeof imageSrc === 'undefined') {
27006    	var imageCurrentSrc = $image[0].currentSrc;
27007    	if (imageCurrentSrc) {
27008    		imageSrc = imageCurrentSrc;
27009    	} else {
27010    		imageSrc = $image.attr('src');
27011    	}
27012		imageSrcLoc = 'src';
27013    }
27014    // End Uncode edit
27015    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27016    $image.data('jg.src', imageSrc); // this will change overtime
27017    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27018    return imageSrc;
27019  };
27020
27021  /** @returns {jQuery} the image in the given entry */
27022  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27023    var $img = $entry.find(this.settings.imgSelector);
27024    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27025    return $img.length === 0 ? null : $img;
27026  };
27027
27028  /** @returns {jQuery} the caption in the given entry */
27029  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27030    var $caption = $entry.find('> .jg-caption');
27031    return $caption.length === 0 ? null : $caption;
27032  };
27033
27034  /**
27035   * Display the entry
27036   *
27037   * @param {jQuery} $entry the entry to display
27038   * @param {int} x the x position where the entry must be positioned
27039   * @param y the y position where the entry must be positioned
27040   * @param imgWidth the image width
27041   * @param imgHeight the image height
27042   * @param rowHeight the row height of the row that owns the entry
27043   */
27044  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27045    $entry.width(imgWidth);
27046    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27047    $entry.css('top', Math.floor(y));//hacked by Uncode
27048    $entry.css('left', x);
27049
27050    var $image = this.imgFromEntry($entry);
27051    if ($image !== null) {
27052      $image.css('width', imgWidth);
27053      $image.css('height', imgHeight);
27054      $image.css('margin-left', - imgWidth / 2);
27055      $image.css('margin-top', - imgHeight / 2);
27056
27057      // Image reloading for an high quality of thumbnails
27058      var imageSrc = $image.data('jg.src');
27059      if (imageSrc) {
27060        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27061
27062        $image.one('error', function () {
27063           this.resetImgSrc($image); //revert to the original thumbnail
27064        });
27065
27066        var loadNewImage = function () {
27067          // if (imageSrc !== newImageSrc) {
27068            $image.attr('src', imageSrc);
27069          // }
27070        };
27071
27072        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27073          this.onImageEvent(imageSrc, (function() {
27074            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27075            $entry.data('jg.loaded', true);
27076          }).bind(this));
27077        } else {
27078          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27079        }
27080
27081      }
27082
27083    } else {
27084      this.showImg($entry);
27085    }
27086
27087    this.displayEntryCaption($entry);
27088  };
27089
27090  /**
27091   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
27092   * or the 'title' attributes.
27093   *
27094   * @param {jQuery} $entry the entry to process
27095   */
27096  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
27097    var $image = this.imgFromEntry($entry);
27098    if ($image !== null && this.settings.captions) {
27099      var $imgCaption = this.captionFromEntry($entry);
27100
27101      // Create it if it doesn't exists
27102      if ($imgCaption === null) {
27103        var caption = $image.attr('alt');
27104        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
27105        if (this.isValidCaption(caption)) { // Create only we found something
27106          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
27107          $entry.append($imgCaption);
27108          $entry.data('jg.createdCaption', true);
27109        }
27110      }
27111
27112      // Create events (we check again the $imgCaption because it can be still inexistent)
27113      if ($imgCaption !== null) {
27114        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
27115        this.addCaptionEventsHandlers($entry);
27116      }
27117    } else {
27118      this.removeCaptionEventsHandlers($entry);
27119    }
27120  };
27121
27122  /**
27123   * Validates the caption
27124   *
27125   * @param caption The caption that should be validated
27126   * @return {boolean} Validation result
27127   */
27128  JustifiedGallery.prototype.isValidCaption = function (caption) {
27129    return (typeof caption !== 'undefined' && caption.length > 0);
27130  };
27131
27132  /**
27133   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
27134   * It shows the caption using jQuery (or using CSS if it is configured so)
27135   *
27136   * @param {Event} eventObject the event object
27137   */
27138  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
27139    var $caption = this.captionFromEntry($(eventObject.currentTarget));
27140    if (this.settings.cssAnimation) {
27141      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
27142    } else {
27143      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
27144        this.settings.captionSettings.visibleOpacity);
27145    }
27146  };
27147
27148  /**
27149   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
27150   * It hides the caption using jQuery (or using CSS if it is configured so)
27151   *
27152   * @param {Event} eventObject the event object
27153   */
27154  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
27155    var $caption = this.captionFromEntry($(eventObject.currentTarget));
27156    if (this.settings.cssAnimation) {
27157      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
27158    } else {
27159      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
27160        this.settings.captionSettings.nonVisibleOpacity);
27161    }
27162  };
27163
27164  /**
27165   * Add the handlers of the entry for the caption
27166   *
27167   * @param $entry the entry to modify
27168   */
27169  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
27170    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
27171    if (typeof captionMouseEvents === 'undefined') {
27172      captionMouseEvents = {
27173        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
27174        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
27175      };
27176      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
27177      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
27178      $entry.data('jg.captionMouseEvents', captionMouseEvents);
27179    }
27180  };
27181
27182  /**
27183   * Remove the handlers of the entry for the caption
27184   *
27185   * @param $entry the entry to modify
27186   */
27187  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
27188    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
27189    if (typeof captionMouseEvents !== 'undefined') {
27190      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
27191      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
27192      $entry.removeData('jg.captionMouseEvents');
27193    }
27194  };
27195
27196  /**
27197   * Clear the building row data to be used for a new row
27198   */
27199  JustifiedGallery.prototype.clearBuildingRow = function () {
27200    this.buildingRow.entriesBuff = [];
27201    this.buildingRow.aspectRatio = 0;
27202    this.buildingRow.width = 0;
27203  };
27204
27205  /**
27206   * Justify the building row, preparing it to
27207   *
27208   * @param isLastRow
27209   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
27210   * @returns a boolean to know if the row has been justified or not
27211   */
27212  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
27213    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
27214    var minHeight = 0;
27215    var availableWidth = this.galleryWidth - 2 * this.border - (
27216      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
27217    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
27218    var defaultRowHeight = this.settings.rowHeight;
27219    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
27220
27221    //Skip the last row if we can't justify it and the lastRow == 'hide'
27222    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
27223      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
27224        $entry = this.buildingRow.entriesBuff[i];
27225        if (this.settings.cssAnimation)
27226          $entry.removeClass('jg-entry-visible');
27227        else {
27228          $entry.stop().fadeTo(0, 0.1);
27229          $entry.find('> img, > a > img').fadeTo(0, 0);
27230        }
27231      }
27232      return -1;
27233    }
27234
27235    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
27236    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
27237      justify = false;
27238
27239      if (this.rows > 0) {
27240        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
27241        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
27242      }
27243    }
27244
27245    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
27246      $entry = this.buildingRow.entriesBuff[i];
27247      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
27248
27249      if (justify) {
27250        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
27251        newImgH = rowHeight;
27252      } else {
27253        newImgW = defaultRowHeight * imgAspectRatio;
27254        newImgH = defaultRowHeight;
27255      }
27256
27257      availableWidth -= Math.round(newImgW);
27258      $entry.data('jg.jwidth', Math.round(newImgW));
27259      $entry.data('jg.jheight', Math.ceil(newImgH));
27260      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
27261    }
27262
27263    this.buildingRow.height = minHeight;
27264    return justify;
27265  };
27266
27267  /**
27268   * Flush a row: justify it, modify the gallery height accordingly to the row height
27269   *
27270   * @param isLastRow
27271   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
27272   */
27273  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
27274    var settings = this.settings;
27275    var $entry, buildingRowRes, offX = this.border, i;
27276
27277    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
27278    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
27279      this.clearBuildingRow();
27280      return;
27281    }
27282
27283    if (this.maxRowHeight) {
27284      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
27285    }
27286
27287    //Align last (unjustified) row
27288    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
27289      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
27290
27291      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
27292        $entry = this.buildingRow.entriesBuff[i];
27293        availableWidth -= $entry.data('jg.jwidth');
27294      }
27295
27296      if (settings.lastRow === 'center')
27297        offX += Math.round(availableWidth / 2);
27298      else if (settings.lastRow === 'right')
27299        offX += availableWidth;
27300    }
27301
27302    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
27303    for (i = 0; i <= lastEntryIdx; i++) {
27304      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
27305      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
27306      offX += $entry.data('jg.jwidth') + settings.margins;
27307    }
27308
27309    //Gallery Height
27310    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
27311    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
27312
27313    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
27314      //Ready for a new row
27315      this.offY += this.buildingRow.height + settings.margins;
27316      this.rows += 1;
27317      this.clearBuildingRow();
27318      this.settings.triggerEvent.call(this, 'jg.rowflush');
27319    }
27320  };
27321
27322
27323  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
27324  var galleryPrevStaticHeight = 0;
27325
27326  JustifiedGallery.prototype.rememberGalleryHeight = function () {
27327    galleryPrevStaticHeight = this.$gallery.height();
27328    this.$gallery.height(galleryPrevStaticHeight);
27329  };
27330
27331  // grow only
27332  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
27333    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
27334    this.$gallery.height(galleryPrevStaticHeight);
27335  };
27336
27337  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
27338    galleryPrevStaticHeight = height;
27339    this.$gallery.height(height);
27340  };
27341
27342  /**
27343   * Checks the width of the gallery container, to know if a new justification is needed
27344   */
27345  JustifiedGallery.prototype.checkWidth = function () {
27346    this.checkWidthIntervalId = setInterval($.proxy(function () {
27347
27348      // if the gallery is not currently visible, abort.
27349      if (!this.$gallery.is(":visible")) return;
27350
27351      var galleryWidth = parseFloat(this.$gallery.width());
27352      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
27353        this.galleryWidth = galleryWidth;
27354        this.rewind();
27355
27356        this.rememberGalleryHeight();
27357
27358        // Restart to analyze
27359        this.startImgAnalyzer(true);
27360      }
27361    }, this), this.settings.refreshTime);
27362  };
27363
27364  /**
27365   * @returns {boolean} a boolean saying if the spinner is active or not
27366   */
27367  JustifiedGallery.prototype.isSpinnerActive = function () {
27368    return this.spinner.intervalId !== null;
27369  };
27370
27371  /**
27372   * @returns {int} the spinner height
27373   */
27374  JustifiedGallery.prototype.getSpinnerHeight = function () {
27375    return this.spinner.$el.innerHeight();
27376  };
27377
27378  /**
27379   * Stops the spinner animation and modify the gallery height to exclude the spinner
27380   */
27381  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
27382    clearInterval(this.spinner.intervalId);
27383    this.spinner.intervalId = null;
27384    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
27385    this.spinner.$el.detach();
27386  };
27387
27388  /**
27389   * Starts the spinner animation
27390   */
27391  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
27392    var spinnerContext = this.spinner;
27393    var $spinnerPoints = spinnerContext.$el.find('span');
27394    clearInterval(spinnerContext.intervalId);
27395    this.$gallery.append(spinnerContext.$el);
27396    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
27397    spinnerContext.intervalId = setInterval(function () {
27398      if (spinnerContext.phase < $spinnerPoints.length) {
27399        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
27400      } else {
27401        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
27402      }
27403      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
27404    }, spinnerContext.timeSlot);
27405  };
27406
27407  /**
27408   * Rewind the image analysis to start from the first entry.
27409   */
27410  JustifiedGallery.prototype.rewind = function () {
27411    this.lastFetchedEntry = null;
27412    this.lastAnalyzedIndex = -1;
27413    this.offY = this.border;
27414    this.rows = 0;
27415    this.clearBuildingRow();
27416  };
27417
27418  /**
27419   * @returns {String} `settings.selector` rejecting spinner element
27420   */
27421  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
27422    return this.settings.selector + ', div:not(.jg-spinner)';
27423  };
27424
27425  /**
27426   * @returns {Array} all entries matched by `settings.selector`
27427   */
27428  JustifiedGallery.prototype.getAllEntries = function () {
27429    var selector = this.getSelectorWithoutSpinner();
27430    return this.$gallery.children(selector).toArray();
27431  };
27432
27433  /**
27434   * Update the entries searching it from the justified gallery HTML element
27435   *
27436   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
27437   * @returns {boolean} true if some entries has been founded
27438   */
27439  JustifiedGallery.prototype.updateEntries = function (norewind) {
27440    var newEntries;
27441
27442    if (norewind && this.lastFetchedEntry != null) {
27443      var selector = this.getSelectorWithoutSpinner();
27444      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
27445    } else {
27446      this.entries = [];
27447      newEntries = this.getAllEntries();
27448    }
27449
27450    if (newEntries.length > 0) {
27451
27452      // Sort or randomize
27453      if ($.isFunction(this.settings.sort)) {
27454        newEntries = this.sortArray(newEntries);
27455      } else if (this.settings.randomize) {
27456        newEntries = this.shuffleArray(newEntries);
27457      }
27458      this.lastFetchedEntry = newEntries[newEntries.length - 1];
27459
27460      // Filter
27461      if (this.settings.filter) {
27462        newEntries = this.filterArray(newEntries);
27463      } else {
27464        this.resetFilters(newEntries);
27465      }
27466
27467    }
27468
27469    this.entries = this.entries.concat(newEntries);
27470    return true;
27471  };
27472
27473  /**
27474   * Apply the entries order to the DOM, iterating the entries and appending the images
27475   *
27476   * @param entries the entries that has been modified and that must be re-ordered in the DOM
27477   */
27478  JustifiedGallery.prototype.insertToGallery = function (entries) {
27479    var that = this;
27480    $.each(entries, function () {
27481      $(this).appendTo(that.$gallery);
27482    });
27483  };
27484
27485  /**
27486   * Shuffle the array using the Fisher-Yates shuffle algorithm
27487   *
27488   * @param a the array to shuffle
27489   * @return the shuffled array
27490   */
27491  JustifiedGallery.prototype.shuffleArray = function (a) {
27492    var i, j, temp;
27493    for (i = a.length - 1; i > 0; i--) {
27494      j = Math.floor(Math.random() * (i + 1));
27495      temp = a[i];
27496      a[i] = a[j];
27497      a[j] = temp;
27498    }
27499    this.insertToGallery(a);
27500    return a;
27501  };
27502
27503  /**
27504   * Sort the array using settings.comparator as comparator
27505   *
27506   * @param a the array to sort (it is sorted)
27507   * @return the sorted array
27508   */
27509  JustifiedGallery.prototype.sortArray = function (a) {
27510    a.sort(this.settings.sort);
27511    this.insertToGallery(a);
27512    return a;
27513  };
27514
27515  /**
27516   * Reset the filters removing the 'jg-filtered' class from all the entries
27517   *
27518   * @param a the array to reset
27519   */
27520  JustifiedGallery.prototype.resetFilters = function (a) {
27521    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
27522  };
27523
27524  /**
27525   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
27526   *
27527   * @param a the array to filter
27528   * @return the filtered array
27529   */
27530  JustifiedGallery.prototype.filterArray = function (a) {
27531    var settings = this.settings;
27532    if ($.type(settings.filter) === 'string') {
27533      // Filter only keeping the entries passed in the string
27534      return a.filter(function (el) {
27535        var $el = $(el);
27536        if ($el.is(settings.filter)) {
27537          $el.removeClass('jg-filtered');
27538          return true;
27539        } else {
27540          $el.addClass('jg-filtered').removeClass('jg-visible');
27541          return false;
27542        }
27543      });
27544    } else if ($.isFunction(settings.filter)) {
27545      // Filter using the passed function
27546      var filteredArr = a.filter(settings.filter);
27547      for (var i = 0; i < a.length; i++) {
27548        if (filteredArr.indexOf(a[i]) === -1) {
27549          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
27550        } else {
27551          $(a[i]).removeClass('jg-filtered');
27552        }
27553      }
27554      return filteredArr;
27555    }
27556  };
27557
27558  /**
27559   * Revert the image src to the default value.
27560   */
27561  JustifiedGallery.prototype.resetImgSrc = function ($img) {
27562    if ($img.data('jg.originalSrcLoc') === 'src') {
27563      $img.attr('src', $img.data('jg.originalSrc'));
27564    } else {
27565      $img.attr('src', '');
27566    }
27567  };
27568
27569  /**
27570   * Destroy the Justified Gallery instance.
27571   *
27572   * It clears all the css properties added in the style attributes. We doesn't backup the original
27573   * values for those css attributes, because it costs (performance) and because in general one
27574   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
27575   * classes). Creating a backup is also difficult because JG could be called multiple times and
27576   * with different style attributes.
27577   */
27578  JustifiedGallery.prototype.destroy = function () {
27579    clearInterval(this.checkWidthIntervalId);
27580    this.stopImgAnalyzerStarter();
27581
27582    // Get fresh entries list since filtered entries are absent in `this.entries`
27583    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
27584      var $entry = $(entry);
27585
27586      // Reset entry style
27587      $entry.css('width', '');
27588      $entry.css('height', '');
27589      $entry.css('top', '');
27590      $entry.css('left', '');
27591      $entry.data('jg.loaded', undefined);
27592      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
27593
27594      // Reset image style
27595      var $img = this.imgFromEntry($entry);
27596      if ($img) {
27597        $img.css('width', '');
27598        $img.css('height', '');
27599        $img.css('margin-left', '');
27600        $img.css('margin-top', '');
27601        this.resetImgSrc($img);
27602        $img.data('jg.originalSrc', undefined);
27603        $img.data('jg.originalSrcLoc', undefined);
27604        $img.data('jg.src', undefined);
27605      }
27606
27607      // Remove caption
27608      this.removeCaptionEventsHandlers($entry);
27609      var $caption = this.captionFromEntry($entry);
27610      if ($entry.data('jg.createdCaption')) {
27611        // remove also the caption element (if created by jg)
27612        $entry.data('jg.createdCaption', undefined);
27613        if ($caption !== null) $caption.remove();
27614      } else {
27615        if ($caption !== null) $caption.fadeTo(0, 1);
27616      }
27617
27618    }, this));
27619
27620    this.$gallery.css('height', '');
27621    this.$gallery.removeClass('justified-gallery');
27622    this.$gallery.data('jg.controller', undefined);
27623    this.settings.triggerEvent.call(this, 'jg.destroy');
27624  };
27625
27626  /**
27627   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
27628   *
27629   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
27630   */
27631  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
27632    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
27633      var $entry = $(this.entries[i]);
27634      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
27635        var availableWidth = this.galleryWidth - 2 * this.border - (
27636          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
27637        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
27638
27639        this.buildingRow.entriesBuff.push($entry);
27640        this.buildingRow.aspectRatio += imgAspectRatio;
27641        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
27642        this.lastAnalyzedIndex = i;
27643
27644        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
27645          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
27646
27647          if (++this.yield.flushed >= this.yield.every) {
27648            this.startImgAnalyzer(isForResize);
27649            return;
27650          }
27651        }
27652      } else if ($entry.data('jg.loaded') !== 'error') {
27653        return;
27654      }
27655    }
27656
27657    // Last row flush (the row is not full)
27658    if (this.buildingRow.entriesBuff.length > 0) {
27659      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
27660    }
27661
27662    if (this.isSpinnerActive()) {
27663      this.stopLoadingSpinnerAnimation();
27664    }
27665
27666    /* Stop, if there is, the timeout to start the analyzeImages.
27667     This is because an image can be set loaded, and the timeout can be set,
27668     but this image can be analyzed yet.
27669     */
27670    this.stopImgAnalyzerStarter();
27671
27672    this.setGalleryFinalHeight(this.galleryHeightToSet);
27673
27674    //On complete callback
27675    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
27676  };
27677
27678  /**
27679   * Stops any ImgAnalyzer starter (that has an assigned timeout)
27680   */
27681  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
27682    this.yield.flushed = 0;
27683    if (this.imgAnalyzerTimeout !== null) {
27684      clearTimeout(this.imgAnalyzerTimeout);
27685      this.imgAnalyzerTimeout = null;
27686    }
27687  };
27688
27689  /**
27690   * Starts the image analyzer. It is not immediately called to let the browser to update the view
27691   *
27692   * @param isForResize specifies if the image analyzer must be called for resizing or not
27693   */
27694  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
27695    var that = this;
27696    this.stopImgAnalyzerStarter();
27697    this.imgAnalyzerTimeout = setTimeout(function () {
27698      that.analyzeImages(isForResize);
27699    }, 0.001); // we can't start it immediately due to a IE different behaviour
27700  };
27701
27702  /**
27703   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
27704   * because some browsers, with a 404 set complete = true.
27705   *
27706   * @param imageSrc the image src to load
27707   * @param onLoad callback that is called when the image has been loaded
27708   * @param onError callback that is called in case of an error
27709   */
27710  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
27711    if (!onLoad && !onError) return;
27712
27713    var memImage = new Image();
27714    var $memImage = $(memImage);
27715    if (onLoad) {
27716      $memImage.one('load', function () {
27717        $memImage.off('load error');
27718        onLoad(memImage);
27719      });
27720    }
27721    if (onError) {
27722      $memImage.one('error', function () {
27723        $memImage.off('load error');
27724        onError(memImage);
27725      });
27726    }
27727    memImage.src = imageSrc;
27728  };
27729
27730  /**
27731   * Init of Justified Gallery controlled
27732   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
27733   */
27734  JustifiedGallery.prototype.init = function () {
27735    var imagesToLoad = false, skippedImages = false, that = this;
27736    $.each(this.entries, function (index, entry) {
27737      var $entry = $(entry);
27738      var $image = that.imgFromEntry($entry);
27739
27740      $entry.addClass('jg-entry');
27741
27742      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
27743
27744        // Link Rel global overwrite
27745        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
27746
27747        // Link Target global overwrite
27748        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
27749
27750        if ($image !== null) {
27751
27752          // Image src
27753          var imageSrc = that.extractImgSrcFromImage($image);
27754
27755          /* If we have the height and the width, we don't wait that the image is loaded,
27756             but we start directly with the justification */
27757          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
27758            var width = parseFloat($image.attr('width'));
27759            var height = parseFloat($image.attr('height'));
27760            if ($image.prop('tagName') === 'svg') {
27761              width = parseFloat($image[0].getBBox().width);
27762              height = parseFloat($image[0].getBBox().height);
27763            }
27764            if (!isNaN(width) && !isNaN(height)) {
27765              $entry.data('jg.width', width);
27766              $entry.data('jg.height', height);
27767              $entry.data('jg.loaded', 'skipped');
27768              skippedImages = true;
27769              that.startImgAnalyzer(false);
27770              return true; // continue
27771            }
27772          }
27773
27774          $entry.data('jg.loaded', false);
27775          imagesToLoad = true;
27776
27777          // Spinner start
27778          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
27779
27780          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
27781            $entry.data('jg.width', loadImg.width);
27782            $entry.data('jg.height', loadImg.height);
27783            $entry.data('jg.loaded', true);
27784            that.startImgAnalyzer(false);
27785          }, function () { // image load error
27786            $entry.data('jg.loaded', 'error');
27787            that.startImgAnalyzer(false);
27788          });
27789
27790        } else {
27791          $entry.data('jg.loaded', true);
27792          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
27793          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
27794        }
27795
27796      }
27797
27798    });
27799
27800    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
27801    this.checkWidth();
27802  };
27803
27804  /**
27805   * Checks that it is a valid number. If a string is passed it is converted to a number
27806   *
27807   * @param settingContainer the object that contains the setting (to allow the conversion)
27808   * @param settingName the setting name
27809   */
27810  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
27811    if ($.type(settingContainer[settingName]) === 'string') {
27812      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
27813    }
27814
27815    if ($.type(settingContainer[settingName]) === 'number') {
27816      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
27817    } else {
27818      throw settingName + ' must be a number';
27819    }
27820  };
27821
27822  /**
27823   * Checks the sizeRangeSuffixes and, if necessary, converts
27824   * its keys from string (e.g. old settings with 'lt100') to int.
27825   */
27826  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
27827    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
27828      throw 'sizeRangeSuffixes must be defined and must be an object';
27829    }
27830
27831    var suffixRanges = [];
27832    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
27833      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
27834    }
27835
27836    var newSizeRngSuffixes = { 0: '' };
27837    for (var i = 0; i < suffixRanges.length; i++) {
27838      if ($.type(suffixRanges[i]) === 'string') {
27839        try {
27840          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
27841          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
27842        } catch (e) {
27843          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
27844        }
27845      } else {
27846        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
27847      }
27848    }
27849
27850    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
27851  };
27852
27853  /**
27854   * check and convert the maxRowHeight setting
27855   * requires rowHeight to be already set
27856   * TODO: should be always called when only rowHeight is changed
27857   * @return number or null
27858   */
27859  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
27860    var newMaxRowHeight = null;
27861    var rowHeight = this.settings.rowHeight;
27862
27863    if ($.type(this.settings.maxRowHeight) === 'string') {
27864      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
27865        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
27866      } else {
27867        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
27868      }
27869    } else if ($.type(this.settings.maxRowHeight) === 'number') {
27870      newMaxRowHeight = this.settings.maxRowHeight;
27871    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
27872      return null;
27873    } else {
27874      throw 'maxRowHeight must be a number or a percentage';
27875    }
27876
27877    // check if the converted value is not a number
27878    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
27879
27880    // check values, maxRowHeight must be >= rowHeight
27881    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
27882
27883    return newMaxRowHeight;
27884  };
27885
27886  /**
27887   * Checks the settings
27888   */
27889  JustifiedGallery.prototype.checkSettings = function () {
27890    this.checkSizeRangesSuffixes();
27891
27892    this.checkOrConvertNumber(this.settings, 'rowHeight');
27893    this.checkOrConvertNumber(this.settings, 'margins');
27894    this.checkOrConvertNumber(this.settings, 'border');
27895    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
27896
27897    var lastRowModes = [
27898      'justify',
27899      'nojustify',
27900      'left',
27901      'center',
27902      'right',
27903      'hide'
27904    ];
27905    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
27906      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
27907    }
27908
27909    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
27910    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
27911      throw 'justifyThreshold must be in the interval [0,1]';
27912    }
27913    if ($.type(this.settings.cssAnimation) !== 'boolean') {
27914      throw 'cssAnimation must be a boolean';
27915    }
27916
27917    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
27918    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
27919
27920    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
27921    if (this.settings.captionSettings.visibleOpacity < 0 ||
27922      this.settings.captionSettings.visibleOpacity > 1) {
27923      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
27924    }
27925
27926    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
27927    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
27928      this.settings.captionSettings.nonVisibleOpacity > 1) {
27929      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
27930    }
27931
27932    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
27933    this.checkOrConvertNumber(this.settings, 'refreshTime');
27934    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
27935    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
27936    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
27937
27938    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
27939      throw 'sort must be false or a comparison function';
27940    }
27941
27942    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
27943      $.type(this.settings.filter) !== 'string') {
27944      throw 'filter must be false, a string or a filter function';
27945    }
27946  };
27947
27948  /**
27949   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
27950   * @returns {Array} sorted suffix ranges
27951   */
27952  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
27953    var suffixRanges = [];
27954    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
27955      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
27956    }
27957    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
27958    return suffixRanges;
27959  };
27960
27961  /**
27962   * Update the existing settings only changing some of them
27963   *
27964   * @param newSettings the new settings (or a subgroup of them)
27965   */
27966  JustifiedGallery.prototype.updateSettings = function (newSettings) {
27967    // In this case Justified Gallery has been called again changing only some options
27968    this.settings = $.extend({}, this.settings, newSettings);
27969    this.checkSettings();
27970
27971    // As reported in the settings: negative value = same as margins, 0 = disabled
27972    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
27973
27974    this.maxRowHeight = this.retrieveMaxRowHeight();
27975    this.suffixRanges = this.retrieveSuffixRanges();
27976  };
27977
27978  JustifiedGallery.prototype.defaults = {
27979    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
27980        {
27981          100: '_t',  // used when longest is less than 100px
27982          240: '_m',  // used when longest is between 101px and 240px
27983          320: '_n',  // ...
27984          500: '',
27985          640: '_z',
27986          1024: '_b'  // used as else case because it is the last
27987        }
27988    */
27989    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
27990    path relative to a specific thumbnail size. The function should accept respectively three arguments:
27991    current path, width and height */
27992    rowHeight: 120, // required? required to be > 0?
27993    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
27994    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
27995    // can't exceed 3 * rowHeight)
27996    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
27997    margins: 1,
27998    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
27999
28000    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28001
28002    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28003                             * (i.e. lastRow setting is not considered) */
28004    waitThumbnailsLoad: true,
28005    captions: true,
28006    cssAnimation: true,
28007    imagesAnimationDuration: 500, // ignored with css animations
28008    captionSettings: { // ignored with css animations
28009      animationDuration: 500,
28010      visibleOpacity: 0.7,
28011      nonVisibleOpacity: 0.0
28012    },
28013    rel: null, // rewrite the rel of each analyzed links
28014    target: null, // rewrite the target of all links
28015    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28016    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28017    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28018    randomize: false,
28019    rtl: false, // right-to-left mode
28020    sort: false, /*
28021      - false: to do not sort
28022      - function: to sort them using the function as comparator (see Array.prototype.sort())
28023    */
28024    filter: false, /*
28025      - false, null or undefined: for a disabled filter
28026      - a string: an entry is kept if entry.is(filter string) returns true
28027                  see jQuery's .is() function for further information
28028      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28029                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28030    */
28031    selector: 'a', // The selector that is used to know what are the entries of the gallery
28032    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28033    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28034      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28035    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28036  };
28037
28038
28039  /**
28040   * Justified Gallery plugin for jQuery
28041   *
28042   * Events
28043   *  - jg.complete : called when all the gallery has been created
28044   *  - jg.resize : called when the gallery has been resized
28045   *  - jg.rowflush : when a new row appears
28046   *
28047   * @param arg the action (or the settings) passed when the plugin is called
28048   * @returns {*} the object itself
28049   */
28050  $.fn.justifiedGallery = function (arg) {
28051    return this.each(function (index, gallery) {
28052
28053      var $gallery = $(gallery);
28054      $gallery.addClass('justified-gallery');
28055
28056      var controller = $gallery.data('jg.controller');
28057      if (typeof controller === 'undefined') {
28058        // Create controller and assign it to the object data
28059        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28060          if (arg === 'destroy') return; // Just a call to an unexisting object
28061          throw 'The argument must be an object';
28062        }
28063        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28064        $gallery.data('jg.controller', controller);
28065      } else if (arg === 'norewind') {
28066        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28067        // ... left to be more readable
28068      } else if (arg === 'destroy') {
28069        controller.destroy();
28070        return;
28071      } else {
28072        // In this case Justified Gallery has been called again changing only some options
28073        controller.updateSettings(arg);
28074        controller.rewind();
28075      }
28076
28077      // Update the entries list
28078      if (!controller.updateEntries(arg === 'norewind')) return;
28079
28080      // Init justified gallery
28081      controller.init();
28082
28083    });
28084  };
28085
28086}));
28087
28088/*!
28089* Customized version of iScroll.js 0.0.1
28090* It fixes bugs affecting its integration with fullpage.js
28091*/
28092/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
28093(function (window, document, Math) {
28094var rAF = window.requestAnimationFrame  ||
28095    window.webkitRequestAnimationFrame  ||
28096    window.mozRequestAnimationFrame     ||
28097    window.oRequestAnimationFrame       ||
28098    window.msRequestAnimationFrame      ||
28099    function (callback) { window.setTimeout(callback, 1000 / 60); };
28100
28101var utils = (function () {
28102    var me = {};
28103
28104    var _elementStyle = document.createElement('div').style;
28105    var _vendor = (function () {
28106        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
28107            transform,
28108            i = 0,
28109            l = vendors.length;
28110
28111        for ( ; i < l; i++ ) {
28112            transform = vendors[i] + 'ransform';
28113            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
28114        }
28115
28116        return false;
28117    })();
28118
28119    function _prefixStyle (style) {
28120        if ( _vendor === false ) return false;
28121        if ( _vendor === '' ) return style;
28122        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
28123    }
28124
28125    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
28126
28127    me.extend = function (target, obj) {
28128        for ( var i in obj ) {
28129            target[i] = obj[i];
28130        }
28131    };
28132
28133    me.addEvent = function (el, type, fn, capture) {
28134        el.addEventListener(type, fn, !!capture);
28135    };
28136
28137    me.removeEvent = function (el, type, fn, capture) {
28138        el.removeEventListener(type, fn, !!capture);
28139    };
28140
28141    me.prefixPointerEvent = function (pointerEvent) {
28142        return window.MSPointerEvent ?
28143            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
28144            pointerEvent;
28145    };
28146
28147    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
28148        var distance = current - start,
28149            speed = Math.abs(distance) / time,
28150            destination,
28151            duration;
28152
28153        deceleration = deceleration === undefined ? 0.0006 : deceleration;
28154
28155        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
28156        duration = speed / deceleration;
28157
28158        if ( destination < lowerMargin ) {
28159            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
28160            distance = Math.abs(destination - current);
28161            duration = distance / speed;
28162        } else if ( destination > 0 ) {
28163            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
28164            distance = Math.abs(current) + destination;
28165            duration = distance / speed;
28166        }
28167
28168        return {
28169            destination: Math.round(destination),
28170            duration: duration
28171        };
28172    };
28173
28174    var _transform = _prefixStyle('transform');
28175
28176    me.extend(me, {
28177        hasTransform: _transform !== false,
28178        hasPerspective: _prefixStyle('perspective') in _elementStyle,
28179        hasTouch: 'ontouchstart' in window,
28180        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
28181        hasTransition: _prefixStyle('transition') in _elementStyle
28182    });
28183
28184    /*
28185    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
28186    - galaxy S2 is ok
28187    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
28188    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
28189   - galaxy S3 is badAndroid (stock brower, webview)
28190     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
28191   - galaxy S4 is badAndroid (stock brower, webview)
28192     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
28193   - galaxy S5 is OK
28194     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
28195   - galaxy S6 is OK
28196     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
28197  */
28198    me.isBadAndroid = (function() {
28199        var appVersion = window.navigator.appVersion;
28200        // Android browser is not a chrome browser.
28201        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
28202            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
28203            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
28204                return parseFloat(safariVersion[1]) < 535.19;
28205            } else {
28206                return true;
28207            }
28208        } else {
28209            return false;
28210        }
28211    })();
28212
28213    me.extend(me.style = {}, {
28214        transform: _transform,
28215        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
28216        transitionDuration: _prefixStyle('transitionDuration'),
28217        transitionDelay: _prefixStyle('transitionDelay'),
28218        transformOrigin: _prefixStyle('transformOrigin')
28219    });
28220
28221    me.hasClass = function (e, c) {
28222        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
28223        return re.test(e.className);
28224    };
28225
28226    me.addClass = function (e, c) {
28227        if ( me.hasClass(e, c) ) {
28228            return;
28229        }
28230
28231        var newclass = e.className.split(' ');
28232        newclass.push(c);
28233        e.className = newclass.join(' ');
28234    };
28235
28236    me.removeClass = function (e, c) {
28237        if ( !me.hasClass(e, c) ) {
28238            return;
28239        }
28240
28241        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
28242        e.className = e.className.replace(re, ' ');
28243    };
28244
28245    me.offset = function (el) {
28246        var left = -el.offsetLeft,
28247            top = -el.offsetTop;
28248
28249        // jshint -W084
28250        while (el = el.offsetParent) {
28251            left -= el.offsetLeft;
28252            top -= el.offsetTop;
28253        }
28254        // jshint +W084
28255
28256        return {
28257            left: left,
28258            top: top
28259        };
28260    };
28261
28262    me.preventDefaultException = function (el, exceptions) {
28263        for ( var i in exceptions ) {
28264            if ( exceptions[i].test(el[i]) ) {
28265                return true;
28266            }
28267        }
28268
28269        return false;
28270    };
28271
28272    me.extend(me.eventType = {}, {
28273        touchstart: 1,
28274        touchmove: 1,
28275        touchend: 1,
28276
28277        mousedown: 2,
28278        mousemove: 2,
28279        mouseup: 2,
28280
28281        pointerdown: 3,
28282        pointermove: 3,
28283        pointerup: 3,
28284
28285        MSPointerDown: 3,
28286        MSPointerMove: 3,
28287        MSPointerUp: 3
28288    });
28289
28290    me.extend(me.ease = {}, {
28291        quadratic: {
28292            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
28293            fn: function (k) {
28294                return k * ( 2 - k );
28295            }
28296        },
28297        circular: {
28298            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)
28299            fn: function (k) {
28300                return Math.sqrt( 1 - ( --k * k ) );
28301            }
28302        },
28303        back: {
28304            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
28305            fn: function (k) {
28306                var b = 4;
28307                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
28308            }
28309        },
28310        bounce: {
28311            style: '',
28312            fn: function (k) {
28313                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
28314                    return 7.5625 * k * k;
28315                } else if ( k < ( 2 / 2.75 ) ) {
28316                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
28317                } else if ( k < ( 2.5 / 2.75 ) ) {
28318                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
28319                } else {
28320                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
28321                }
28322            }
28323        },
28324        elastic: {
28325            style: '',
28326            fn: function (k) {
28327                var f = 0.22,
28328                    e = 0.4;
28329
28330                if ( k === 0 ) { return 0; }
28331                if ( k == 1 ) { return 1; }
28332
28333                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
28334            }
28335        }
28336    });
28337
28338    me.tap = function (e, eventName) {
28339        var ev = document.createEvent('Event');
28340        ev.initEvent(eventName, true, true);
28341        ev.pageX = e.pageX;
28342        ev.pageY = e.pageY;
28343        e.target.dispatchEvent(ev);
28344    };
28345
28346    me.click = function (e) {
28347        var target = e.target,
28348            ev;
28349
28350        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
28351            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
28352            // initMouseEvent is deprecated.
28353            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
28354            ev.initEvent('click', true, true);
28355            ev.view = e.view || window;
28356            ev.detail = 1;
28357            ev.screenX = target.screenX || 0;
28358            ev.screenY = target.screenY || 0;
28359            ev.clientX = target.clientX || 0;
28360            ev.clientY = target.clientY || 0;
28361            ev.ctrlKey = !!e.ctrlKey;
28362            ev.altKey = !!e.altKey;
28363            ev.shiftKey = !!e.shiftKey;
28364            ev.metaKey = !!e.metaKey;
28365            ev.button = 0;
28366            ev.relatedTarget = null;
28367            ev._constructed = true;
28368            target.dispatchEvent(ev);
28369        }
28370    };
28371
28372    return me;
28373})();
28374function IScroll (el, options) {
28375    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
28376    this.scroller = this.wrapper.children[0];
28377    this.scrollerStyle = this.scroller.style;       // cache style for better performance
28378
28379    this.options = {
28380
28381        resizeScrollbars: true,
28382
28383        mouseWheelSpeed: 20,
28384
28385        snapThreshold: 0.334,
28386
28387// INSERT POINT: OPTIONS
28388        disablePointer : !utils.hasPointer,
28389        disableTouch : utils.hasPointer || !utils.hasTouch,
28390        disableMouse : utils.hasPointer || utils.hasTouch,
28391        startX: 0,
28392        startY: 0,
28393        scrollY: true,
28394        directionLockThreshold: 5,
28395        momentum: true,
28396
28397        bounce: true,
28398        bounceTime: 600,
28399        bounceEasing: '',
28400
28401        preventDefault: true,
28402        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
28403
28404        HWCompositing: true,
28405        useTransition: true,
28406        useTransform: true,
28407        bindToWrapper: typeof window.onmousedown === "undefined"
28408    };
28409
28410    for ( var i in options ) {
28411        this.options[i] = options[i];
28412    }
28413
28414    // Normalize options
28415    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
28416
28417    this.options.useTransition = utils.hasTransition && this.options.useTransition;
28418    this.options.useTransform = utils.hasTransform && this.options.useTransform;
28419
28420    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
28421    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
28422
28423    // If you want eventPassthrough I have to lock one of the axes
28424    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
28425    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
28426
28427    // With eventPassthrough we also need lockDirection mechanism
28428    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
28429    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
28430
28431    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
28432
28433    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
28434
28435    if ( this.options.tap === true ) {
28436        this.options.tap = 'tap';
28437    }
28438
28439    // https://github.com/cubiq/iscroll/issues/1029
28440    if (!this.options.useTransition && !this.options.useTransform) {
28441        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
28442            this.scrollerStyle.position = "relative";
28443        }
28444    }
28445
28446    if ( this.options.shrinkScrollbars == 'scale' ) {
28447        this.options.useTransition = false;
28448    }
28449
28450    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
28451
28452// INSERT POINT: NORMALIZATION
28453
28454    // Some defaults
28455    this.x = 0;
28456    this.y = 0;
28457    this.directionX = 0;
28458    this.directionY = 0;
28459    this._events = {};
28460
28461// INSERT POINT: DEFAULTS
28462
28463    this._init();
28464    this.refresh();
28465
28466    this.scrollTo(this.options.startX, this.options.startY);
28467    this.enable();
28468}
28469
28470IScroll.prototype = {
28471    version: '5.2.0',
28472
28473    _init: function () {
28474        this._initEvents();
28475
28476        if ( this.options.scrollbars || this.options.indicators ) {
28477            this._initIndicators();
28478        }
28479
28480        if ( this.options.mouseWheel ) {
28481            this._initWheel();
28482        }
28483
28484        if ( this.options.snap ) {
28485            this._initSnap();
28486        }
28487
28488        if ( this.options.keyBindings ) {
28489            this._initKeys();
28490        }
28491
28492// INSERT POINT: _init
28493
28494    },
28495
28496    destroy: function () {
28497        this._initEvents(true);
28498        clearTimeout(this.resizeTimeout);
28499        this.resizeTimeout = null;
28500        this._execEvent('destroy');
28501    },
28502
28503    _transitionEnd: function (e) {
28504        if ( e.target != this.scroller || !this.isInTransition ) {
28505            return;
28506        }
28507
28508        this._transitionTime();
28509        if ( !this.resetPosition(this.options.bounceTime) ) {
28510            this.isInTransition = false;
28511            this._execEvent('scrollEnd');
28512        }
28513    },
28514
28515    _start: function (e) {
28516        // React to left mouse button only
28517        if ( utils.eventType[e.type] != 1 ) {
28518          // for button property
28519          // http://unixpapa.com/js/mouse.html
28520          var button;
28521        if (!e.which) {
28522          /* IE case */
28523          button = (e.button < 2) ? 0 :
28524                   ((e.button == 4) ? 1 : 2);
28525        } else {
28526          /* All others */
28527          button = e.button;
28528        }
28529            if ( button !== 0 ) {
28530                return;
28531            }
28532        }
28533
28534        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
28535            return;
28536        }
28537
28538        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
28539            e.preventDefault();
28540        }
28541
28542        var point = e.touches ? e.touches[0] : e,
28543            pos;
28544
28545        this.initiated  = utils.eventType[e.type];
28546        this.moved      = false;
28547        this.distX      = 0;
28548        this.distY      = 0;
28549        this.directionX = 0;
28550        this.directionY = 0;
28551        this.directionLocked = 0;
28552
28553        this.startTime = utils.getTime();
28554
28555        if ( this.options.useTransition && this.isInTransition ) {
28556            this._transitionTime();
28557            this.isInTransition = false;
28558            pos = this.getComputedPosition();
28559            this._translate(Math.round(pos.x), Math.round(pos.y));
28560            this._execEvent('scrollEnd');
28561        } else if ( !this.options.useTransition && this.isAnimating ) {
28562            this.isAnimating = false;
28563            this._execEvent('scrollEnd');
28564        }
28565
28566        this.startX    = this.x;
28567        this.startY    = this.y;
28568        this.absStartX = this.x;
28569        this.absStartY = this.y;
28570        this.pointX    = point.pageX;
28571        this.pointY    = point.pageY;
28572
28573        this._execEvent('beforeScrollStart');
28574    },
28575
28576    _move: function (e) {
28577        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
28578            return;
28579        }
28580
28581        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
28582            e.preventDefault();
28583        }
28584
28585        var point       = e.touches ? e.touches[0] : e,
28586            deltaX      = point.pageX - this.pointX,
28587            deltaY      = point.pageY - this.pointY,
28588            timestamp   = utils.getTime(),
28589            newX, newY,
28590            absDistX, absDistY;
28591
28592        this.pointX     = point.pageX;
28593        this.pointY     = point.pageY;
28594
28595        this.distX      += deltaX;
28596        this.distY      += deltaY;
28597        absDistX        = Math.abs(this.distX);
28598        absDistY        = Math.abs(this.distY);
28599
28600        // We need to move at least 10 pixels for the scrolling to initiate
28601        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
28602            return;
28603        }
28604
28605        // If you are scrolling in one direction lock the other
28606        if ( !this.directionLocked && !this.options.freeScroll ) {
28607            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
28608                this.directionLocked = 'h';     // lock horizontally
28609            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
28610                this.directionLocked = 'v';     // lock vertically
28611            } else {
28612                this.directionLocked = 'n';     // no lock
28613            }
28614        }
28615
28616        if ( this.directionLocked == 'h' ) {
28617            if ( this.options.eventPassthrough == 'vertical' ) {
28618                e.preventDefault();
28619            } else if ( this.options.eventPassthrough == 'horizontal' ) {
28620                this.initiated = false;
28621                return;
28622            }
28623
28624            deltaY = 0;
28625        } else if ( this.directionLocked == 'v' ) {
28626            if ( this.options.eventPassthrough == 'horizontal' ) {
28627                e.preventDefault();
28628            } else if ( this.options.eventPassthrough == 'vertical' ) {
28629                this.initiated = false;
28630                return;
28631            }
28632
28633            deltaX = 0;
28634        }
28635
28636        deltaX = this.hasHorizontalScroll ? deltaX : 0;
28637        deltaY = this.hasVerticalScroll ? deltaY : 0;
28638
28639        newX = this.x + deltaX;
28640        newY = this.y + deltaY;
28641
28642        // Slow down if outside of the boundaries
28643        if ( newX > 0 || newX < this.maxScrollX ) {
28644            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
28645        }
28646        if ( newY > 0 || newY < this.maxScrollY ) {
28647            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
28648        }
28649
28650        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
28651        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
28652
28653        if ( !this.moved ) {
28654            this._execEvent('scrollStart');
28655        }
28656
28657        this.moved = true;
28658
28659        this._translate(newX, newY);
28660
28661/* REPLACE START: _move */
28662
28663        if ( timestamp - this.startTime > 300 ) {
28664            this.startTime = timestamp;
28665            this.startX = this.x;
28666            this.startY = this.y;
28667        }
28668
28669/* REPLACE END: _move */
28670
28671    },
28672
28673    _end: function (e) {
28674        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
28675            return;
28676        }
28677
28678        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
28679            e.preventDefault();
28680        }
28681
28682        var point = e.changedTouches ? e.changedTouches[0] : e,
28683            momentumX,
28684            momentumY,
28685            duration = utils.getTime() - this.startTime,
28686            newX = Math.round(this.x),
28687            newY = Math.round(this.y),
28688            distanceX = Math.abs(newX - this.startX),
28689            distanceY = Math.abs(newY - this.startY),
28690            time = 0,
28691            easing = '';
28692
28693        this.isInTransition = 0;
28694        this.initiated = 0;
28695        this.endTime = utils.getTime();
28696
28697        // reset if we are outside of the boundaries
28698        if ( this.resetPosition(this.options.bounceTime) ) {
28699            return;
28700        }
28701
28702        this.scrollTo(newX, newY);  // ensures that the last position is rounded
28703
28704        // we scrolled less than 10 pixels
28705        if ( !this.moved ) {
28706            if ( this.options.tap ) {
28707                utils.tap(e, this.options.tap);
28708            }
28709
28710            if ( this.options.click ) {
28711                utils.click(e);
28712            }
28713
28714            this._execEvent('scrollCancel');
28715            return;
28716        }
28717
28718        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
28719            this._execEvent('flick');
28720            return;
28721        }
28722
28723        // start momentum animation if needed
28724        if ( this.options.momentum && duration < 300 ) {
28725            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 };
28726            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 };
28727            newX = momentumX.destination;
28728            newY = momentumY.destination;
28729            time = Math.max(momentumX.duration, momentumY.duration);
28730            this.isInTransition = 1;
28731        }
28732
28733
28734        if ( this.options.snap ) {
28735            var snap = this._nearestSnap(newX, newY);
28736            this.currentPage = snap;
28737            time = this.options.snapSpeed || Math.max(
28738                    Math.max(
28739                        Math.min(Math.abs(newX - snap.x), 1000),
28740                        Math.min(Math.abs(newY - snap.y), 1000)
28741                    ), 300);
28742            newX = snap.x;
28743            newY = snap.y;
28744
28745            this.directionX = 0;
28746            this.directionY = 0;
28747            easing = this.options.bounceEasing;
28748        }
28749
28750// INSERT POINT: _end
28751
28752        if ( newX != this.x || newY != this.y ) {
28753            // change easing function when scroller goes out of the boundaries
28754            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
28755                easing = utils.ease.quadratic;
28756            }
28757
28758            this.scrollTo(newX, newY, time, easing);
28759            return;
28760        }
28761
28762        this._execEvent('scrollEnd');
28763    },
28764
28765    _resize: function () {
28766        var that = this;
28767
28768        clearTimeout(this.resizeTimeout);
28769
28770        this.resizeTimeout = setTimeout(function () {
28771            that.refresh();
28772        }, this.options.resizePolling);
28773    },
28774
28775    resetPosition: function (time) {
28776        var x = this.x,
28777            y = this.y;
28778
28779        time = time || 0;
28780
28781        if ( !this.hasHorizontalScroll || this.x > 0 ) {
28782            x = 0;
28783        } else if ( this.x < this.maxScrollX ) {
28784            x = this.maxScrollX;
28785        }
28786
28787        if ( !this.hasVerticalScroll || this.y > 0 ) {
28788            y = 0;
28789        } else if ( this.y < this.maxScrollY ) {
28790            y = this.maxScrollY;
28791        }
28792
28793        if ( x == this.x && y == this.y ) {
28794            return false;
28795        }
28796
28797        this.scrollTo(x, y, time, this.options.bounceEasing);
28798
28799        return true;
28800    },
28801
28802    disable: function () {
28803        this.enabled = false;
28804    },
28805
28806    enable: function () {
28807        this.enabled = true;
28808    },
28809
28810    refresh: function () {
28811        var rf = this.wrapper.offsetHeight;     // Force reflow
28812
28813        this.wrapperWidth   = this.wrapper.clientWidth;
28814        this.wrapperHeight  = this.wrapper.clientHeight;
28815
28816/* REPLACE START: refresh */
28817
28818        this.scrollerWidth  = this.scroller.offsetWidth;
28819        this.scrollerHeight = this.scroller.offsetHeight;
28820
28821        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
28822        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
28823
28824/* REPLACE END: refresh */
28825
28826        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
28827        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
28828
28829        if ( !this.hasHorizontalScroll ) {
28830            this.maxScrollX = 0;
28831            this.scrollerWidth = this.wrapperWidth;
28832        }
28833
28834        if ( !this.hasVerticalScroll ) {
28835            this.maxScrollY = 0;
28836            this.scrollerHeight = this.wrapperHeight;
28837        }
28838
28839        this.endTime = 0;
28840        this.directionX = 0;
28841        this.directionY = 0;
28842
28843        this.wrapperOffset = utils.offset(this.wrapper);
28844
28845        this._execEvent('refresh');
28846
28847        this.resetPosition();
28848
28849// INSERT POINT: _refresh
28850
28851    },
28852
28853
28854    on: function (type, fn) {
28855        if ( !this._events[type] ) {
28856            this._events[type] = [];
28857        }
28858
28859        this._events[type].push(fn);
28860    },
28861
28862    off: function (type, fn) {
28863        if ( !this._events[type] ) {
28864            return;
28865        }
28866
28867        var index = this._events[type].indexOf(fn);
28868
28869        if ( index > -1 ) {
28870            this._events[type].splice(index, 1);
28871        }
28872    },
28873
28874    _execEvent: function (type) {
28875        if ( !this._events[type] ) {
28876            return;
28877        }
28878
28879        var i = 0,
28880            l = this._events[type].length;
28881
28882        if ( !l ) {
28883            return;
28884        }
28885
28886        for ( ; i < l; i++ ) {
28887            this._events[type][i].apply(this, [].slice.call(arguments, 1));
28888        }
28889    },
28890
28891    scrollBy: function (x, y, time, easing) {
28892        x = this.x + x;
28893        y = this.y + y;
28894        time = time || 0;
28895
28896        this.scrollTo(x, y, time, easing);
28897    },
28898
28899    scrollTo: function (x, y, time, easing) {
28900        easing = easing || utils.ease.circular;
28901
28902        this.isInTransition = this.options.useTransition && time > 0;
28903        var transitionType = this.options.useTransition && easing.style;
28904        if ( !time || transitionType ) {
28905                if(transitionType) {
28906                    this._transitionTimingFunction(easing.style);
28907                    this._transitionTime(time);
28908                }
28909            this._translate(x, y);
28910        } else {
28911            this._animate(x, y, time, easing.fn);
28912        }
28913    },
28914
28915    scrollToElement: function (el, time, offsetX, offsetY, easing) {
28916        el = el.nodeType ? el : this.scroller.querySelector(el);
28917
28918        if ( !el ) {
28919            return;
28920        }
28921
28922        var pos = utils.offset(el);
28923
28924        pos.left -= this.wrapperOffset.left;
28925        pos.top  -= this.wrapperOffset.top;
28926
28927        // if offsetX/Y are true we center the element to the screen
28928        if ( offsetX === true ) {
28929            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
28930        }
28931        if ( offsetY === true ) {
28932            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
28933        }
28934
28935        pos.left -= offsetX || 0;
28936        pos.top  -= offsetY || 0;
28937
28938        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
28939        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
28940
28941        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
28942
28943        this.scrollTo(pos.left, pos.top, time, easing);
28944    },
28945
28946    _transitionTime: function (time) {
28947        if (!this.options.useTransition) {
28948            return;
28949        }
28950        time = time || 0;
28951        var durationProp = utils.style.transitionDuration;
28952        if(!durationProp) {
28953            return;
28954        }
28955
28956        this.scrollerStyle[durationProp] = time + 'ms';
28957
28958        if ( !time && utils.isBadAndroid ) {
28959            this.scrollerStyle[durationProp] = '0.0001ms';
28960            // remove 0.0001ms
28961            var self = this;
28962            rAF(function() {
28963                if(self.scrollerStyle[durationProp] === '0.0001ms') {
28964                    self.scrollerStyle[durationProp] = '0s';
28965                }
28966            });
28967        }
28968
28969
28970        if ( this.indicators ) {
28971            for ( var i = this.indicators.length; i--; ) {
28972                this.indicators[i].transitionTime(time);
28973            }
28974        }
28975
28976
28977// INSERT POINT: _transitionTime
28978
28979    },
28980
28981    _transitionTimingFunction: function (easing) {
28982        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
28983
28984
28985        if ( this.indicators ) {
28986            for ( var i = this.indicators.length; i--; ) {
28987                this.indicators[i].transitionTimingFunction(easing);
28988            }
28989        }
28990
28991
28992// INSERT POINT: _transitionTimingFunction
28993
28994    },
28995
28996    _translate: function (x, y) {
28997        //Uncode addition
28998        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
28999            return false;
29000
29001        if ( this.options.useTransform ) {
29002
29003/* REPLACE START: _translate */
29004
29005            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29006
29007/* REPLACE END: _translate */
29008
29009        } else {
29010            x = Math.round(x);
29011            y = Math.round(y);
29012            this.scrollerStyle.left = x + 'px';
29013            this.scrollerStyle.top = y + 'px';
29014        }
29015
29016        this.x = x;
29017        this.y = y;
29018
29019
29020        if ( this.indicators ) {
29021            for ( var i = this.indicators.length; i--; ) {
29022                this.indicators[i].updatePosition();
29023            }
29024        }
29025
29026        //Uncode addition
29027        var uncodevent = new CustomEvent('fp-slide-scroll');
29028        window.dispatchEvent(uncodevent);
29029
29030// INSERT POINT: _translate
29031
29032    },
29033
29034    _initEvents: function (remove) {
29035        var eventType = remove ? utils.removeEvent : utils.addEvent,
29036            target = this.options.bindToWrapper ? this.wrapper : window;
29037
29038        eventType(window, 'orientationchange', this);
29039        eventType(window, 'resize', this);
29040
29041        if ( this.options.click ) {
29042            eventType(this.wrapper, 'click', this, true);
29043        }
29044
29045        if ( !this.options.disableMouse ) {
29046            eventType(this.wrapper, 'mousedown', this);
29047            eventType(target, 'mousemove', this);
29048            eventType(target, 'mousecancel', this);
29049            eventType(target, 'mouseup', this);
29050        }
29051
29052        if ( utils.hasPointer && !this.options.disablePointer ) {
29053            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29054            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29055            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29056            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29057        }
29058
29059        if ( utils.hasTouch && !this.options.disableTouch ) {
29060            eventType(this.wrapper, 'touchstart', this);
29061            eventType(target, 'touchmove', this);
29062            eventType(target, 'touchcancel', this);
29063            eventType(target, 'touchend', this);
29064        }
29065
29066        eventType(this.scroller, 'transitionend', this);
29067        eventType(this.scroller, 'webkitTransitionEnd', this);
29068        eventType(this.scroller, 'oTransitionEnd', this);
29069        eventType(this.scroller, 'MSTransitionEnd', this);
29070    },
29071
29072    getComputedPosition: function () {
29073        var matrix = window.getComputedStyle(this.scroller, null),
29074            x, y;
29075
29076        if ( this.options.useTransform ) {
29077            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29078            x = +(matrix[12] || matrix[4]);
29079            y = +(matrix[13] || matrix[5]);
29080        } else {
29081            x = +matrix.left.replace(/[^-\d.]/g, '');
29082            y = +matrix.top.replace(/[^-\d.]/g, '');
29083        }
29084
29085        return { x: x, y: y };
29086    },
29087    _initIndicators: function () {
29088        var interactive = this.options.interactiveScrollbars,
29089            customStyle = typeof this.options.scrollbars != 'string',
29090            indicators = [],
29091            indicator;
29092
29093        var that = this;
29094
29095        this.indicators = [];
29096
29097        if ( this.options.scrollbars ) {
29098            // Vertical scrollbar
29099            if ( this.options.scrollY ) {
29100                indicator = {
29101                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
29102                    interactive: interactive,
29103                    defaultScrollbars: true,
29104                    customStyle: customStyle,
29105                    resize: this.options.resizeScrollbars,
29106                    shrink: this.options.shrinkScrollbars,
29107                    fade: this.options.fadeScrollbars,
29108                    listenX: false
29109                };
29110
29111                this.wrapper.appendChild(indicator.el);
29112                indicators.push(indicator);
29113            }
29114
29115            // Horizontal scrollbar
29116            if ( this.options.scrollX ) {
29117                indicator = {
29118                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
29119                    interactive: interactive,
29120                    defaultScrollbars: true,
29121                    customStyle: customStyle,
29122                    resize: this.options.resizeScrollbars,
29123                    shrink: this.options.shrinkScrollbars,
29124                    fade: this.options.fadeScrollbars,
29125                    listenY: false
29126                };
29127
29128                this.wrapper.appendChild(indicator.el);
29129                indicators.push(indicator);
29130            }
29131        }
29132
29133        if ( this.options.indicators ) {
29134            // TODO: check concat compatibility
29135            indicators = indicators.concat(this.options.indicators);
29136        }
29137
29138        for ( var i = indicators.length; i--; ) {
29139            this.indicators.push( new Indicator(this, indicators[i]) );
29140        }
29141
29142        // TODO: check if we can use array.map (wide compatibility and performance issues)
29143        function _indicatorsMap (fn) {
29144            if (that.indicators) {
29145                for ( var i = that.indicators.length; i--; ) {
29146                    fn.call(that.indicators[i]);
29147                }
29148            }
29149        }
29150
29151        if ( this.options.fadeScrollbars ) {
29152            this.on('scrollEnd', function () {
29153                _indicatorsMap(function () {
29154                    this.fade();
29155                });
29156            });
29157
29158            this.on('scrollCancel', function () {
29159                _indicatorsMap(function () {
29160                    this.fade();
29161                });
29162            });
29163
29164            this.on('scrollStart', function () {
29165                _indicatorsMap(function () {
29166                    this.fade(1);
29167                });
29168            });
29169
29170            this.on('beforeScrollStart', function () {
29171                _indicatorsMap(function () {
29172                    this.fade(1, true);
29173                });
29174            });
29175        }
29176
29177
29178        this.on('refresh', function () {
29179            _indicatorsMap(function () {
29180                this.refresh();
29181            });
29182        });
29183
29184        this.on('destroy', function () {
29185            _indicatorsMap(function () {
29186                this.destroy();
29187            });
29188
29189            delete this.indicators;
29190        });
29191    },
29192
29193    _initWheel: function () {
29194        utils.addEvent(this.wrapper, 'wheel', this);
29195        utils.addEvent(this.wrapper, 'mousewheel', this);
29196        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
29197
29198        this.on('destroy', function () {
29199            clearTimeout(this.wheelTimeout);
29200            this.wheelTimeout = null;
29201            utils.removeEvent(this.wrapper, 'wheel', this);
29202            utils.removeEvent(this.wrapper, 'mousewheel', this);
29203            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
29204        });
29205    },
29206
29207    _wheel: function (e) {
29208        if ( !this.enabled ) {
29209            return;
29210        }
29211
29212        var wheelDeltaX, wheelDeltaY,
29213            newX, newY,
29214            that = this;
29215
29216        if ( this.wheelTimeout === undefined ) {
29217            that._execEvent('scrollStart');
29218        }
29219
29220        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
29221        clearTimeout(this.wheelTimeout);
29222        this.wheelTimeout = setTimeout(function () {
29223            if(!that.options.snap) {
29224                that._execEvent('scrollEnd');
29225            }
29226            that.wheelTimeout = undefined;
29227        }, 400);
29228
29229        if ( 'deltaX' in e ) {
29230            if (e.deltaMode === 1) {
29231                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
29232                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
29233            } else {
29234                wheelDeltaX = -e.deltaX;
29235                wheelDeltaY = -e.deltaY;
29236            }
29237        } else if ( 'wheelDeltaX' in e ) {
29238            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
29239            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
29240        } else if ( 'wheelDelta' in e ) {
29241            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
29242        } else if ( 'detail' in e ) {
29243            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
29244        } else {
29245            return;
29246        }
29247
29248        wheelDeltaX *= this.options.invertWheelDirection;
29249        wheelDeltaY *= this.options.invertWheelDirection;
29250
29251        if ( !this.hasVerticalScroll ) {
29252            wheelDeltaX = wheelDeltaY;
29253            wheelDeltaY = 0;
29254        }
29255
29256        if ( this.options.snap ) {
29257            newX = this.currentPage.pageX;
29258            newY = this.currentPage.pageY;
29259
29260            if ( wheelDeltaX > 0 ) {
29261                newX--;
29262            } else if ( wheelDeltaX < 0 ) {
29263                newX++;
29264            }
29265
29266            if ( wheelDeltaY > 0 ) {
29267                newY--;
29268            } else if ( wheelDeltaY < 0 ) {
29269                newY++;
29270            }
29271
29272            this.goToPage(newX, newY);
29273
29274            return;
29275        }
29276
29277        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
29278        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
29279
29280        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
29281        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
29282
29283        if ( newX > 0 ) {
29284            newX = 0;
29285        } else if ( newX < this.maxScrollX ) {
29286            newX = this.maxScrollX;
29287        }
29288
29289        if ( newY > 0 ) {
29290            newY = 0;
29291        } else if ( newY < this.maxScrollY ) {
29292            newY = this.maxScrollY;
29293        }
29294
29295        this.scrollTo(newX, newY, 0);
29296
29297// INSERT POINT: _wheel
29298    },
29299
29300    _initSnap: function () {
29301        this.currentPage = {};
29302
29303        if ( typeof this.options.snap == 'string' ) {
29304            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
29305        }
29306
29307        this.on('refresh', function () {
29308            var i = 0, l,
29309                m = 0, n,
29310                cx, cy,
29311                x = 0, y,
29312                stepX = this.options.snapStepX || this.wrapperWidth,
29313                stepY = this.options.snapStepY || this.wrapperHeight,
29314                el;
29315
29316            this.pages = [];
29317
29318            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
29319                return;
29320            }
29321
29322            if ( this.options.snap === true ) {
29323                cx = Math.round( stepX / 2 );
29324                cy = Math.round( stepY / 2 );
29325
29326                while ( x > -this.scrollerWidth ) {
29327                    this.pages[i] = [];
29328                    l = 0;
29329                    y = 0;
29330
29331                    while ( y > -this.scrollerHeight ) {
29332                        this.pages[i][l] = {
29333                            x: Math.max(x, this.maxScrollX),
29334                            y: Math.max(y, this.maxScrollY),
29335                            width: stepX,
29336                            height: stepY,
29337                            cx: x - cx,
29338                            cy: y - cy
29339                        };
29340
29341                        y -= stepY;
29342                        l++;
29343                    }
29344
29345                    x -= stepX;
29346                    i++;
29347                }
29348            } else {
29349                el = this.options.snap;
29350                l = el.length;
29351                n = -1;
29352
29353                for ( ; i < l; i++ ) {
29354                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
29355                        m = 0;
29356                        n++;
29357                    }
29358
29359                    if ( !this.pages[m] ) {
29360                        this.pages[m] = [];
29361                    }
29362
29363                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
29364                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
29365                    cx = x - Math.round(el[i].offsetWidth / 2);
29366                    cy = y - Math.round(el[i].offsetHeight / 2);
29367
29368                    this.pages[m][n] = {
29369                        x: x,
29370                        y: y,
29371                        width: el[i].offsetWidth,
29372                        height: el[i].offsetHeight,
29373                        cx: cx,
29374                        cy: cy
29375                    };
29376
29377                    if ( x > this.maxScrollX ) {
29378                        m++;
29379                    }
29380                }
29381            }
29382
29383            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
29384
29385            // Update snap threshold if needed
29386            if ( this.options.snapThreshold % 1 === 0 ) {
29387                this.snapThresholdX = this.options.snapThreshold;
29388                this.snapThresholdY = this.options.snapThreshold;
29389            } else {
29390                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
29391                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
29392            }
29393        });
29394
29395        this.on('flick', function () {
29396            var time = this.options.snapSpeed || Math.max(
29397                    Math.max(
29398                        Math.min(Math.abs(this.x - this.startX), 1000),
29399                        Math.min(Math.abs(this.y - this.startY), 1000)
29400                    ), 300);
29401
29402            this.goToPage(
29403                this.currentPage.pageX + this.directionX,
29404                this.currentPage.pageY + this.directionY,
29405                time
29406            );
29407        });
29408    },
29409
29410    _nearestSnap: function (x, y) {
29411        if ( !this.pages.length ) {
29412            return { x: 0, y: 0, pageX: 0, pageY: 0 };
29413        }
29414
29415        var i = 0,
29416            l = this.pages.length,
29417            m = 0;
29418
29419        // Check if we exceeded the snap threshold
29420        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
29421            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
29422            return this.currentPage;
29423        }
29424
29425        if ( x > 0 ) {
29426            x = 0;
29427        } else if ( x < this.maxScrollX ) {
29428            x = this.maxScrollX;
29429        }
29430
29431        if ( y > 0 ) {
29432            y = 0;
29433        } else if ( y < this.maxScrollY ) {
29434            y = this.maxScrollY;
29435        }
29436
29437        for ( ; i < l; i++ ) {
29438            if ( x >= this.pages[i][0].cx ) {
29439                x = this.pages[i][0].x;
29440                break;
29441            }
29442        }
29443
29444        l = this.pages[i].length;
29445
29446        for ( ; m < l; m++ ) {
29447            if ( y >= this.pages[0][m].cy ) {
29448                y = this.pages[0][m].y;
29449                break;
29450            }
29451        }
29452
29453        if ( i == this.currentPage.pageX ) {
29454            i += this.directionX;
29455
29456            if ( i < 0 ) {
29457                i = 0;
29458            } else if ( i >= this.pages.length ) {
29459                i = this.pages.length - 1;
29460            }
29461
29462            x = this.pages[i][0].x;
29463        }
29464
29465        if ( m == this.currentPage.pageY ) {
29466            m += this.directionY;
29467
29468            if ( m < 0 ) {
29469                m = 0;
29470            } else if ( m >= this.pages[0].length ) {
29471                m = this.pages[0].length - 1;
29472            }
29473
29474            y = this.pages[0][m].y;
29475        }
29476
29477        return {
29478            x: x,
29479            y: y,
29480            pageX: i,
29481            pageY: m
29482        };
29483    },
29484
29485    goToPage: function (x, y, time, easing) {
29486        easing = easing || this.options.bounceEasing;
29487
29488        if ( x >= this.pages.length ) {
29489            x = this.pages.length - 1;
29490        } else if ( x < 0 ) {
29491            x = 0;
29492        }
29493
29494        if ( y >= this.pages[x].length ) {
29495            y = this.pages[x].length - 1;
29496        } else if ( y < 0 ) {
29497            y = 0;
29498        }
29499
29500        var posX = this.pages[x][y].x,
29501            posY = this.pages[x][y].y;
29502
29503        time = time === undefined ? this.options.snapSpeed || Math.max(
29504            Math.max(
29505                Math.min(Math.abs(posX - this.x), 1000),
29506                Math.min(Math.abs(posY - this.y), 1000)
29507            ), 300) : time;
29508
29509        this.currentPage = {
29510            x: posX,
29511            y: posY,
29512            pageX: x,
29513            pageY: y
29514        };
29515
29516        this.scrollTo(posX, posY, time, easing);
29517    },
29518
29519    next: function (time, easing) {
29520        var x = this.currentPage.pageX,
29521            y = this.currentPage.pageY;
29522
29523        x++;
29524
29525        if ( x >= this.pages.length && this.hasVerticalScroll ) {
29526            x = 0;
29527            y++;
29528        }
29529
29530        this.goToPage(x, y, time, easing);
29531    },
29532
29533    prev: function (time, easing) {
29534        var x = this.currentPage.pageX,
29535            y = this.currentPage.pageY;
29536
29537        x--;
29538
29539        if ( x < 0 && this.hasVerticalScroll ) {
29540            x = 0;
29541            y--;
29542        }
29543
29544        this.goToPage(x, y, time, easing);
29545    },
29546
29547    _initKeys: function (e) {
29548        // default key bindings
29549        var keys = {
29550            pageUp: 33,
29551            pageDown: 34,
29552            end: 35,
29553            home: 36,
29554            left: 37,
29555            up: 38,
29556            right: 39,
29557            down: 40
29558        };
29559        var i;
29560
29561        // if you give me characters I give you keycode
29562        if ( typeof this.options.keyBindings == 'object' ) {
29563            for ( i in this.options.keyBindings ) {
29564                if ( typeof this.options.keyBindings[i] == 'string' ) {
29565                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
29565deAt(0);
29566                }
29567            }
29568        } else {
29569            this.options.keyBindings = {};
29570        }
29571
29572        for ( i in keys ) {
29573            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
29574        }
29575
29576        utils.addEvent(window, 'keydown', this);
29577
29578        this.on('destroy', function () {
29579            utils.removeEvent(window, 'keydown', this);
29580        });
29581    },
29582
29583    _key: function (e) {
29584        if ( !this.enabled ) {
29585            return;
29586        }
29587
29588        var snap = this.options.snap,   // we are using this alot, better to cache it
29589            newX = snap ? this.currentPage.pageX : this.x,
29590            newY = snap ? this.currentPage.pageY : this.y,
29591            now = utils.getTime(),
29592            prevTime = this.keyTime || 0,
29593            acceleration = 0.250,
29594            pos;
29595
29596        if ( this.options.useTransition && this.isInTransition ) {
29597            pos = this.getComputedPosition();
29598
29599            this._translate(Math.round(pos.x), Math.round(pos.y));
29600            this.isInTransition = false;
29601        }
29602
29603        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
29604
29605        switch ( e.keyCode ) {
29606            case this.options.keyBindings.pageUp:
29607                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
29608                    newX += snap ? 1 : this.wrapperWidth;
29609                } else {
29610                    newY += snap ? 1 : this.wrapperHeight;
29611                }
29612                break;
29613            case this.options.keyBindings.pageDown:
29614                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
29615                    newX -= snap ? 1 : this.wrapperWidth;
29616                } else {
29617                    newY -= snap ? 1 : this.wrapperHeight;
29618                }
29619                break;
29620            case this.options.keyBindings.end:
29621                newX = snap ? this.pages.length-1 : this.maxScrollX;
29622                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
29623                break;
29624            case this.options.keyBindings.home:
29625                newX = 0;
29626                newY = 0;
29627                break;
29628            case this.options.keyBindings.left:
29629                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
29630                break;
29631            case this.options.keyBindings.up:
29632                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
29633                break;
29634            case this.options.keyBindings.right:
29635                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
29636                break;
29637            case this.options.keyBindings.down:
29638                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
29639                break;
29640            default:
29641                return;
29642        }
29643
29644        if ( snap ) {
29645            this.goToPage(newX, newY);
29646            return;
29647        }
29648
29649        if ( newX > 0 ) {
29650            newX = 0;
29651            this.keyAcceleration = 0;
29652        } else if ( newX < this.maxScrollX ) {
29653            newX = this.maxScrollX;
29654            this.keyAcceleration = 0;
29655        }
29656
29657        if ( newY > 0 ) {
29658            newY = 0;
29659            this.keyAcceleration = 0;
29660        } else if ( newY < this.maxScrollY ) {
29661            newY = this.maxScrollY;
29662            this.keyAcceleration = 0;
29663        }
29664
29665        this.scrollTo(newX, newY, 0);
29666
29667        this.keyTime = now;
29668    },
29669
29670    _animate: function (destX, destY, duration, easingFn) {
29671        var that = this,
29672            startX = this.x,
29673            startY = this.y,
29674            startTime = utils.getTime(),
29675            destTime = startTime + duration;
29676
29677        function step () {
29678            var now = utils.getTime(),
29679                newX, newY,
29680                easing;
29681
29682            if ( now >= destTime ) {
29683                that.isAnimating = false;
29684                that._translate(destX, destY);
29685
29686                if ( !that.resetPosition(that.options.bounceTime) ) {
29687                    that._execEvent('scrollEnd');
29688                }
29689
29690                return;
29691            }
29692
29693            now = ( now - startTime ) / duration;
29694            easing = easingFn(now);
29695            newX = ( destX - startX ) * easing + startX;
29696            newY = ( destY - startY ) * easing + startY;
29697            that._translate(newX, newY);
29698
29699            if ( that.isAnimating ) {
29700                rAF(step);
29701            }
29702        }
29703
29704        this.isAnimating = true;
29705        step();
29706    },
29707    handleEvent: function (e) {
29708        switch ( e.type ) {
29709            case 'touchstart':
29710            case 'pointerdown':
29711            case 'MSPointerDown':
29712            case 'mousedown':
29713                this._start(e);
29714                break;
29715            case 'touchmove':
29716            case 'pointermove':
29717            case 'MSPointerMove':
29718            case 'mousemove':
29719                this._move(e);
29720                break;
29721            case 'touchend':
29722            case 'pointerup':
29723            case 'MSPointerUp':
29724            case 'mouseup':
29725            case 'touchcancel':
29726            case 'pointercancel':
29727            case 'MSPointerCancel':
29728            case 'mousecancel':
29729                this._end(e);
29730                break;
29731            case 'orientationchange':
29732            case 'resize':
29733                this._resize();
29734                break;
29735            case 'transitionend':
29736            case 'webkitTransitionEnd':
29737            case 'oTransitionEnd':
29738            case 'MSTransitionEnd':
29739                this._transitionEnd(e);
29740                break;
29741            case 'wheel':
29742            case 'DOMMouseScroll':
29743            case 'mousewheel':
29744                this._wheel(e);
29745                break;
29746            case 'keydown':
29747                this._key(e);
29748                break;
29749            case 'click':
29750                if ( this.enabled && !e._constructed ) {
29751                    e.preventDefault();
29752                    e.stopPropagation();
29753                }
29754                break;
29755        }
29756    }
29757};
29758function createDefaultScrollbar (direction, interactive, type) {
29759    var scrollbar = document.createElement('div'),
29760        indicator = document.createElement('div');
29761
29762    if ( type === true ) {
29763        scrollbar.style.cssText = 'position:absolute;z-index:9999';
29764        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';
29765    }
29766
29767    indicator.className = 'iScrollIndicator';
29768
29769    if ( direction == 'h' ) {
29770        if ( type === true ) {
29771            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
29772            indicator.style.height = '100%';
29773        }
29774        scrollbar.className = 'iScrollHorizontalScrollbar';
29775    } else {
29776        if ( type === true ) {
29777            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
29778            indicator.style.width = '100%';
29779        }
29780        scrollbar.className = 'iScrollVerticalScrollbar';
29781    }
29782
29783    scrollbar.style.cssText += ';overflow:hidden';
29784
29785    if ( !interactive ) {
29786        scrollbar.style.pointerEvents = 'none';
29787    }
29788
29789    scrollbar.appendChild(indicator);
29790
29791    return scrollbar;
29792}
29793
29794function Indicator (scroller, options) {
29795    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
29796    this.wrapperStyle = this.wrapper.style;
29797    this.indicator = this.wrapper.children[0];
29798    this.indicatorStyle = this.indicator.style;
29799    this.scroller = scroller;
29800
29801    this.options = {
29802        listenX: true,
29803        listenY: true,
29804        interactive: false,
29805        resize: true,
29806        defaultScrollbars: false,
29807        shrink: false,
29808        fade: false,
29809        speedRatioX: 0,
29810        speedRatioY: 0
29811    };
29812
29813    for ( var i in options ) {
29814        this.options[i] = options[i];
29815    }
29816
29817    this.sizeRatioX = 1;
29818    this.sizeRatioY = 1;
29819    this.maxPosX = 0;
29820    this.maxPosY = 0;
29821
29822    if ( this.options.interactive ) {
29823        if ( !this.options.disableTouch ) {
29824            utils.addEvent(this.indicator, 'touchstart', this);
29825            utils.addEvent(window, 'touchend', this);
29826        }
29827        if ( !this.options.disablePointer ) {
29828            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
29829            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
29830        }
29831        if ( !this.options.disableMouse ) {
29832            utils.addEvent(this.indicator, 'mousedown', this);
29833            utils.addEvent(window, 'mouseup', this);
29834        }
29835    }
29836
29837    if ( this.options.fade ) {
29838        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
29839        var durationProp = utils.style.transitionDuration;
29840        if(!durationProp) {
29841            return;
29842        }
29843        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
29844        // remove 0.0001ms
29845        var self = this;
29846        if(utils.isBadAndroid) {
29847            rAF(function() {
29848                if(self.wrapperStyle[durationProp] === '0.0001ms') {
29849                    self.wrapperStyle[durationProp] = '0s';
29850                }
29851            });
29852        }
29853        this.wrapperStyle.opacity = '0';
29854    }
29855}
29856
29857Indicator.prototype = {
29858    handleEvent: function (e) {
29859        switch ( e.type ) {
29860            case 'touchstart':
29861            case 'pointerdown':
29862            case 'MSPointerDown':
29863            case 'mousedown':
29864                this._start(e);
29865                break;
29866            case 'touchmove':
29867            case 'pointermove':
29868            case 'MSPointerMove':
29869            case 'mousemove':
29870                this._move(e);
29871                break;
29872            case 'touchend':
29873            case 'pointerup':
29874            case 'MSPointerUp':
29875            case 'mouseup':
29876            case 'touchcancel':
29877            case 'pointercancel':
29878            case 'MSPointerCancel':
29879            case 'mousecancel':
29880                this._end(e);
29881                break;
29882        }
29883    },
29884
29885    destroy: function () {
29886        if ( this.options.fadeScrollbars ) {
29887            clearTimeout(this.fadeTimeout);
29888            this.fadeTimeout = null;
29889        }
29890        if ( this.options.interactive ) {
29891            utils.removeEvent(this.indicator, 'touchstart', this);
29892            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
29893            utils.removeEvent(this.indicator, 'mousedown', this);
29894
29895            utils.removeEvent(window, 'touchmove', this);
29896            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
29897            utils.removeEvent(window, 'mousemove', this);
29898
29899            utils.removeEvent(window, 'touchend', this);
29900            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
29901            utils.removeEvent(window, 'mouseup', this);
29902        }
29903
29904        if ( this.options.defaultScrollbars ) {
29905            this.wrapper.parentNode.removeChild(this.wrapper);
29906        }
29907    },
29908
29909    _start: function (e) {
29910        var point = e.touches ? e.touches[0] : e;
29911
29912        e.preventDefault();
29913        e.stopPropagation();
29914
29915        this.transitionTime();
29916
29917        this.initiated = true;
29918        this.moved = false;
29919        this.lastPointX = point.pageX;
29920        this.lastPointY = point.pageY;
29921
29922        this.startTime  = utils.getTime();
29923
29924        if ( !this.options.disableTouch ) {
29925            utils.addEvent(window, 'touchmove', this);
29926        }
29927        if ( !this.options.disablePointer ) {
29928            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
29929        }
29930        if ( !this.options.disableMouse ) {
29931            utils.addEvent(window, 'mousemove', this);
29932        }
29933
29934        this.scroller._execEvent('beforeScrollStart');
29935    },
29936
29937    _move: function (e) {
29938        var point = e.touches ? e.touches[0] : e,
29939            deltaX, deltaY,
29940            newX, newY,
29941            timestamp = utils.getTime();
29942
29943        if ( !this.moved ) {
29944            this.scroller._execEvent('scrollStart');
29945        }
29946
29947        this.moved = true;
29948
29949        deltaX = point.pageX - this.lastPointX;
29950        this.lastPointX = point.pageX;
29951
29952        deltaY = point.pageY - this.lastPointY;
29953        this.lastPointY = point.pageY;
29954
29955        newX = this.x + deltaX;
29956        newY = this.y + deltaY;
29957
29958        this._pos(newX, newY);
29959
29960// INSERT POINT: indicator._move
29961
29962        e.preventDefault();
29963        e.stopPropagation();
29964    },
29965
29966    _end: function (e) {
29967        if ( !this.initiated ) {
29968            return;
29969        }
29970
29971        this.initiated = false;
29972
29973        e.preventDefault();
29974        e.stopPropagation();
29975
29976        utils.removeEvent(window, 'touchmove', this);
29977        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
29978        utils.removeEvent(window, 'mousemove', this);
29979
29980        if ( this.scroller.options.snap ) {
29981            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
29982
29983            var time = this.options.snapSpeed || Math.max(
29984                    Math.max(
29985                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
29986                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
29987                    ), 300);
29988
29989            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
29990                this.scroller.directionX = 0;
29991                this.scroller.directionY = 0;
29992                this.scroller.currentPage = snap;
29993                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
29994            }
29995        }
29996
29997        if ( this.moved ) {
29998            this.scroller._execEvent('scrollEnd');
29999        }
30000    },
30001
30002    transitionTime: function (time) {
30003        time = time || 0;
30004        var durationProp = utils.style.transitionDuration;
30005        if(!durationProp) {
30006            return;
30007        }
30008
30009        this.indicatorStyle[durationProp] = time + 'ms';
30010
30011        if ( !time && utils.isBadAndroid ) {
30012            this.indicatorStyle[durationProp] = '0.0001ms';
30013            // remove 0.0001ms
30014            var self = this;
30015            rAF(function() {
30016                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30017                    self.indicatorStyle[durationProp] = '0s';
30018                }
30019            });
30020        }
30021    },
30022
30023    transitionTimingFunction: function (easing) {
30024        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30025    },
30026
30027    refresh: function () {
30028        this.transitionTime();
30029
30030        if ( this.options.listenX && !this.options.listenY ) {
30031            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30032        } else if ( this.options.listenY && !this.options.listenX ) {
30033            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30034        } else {
30035            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30036        }
30037
30038        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30039            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30040            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30041
30042            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30043                if ( this.options.listenX ) {
30044                    this.wrapper.style.right = '8px';
30045                } else {
30046                    this.wrapper.style.bottom = '8px';
30047                }
30048            }
30049        } else {
30050            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30051            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30052
30053            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30054                if ( this.options.listenX ) {
30055                    this.wrapper.style.right = '2px';
30056                } else {
30057                    this.wrapper.style.bottom = '2px';
30058                }
30059            }
30060        }
30061
30062        var r = this.wrapper.offsetHeight;  // force refresh
30063
30064        if ( this.options.listenX ) {
30065            this.wrapperWidth = this.wrapper.clientWidth;
30066            if ( this.options.resize ) {
30067                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30068                this.indicatorStyle.width = this.indicatorWidth + 'px';
30069            } else {
30070                this.indicatorWidth = this.indicator.clientWidth;
30071            }
30072
30073            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30074
30075            if ( this.options.shrink == 'clip' ) {
30076                this.minBoundaryX = -this.indicatorWidth + 8;
30077                this.maxBoundaryX = this.wrapperWidth - 8;
30078            } else {
30079                this.minBoundaryX = 0;
30080                this.maxBoundaryX = this.maxPosX;
30081            }
30082
30083            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30084        }
30085
30086        if ( this.options.listenY ) {
30087            this.wrapperHeight = this.wrapper.clientHeight;
30088            if ( this.options.resize ) {
30089                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
30090                this.indicatorStyle.height = this.indicatorHeight + 'px';
30091            } else {
30092                this.indicatorHeight = this.indicator.clientHeight;
30093            }
30094
30095            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30096
30097            if ( this.options.shrink == 'clip' ) {
30098                this.minBoundaryY = -this.indicatorHeight + 8;
30099                this.maxBoundaryY = this.wrapperHeight - 8;
30100            } else {
30101                this.minBoundaryY = 0;
30102                this.maxBoundaryY = this.maxPosY;
30103            }
30104
30105            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30106            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
30107        }
30108
30109        this.updatePosition();
30110    },
30111
30112    updatePosition: function () {
30113        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
30114            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
30115
30116        if ( !this.options.ignoreBoundaries ) {
30117            if ( x < this.minBoundaryX ) {
30118                if ( this.options.shrink == 'scale' ) {
30119                    this.width = Math.max(this.indicatorWidth + x, 8);
30120                    this.indicatorStyle.width = this.width + 'px';
30121                }
30122                x = this.minBoundaryX;
30123            } else if ( x > this.maxBoundaryX ) {
30124                if ( this.options.shrink == 'scale' ) {
30125                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
30126                    this.indicatorStyle.width = this.width + 'px';
30127                    x = this.maxPosX + this.indicatorWidth - this.width;
30128                } else {
30129                    x = this.maxBoundaryX;
30130                }
30131            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
30132                this.width = this.indicatorWidth;
30133                this.indicatorStyle.width = this.width + 'px';
30134            }
30135
30136            if ( y < this.minBoundaryY ) {
30137                if ( this.options.shrink == 'scale' ) {
30138                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
30139                    this.indicatorStyle.height = this.height + 'px';
30140                }
30141                y = this.minBoundaryY;
30142            } else if ( y > this.maxBoundaryY ) {
30143                if ( this.options.shrink == 'scale' ) {
30144                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
30145                    this.indicatorStyle.height = this.height + 'px';
30146                    y = this.maxPosY + this.indicatorHeight - this.height;
30147                } else {
30148                    y = this.maxBoundaryY;
30149                }
30150            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
30151                this.height = this.indicatorHeight;
30152                this.indicatorStyle.height = this.height + 'px';
30153            }
30154        }
30155
30156        this.x = x;
30157        this.y = y;
30158
30159        if ( this.scroller.options.useTransform ) {
30160            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
30161        } else {
30162            this.indicatorStyle.left = x + 'px';
30163            this.indicatorStyle.top = y + 'px';
30164        }
30165    },
30166
30167    _pos: function (x, y) {
30168        if ( x < 0 ) {
30169            x = 0;
30170        } else if ( x > this.maxPosX ) {
30171            x = this.maxPosX;
30172        }
30173
30174        if ( y < 0 ) {
30175            y = 0;
30176        } else if ( y > this.maxPosY ) {
30177            y = this.maxPosY;
30178        }
30179
30180        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
30181        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
30182
30183        this.scroller.scrollTo(x, y);
30184    },
30185
30186    fade: function (val, hold) {
30187        if ( hold && !this.visible ) {
30188            return;
30189        }
30190
30191        clearTimeout(this.fadeTimeout);
30192        this.fadeTimeout = null;
30193
30194        var time = val ? 250 : 500,
30195            delay = val ? 0 : 300;
30196
30197        val = val ? '1' : '0';
30198
30199        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
30200
30201        this.fadeTimeout = setTimeout((function (val) {
30202            this.wrapperStyle.opacity = val;
30203            this.visible = +val;
30204        }).bind(this, val), delay);
30205    }
30206};
30207
30208IScroll.utils = utils;
30209
30210if ( typeof module != 'undefined' && module.exports ) {
30211    module.exports = IScroll;
30212} else if ( typeof define == 'function' && define.amd ) {
30213        define( function () { return IScroll; } );
30214} else {
30215    window.IScroll = IScroll;
30216}
30217
30218})(window, document, Math);
30219/*!
30220 * fullPage 2.9.4
30221 * https://github.com/alvarotrigo/fullPage.js
30222 * @license MIT licensed
30223 *
30224 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
30225 */
30226(function(global, factory) {
30227    'use strict';
30228    if (typeof define === 'function' && define.amd) {
30229        define(['jquery'], function($) {
30230          return factory($, global, global.document, global.Math);
30231        });
30232    } else if (typeof exports === "object" && exports) {
30233        module.exports = factory(require('jquery'), global, global.document, global.Math);
30234    } else {
30235        factory(jQuery, global, global.document, global.Math);
30236    }
30237})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
30238    'use strict';
30239
30240    // keeping central set of classnames and selectors
30241    var WRAPPER =               'fullpage-wrapper';
30242    var WRAPPER_SEL =           '.' + WRAPPER;
30243
30244    // slimscroll
30245    var SCROLLABLE =            'fp-scrollable';
30246    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
30247
30248    // util
30249    var RESPONSIVE =            'fp-responsive';
30250    var NO_TRANSITION =         'fp-notransition';
30251    var DESTROYED =             'fp-destroyed';
30252    var ENABLED =               'fp-enabled';
30253    var VIEWING_PREFIX =        'fp-viewing';
30254    var ACTIVE =                'active';
30255    var ACTIVE_SEL =            '.' + ACTIVE;
30256    var COMPLETELY =            'fp-completely';
30257    var COMPLETELY_SEL =        '.' + COMPLETELY;
30258
30259    // section
30260    var SECTION_DEFAULT_SEL =   '.section';
30261    var SECTION =               'fp-section';
30262    var SECTION_SEL =           '.' + SECTION;
30263    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
30264    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
30265    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
30266    var TABLE_CELL =            'fp-tableCell';
30267    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
30268    var AUTO_HEIGHT =           'fp-auto-height';
30269    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
30270    var NORMAL_SCROLL =         'fp-normal-scroll';
30271    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
30272
30273    // section nav
30274    var SECTION_NAV =           'fp-nav';
30275    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
30276    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
30277    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
30278    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
30279
30280    // slide
30281    var SLIDE_DEFAULT_SEL =     '.slide';
30282    var SLIDE =                 'fp-slide';
30283    var SLIDE_SEL =             '.' + SLIDE;
30284    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
30285    var SLIDES_WRAPPER =        'fp-slides';
30286    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
30287    var SLIDES_CONTAINER =      'fp-slidesContainer';
30288    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
30289    var TABLE =                 'fp-table';
30290
30291    // slide nav
30292    var SLIDES_NAV =            'fp-slidesNav';
30293    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
30294    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
30295    var SLIDES_ARROW =          'fp-controlArrow';
30296    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
30297    var SLIDES_PREV =           'fp-prev';
30298    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
30299    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
30300    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
30301    var SLIDES_NEXT =           'fp-next';
30302    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
30303    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
30304    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
30305
30306    var $window = $(window);
30307    var $document = $(document);
30308
30309    // Default options for iScroll.js used when using scrollOverflow
30310    var iscrollOptions = {
30311        scrollbars: true,
30312        mouseWheel: true,
30313        hideScrollbars: false,
30314        fadeScrollbars: false,
30315        disableMouse: true,
30316        interactiveScrollbars: true,
30317        bounce: false,
30318    };
30319
30320    $.fn.fullpage = function(options) {
30321        //only once my friend!
30322        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
30323
30324        // common jQuery objects
30325        var $htmlBody = $('html, body');
30326        var $body = $('body');
30327
30328        var FP = $.fn.fullpage;
30329
30330        // Creating some defaults, extending them with any options that were provided
30331        options = $.extend({
30332            //navigation
30333            menu: false,
30334            anchors:[],
30335            lockAnchors: false,
30336            navigation: false,
30337            navigationPosition: 'right',
30338            navigationTooltips: [],
30339            showActiveTooltip: false,
30340            slidesNavigation: false,
30341            slidesNavPosition: 'bottom',
30342            scrollBar: false,
30343            hybrid: false,
30344
30345            //scrolling
30346            css3: true,
30347            scrollingSpeed: 700,
30348            autoScrolling: true,
30349            fitToSection: true,
30350            fitToSectionDelay: 1000,
30351            easing: 'easeInOutCubic',
30352            easingcss3: 'ease',
30353            loopBottom: false,
30354            loopTop: false,
30355            loopHorizontal: true,
30356            continuousVertical: false,
30357            continuousHorizontal: false,
30358            scrollHorizontally: false,
30359            interlockedSlides: false,
30360            dragAndMove: false,
30361            offsetSections: false,
30362            resetSliders: false,
30363            fadingEffect: false,
30364            normalScrollElements: null,
30365            scrollOverflow: false,
30366            scrollOverflowReset: false,
30367            scrollOverflowHandler: iscrollHandler,
30368            scrollOverflowOptions: null,
30369            touchSensitivity: 5,
30370            normalScrollElementTouchThreshold: 5,
30371            bigSectionsDestination: null,
30372
30373            //Accessibility
30374            keyboardScrolling: true,
30375            animateAnchor: true,
30376            recordHistory: true,
30377
30378            //design
30379            controlArrows: true,
30380            controlArrowColor: '#fff',
30381            verticalCentered: true,
30382            sectionsColor : [],
30383            paddingTop: 0,
30384            paddingBottom: 0,
30385            fixedElements: null,
30386            responsive: 0, //backwards compabitility with responsiveWiddth
30387            responsiveWidth: 0,
30388            responsiveHeight: 0,
30389            responsiveSlides: false,
30390            parallax: false,
30391            parallaxOptions: {
30392                type: 'reveal',
30393                percentage: 62,
30394                property: 'translate'
30395            },
30396
30397            //Custom selectors
30398            sectionSelector: SECTION_DEFAULT_SEL,
30399            slideSelector: SLIDE_DEFAULT_SEL,
30400
30401            //events
30402            afterLoad: null,
30403            onLeave: null,
30404            afterRender: null,
30405            afterResize: null,
30406            afterReBuild: null,
30407            afterSlideLoad: null,
30408            onSlideLeave: null,
30409            afterResponsive: null,
30410
30411            lazyLoading: true
30412        }, options);
30413
30414        //flag to avoid very fast sliding for landscape sliders
30415        var slideMoving = false;
30416
30417        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
30418        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
30419        var container = $(this);
30420        var windowsHeight = $window.height();
30421        var isResizing = false;
30422        var isWindowFocused = true;
30423        var lastScrolledDestiny;
30424        var lastScrolledSlide;
30425        var canScroll = true;
30426        var scrollings = [];
30427        var controlPressed;
30428        var startingSection;
30429        var isScrollAllowed = {};
30430        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
30431        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
30432        var MSPointer = getMSPointer();
30433        var events = {
30434            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
30435            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
30436        };
30437
30438        //cheks for passive event support
30439        //added by Uncode from new fullPage updates
30440        var g_supportsPassive = false;
30441        try {
30442          var opts = Object.defineProperty({}, 'passive', {
30443            get: function() {
30444              g_supportsPassive = true;
30445            }
30446          });
30447          window.addEventListener("testPassive", null, opts);
30448          window.removeEventListener("testPassive", null, opts);
30449        } catch (e) {}
30450
30451        //timeouts
30452        var resizeId;
30453        var afterSectionLoadsId;
30454        var afterSlideLoadsId;
30455        var scrollId;
30456        var scrollId2;
30457        var keydownId;
30458        var originals = $.extend(true, {}, options); //deep copy
30459
30460        //Uncode addition
30461        var $masthead = $('#masthead');
30462        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
30463        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
30464        var bodyBorder = UNCODE.bodyBorder;
30465        var adminBarHeight = UNCODE.adminBarHeight;
30466
30467        displayWarnings();
30468
30469        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
30470        iscrollOptions.click = isTouch; // see #2035
30471
30472        //extending iScroll options with the user custom ones
30473        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
30474
30475        //easeInOutCubic animation included in the plugin
30476        $.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;}});
30477
30478        /**
30479        * Sets the autoScroll option.
30480        * It changes the scroll bar visibility and the history of the site as a result.
30481        */
30482        function setAutoScrolling(value, type){
30483            //removing the transformation
30484            if(!value){
30485                silentScroll(0);
30486            }
30487
30488            setVariableState('autoScrolling', value, type);
30489
30490            var element = $(SECTION_ACTIVE_SEL);
30491
30492            if(options.autoScrolling && !options.scrollBar){
30493                $htmlBody.css({
30494                    'overflow' : 'hidden !important',
30495                    'height' : '100%'
30496                });
30497
30498                //Uncode addition
30499                //setRecordHistory(originals.recordHistory, 'internal');
30500
30501                //for IE touch devices
30502                container.css({
30503                    '-ms-touch-action': 'none',
30504                    'touch-action': 'none'
30505                });
30506
30507                if(element.length){
30508                    //moving the container up
30509                    silentScroll(element.position().top);
30510                }
30511
30512            }else{
30513                $htmlBody.css({
30514                    'overflow' : 'visible !important',
30515                    'height' : 'initial'
30516                });
30517
30518                //Uncode addition
30519                //setRecordHistory(false, 'internal');
30520
30521                //for IE touch devices
30522                container.css({
30523                    '-ms-touch-action': '',
30524                    'touch-action': ''
30525                });
30526
30527                //scrolling the page to the section with no animation
30528                if (element.length) {
30529                    $htmlBody.scrollTop(element.position().top);
30530                }
30531            }
30532        }
30533
30534        /**
30535        * Defines wheter to record the history for each hash change in the URL.
30536        */
30537        function setRecordHistory(value, type){
30538            setVariableState('recordHistory', value, type);
30539        }
30540
30541        /**
30542        * Defines the scrolling speed
30543        */
30544        function setScrollingSpeed(value, type){
30545            setVariableState('scrollingSpeed', value, type);
30546        }
30547
30548        /**
30549        * Sets fitToSection
30550        */
30551        function setFitToSection(value, type){
30552            setVariableState('fitToSection', value, type);
30553        }
30554
30555        /**
30556        * Sets lockAnchors
30557        */
30558        function setLockAnchors(value){
30559            options.lockAnchors = value;
30560        }
30561
30562        /**
30563        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
30564        */
30565        function setMouseWheelScrolling(value){
30566            if(value){
30567                addMouseWheelHandler();
30568                addMiddleWheelHandler();
30569            }else{
30570                removeMouseWheelHandler();
30571                removeMiddleWheelHandler();
30572            }
30573        }
30574
30575        /**
30576        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
30577        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
30578        *
30579        * @param directions string containing the direction or directions separated by comma.
30580        */
30581        function setAllowScrolling(value, directions){
30582            if(typeof directions !== 'undefined'){
30583                directions = directions.replace(/ /g,'').split(',');
30584
30585                $.each(directions, function (index, direction){
30586                    setIsScrollAllowed(value, direction, 'm');
30587                });
30588            }
30589            else if(value){
30590                setMouseWheelScrolling(true);
30591                addTouchHandler();
30592            }else{
30593                setMouseWheelScrolling(false);
30594                removeTouchHandler();
30595            }
30596        }
30597
30598        /**
30599        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
30600        */
30601        function setKeyboardScrolling(value, directions){
30602            if(typeof directions !== 'undefined'){
30603                directions = directions.replace(/ /g,'').split(',');
30604
30605                $.each(directions, function (index, direction){
30606                    setIsScrollAllowed(value, direction, 'k');
30607                });
30608            }else{
30609                options.keyboardScrolling = value;
30610            }
30611        }
30612
30613        /**
30614        * Moves the page up one section.
30615        */
30616        function moveSectionUp(){
30617            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
30618
30619            //looping to the bottom if there's no more sections above
30620            if (!prev.length && (options.loopTop || options.continuousVertical)) {
30621                prev = $(SECTION_SEL).last();
30622            }
30623
30624            if (prev.length) {
30625                scrollPage(prev, null, true);
30626            }
30627        }
30628
30629        /**
30630        * Moves the page down one section.
30631        */
30632        function moveSectionDown(){
30633            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
30634
30635            //looping to the top if there's no more sections below
30636            if(!next.length &&
30637                (options.loopBottom || options.continuousVertical)){
30638                next = $(SECTION_SEL).first();
30639            }
30640
30641            if(next.length){
30642                scrollPage(next, null, false);
30643            }
30644        }
30645
30646        /**
30647        * Moves the page to the given section and slide with no animation.
30648        * Anchors or index positions can be used as params.
30649        */
30650        function silentMoveTo(sectionAnchor, slideAnchor){
30651            setScrollingSpeed (0, 'internal');
30652            moveTo(sectionAnchor, slideAnchor);
30653            setScrollingSpeed (originals.scrollingSpeed, 'internal');
30654        }
30655
30656        /**
30657        * Moves the page to the given section and slide.
30658        * Anchors or index positions can be used as params.
30659        */
30660        function moveTo(sectionAnchor, slideAnchor){
30661            var destiny = getSectionByAnchor(sectionAnchor);
30662
30663            if (typeof slideAnchor !== 'undefined'){
30664                scrollPageAndSlide(sectionAnchor, slideAnchor);
30665            }else if(destiny.length > 0){
30666                scrollPage(destiny);
30667            }
30668        }
30669
30670        /**
30671        * Slides right the slider of the active section.
30672        * Optional `section` param.
30673        */
30674        function moveSlideRight(section){
30675            moveSlide('right', section);
30676        }
30677
30678        /**
30679        * Slides left the slider of the active section.
30680        * Optional `section` param.
30681        */
30682        function moveSlideLeft(section){
30683            moveSlide('left', section);
30684        }
30685
30686        /**
30687         * When resizing is finished, we adjust the slides sizes and positions
30688         */
30689        function reBuild(resizing){
30690            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
30691
30692            isResizing = true;
30693
30694            windowsHeight = $window.height();  //updating global var
30695
30696            $(SECTION_SEL).each(function(){
30697                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
30698                var slides = $(this).find(SLIDE_SEL);
30699
30700                //adjusting the height of the table-cell for IE and Firefox
30701                if(options.verticalCentered){
30702                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
30703                }
30704
30705                $(this).css('height', windowsHeight + 'px');
30706
30707                //resizing the scrolling divs
30708                if(options.scrollOverflow){
30709                    if(slides.length){
30710                        slides.each(function(){
30711                            createScrollBar($(this));
30712                        });
30713                    }else{
30714                        createScrollBar($(this));
30715                    }
30716                }
30717
30718                //adjusting the position fo the FULL WIDTH slides...
30719                if (slides.length > 1) {
30720                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
30721                }
30722            });
30723
30724            var activeSection = $(SECTION_ACTIVE_SEL);
30725            var sectionIndex = activeSection.index(SECTION_SEL);
30726
30727            //isn't it the first section?
30728            if(sectionIndex){
30729                //adjusting the position for the current section
30730                silentMoveTo(sectionIndex + 1);
30731            }
30732
30733            isResizing = false;
30734            // Uncode change
30735            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
30736            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
30737            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
30738        }
30739
30740        /**
30741        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
30742        * are smaller than the set limit values.
30743        */
30744        function setResponsive(active){
30745            var isResponsive = $body.hasClass(RESPONSIVE);
30746
30747            if(active){
30748                if(!isResponsive){
30749                    setAutoScrolling(false, 'internal');
30750                    setFitToSection(false, 'internal');
30751                    $(SECTION_NAV_SEL).hide();
30752                    $body.addClass(RESPONSIVE);
30753                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
30754                }
30755            }
30756            else if(isResponsive){
30757                setAutoScrolling(originals.autoScrolling, 'internal');
30758                setFitToSection(originals.autoScrolling, 'internal');
30759                $(SECTION_NAV_SEL).show();
30760                $body.removeClass(RESPONSIVE);
30761                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
30762            }
30763        }
30764
30765        if($(this).length){
30766            //public functions
30767            FP.setAutoScrolling = setAutoScrolling;
30768            FP.setRecordHistory = setRecordHistory;
30769            FP.setScrollingSpeed = setScrollingSpeed;
30770            FP.setFitToSection = setFitToSection;
30771            FP.setLockAnchors = setLockAnchors;
30772            FP.setMouseWheelScrolling = setMouseWheelScrolling;
30773            FP.setAllowScrolling = setAllowScrolling;
30774            FP.setKeyboardScrolling = setKeyboardScrolling;
30775            FP.moveSectionUp = moveSectionUp;
30776            FP.moveSectionDown = moveSectionDown;
30777            FP.silentMoveTo = silentMoveTo;
30778            FP.moveTo = moveTo;
30779            FP.moveSlideRight = moveSlideRight;
30780            FP.moveSlideLeft = moveSlideLeft;
30781            FP.fitToSection = fitToSection;
30782            FP.reBuild = reBuild;
30783            FP.setResponsive = setResponsive;
30784            FP.destroy = destroy;
30785
30786            init();
30787
30788            bindEvents();
30789        }
30790
30791        function init(){
30792            //if css3 is not supported, it will use jQuery animations
30793            if(options.css3){
30794                options.css3 = support3d();
30795            }
30796
30797            options.scrollBar = options.scrollBar || options.hybrid;
30798
30799            setOptionsFromDOM();
30800            prepareDom();
30801            setAllowScrolling(true);
30802            setAutoScrolling(options.autoScrolling, 'internal');
30803            responsive();
30804
30805            //setting the class for the body element
30806            setBodyClass();
30807
30808            //Uncode addition
30809            // if(document.readyState === 'complete'){
30810            //     scrollToAnchor();
30811            // }
30812            // $window.on('load', scrollToAnchor);
30813        }
30814
30815        function bindEvents(){
30816            $window
30817                //when scrolling...
30818                //.on('scroll', scrollHandler)
30819
30820                //detecting any change on the URL to scroll to the given anchor link
30821                //(a way to detect back history button as we play with the hashes on the URL)
30822                .on('hashchange', hashChangeHandler)
30823
30824                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
30825                .blur(blurHandler)
30826
30827                //when resizing the site, we adjust the heights of the sections, slimScroll...
30828                .resize(resizeHandler);
30829
30830            $document
30831                //Sliding with arrow keys, both, vertical and horizontal
30832                .keydown(keydownHandler)
30833
30834                //to prevent scrolling while zooming
30835                .keyup(keyUpHandler)
30836
30837                //Scrolls to the section when clicking the navigation bullet
30838                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
30839
30840                //Scrolls the slider to the given slide destination for the given section
30841                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
30842
30843                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
30844
30845            //Scrolling horizontally when clicking on the slider controls.
30846            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
30847
30848            /**
30849            * Applying normalScroll elements.
30850            * Ignoring the scrolls over the specified selectors.
30851            */
30852            if(options.normalScrollElements){
30853                $document.on('mouseenter', options.normalScrollElements, function () {
30854                    setMouseWheelScrolling(false);
30855                });
30856
30857                $document.on('mouseleave', options.normalScrollElements, function(){
30858                    setMouseWheelScrolling(true);
30859                });
30860            }
30861        }
30862
30863        /**
30864        * Setting options from DOM elements if they are not provided.
30865        */
30866        function setOptionsFromDOM(){
30867            var sections = container.find(options.sectionSelector);
30868
30869            //no anchors option? Checking for them in the DOM attributes
30870            if(!options.anchors.length){
30871                options.anchors = sections.filter('[data-anchor]').map(function(){
30872                    return $(this).data('anchor').toString();
30873                }).get();
30874            }
30875
30876            //no tooltips option? Checking for them in the DOM attributes
30877            if(!options.navigationTooltips.length){
30878                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
30879                    return $(this).data('tooltip').toString();
30880                }).get();
30881            }
30882        }
30883
30884        /**
30885        * Works over the DOM structure to set it up for the current fullpage options.
30886        */
30887        function prepareDom(){
30888            container.css({
30889                'height': '100%',
30890                'position': 'relative'
30891            });
30892
30893            //adding a class to recognize the container internally in the code
30894            container.addClass(WRAPPER);
30895            $('html').addClass(ENABLED);
30896
30897            windowsHeight = $window.height();
30898
30899            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
30900
30901            addInternalSelectors();
30902
30903             //styling the sections / slides / menu
30904            $(SECTION_SEL).each(function(index){
30905                var section = $(this);
30906                var slides = section.find(SLIDE_SEL);
30907                var numSlides = slides.length;
30908
30909                styleSection(section, index);
30910                styleMenu(section, index);
30911
30912                // if there's any slide
30913                if (numSlides > 0) {
30914                    styleSlides(section, slides, numSlides);
30915                }else{
30916                    if(options.verticalCentered){
30917                        addTableClass(section);
30918                    }
30919                }
30920            });
30921
30922            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
30923            if(options.fixedElements && options.css3){
30924                $(options.fixedElements).appendTo($body);
30925            }
30926
30927            //vertical centered of the navigation + active bullet
30928            if(options.navigation){
30929                addVerticalNavigation();
30930            }
30931
30932            enableYoutubeAPI();
30933
30934            if(options.scrollOverflow){
30935                if(document.readyState === 'complete'){
30936                    createScrollBarHandler();
30937                }
30938                //after DOM and images are loaded
30939                $window.on('load', createScrollBarHandler);
30940            }else{
30941                afterRenderActions();
30942            }
30943        }
30944
30945        /**
30946        * Styles the horizontal slides for a section.
30947        */
30948        function styleSlides(section, slides, numSlides){
30949            var sliderWidth = numSlides * 100;
30950            var slideWidth = 100 / numSlides;
30951
30952            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
30953            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
30954
30955            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
30956
30957            if(numSlides > 1){
30958                if(options.controlArrows){
30959                    createSlideArrows(section);
30960                }
30961
30962                if(options.slidesNavigation){
30963                    addSlidesNavigation(section, numSlides);
30964                }
30965            }
30966
30967            slides.each(function(index) {
30968                $(this).css('width', slideWidth + '%');
30969
30970                if(options.verticalCentered){
30971                    addTableClass($(this));
30972                }
30973            });
30974
30975            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
30976
30977            //if the slide won't be an starting point, the default will be the first one
30978            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
30978ide by default.
30979            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
30980                silentLandscapeScroll(startingSlide, 'internal');
30981            }else{
30982                slides.eq(0).addClass(ACTIVE);
30983            }
30984        }
30985
30986        /**
30987        * Styling vertical sections
30988        */
30989        function styleSection(section, index){
30990            //if no active section is defined, the 1st one will be the default one
30991            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
30992                section.addClass(ACTIVE);
30993            }
30994            startingSection = $(SECTION_ACTIVE_SEL);
30995
30996            section.css('height', windowsHeight + 'px');
30997
30998            if(options.paddingTop){
30999                section.css('padding-top', options.paddingTop);
31000            }
31001
31002            if(options.paddingBottom){
31003                section.css('padding-bottom', options.paddingBottom);
31004            }
31005
31006            if (typeof options.sectionsColor[index] !==  'undefined') {
31007                section.css('background-color', options.sectionsColor[index]);
31008            }
31009
31010            if (typeof options.anchors[index] !== 'undefined') {
31011                section.attr('data-anchor', options.anchors[index]);
31012            }
31013        }
31014
31015        /**
31016        * Sets the data-anchor attributes to the menu elements and activates the current one.
31017        */
31018        function styleMenu(section, index){
31019            if (typeof options.anchors[index] !== 'undefined') {
31020                //activating the menu / nav element on load
31021                if(section.hasClass(ACTIVE)){
31022                    activateMenuAndNav(options.anchors[index], index);
31023                }
31024            }
31025
31026            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31027            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31028                $(options.menu).appendTo($body);
31029            }
31030        }
31031
31032        /**
31033        * Adds internal classes to be able to provide customizable selectors
31034        * keeping the link with the style sheet.
31035        */
31036        function addInternalSelectors(){
31037            container.find(options.sectionSelector).addClass(SECTION);
31038            container.find(options.slideSelector).addClass(SLIDE);
31039        }
31040
31041        /**
31042        * Creates the control arrows for the given section
31043        */
31044        function createSlideArrows(section){
31045            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31046
31047            if(options.controlArrowColor!='#fff'){
31048                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31049                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31050            }
31051
31052            if(!options.loopHorizontal){
31053                section.find(SLIDES_ARROW_PREV_SEL).hide();
31054            }
31055        }
31056
31057        /**
31058        * Creates a vertical navigation bar.
31059        */
31060        function addVerticalNavigation(){
31061            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31062            var nav = $(SECTION_NAV_SEL);
31063
31064            nav.addClass(function() {
31065                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31066            });
31067
31068            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31069                var link = '';
31070                if (options.anchors.length) {
31071                    link = options.anchors[i];
31072                }
31073
31074                var li = '<li><a href="#' + link + '"><span></span></a>';
31075
31076                // Only add tooltip if needed (defined by user)
31077                var tooltip = options.navigationTooltips[i];
31078
31079                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31080                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31081                }
31082
31083                li += '</li>';
31084
31085                nav.find('ul').append(li);
31086            }
31087
31088            //centering it vertically
31089            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
31090
31091            //activating the current active section
31092            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
31093        }
31094
31095        /**
31096        * Creates the slim scroll scrollbar for the sections and slides inside them.
31097        */
31098        function createScrollBarHandler(){
31099            $(SECTION_SEL).each(function(){
31100                var slides = $(this).find(SLIDE_SEL);
31101
31102                if(slides.length){
31103                    slides.each(function(){
31104                        createScrollBar($(this));
31105                    });
31106                }else{
31107                    createScrollBar($(this));
31108                }
31109
31110            });
31111            afterRenderActions();
31112        }
31113
31114        /*
31115        * Enables the Youtube videos API so we can control their flow if necessary.
31116        */
31117        function enableYoutubeAPI(){
31118            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
31119                addURLParam($(this), 'enablejsapi=1');
31120            });
31121        }
31122
31123        /**
31124        * Adds a new parameter and its value to the `src` of a given element
31125        */
31126        function addURLParam(element, newParam){
31127            var originalSrc = element.attr('src');
31128            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
31129        }
31130
31131        /*
31132        * Returns the prefix sign to use for a new parameter in an existen URL.
31133        *
31134        * @return {String}  ? | &
31135        */
31136        function getUrlParamSign(url){
31137            return ( !/\?/.test( url ) ) ? '?' : '&';
31138        }
31139
31140        /**
31141        * Actions and callbacks to fire afterRender
31142        */
31143        function afterRenderActions(){
31144            var section = $(SECTION_ACTIVE_SEL);
31145
31146            section.addClass(COMPLETELY);
31147
31148            if(options.scrollOverflowHandler.afterRender){
31149                options.scrollOverflowHandler.afterRender(section);
31150            }
31151            lazyLoad(section);
31152            playMedia(section);
31153            options.scrollOverflowHandler.afterLoad();
31154
31155            if(isDestinyTheStartingSection()){
31156                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
31157            }
31158
31159            // Uncode change
31160            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
31161            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
31162        }
31163
31164        /**
31165        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
31166        */
31167        function isDestinyTheStartingSection(){
31168            var anchors =  window.location.hash.replace('#', '').split('/');
31169            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
31170
31171            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
31172        }
31173
31174
31175        var isScrolling = false;
31176        var lastScroll = 0;
31177
31178        //when scrolling...
31179        function scrollHandler(){
31180            var currentSection;
31181
31182            if(!options.autoScrolling || options.scrollBar){
31183                var currentScroll = $window.scrollTop();
31184                var scrollDirection = getScrollDirection(currentScroll);
31185                var visibleSectionIndex = 0;
31186                var screen_mid = currentScroll + ($window.height() / 2.0);
31187                var isAtBottom = $body.height() - $window.height() === currentScroll;
31188                var sections =  document.querySelectorAll(SECTION_SEL);
31189
31190                //when using `auto-height` for a small last section it won't be centered in the viewport
31191                if(isAtBottom){
31192                    visibleSectionIndex = sections.length - 1;
31193                }
31194                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
31195                else if(!currentScroll){
31196                    visibleSectionIndex = 0;
31197                }
31198
31199                //taking the section which is showing more content in the viewport
31200                else{
31201                    for (var i = 0; i < sections.length; ++i) {
31202                        var section = sections[i];
31203
31204                        // Pick the the last section which passes the middle line of the screen.
31205                        if (section.offsetTop <= screen_mid)
31206                        {
31207                            visibleSectionIndex = i;
31208                        }
31209                    }
31210                }
31211
31212                if(isCompletelyInViewPort(scrollDirection)){
31213                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
31214                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
31215                    }
31216                }
31217
31218                //geting the last one, the current one on the screen
31219                currentSection = $(sections).eq(visibleSectionIndex);
31220
31221                //setting the visible section as active when manually scrolling
31222                //executing only once the first time we reach the section
31223                if(!currentSection.hasClass(ACTIVE)){
31224                    isScrolling = true;
31225                    var leavingSection = $(SECTION_ACTIVE_SEL);
31226                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
31227                    var yMovement = getYmovement(currentSection);
31228                    var anchorLink  = currentSection.data('anchor');
31229                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
31230                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
31231                    var slideIndex;
31232                    var slideAnchorLink;
31233
31234                    if(activeSlide.length){
31235                        slideAnchorLink = activeSlide.data('anchor');
31236                        slideIndex = activeSlide.index();
31237                    }
31238
31239                    if(canScroll){
31240                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
31241
31242                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
31243                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
31244
31245                        stopMedia(leavingSection);
31246                        lazyLoad(currentSection);
31247                        playMedia(currentSection);
31248
31249                        activateMenuAndNav(anchorLink, sectionIndex - 1);
31250
31251                        if(options.anchors.length){
31252                            //needed to enter in hashChange event when using the menu with anchor links
31253                            lastScrolledDestiny = anchorLink;
31254                        }
31255                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
31256                    }
31257
31258                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
31259                    clearTimeout(scrollId);
31260                    scrollId = setTimeout(function(){
31261                        isScrolling = false;
31262                    }, 100);
31263                }
31264
31265                if(options.fitToSection){
31266                    //for the auto adjust of the viewport to fit a whole section
31267                    clearTimeout(scrollId2);
31268
31269                    scrollId2 = setTimeout(function(){
31270                        //checking it again in case it changed during the delay
31271                        if(options.fitToSection){
31272                            fitToSection();
31273                        }
31274                    }, options.fitToSectionDelay);
31275                }
31276            }
31277        }
31278
31279        /**
31280        * Fits the site to the nearest active section
31281        */
31282        function fitToSection(){
31283            //checking fitToSection again in case it was set to false before the timeout delay
31284            if(canScroll){
31285                //allows to scroll to an active section and
31286                //if the section is already active, we prevent firing callbacks
31287                isResizing = true;
31288
31289                scrollPage($(SECTION_ACTIVE_SEL));
31290                isResizing = false;
31291            }
31292        }
31293
31294        /**
31295        * Determines whether the active section has seen in its whole or not.
31296        */
31297        function isCompletelyInViewPort(movement){
31298            var top = $(SECTION_ACTIVE_SEL).position().top;
31299            var bottom = top + $window.height();
31300
31301            if(movement == 'up'){
31302                return bottom >= ($window.scrollTop() + $window.height());
31303            }
31304            return top <= $window.scrollTop();
31305        }
31306
31307        /**
31308        * Gets the directon of the the scrolling fired by the scroll event.
31309        */
31310        function getScrollDirection(currentScroll){
31311            var direction = currentScroll > lastScroll ? 'down' : 'up';
31312
31313            lastScroll = currentScroll;
31314
31315            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
31316            previousDestTop = currentScroll;
31317
31318            return direction;
31319        }
31320
31321        /**
31322        * Determines the way of scrolling up or down:
31323        * by 'automatically' scrolling a section or by using the default and normal scrolling.
31324        */
31325        function scrolling(type, scrollable){
31326            if (!isScrollAllowed.m[type]){
31327                return;
31328            }
31329            var check = (type === 'down') ? 'bottom' : 'top';
31330            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
31331
31332            if(scrollable.length > 0 ){
31333                //is the scrollbar at the start/end of the scroll?
31334                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
31335                    scrollSection();
31336                }else{
31337                    return true;
31338                }
31339            }else{
31340                // moved up/down
31341                scrollSection();
31342            }
31343        }
31344
31345        /*
31346        * Preventing bouncing in iOS #2285
31347        */
31348        function preventBouncing(event){
31349            var e = event.originalEvent;
31350            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
31351                //preventing the easing on iOS devices
31352                event.preventDefault();
31353            }
31354        }
31355
31356        var touchStartY = 0;
31357        var touchStartX = 0;
31358        var touchEndY = 0;
31359        var touchEndX = 0;
31360
31361        /* Detecting touch events
31362
31363        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
31364        * This way, the touchstart and the touch moves shows an small difference between them which is the
31365        * used one to determine the direction.
31366        */
31367        function touchMoveHandler(event){
31368            var e = event.originalEvent;
31369            var activeSection = $(e.target).closest(SECTION_SEL);
31370
31371            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
31372            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
31373
31374                if(options.autoScrolling){
31375                    //preventing the easing on iOS devices
31376                    event.preventDefault();
31377                }
31378
31379                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
31380                var touchEvents = getEventsPage(e);
31381
31382                touchEndY = touchEvents.y;
31383                touchEndX = touchEvents.x;
31384
31385                //if movement in the X axys is greater than in the Y and the currect section has slides...
31386                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
31387
31388                    //is the movement greater than the minimum resistance to scroll?
31389                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
31390                        if (touchStartX > touchEndX) {
31391                            if(isScrollAllowed.m.right){
31392                                moveSlideRight(activeSection); //next
31393                            }
31394                        } else {
31395                            if(isScrollAllowed.m.left){
31396                                moveSlideLeft(activeSection); //prev
31397                            }
31398                        }
31399                    }
31400                }
31401
31402                //vertical scrolling (only when autoScrolling is enabled)
31403                else if(options.autoScrolling && canScroll){
31404
31405                    //is the movement greater than the minimum resistance to scroll?
31406                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
31407                        if (touchStartY > touchEndY) {
31408                            scrolling('down', scrollable);
31409                        } else if (touchEndY > touchStartY) {
31410                            scrolling('up', scrollable);
31411                        }
31412                    }
31413                }
31414            }
31415        }
31416
31417        /**
31418         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
31419         * Currently works well for iOS - Android might need some testing
31420         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
31421         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
31422         * @return {boolean} true if there is a match to options.normalScrollElements
31423         */
31424        function checkParentForNormalScrollElement (el, hop) {
31425            hop = hop || 0;
31426            var parent = $(el).parent();
31427
31428            if (hop < options.normalScrollElementTouchThreshold &&
31429                parent.is(options.normalScrollElements) ) {
31430                return true;
31431            } else if (hop == options.normalScrollElementTouchThreshold) {
31432                return false;
31433            } else {
31434                return checkParentForNormalScrollElement(parent, ++hop);
31435            }
31436        }
31437
31438        /**
31439        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
31440        * this way we make sure that is really a touch event what IE is detecting.
31441        */
31442        function isReallyTouch(e){
31443            //if is not IE   ||  IE is detecting `touch` or `pen`
31444            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
31445        }
31446
31447        /**
31448        * Handler for the touch start event.
31449        */
31450        function touchStartHandler(event){
31451            var e = event.originalEvent;
31452
31453            //stopping the auto scroll to adjust to a section
31454            if(options.fitToSection){
31455                $htmlBody.stop();
31456            }
31457
31458            if(isReallyTouch(e)){
31459                var touchEvents = getEventsPage(e);
31460                touchStartY = touchEvents.y;
31461                touchStartX = touchEvents.x;
31462            }
31463        }
31464
31465        /**
31466        * Gets the average of the last `number` elements of the given array.
31467        */
31468        function getAverage(elements, number){
31469            var sum = 0;
31470
31471            //taking `number` elements from the end to make the average, if there are not enought, 1
31472            var lastElements = elements.slice(Math.max(elements.length - number, 1));
31473
31474            for(var i = 0; i < lastElements.length; i++){
31475                sum = sum + lastElements[i];
31476            }
31477
31478            return Math.ceil(sum/number);
31479        }
31480
31481        /**
31482         * Detecting mousewheel scrolling
31483         *
31484         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
31485         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
31486         */
31487        var prevTime = new Date().getTime();
31488
31489        function MouseWheelHandler(e) {
31490            var curTime = new Date().getTime();
31491            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
31492
31493            //autoscrolling and not zooming?
31494            if(options.autoScrolling && !controlPressed && !isNormalScroll){
31495                // cross-browser wheel delta
31496                e = e || window.event;
31497                var value = e.wheelDelta || -e.deltaY || -e.detail;
31498                var delta = Math.max(-1, Math.min(1, value));
31499
31500                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
31501                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
31502
31503                //Limiting the array to 150 (lets not waste memory!)
31504                if(scrollings.length > 149){
31505                    scrollings.shift();
31506                }
31507
31508                //keeping record of the previous scrollings
31509                scrollings.push(Math.abs(value));
31510
31511                //preventing to scroll the site on mouse wheel when scrollbar is present
31512                if(options.scrollBar){
31513                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
31514                }
31515
31516                var activeSection = $(SECTION_ACTIVE_SEL);
31517                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
31518
31519                //time difference between the last scroll and the current one
31520                var timeDiff = curTime-prevTime;
31521                prevTime = curTime;
31522
31523                //haven't they scrolled in a while?
31524                //(enough to be consider a different scrolling action to scroll another section)
31525                if(timeDiff > 200){
31526                    //emptying the array, we dont care about old scrollings for our averages
31527                    scrollings = [];
31528                }
31529
31530                if(canScroll){
31531                    var averageEnd = getAverage(scrollings, 10);
31532                    var averageMiddle = getAverage(scrollings, 70);
31533                    var isAccelerating = averageEnd >= averageMiddle;
31534
31535                    //to avoid double swipes...
31536                    if(isAccelerating && isScrollingVertically){
31537                        //scrolling down?
31538                        if (delta < 0) {
31539                            scrolling('down', scrollable);
31540
31541                        //scrolling up?
31542                        }else {
31543                            scrolling('up', scrollable);
31544                        }
31545                    }
31546                }
31547
31548                return false;
31549            }
31550
31551            if(options.fitToSection){
31552                //stopping the auto scroll to adjust to a section
31553                $htmlBody.stop();
31554            }
31555        }
31556
31557        /**
31558        * Slides a slider to the given direction.
31559        * Optional `section` param.
31560        */
31561        function moveSlide(direction, section){
31562            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
31563            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
31564            var numSlides = slides.find(SLIDE_SEL).length;
31565
31566            // more than one slide needed and nothing should be sliding
31567            if (!slides.length || slideMoving || numSlides < 2) {
31568                return;
31569            }
31570
31571            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
31572            var destiny = null;
31573
31574            if(direction === 'left'){
31575                destiny = currentSlide.prev(SLIDE_SEL);
31576            }else{
31577                destiny = currentSlide.next(SLIDE_SEL);
31578            }
31579
31580            //isn't there a next slide in the secuence?
31581            if(!destiny.length){
31582                //respect loopHorizontal settin
31583                if (!options.loopHorizontal) return;
31584
31585                if(direction === 'left'){
31586                    destiny = currentSlide.siblings(':last');
31587                }else{
31588                    destiny = currentSlide.siblings(':first');
31589                }
31590            }
31591
31592            slideMoving = true;
31593
31594            landscapeScroll(slides, destiny, direction);
31595        }
31596
31597        /**
31598        * Maintains the active slides in the viewport
31599        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
31600        */
31601        function keepSlidesPosition(){
31602            $(SLIDE_ACTIVE_SEL).each(function(){
31603                silentLandscapeScroll($(this), 'internal');
31604            });
31605        }
31606
31607        var previousDestTop = 0;
31608        /**
31609        * Returns the destination Y position based on the scrolling direction and
31610        * the height of the section.
31611        */
31612        function getDestinationPosition(element){
31613            var elemPosition = element.position();
31614
31615            //top of the desination will be at the top of the viewport
31616            var position = elemPosition.top;
31617            var isScrollingDown =  elemPosition.top > previousDestTop;
31618            var sectionBottom = position - windowsHeight + element.outerHeight();
31619            var bigSectionsDestination = options.bigSectionsDestination;
31620
31621            //Uncode addition
31622            var containerH = container.outerHeight();
31623            var containerPosition = container.offset();
31624
31625            //########### Commented by Uncode - START ###########
31626            //is the destination element bigger than the viewport?
31627            // if(element.outerHeight() > windowsHeight){
31628            //     //scrolling up?
31629            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
31630            //         position = sectionBottom;
31631            //     }
31632            // }
31633
31634            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
31635            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
31636            //     //The bottom of the destination will be at the bottom of the viewport
31637            //     position = sectionBottom;
31638            // }
31639            //########### Commented by Uncode - END ###########
31640
31641            //Uncode addition
31642            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
31643                position += 18;
31644            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
31645                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
31646            }
31647
31648            /*
31649            Keeping record of the last scrolled position to determine the scrolling direction.
31650            No conventional methods can be used as the scroll bar might not be present
31651            AND the section might not be active if it is auto-height and didnt reach the middle
31652            of the viewport.
31653            */
31654            previousDestTop = position;
31655            return position;
31656        }
31657
31658        /**
31659        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
31660        */
31661        function scrollPage(element, callback, isMovementUp){
31662            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
31663
31664            var dtop = getDestinationPosition(element);
31665            var slideAnchorLink;
31666            var slideIndex;
31667
31668            //local variables
31669            var v = {
31670                element: element,
31671                callback: callback,
31672                isMovementUp: isMovementUp,
31673                dtop: dtop,
31674                yMovement: getYmovement(element),
31675                anchorLink: element.data('anchor'),
31676                sectionIndex: element.index(SECTION_SEL),
31677                activeSlide: element.find(SLIDE_ACTIVE_SEL),
31678                activeSection: $(SECTION_ACTIVE_SEL),
31679                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
31680
31681                //caching the value of isResizing at the momment the function is called
31682                //because it will be checked later inside a setTimeout and the value might change
31683                localIsResizing: isResizing
31684            };
31685
31686            //quiting when destination scroll is the same as the current one
31687            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
31688
31689            if(v.activeSlide.length){
31690                slideAnchorLink = v.activeSlide.data('anchor');
31691                slideIndex = v.activeSlide.index();
31692            }
31693
31694            // If continuousVertical && we need to wrap around
31695            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
31696                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
31697                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
31698
31699                v = createInfiniteSections(v);
31700            }
31701
31702            //callback (onLeave) if the site is not just resizing and readjusting the slides
31703            if($.isFunction(options.onLeave) && !v.localIsResizing){
31704                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
31705                    return;
31706                }
31707            }
31708
31709            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
31710            if(!v.localIsResizing){
31711                stopMedia(v.activeSection);
31712            }
31713
31714            options.scrollOverflowHandler.beforeLeave();
31715            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
31716            lazyLoad(element);
31717            options.scrollOverflowHandler.onLeave();
31718
31719
31720            //preventing from activating the MouseWheelHandler event
31721            //more than once if the page is scrolling
31722            canScroll = false;
31723
31724            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
31725
31726            performMovement(v);
31727
31728            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
31729            lastScrolledDestiny = v.anchorLink;
31730
31731            //avoid firing it twice (as it does also on scroll)
31732            activateMenuAndNav(v.anchorLink, v.sectionIndex);
31733        }
31734
31735        /**
31736        * Performs the vertical movement (by CSS3 or by jQuery)
31737        */
31738        function performMovement(v){
31739            // using CSS3 translate functionality
31740            if (options.css3 && options.autoScrolling && !options.scrollBar) {
31741
31742                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
31743                // that's why we round it to 0.
31744                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
31745                transformContainer(translate3d, true);
31746
31747                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
31748                //scrollingSpeed to change in case of using silentMoveTo();
31749                if(options.scrollingSpeed){
31750                    clearTimeout(afterSectionLoadsId);
31751                    afterSectionLoadsId = setTimeout(function () {
31752                        afterSectionLoads(v);
31753                    }, options.scrollingSpeed);
31754                }else{
31755                    afterSectionLoads(v);
31756                }
31757            }
31758
31759            // using jQuery animate
31760            else{
31761                var scrollSettings = getScrollSettings(v);
31762
31763                $(scrollSettings.element).animate(
31764                    scrollSettings.options,
31765                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
31766                    if(options.scrollBar){
31767
31768                        /* Hack!
31769                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
31770                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
31771
31772                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
31773                        */
31774                        setTimeout(function(){
31775                            afterSectionLoads(v);
31776                        },30);
31777                    }else{
31778                        afterSectionLoads(v);
31779                    }
31780                });
31781            }
31782        }
31783
31784        /**
31785        * Gets the scrolling settings depending on the plugin autoScrolling option
31786        */
31787        function getScrollSettings(v){
31788            var scroll = {};
31789
31790            if(options.autoScrolling && !options.scrollBar){
31791                scroll.options = { 'top': -v.dtop};
31792                scroll.element = WRAPPER_SEL;
31793            }else{
31794                scroll.options = { 'scrollTop': v.dtop};
31795                scroll.element = 'html, body';
31796            }
31797
31798            return scroll;
31799        }
31800
31801        /**
31802        * Adds sections before or after the current one to create the infinite effect.
31803        */
31804        function createInfiniteSections(v){
31805            // Scrolling down
31806            if (!v.isMovementUp) {
31807                // Move all previous sections to after the active section
31808                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
31809            }
31810            else { // Scrolling up
31811                // Move all next sections to before the active section
31812                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
31813            }
31814
31815            // Maintain the displayed position (now that we changed the element order)
31816            silentScroll($(SECTION_ACTIVE_SEL).position().top);
31817
31818            // Maintain the active slides visible in the viewport
31819            keepSlidesPosition();
31820
31821            // save for later the elements that still need to be reordered
31822            v.wrapAroundElements = v.activeSection;
31823
31824            // Recalculate animation variables
31825            v.dtop = v.element.position().top;
31826            v.yMovement = getYmovement(v.element);
31827
31828            return v;
31829        }
31830
31831        /**
31832        * Fix section order after continuousVertical changes have been animated
31833        */
31834        function continuousVerticalFixSectionOrder (v) {
31835            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
31836            // finish moving the elements around so the direct navigation will function more simply
31837            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
31838                return;
31839            }
31840
31841            if (v.isMovementUp) {
31842                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
31843            }
31844            else {
31845                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
31846            }
31847
31848            silentScroll($(SECTION_ACTIVE_SEL).position().top);
31849
31850            // Maintain the active slides visible in the viewport
31851            keepSlidesPosition();
31852        }
31853
31854
31855        /**
31856        * Actions to do once the section is loaded.
31857        */
31858        function afterSectionLoads (v){
31859            continuousVerticalFixSectionOrder(v);
31860
31861            //callback (afterLoad) if the site is not just resizing and readjusting the slides
31862            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
31863            options.scrollOverflowHandler.afterLoad();
31864
31865            if(!v.localIsResizing){
31866                playMedia(v.element);
31867            }
31868
31869            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
31870
31871            canScroll = true;
31872
31873            $.isFunction(v.callback) && v.callback.call(this);
31874        }
31875
31876        /**
31877        * Sets the value for the given attribute from the `data-` attribute with the same suffix
31878        * ie: data-srcset ==> srcset  |  data-src ==> src
31879        */
31880        function setSrc(element, attribute){
31881            element
31882                .attr(attribute, element.data(attribute))
31883                .removeAttr('data-' + attribute);
31884        }
31885
31886        /**
31887        * Lazy loads image, video and audio elements.
31888        */
31889        function lazyLoad(destiny){
31890            if (!options.lazyLoading){
31891                return;
31892            }
31893
31894            var panel = getSlideOrSection(destiny);
31895            var element;
31896
31897            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
31898                element = $(this);
31899
31900                $.each(['src', 'srcset'], function(index, type){
31901                    var attribute = element.attr('data-' + type);
31902                    if(typeof attribute !== 'undefined' && attribute){
31903                        setSrc(element, type);
31904                    }
31905                });
31906
31907                if(element.is('source')){
31908                    element.closest('video').get(0).load();
31909                }
31910            });
31911        }
31912
31913        /**
31914        * Plays video and audio elements.
31915        */
31916        function playMedia(destiny){
31917            var panel = getSlideOrSection(destiny);
31918
31919            //playing HTML5 media elements
31920            panel.find('video, audio').each(function(){
31921                var element = $(this).get(0);
31922
31923                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
31924                    element.play();
31925                }
31926            });
31927
31928            //youtube videos
31929            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
31930                var element = $(this).get(0);
31931
31932                if ( element.hasAttribute('data-autoplay') ){
31933                    playYoutube(element);
31934                }
31935
31936                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
31937                element.onload = function() {
31938                    if ( element.hasAttribute('data-autoplay') ){
31939                        playYoutube(element);
31940                    }
31941                };
31942            });
31943        }
31944
31945        /**
31946        * Plays a youtube video
31947        */
31948        function playYoutube(element){
31949            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
31950        }
31951
31952        /**
31953        * Stops video and audio elements.
31954        */
31955        function stopMedia(destiny){
31956            var panel = getSlideOrSection(destiny);
31957
31958            //stopping HTML5 media elements
31959            panel.find('video, audio').each(function(){
31960                var element = $(this).get(0);
31961
31962                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
31963                    element.pause();
31964                }
31965            });
31966
31967            //youtube videos
31968            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
31969                var element = $(this).get(0);
31970
31971                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
31972                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
31973                }
31974            });
31975        }
31976
31977        /**
31978        * Gets the active slide (or section) for the given section
31979        */
31980        function getSlideOrSection(destiny){
31981            var slide = destiny.find(SLIDE_ACTIVE_SEL);
31982            if( slide.length ) {
31983                destiny = $(slide);
31984            }
31985
31986            return destiny;
31987        }
31988
31989        /**
31990        * Scrolls to the anchor in the URL when loading the site
31991        */
31992        function scrollToAnchor(){
31993            //getting the anchor link in the URL and deleting the `#`
31994            var value =  window.location.hash.replace('#', '').split('/');
31995            var sectionAnchor = decodeURIComponent(value[0]);
31996            var slideAnchor = decodeURIComponent(value[1]);
31997
31998            if(sectionAnchor){  //if theres any #
31999                if(options.animateAnchor){
32000                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32001                }else{
32002                    silentMoveTo(sectionAnchor, slideAnchor);
32003                }
32004            }
32005        }
32006
32007        /**
32008        * Detecting any change on the URL to scroll to the given anchor link
32009        * (a way to detect back history button as we play with the hashes on the URL)
32010        */
32011        function hashChangeHandler(){
32012            if(!isScrolling && !options.lockAnchors){
32013                var value =  window.location.hash.replace('#', '').split('/');
32014                var sectionAnchor = decodeURIComponent(value[0]);
32015                var slideAnchor = decodeURIComponent(value[1]);
32016
32017                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32018                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32019                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32020
32021
32022                if(sectionAnchor.length){
32023                    /*in order to call scrollpage() only once for each destination at a time
32024                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32025                    event is fired on every scroll too.*/
32026                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32027                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32028                    }
32029                }
32030            }
32031        }
32032
32033        //Sliding with arrow keys, both, vertical and horizontal
32034        function keydownHandler(e) {
32035
32036            clearTimeout(keydownId);
32037
32038            var activeElement = $(':focus');
32039
32040            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32041                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32042                options.keyboardScrolling && options.autoScrolling){
32043                var keyCode = e.which;
32044
32045                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32046                var keyControls = [40, 38, 32, 33, 34];
32047                if($.inArray(keyCode, keyControls) > -1){
32048                    e.preventDefault();
32049                }
32050
32051                controlPressed = e.ctrlKey;
32052
32053                keydownId = setTimeout(function(){
32054                    onkeydown(e);
32055                },150);
32056            }
32057        }
32058
32059        function tooltipTextHandler(){
32060            $(this).prev().trigger('click');
32061        }
32062
32063        //to prevent scrolling while zooming
32064        function keyUpHandler(e){
32065            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32066                controlPressed = e.ctrlKey;
32067            }
32068        }
32069
32070        //binding the mousemove when the mouse's middle button is released
32071        function mouseDownHandler(e){
32072            //middle button
32073            if (e.which == 2){
32074                oldPageY = e.pageY;
32075                container.on('mousemove', mouseMoveHandler);
32076            }
32077        }
32078
32079        //unbinding the mousemove when the mouse's middle button is released
32080        function mouseUpHandler(e){
32081            //middle button
32082            if (e.which == 2){
32083                container.off('mousemove');
32084            }
32085        }
32086
32087        //Scrolling horizontally when clicking on the slider controls.
32088        function slideArrowHandler(){
32089            var section = $(this).closest(SECTION_SEL);
32090
32091            if ($(this).hasClass(SLIDES_PREV)) {
32092                if(isScrollAllowed.m.left){
32093                    moveSlideLeft(section);
32094                }
32095            } else {
32096                if(isScrollAllowed.m.right){
32097                    moveSlideRight(section);
32098                }
32099            }
32100        }
32101
32102        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32103        function blurHandler(){
32104            isWindowFocused = false;
32105            controlPressed = false;
32106        }
32107
32108        //Scrolls to the section when clicking the navigation bullet
32109        function sectionBulletHandler(e){
32110            e.preventDefault();
32111            var index = $(this).parent().index();
32112            scrollPage($(SECTION_SEL).eq(index));
32113        }
32114
32115        //Scrolls the slider to the given slide destination for the given section
32116        function slideBulletHandler(e){
32117            e.preventDefault();
32118            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
32119            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
32120
32121            landscapeScroll(slides, destiny);
32122        }
32123
32124        /**
32125        * Keydown event
32126        */
32127        function onkeydown(e){
32128            var shiftPressed = e.shiftKey;
32129
32130            //do nothing if we can not scroll or we are not using horizotnal key arrows.
32131            if(!canScroll && [37,39].indexOf(e.which) < 0){
32132                return;
32133            }
32134
32135            switch (e.which) {
32136                //up
32137                case 38:
32138                case 33:
32139                    if(isScrollAllowed.k.up){
32140                        moveSectionUp();
32141                    }
32142                    break;
32143
32144                //down
32145                case 32: //spacebar
32146                    if(shiftPressed && isScrollAllowed.k.up){
32147                        moveSectionUp();
32148                        break;
32149                    }
32150                /* falls through */
32151                case 40:
32152                case 34:
32153                    if(isScrollAllowed.k.down){
32154                        moveSectionDown();
32155                    }
32156                    break;
32157
32158                //Home
32159                case 36:
32160                    if(isScrollAllowed.k.up){
32161                        moveTo(1);
32162                    }
32163                    break;
32164
32165                //End
32166                case 35:
32167                     if(isScrollAllowed.k.down){
32168                        moveTo( $(SECTION_SEL).length );
32169                    }
32170                    break;
32171
32172                //left
32173                case 37:
32174                    if(isScrollAllowed.k.left){
32175                        moveSlideLeft();
32176                    }
32177                    break;
32178
32179                //right
32180                case 39:
32181                    if(isScrollAllowed.k.right){
32182                        moveSlideRight();
32183                    }
32184                    break;
32185
32186                default:
32187                    return; // exit this handler for other keys
32188            }
32189        }
32190
32191        /**
32192        * Detecting the direction of the mouse movement.
32193        * Used only for the middle button of the mouse.
32194        */
32195        var oldPageY = 0;
32196        function mouseMoveHandler(e){
32197            if(canScroll){
32198                // moving up
32199                if (e.pageY < oldPageY && isScrollAllowed.m.up){
32200                    moveSectionUp();
32201                }
32202
32203                // moving down
32204                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
32205                    moveSectionDown();
32206                }
32207            }
32208            oldPageY = e.pageY;
32209        }
32210
32211        /**
32212        * Scrolls horizontal sliders.
32213        */
32214        function landscapeScroll(slides, destiny, direction){
32215            var section = slides.closest(SECTION_SEL);
32216            var v = {
32217                slides: slides,
32218                destiny: destiny,
32219                direction: direction,
32220                destinyPos: destiny.position(),
32221                slideIndex: destiny.index(),
32222                section: section,
32223                sectionIndex: section.index(SECTION_SEL),
32224                anchorLink: section.data('anchor'),
32225                slidesNav: section.find(SLIDES_NAV_SEL),
32226                slideAnchor:  getAnchor(destiny),
32227                prevSlide: section.find(SLIDE_ACTIVE_SEL),
32228                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
32229
32230                //caching the value of isResizing at the momment the function is called
32231                //because it will be checked later inside a setTimeout and the value might change
32232                localIsResizing: isResizing
32233            };
32234            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
32235            v.direction = v.direction ? v.direction : v.xMovement;
32236
32237            //important!! Only do it when not resizing
32238            if(!v.localIsResizing){
32239                //preventing from scrolling to the next/prev section when using scrollHorizontally
32240                canScroll = false;
32241            }
32242
32243            if(options.onSlideLeave){
32244
32245                //if the site is not just resizing and readjusting the slides
32246                if(!v.localIsResizing && v.xMovement!=='none'){
32247                    if($.isFunction( options.onSlideLeave )){
32248                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
32249                            slideMoving = false;
32250                            return;
32251                        }
32252                    }
32253                }
32254            }
32255
32256            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32257
32258            if(!v.localIsResizing){
32259                stopMedia(v.prevSlide);
32260                lazyLoad(destiny);
32261            }
32262
32263            if(!options.loopHorizontal && options.controlArrows){
32264                //hidding it for the fist slide, showing for the rest
32265                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
32266
32267                //hidding it for the last slide, showing for the rest
32268                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
32269            }
32270
32271            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
32272            if(section.hasClass(ACTIVE) && !v.localIsResizing){
32273                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
32274            }
32275
32276            performHorizontalMove(slides, v, true);
32277        }
32278
32279
32280        function afterSlideLoads(v){
32281            activeSlidesNavigation(v.slidesNav, v.slideIndex);
32282
32283            //if the site is not just resizing and readjusting the slides
32284            if(!v.localIsResizing){
32285                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
32286
32287                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
32288                //and to prevent double scroll right after a windows resize
32289                canScroll = true;
32290
32291                playMedia(v.destiny);
32292            }
32293
32294            //letting them slide again
32295            slideMoving = false;
32296        }
32297
32298        /**
32299        * Performs the horizontal movement. (CSS3 or jQuery)
32300        *
32301        * @param fireCallback {Bool} - determines whether or not to fire the callback
32302        */
32303        function performHorizontalMove(slides, v, fireCallback){
32304            var destinyPos = v.destinyPos;
32305
32306            if(options.css3){
32307                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
32308
32309                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
32310
32311                afterSlideLoadsId = setTimeout(function(){
32312                    fireCallback && afterSlideLoads(v);
32313                }, options.scrollingSpeed, options.easing);
32314            }else{
32315                slides.animate({
32316                    scrollLeft : Math.round(destinyPos.left)
32317                }, options.scrollingSpeed, options.easing, function() {
32318
32319                    fireCallback && afterSlideLoads(v);
32320                });
32321            }
32322        }
32323
32324        /**
32325        * Sets the state for the horizontal bullet navigations.
32326        */
32327        function activeSlidesNavigation(slidesNav, slideIndex){
32328            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
32329            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
32330        }
32331
32332        var previousHeight = windowsHeight;
32333
32334        //when resizing the site, we adjust the heights of the sections, slimScroll...
32335        function resizeHandler(){
32336            //checking if it needs to get responsive
32337            responsive();
32338
32339            // rebuild immediately on touch devices
32340            if (isTouchDevice) {
32341                var activeElement = $(document.activeElement);
32342
32343                //if the keyboard is NOT visible
32344                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
32345                    var currentHeight = $window.height();
32346
32347                    //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)
32348                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
32349                        reBuild(true);
32350                        previousHeight = currentHeight;
32351                    }
32352                }
32353            }else{
32354                //in order to call the functions only when the resize is finished
32355                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
32356                clearTimeout(resizeId);
32357
32358                resizeId = setTimeout(function(){
32359                    reBuild(true);
32360                }, 350);
32361            }
32362        }
32363
32364        /**
32365        * Checks if the site needs to get responsive and disables autoScrolling if so.
32366        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
32367        */
32368        function responsive(){
32369            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
32370            var heightLimit = options.responsiveHeight;
32371
32372            //only calculating what we need. Remember its called on the resize event.
32373            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
32374            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
32375
32376            if(widthLimit && heightLimit){
32377                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
32378            }
32379            else if(widthLimit){
32380                setResponsive(isBreakingPointWidth);
32381            }
32382            else if(heightLimit){
32383                setResponsive(isBreakingPointHeight);
32384            }
32385        }
32386
32387        /**
32388        * Adds transition animations for the given element
32389        */
32390        function addAnimation(container, element){
32391            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
32392
32393            container.removeClass(NO_TRANSITION);
32394            return container.css({
32395                '-webkit-transition': transition,
32396                'transition': transition
32397            });
32398        }
32399
32400        /**
32401        * Remove transition animations for the given element
32402        */
32403        function removeAnimation(element){
32404            return element.addClass(NO_TRANSITION);
32405        }
32406
32407        /**
32408        * Activating the vertical navigation bullets according to the given slide name.
32409        */
32410        function activateNavDots(name, sectionIndex){
32411            if(options.navigation){
32412                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
32413                if(name){
32414                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
32415                }else{
32416                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
32417                }
32418            }
32419        }
32420
32421        /**
32422        * Activating the website main menu elements according to the given slide name.
32423        */
32424        function activateMenuElement(name){
32425            if(options.menu){
32426                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
32427                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
32428            }
32429        }
32430
32431        /**
32432        * Sets to active the current menu and vertical nav items.
32433        */
32434        function activateMenuAndNav(anchor, index){
32435            activateMenuElement(anchor);
32436            activateNavDots(anchor, index);
32437        }
32438
32439        /**
32440        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
32441        * from the current section.
32442        */
32443        function getYmovement(destiny){
32444            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
32445            var toIndex = destiny.index(SECTION_SEL);
32446            if( fromIndex == toIndex){
32447                return 'none';
32448            }
32449            if(fromIndex > toIndex){
32450                return 'up';
32451            }
32452            return 'down';
32453        }
32454
32455        /**
32456        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
32457        * from the current slide.
32458        */
32459        function getXmovement(fromIndex, toIndex){
32460            if( fromIndex == toIndex){
32461                return 'none';
32462            }
32463            if(fromIndex > toIndex){
32464                return 'left';
32465            }
32466            return 'right';
32467        }
32468
32469        /**
32470        * Checks if the element needs scrollbar and if the user wants to apply it.
32471        * If so it creates it.
32472        *
32473        * @param {Object} element   jQuery object of the section or slide
32474        */
32475        function createScrollBar(element){
32476            //User doesn't want scrollbar here? Sayonara baby!
32477            if(element.hasClass('fp-noscroll')) return;
32478
32479            //needed to make `scrollHeight` work under Opera 12
32480            element.css('overflow', 'hidden');
32481
32482            var scrollOverflowHandler = options.scrollOverflowHandler;
32483            var wrap = scrollOverflowHandler.wrapContent();
32484            //in case element is a slide
32485            var section = element.closest(SECTION_SEL);
32486            var scrollable = scrollOverflowHandler.scrollable(element);
32487            var contentHeight;
32488
32489            //if there was scroll, the contentHeight will be the one in the scrollable section
32490            if(scrollable.length){
32491                contentHeight = scrollOverflowHandler.scrollHeight(element);
32492            }else{
32493                contentHeight = element.get(0).scrollHeight;
32494                if(options.verticalCentered){
32495                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
32496                }
32497            }
32498
32499            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
32500
32501            //needs scroll?
32502            if ( contentHeight > scrollHeight) {
32503                //did we already have an scrollbar ? Updating it
32504                if(scrollable.length){
32505                    scrollOverflowHandler.update(element, scrollHeight);
32506                }
32507                //creating the scrolling
32508                else{
32509                    if(options.verticalCentered){
32510                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
32511                    }else{
32512                        element.wrapInner(wrap);
32513                    }
32514                    scrollOverflowHandler.create(element, scrollHeight);
32515                }
32516            }
32517            //removing the scrolling when it is not necessary anymore
32518            else{
32519                scrollOverflowHandler.remove(element);
32520            }
32521
32522            //undo
32523            element.css('overflow', '');
32524        }
32525
32526        function addTableClass(element){
32527            //In case we are styling for the 2nd time as in with reponsiveSlides
32528            if(!element.hasClass(TABLE)){
32529                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
32530            }
32531        }
32532
32533        function getTableHeight(element){
32534            var sectionHeight = windowsHeight;
32535
32536            if(options.paddingTop || options.paddingBottom){
32537                var section = element;
32538                if(!section.hasClass(SECTION)){
32539                    section = element.closest(SECTION_SEL);
32540                }
32541
32542                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
32543                sectionHeight = (windowsHeight - paddings);
32544            }
32545
32546            return sectionHeight;
32547        }
32548
32549        /**
32550        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
32551        */
32552        function transformContainer(translate3d, animated){
32553            if(animated){
32554                addAnimation(container);
32555            }else{
32556                removeAnimation(container);
32557            }
32558
32559            container.css(getTransforms(translate3d));
32560
32561            //syncronously removing the class after the animation has been applied.
32562            setTimeout(function(){
32563                container.removeClass(NO_TRANSITION);
32564            },10);
32565        }
32566
32567        /**
32568        * Gets a section by its anchor / index
32569        */
32570        function getSectionByAnchor(sectionAnchor){
32571            if(!sectionAnchor) return [];
32572
32573            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
32574            if(!section.length){
32575                section = $(SECTION_SEL).eq( sectionAnchor -1);
32576            }
32577
32578            return section;
32579        }
32580
32581        /**
32582        * Gets a slide inside a given section by its anchor / index
32583        */
32584        function getSlideByAnchor(slideAnchor, section){
32585            var slides = section.find(SLIDES_WRAPPER_SEL);
32586            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
32587
32588            if(!slide.length){
32589                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
32590            }
32591
32592            return slide;
32593        }
32594
32595        /**
32596        * Scrolls to the given section and slide anchors
32597        */
32598        function scrollPageAndSlide(destiny, slide){
32599            var section = getSectionByAnchor(destiny);
32600
32601            //do nothing if there's no section with the given anchor name
32602            if(!section.length) return;
32603
32604            //default slide
32605            if (typeof slide === 'undefined') {
32606                slide = 0;
32607            }
32608
32609            //we need to scroll to the section and then to the slide
32610            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
32611                scrollPage(section, function(){
32612                    scrollSlider(section, slide);
32613                });
32614            }
32615            //if we were already in the section
32616            else{
32617                scrollSlider(section, slide);
32618            }
32619        }
32620
32621        /**
32622        * Scrolls the slider to the given slide destination for the given section
32623        */
32624        function scrollSlider(section, slideAnchor){
32625            if(typeof slideAnchor !== 'undefined'){
32626                var slides = section.find(SLIDES_WRAPPER_SEL);
32627                var destiny =  getSlideByAnchor(slideAnchor, section);
32628
32629                if(destiny.length){
32630                    landscapeScroll(slides, destiny);
32631                }
32632            }
32633        }
32634
32635        /**
32636        * Creates a landscape navigation bar with dots for horizontal sliders.
32637        */
32638        function addSlidesNavigation(section, numSlides){
32639            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
32640            var nav = section.find(SLIDES_NAV_SEL);
32641
32642            //top or bottom
32643            nav.addClass(options.slidesNavPosition);
32644
32645            for(var i=0; i< numSlides; i++){
32646                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
32647            }
32648
32649            //centering it
32650            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
32651
32652            nav.find('li').first().find('a').addClass(ACTIVE);
32653        }
32654
32655
32656        /**
32657        * Sets the state of the website depending on the active section/slide.
32658        * It changes the URL hash when needed and updates the body class.
32659        */
32660        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
32661            var sectionHash = '';
32662
32663            if(options.anchors.length && !options.lockAnchors){
32664
32665                //isn't it the first slide?
32666                if(slideIndex){
32667                    if(typeof anchorLink !== 'undefined'){
32668                        sectionHash = anchorLink;
32669                    }
32670
32671                    //slide without anchor link? We take the index instead.
32672                    if(typeof slideAnchor === 'undefined'){
32673                        slideAnchor = slideIndex;
32674                    }
32675
32676                    lastScrolledSlide = slideAnchor;
32677                    setUrlHash(sectionHash + '/' + slideAnchor);
32678
32679                //first slide won't have slide anchor, just the section one
32680                }else if(typeof slideIndex !== 'undefined'){
32681                    lastScrolledSlide = slideAnchor;
32682                    setUrlHash(anchorLink);
32683                }
32684
32685                //section without slides
32686                else{
32687                    setUrlHash(anchorLink);
32688                }
32689            }
32690
32691            setBodyClass();
32692        }
32693
32694        /**
32695        * Sets the URL hash.
32696        */
32697        function setUrlHash(url){
32698            //Uncode addition
32699            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
32700                return false;
32701
32702            if(options.recordHistory){
32703                location.hash = url;
32704            }else{
32705                //Uncode addition
32706                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
32707                // if(isTouchDevice || isTouch){
32708                //     window.history.replaceState(undefined, undefined, '#' + url);
32709                // }else{
32710                //     var baseUrl = window.location.href.split('#')[0];
32711                //     window.location.replace( baseUrl + '#' + url );
32712                // }
32713                return false;
32714            }
32715        }
32716
32717        /**
32718        * Gets the anchor for the given slide / section. Its index will be used if there's none.
32719        */
32720        function getAnchor(element){
32721            var anchor = element.data('anchor');
32722            var index = element.index();
32723
32724            //Slide without anchor link? We take the index instead.
32725            if(typeof anchor === 'undefined'){
32726                anchor = index;
32727            }
32728
32729            return anchor;
32730        }
32731
32732        /**
32733        * Sets a class for the body of the page depending on the active section / slide
32734        */
32735        function setBodyClass(){
32736            var section = $(SECTION_ACTIVE_SEL);
32737            var slide = section.find(SLIDE_ACTIVE_SEL);
32738
32739            var sectionAnchor = getAnchor(section);
32740            var slideAnchor = getAnchor(slide);
32741
32742            var text = String(sectionAnchor);
32743
32744            if(slide.length){
32745                text = text + '-' + slideAnchor;
32746            }
32747
32748            //changing slash for dash to make it a valid CSS style
32749            text = text.replace('/', '-').replace('#','');
32750
32751            //removing previous anchor classes
32752            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
32753            $body[0].className = $body[0].className.replace(classRe, '');
32754
32755            //adding the current anchor
32756            $body.addClass(VIEWING_PREFIX + '-' + text);
32757        }
32758
32759        /**
32760        * Checks for translate3d support
32761        * @return boolean
32762        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
32763        */
32764        function support3d() {
32765            var el = document.createElement('p'),
32766                has3d,
32767                transforms = {
32768                    'webkitTransform':'-webkit-transform',
32769                    'OTransform':'-o-transform',
32770                    'msTransform':'-ms-transform',
32771                    'MozTransform':'-moz-transform',
32772                    'transform':'transform'
32773                };
32774
32775            // Add it to the body to get the computed style.
32776            document.body.insertBefore(el, null);
32777
32778            for (var t in transforms) {
32779                if (el.style[t] !== undefined) {
32780                    el.style[t] = 'translate3d(1px,1px,1px)';
32781                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
32782                }
32783            }
32784
32785            document.body.removeChild(el);
32786
32787            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
32788        }
32789
32790        /**
32791        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
32792        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
32793        */
32794        function removeMouseWheelHandler(){
32795            if (document.addEventListener) {
32796                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
32797                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
32798                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
32799            } else {
32800                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
32801            }
32802        }
32803
32804        /**
32805        * Adds the auto scrolling action for the mouse wheel and trackpad.
32806        * After this function is called, the mousewheel and trackpad movements will scroll through sections
32807        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
32808        */
32809        function addMouseWheelHandler(){
32810            var prefix = '';
32811            var _addEventListener;
32812
32813            if (window.addEventListener){
32814                _addEventListener = "addEventListener";
32815            }else{
32816                _addEventListener = "attachEvent";
32817                prefix = 'on';
32818            }
32819
32820             // detect available wheel event
32821            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
32822                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
32823                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
32824            var passiveEvent = g_supportsPassive ? {passive: false }
32824: false;
32825
32826
32827            if(support == 'DOMMouseScroll'){
32828                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
32829            }
32830
32831            //handle MozMousePixelScroll in older Firefox
32832            else{
32833                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
32834            }
32835        }
32836
32837        /**
32838        * Binding the mousemove when the mouse's middle button is pressed
32839        */
32840        function addMiddleWheelHandler(){
32841            container
32842                .on('mousedown', mouseDownHandler)
32843                .on('mouseup', mouseUpHandler);
32844        }
32845
32846        /**
32847        * Unbinding the mousemove when the mouse's middle button is released
32848        */
32849        function removeMiddleWheelHandler(){
32850            container
32851                .off('mousedown', mouseDownHandler)
32852                .off('mouseup', mouseUpHandler);
32853        }
32854
32855        /**
32856        * Adds the possibility to auto scroll through sections on touch devices.
32857        */
32858        function addTouchHandler(){
32859            if(isTouchDevice || isTouch){
32860                if(options.autoScrolling){
32861                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
32862                }
32863
32864                $(WRAPPER_SEL)
32865                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
32866                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
32867            }
32868        }
32869
32870        /**
32871        * Removes the auto scrolling for touch devices.
32872        */
32873        function removeTouchHandler(){
32874            if(isTouchDevice || isTouch){
32875                $(WRAPPER_SEL)
32876                    .off(events.touchstart)
32877                    .off(events.touchmove);
32878            }
32879        }
32880
32881        /*
32882        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
32883        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
32884        */
32885        function getMSPointer(){
32886            var pointer;
32887
32888            //IE >= 11 & rest of browsers
32889            if(window.PointerEvent){
32890                pointer = { down: 'pointerdown', move: 'pointermove'};
32891            }
32892
32893            //IE < 11
32894            else{
32895                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
32896            }
32897
32898            return pointer;
32899        }
32900
32901        /**
32902        * Gets the pageX and pageY properties depending on the browser.
32903        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
32904        */
32905        function getEventsPage(e){
32906            var events = [];
32907
32908            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
32909            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
32910
32911            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
32912            if(isTouch && isReallyTouch(e) && options.scrollBar){
32913                events.y = e.touches[0].pageY;
32914                events.x = e.touches[0].pageX;
32915            }
32916
32917            return events;
32918        }
32919
32920        /**
32921        * Slides silently (with no animation) the active slider to the given slide.
32922        * @param noCallback {bool} true or defined -> no callbacks
32923        */
32924        function silentLandscapeScroll(activeSlide, noCallbacks){
32925            setScrollingSpeed (0, 'internal');
32926
32927            if(typeof noCallbacks !== 'undefined'){
32928                //preventing firing callbacks afterSlideLoad etc.
32929                isResizing = true;
32930            }
32931
32932            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
32933
32934            if(typeof noCallbacks !== 'undefined'){
32935                isResizing = false;
32936            }
32937
32938            setScrollingSpeed(originals.scrollingSpeed, 'internal');
32939        }
32940
32941        /**
32942        * Scrolls silently (with no animation) the page to the given Y position.
32943        */
32944        function silentScroll(top){
32945            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32946            // that's why we round it to 0.
32947            var roundedTop = Math.round(top);
32948
32949            if (options.css3 && options.autoScrolling && !options.scrollBar){
32950                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
32951                transformContainer(translate3d, false);
32952            }
32953            else if(options.autoScrolling && !options.scrollBar){
32954                container.css('top', -roundedTop);
32955            }
32956            else{
32957                $htmlBody.scrollTop(roundedTop);
32958            }
32959        }
32960
32961        /**
32962        * Returns the cross-browser transform string.
32963        */
32964        function getTransforms(translate3d){
32965            return {
32966                '-webkit-transform': translate3d,
32967                '-moz-transform': translate3d,
32968                '-ms-transform':translate3d,
32969                'transform': translate3d
32970            };
32971        }
32972
32973        /**
32974        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
32975        * @type  m (mouse) or k (keyboard)
32976        */
32977        function setIsScrollAllowed(value, direction, type){
32978            switch (direction){
32979                case 'up': isScrollAllowed[type].up = value; break;
32980                case 'down': isScrollAllowed[type].down = value; break;
32981                case 'left': isScrollAllowed[type].left = value; break;
32982                case 'right': isScrollAllowed[type].right = value; break;
32983                case 'all':
32984                    if(type == 'm'){
32985                        setAllowScrolling(value);
32986                    }else{
32987                        setKeyboardScrolling(value);
32988                    }
32989            }
32990        }
32991
32992        /*
32993        * Destroys fullpage.js plugin events and optinally its html markup and styles
32994        */
32995        function destroy(all){
32996            setAutoScrolling(false, 'internal');
32997            setAllowScrolling(false);
32998            setKeyboardScrolling(false);
32999            container.addClass(DESTROYED);
33000
33001            clearTimeout(afterSlideLoadsId);
33002            clearTimeout(afterSectionLoadsId);
33003            clearTimeout(resizeId);
33004            clearTimeout(scrollId);
33005            clearTimeout(scrollId2);
33006
33007            $window
33008                .off('scroll', scrollHandler)
33009                .off('hashchange', hashChangeHandler)
33010                .off('resize', resizeHandler);
33011
33012            $document
33013                .off('click touchstart', SECTION_NAV_SEL + ' a')
33014                .off('mouseenter', SECTION_NAV_SEL + ' li')
33015                .off('mouseleave', SECTION_NAV_SEL + ' li')
33016                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33017                .off('mouseover', options.normalScrollElements)
33018                .off('mouseout', options.normalScrollElements);
33019
33020            $(SECTION_SEL)
33021                .off('click touchstart', SLIDES_ARROW_SEL);
33022
33023            clearTimeout(afterSlideLoadsId);
33024            clearTimeout(afterSectionLoadsId);
33025
33026            //lets make a mess!
33027            if(all){
33028                destroyStructure();
33029            }
33030        }
33031
33032        /*
33033        * Removes inline styles added by fullpage.js
33034        */
33035        function destroyStructure(){
33036            //reseting the `top` or `translate` properties to 0
33037            silentScroll(0);
33038
33039            //loading all the lazy load content
33040            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33041                setSrc($(this), 'src');
33042            });
33043
33044            container.find('img[data-srcset]').each(function(){
33045                setSrc($(this), 'srcset');
33046            });
33047
33048            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33049
33050            //removing inline styles
33051            $(SECTION_SEL).css( {
33052                'height': '',
33053                'background-color' : '',
33054                'padding': ''
33055            });
33056
33057            $(SLIDE_SEL).css( {
33058                'width': ''
33059            });
33060
33061            container.css({
33062                'height': '',
33063                'position': '',
33064                '-ms-touch-action': '',
33065                'touch-action': ''
33066            });
33067
33068            $htmlBody.css({
33069                'overflow': '',
33070                'height': ''
33071            });
33072
33073            // remove .fp-enabled class
33074            $('html').removeClass(ENABLED);
33075
33076            // remove .fp-responsive class
33077            $body.removeClass(RESPONSIVE);
33078
33079            // remove all of the .fp-viewing- classes
33080            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33081                if (className.indexOf(VIEWING_PREFIX) === 0) {
33082                    $body.removeClass(className);
33083                }
33084            });
33085
33086            //removing added classes
33087            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
33088                options.scrollOverflowHandler.remove($(this));
33089                $(this).removeClass(TABLE + ' ' + ACTIVE);
33090            });
33091
33092            removeAnimation(container);
33093
33094            //Unwrapping content
33095            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
33096                //unwrap not being use in case there's no child element inside and its just text
33097                $(this).replaceWith(this.childNodes);
33098            });
33099
33100            //removing the applied transition from the fullpage wrapper
33101            container.css({
33102                '-webkit-transition': 'none',
33103                'transition': 'none'
33104            });
33105
33106            //scrolling the page to the top with no animation
33107            $htmlBody.scrollTop(0);
33108
33109            //removing selectors
33110            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
33111            $.each(usedSelectors, function(index, value){
33112                $('.' + value).removeClass(value);
33113            });
33114        }
33115
33116        /*
33117        * Sets the state for a variable with multiple states (original, and temporal)
33118        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
33119        * This function is used to keep track of both states, the original and the temporal one.
33120        * If type is not 'internal', then we assume the user is globally changing the variable.
33121        */
33122        function setVariableState(variable, value, type){
33123            options[variable] = value;
33124            if(type !== 'internal'){
33125                originals[variable] = value;
33126            }
33127        }
33128
33129        /**
33130        * Displays warnings
33131        */
33132        function displayWarnings(){
33133            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
33134            //UNCODE.addition
33135            // if($('html').hasClass(ENABLED)){
33136            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
33137            //     return;
33138            // }
33139
33140            // Disable mutually exclusive settings
33141            //UNCODE.addition
33142            // if (options.continuousVertical &&
33143            //     (options.loopTop || options.loopBottom)) {
33144            //     options.continuousVertical = false;
33145            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
33146            // }
33147
33148            // if(options.scrollBar && options.scrollOverflow){
33149            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
33150            // }
33151
33152            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
33153            //     options.continuousVertical = false;
33154            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
33155            // }
33156
33157            //using extensions? Wrong file!
33158            $.each(extensions, function(index, extension){
33159                //is the option set to true?
33160                if(options[extension]){
33161                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
33162                }
33163            });
33164
33165            //anchors can not have the same value as any element ID or NAME
33166            $.each(options.anchors, function(index, name){
33167
33168                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
33169                var nameAttr = $document.find('[name]').filter(function() {
33170                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
33171                });
33172
33173                var idAttr = $document.find('[id]').filter(function() {
33174                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
33175                });
33176
33177                if(idAttr.length || nameAttr.length ){
33178                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
33179                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
33180                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
33181                }
33182            });
33183        }
33184
33185        /**
33186        * Shows a message in the console of the given type.
33187        */
33188        function showError(type, text){
33189            console && console[type] && console[type]('fullPage: ' + text);
33190        }
33191
33192    }; //end of $.fn.fullpage
33193
33194    if(typeof IScroll !== 'undefined'){
33195        /*
33196        * Turns iScroll `mousewheel` option off dynamically
33197        * https://github.com/cubiq/iscroll/issues/1036
33198        */
33199        IScroll.prototype.wheelOn = function () {
33200            this.wrapper.addEventListener('wheel', this);
33201            this.wrapper.addEventListener('mousewheel', this);
33202            this.wrapper.addEventListener('DOMMouseScroll', this);
33203        };
33204
33205        /*
33206        * Turns iScroll `mousewheel` option on dynamically
33207        * https://github.com/cubiq/iscroll/issues/1036
33208        */
33209        IScroll.prototype.wheelOff = function () {
33210            this.wrapper.removeEventListener('wheel', this);
33211            this.wrapper.removeEventListener('mousewheel', this);
33212            this.wrapper.removeEventListener('DOMMouseScroll', this);
33213        };
33214    }
33215
33216    /**
33217     * An object to handle overflow scrolling.
33218     * This uses jquery.slimScroll to accomplish overflow scrolling.
33219     * It is possible to pass in an alternate scrollOverflowHandler
33220     * to the fullpage.js option that implements the same functions
33221     * as this handler.
33222     *
33223     * @type {Object}
33224     */
33225    var iscrollHandler = {
33226        refreshId: null,
33227        iScrollInstances: [],
33228
33229        // Enables or disables the mouse wheel for the active section or all slides in it
33230        toggleWheel: function(value){
33231            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
33232            scrollable.each(function(){
33233                var iScrollInstance = $(this).data('iscrollInstance');
33234                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
33235                    if(value){
33236                        iScrollInstance.wheelOn();
33237                    }
33238                    else{
33239                        iScrollInstance.wheelOff();
33240                    }
33241                }
33242            });
33243        },
33244
33245        /**
33246        * Turns off iScroll for the destination section.
33247        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
33248        * scroll the destination section/slide before the sections animations ends.
33249        */
33250        onLeave: function(){
33251            iscrollHandler.toggleWheel(false);
33252        },
33253
33254        // Turns off iScroll for the leaving section
33255        beforeLeave: function(){
33256            iscrollHandler.onLeave()
33257        },
33258
33259        // Turns on iScroll on section load
33260        afterLoad: function(){
33261            iscrollHandler.toggleWheel(true);
33262        },
33263
33264        /**
33265         * Called when overflow scrolling is needed for a section.
33266         *
33267         * @param  {Object} element      jQuery object containing current section
33268         * @param  {Number} scrollHeight Current window height in pixels
33269         */
33270        create: function(element, scrollHeight) {
33271            var scrollable = element.find(SCROLLABLE_SEL);
33272
33273            scrollable.height(scrollHeight);
33274            scrollable.each(function() {
33275                var $this = $(this);
33276                var iScrollInstance = $this.data('iscrollInstance');
33277                if (iScrollInstance) {
33278                    $.each(iscrollHandler.iScrollInstances, function(){
33279                        $(this).destroy();
33280                    });
33281                }
33282
33283                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
33284                iscrollHandler.iScrollInstances.push(iScrollInstance);
33285
33286                //off by default until the section gets active
33287                iScrollInstance.wheelOff();
33288
33289                $this.data('iscrollInstance', iScrollInstance);
33290            });
33291        },
33292
33293        /**
33294         * Return a boolean depending on whether the scrollable element is a
33295         * the end or at the start of the scrolling depending on the given type.
33296         *
33297         * @param  {String}  type       Either 'top' or 'bottom'
33298         * @param  {Object}  scrollable jQuery object for the scrollable element
33299         * @return {Boolean}
33300         */
33301        isScrolled: function(type, scrollable) {
33302            var scroller = scrollable.data('iscrollInstance');
33303
33304            //no scroller?
33305            if (!scroller) {
33306                return true;
33307            }
33308
33309            if (type === 'top') {
33310                return scroller.y >= 0 && !scrollable.scrollTop();
33311            } else if (type === 'bottom') {
33312                return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
33313            }
33314        },
33315
33316        /**
33317         * Returns the scrollable element for the given section.
33318         * If there are landscape slides, will only return a scrollable element
33319         * if it is in the active slide.
33320         *
33321         * @param  {Object}  activeSection jQuery object containing current section
33322         * @return {Boolean}
33323         */
33324        scrollable: function(activeSection){
33325            // if there are landscape slides, we check if the scrolling bar is in the current one or not
33326            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
33327                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
33328            }
33329            return activeSection.find(SCROLLABLE_SEL);
33330        },
33331
33332        /**
33333         * Returns the scroll height of the wrapped content.
33334         * If this is larger than the window height minus section padding,
33335         * overflow scrolling is needed.
33336         *
33337         * @param  {Object} element jQuery object containing current section
33338         * @return {Number}
33339         */
33340        scrollHeight: function(element) {
33341            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
33342        },
33343
33344        /**
33345         * Called when overflow scrolling is no longer needed for a section.
33346         *
33347         * @param  {Object} element      jQuery object containing current section
33348         */
33349        remove: function(element) {
33350            var scrollable = element.find(SCROLLABLE_SEL);
33351            if (scrollable.length) {
33352                var iScrollInstance = scrollable.data('iscrollInstance');
33353                iScrollInstance.destroy();
33354
33355                scrollable.data('iscrollInstance', null);
33356            }
33357            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
33358        },
33359
33360        /**
33361         * Called when overflow scrolling has already been setup but the
33362         * window height has potentially changed.
33363         *
33364         * @param  {Object}
33364 element      jQuery object containing current section
33365         * @param  {Number} scrollHeight Current window height in pixels
33366         */
33367        update: function(element, scrollHeight) {
33368            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
33369            //short period of time.
33370            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
33371            clearTimeout(iscrollHandler.refreshId);
33372            iscrollHandler.refreshId = setTimeout(function(){
33373                $.each(iscrollHandler.iScrollInstances, function(){
33374                    $(this).get(0).refresh();
33375                });
33376            }, 150);
33377
33378            //updating the wrappers height
33379            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
33380        },
33381
33382        /**
33383         * Called to get any additional elements needed to wrap the section
33384         * content in order to facilitate overflow scrolling.
33385         *
33386         * @return {String|Object} Can be a string containing HTML,
33387         *                         a DOM element, or jQuery object.
33388         */
33389        wrapContent: function() {
33390            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
33391        }
33392    };
33393});
33394
33395(function (global, factory) {
33396	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
33397	typeof define === 'function' && define.amd ? define(['exports'], factory) :
33398	(global = global || self, factory(global.window = global.window || {}));
33399}(this, (function (exports) { 'use strict';
33400
33401	/*!
33402	 * ScrollTrigger 3.8.0
33403	 * https://greensock.com
33404	 *
33405	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
33406	 * Subject to the terms at https://greensock.com/standard-license or for
33407	 * Club GreenSock members, the agreement issued with that membership.
33408	 * @author: Jack Doyle, [email protected]
33409	*/
33410	var gsap,
33411	    _coreInitted,
33412	    _win,
33413	    _doc,
33414	    _docEl,
33415	    _body,
33416	    _root,
33417	    _resizeDelay,
33418	    _raf,
33419	    _request,
33420	    _toArray,
33421	    _clamp,
33422	    _time2,
33423	    _syncInterval,
33424	    _refreshing,
33425	    _pointerIsDown,
33426	    _transformProp,
33427	    _i,
33428	    _prevWidth,
33429	    _prevHeight,
33430	    _autoRefresh,
33431	    _sort,
33432	    _suppressOverwrites,
33433	    _ignoreResize,
33434	    _limitCallbacks,
33435	    _startup = 1,
33436	    _proxies = [],
33437	    _scrollers = [],
33438	    _getTime = Date.now,
33439	    _time1 = _getTime(),
33440	    _lastScrollTime = 0,
33441	    _enabled = 1,
33442	    _passThrough = function _passThrough(v) {
33443	  return v;
33444	},
33445	    _getTarget = function _getTarget(t) {
33446	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
33447	},
33448	    _round = function _round(value) {
33449	  return Math.round(value * 100000) / 100000 || 0;
33450	},
33451	    _windowExists = function _windowExists() {
33452	  return typeof window !== "undefined";
33453	},
33454	    _getGSAP = function _getGSAP() {
33455	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
33456	},
33457	    _isViewport = function _isViewport(e) {
33458	  return !!~_root.indexOf(e);
33459	},
33460	    _getProxyProp = function _getProxyProp(element, property) {
33461	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
33462	},
33463	    _getScrollFunc = function _getScrollFunc(element, _ref) {
33464	  var s = _ref.s,
33465	      sc = _ref.sc;
33466
33467	  var i = _scrollers.indexOf(element),
33468	      offset = sc === _vertical.sc ? 1 : 2;
33469
33470	  !~i && (i = _scrollers.push(element) - 1);
33471	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
33472	    return arguments.length ? element[s] = value : element[s];
33473	  }));
33474	},
33475	    _getBoundsFunc = function _getBoundsFunc(element) {
33476	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
33477	    _winOffsets.width = _win.innerWidth;
33478	    _winOffsets.height = _win.innerHeight;
33479	    return _winOffsets;
33480	  } : function () {
33481	    return _getBounds(element);
33482	  });
33483	},
33484	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
33485	  var d = _ref2.d,
33486	      d2 = _ref2.d2,
33487	      a = _ref2.a;
33488	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
33489	    return a()[d];
33490	  } : function () {
33491	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
33492	  };
33493	},
33494	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
33495	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
33496	    return _winOffsets;
33497	  };
33498	},
33499	    _maxScroll = function _maxScroll(element, _ref3) {
33500	  var s = _ref3.s,
33501	      d2 = _ref3.d2,
33502	      d = _ref3.d,
33503	      a = _ref3.a;
33504	  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];
33505	},
33506	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
33507	  for (var i = 0; i < _autoRefresh.length; i += 3) {
33508	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
33509	  }
33510	},
33511	    _isString = function _isString(value) {
33512	  return typeof value === "string";
33513	},
33514	    _isFunction = function _isFunction(value) {
33515	  return typeof value === "function";
33516	},
33517	    _isNumber = function _isNumber(value) {
33518	  return typeof value === "number";
33519	},
33520	    _isObject = function _isObject(value) {
33521	  return typeof value === "object";
33522	},
33523	    _callIfFunc = function _callIfFunc(value) {
33524	  return _isFunction(value) && value();
33525	},
33526	    _combineFunc = function _combineFunc(f1, f2) {
33527	  return function () {
33528	    var result1 = _callIfFunc(f1),
33529	        result2 = _callIfFunc(f2);
33530
33531	    return function () {
33532	      _callIfFunc(result1);
33533
33534	      _callIfFunc(result2);
33535	    };
33536	  };
33537	},
33538	    _endAnimation = function _endAnimation(animation, reversed, pause) {
33539	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
33540	},
33541	    _callback = function _callback(self, func) {
33542	  var result = func(self);
33543	  result && result.totalTime && (self.callbackAnimation = result);
33544	},
33545	    _abs = Math.abs,
33546	    _scrollLeft = "scrollLeft",
33547	    _scrollTop = "scrollTop",
33548	    _left = "left",
33549	    _top = "top",
33550	    _right = "right",
33551	    _bottom = "bottom",
33552	    _width = "width",
33553	    _height = "height",
33554	    _Right = "Right",
33555	    _Left = "Left",
33556	    _Top = "Top",
33557	    _Bottom = "Bottom",
33558	    _padding = "padding",
33559	    _margin = "margin",
33560	    _Width = "Width",
33561	    _Height = "Height",
33562	    _px = "px",
33563	    _horizontal = {
33564	  s: _scrollLeft,
33565	  p: _left,
33566	  p2: _Left,
33567	  os: _right,
33568	  os2: _Right,
33569	  d: _width,
33570	  d2: _Width,
33571	  a: "x",
33572	  sc: function sc(value) {
33573	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
33574	  }
33575	},
33576	    _vertical = {
33577	  s: _scrollTop,
33578	  p: _top,
33579	  p2: _Top,
33580	  os: _bottom,
33581	  os2: _Bottom,
33582	  d: _height,
33583	  d2: _Height,
33584	  a: "y",
33585	  op: _horizontal,
33586	  sc: function sc(value) {
33587	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
33588	  }
33589	},
33590	    _getComputedStyle = function _getComputedStyle(element) {
33591	  return _win.getComputedStyle(element);
33592	},
33593	    _makePositionable = function _makePositionable(element) {
33594	  var position = _getComputedStyle(element).position;
33595
33596	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
33597	},
33598	    _setDefaults = function _setDefaults(obj, defaults) {
33599	  for (var p in defaults) {
33600	    p in obj || (obj[p] = defaults[p]);
33601	  }
33602
33603	  return obj;
33604	},
33605	    _getBounds = function _getBounds(element, withoutTransforms) {
33606	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
33607	    x: 0,
33608	    y: 0,
33609	    xPercent: 0,
33610	    yPercent: 0,
33611	    rotation: 0,
33612	    rotationX: 0,
33613	    rotationY: 0,
33614	    scale: 1,
33615	    skewX: 0,
33616	    skewY: 0
33617	  }).progress(1),
33618	      bounds = element.getBoundingClientRect();
33619	  tween && tween.progress(0).kill();
33620	  return bounds;
33621	},
33622	    _getSize = function _getSize(element, _ref4) {
33623	  var d2 = _ref4.d2;
33624	  return element["offset" + d2] || element["client" + d2] || 0;
33625	},
33626	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
33627	  var a = [],
33628	      labels = timeline.labels,
33629	      duration = timeline.duration(),
33630	      p;
33631
33632	  for (p in labels) {
33633	    a.push(labels[p] / duration);
33634	  }
33635
33636	  return a;
33637	},
33638	    _getClosestLabel = function _getClosestLabel(animation) {
33639	  return function (value) {
33640	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
33641	  };
33642	},
33643	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
33644	  var snap = gsap.utils.snap(snapIncrementOrArray),
33645	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
33646	    return a - b;
33647	  });
33648	  return a ? function (value, direction) {
33649	    var i;
33650
33651	    if (!direction) {
33652	      return snap(value);
33653	    }
33654
33655	    if (direction > 0) {
33656	      value -= 1e-4;
33657
33658	      for (i = 0; i < a.length; i++) {
33659	        if (a[i] >= value) {
33660	          return a[i];
33661	        }
33662	      }
33663
33664	      return a[i - 1];
33665	    } else {
33666	      i = a.length;
33667	      value += 1e-4;
33668
33669	      while (i--) {
33670	        if (a[i] <= value) {
33671	          return a[i];
33672	        }
33673	      }
33674	    }
33675
33676	    return a[0];
33677	  } : function (value, direction) {
33678	    var snapped = snap(value);
33679	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
33680	  };
33681	},
33682	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
33683	  return function (value, st) {
33684	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
33685	  };
33686	},
33687	    _multiListener = function _multiListener(func, element, types, callback) {
33688	  return types.split(",").forEach(function (type) {
33689	    return func(element, type, callback);
33690	  });
33691	},
33692	    _addListener = function _addListener(element, type, func) {
33693	  return element.addEventListener(type, func, {
33694	    passive: true
33695	  });
33696	},
33697	    _removeListener = function _removeListener(element, type, func) {
33698	  return element.removeEventListener(type, func);
33699	},
33700	    _markerDefaults = {
33701	  startColor: "green",
33702	  endColor: "red",
33703	  indent: 0,
33704	  fontSize: "16px",
33705	  fontWeight: "normal"
33706	},
33707	    _defaults = {
33708	  toggleActions: "play",
33709	  anticipatePin: 0
33710	},
33711	    _keywords = {
33712	  top: 0,
33713	  left: 0,
33714	  center: 0.5,
33715	  bottom: 1,
33716	  right: 1
33717	},
33718	    _offsetToPx = function _offsetToPx(value, size) {
33719	  if (_isString(value)) {
33720	    var eqIndex = value.indexOf("="),
33721	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
33722
33723	    if (~eqIndex) {
33724	      value.indexOf("%") > eqIndex && (relative *= size / 100);
33725	      value = value.substr(0, eqIndex - 1);
33726	    }
33727
33728	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
33729	  }
33730
33731	  return value;
33732	},
33733	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
33734	  var startColor = _ref5.startColor,
33735	      endColor = _ref5.endColor,
33736	      fontSize = _ref5.fontSize,
33737	      indent = _ref5.indent,
33738	      fontWeight = _ref5.fontWeight;
33739
33740	  var e = _doc.createElement("div"),
33741	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
33742	      isScroller = type.indexOf("scroller") !== -1,
33743	      parent = useFixedPosition ? _body : container,
33744	      isStart = type.indexOf("start") !== -1,
33745	      color = isStart ? startColor : endColor,
33746	      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;";
33747
33748	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
33749	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
33750	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
33751	  e._isStart = isStart;
33752	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
33753	  e.style.cssText = css;
33754	  e.innerText = name || name === 0 ? type + "-" + name : type;
33755	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
33756	  e._offset = e["offset" + direction.op.d2];
33757
33758	  _positionMarker(e, 0, direction, isStart);
33759
33760	  return e;
33761	},
33762	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
33763	  var vars = {
33764	    display: "block"
33765	  },
33766	      side = direction[flipped ? "os2" : "p2"],
33767	      oppositeSide = direction[flipped ? "p2" : "os2"];
33768	  marker._isFlipped = flipped;
33769	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
33770	  vars[direction.a] = flipped ? "1px" : 0;
33771	  vars["border" + side + _Width] = 1;
33772	  vars["border" + oppositeSide + _Width] = 0;
33773	  vars[direction.p] = start + "px";
33774	  gsap.set(marker, vars);
33775	},
33776	    _triggers = [],
33777	    _ids = {},
33778	    _sync = function _sync() {
33779	  return _getTime() - _lastScrollTime > 20 && _updateAll();
33780	},
33781	    _onScroll = function _onScroll() {
33782	  var time = _getTime();
33783
33784	  if (_lastScrollTime !== time) {
33785	    _updateAll();
33786
33787	    _lastScrollTime || _dispatch("scrollStart");
33788	    _lastScrollTime = time;
33789	  } else if (!_request) {
33790	    _request = _raf(_updateAll);
33791	  }
33792	},
33793	    _onResize = function _onResize() {
33794	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
33795	},
33796	    _listeners = {},
33797	    _emptyArray = [],
33798	    _media = [],
33799	    _creatingMedia,
33800	    _lastMediaTick,
33801	    _onMediaChange = function _onMediaChange(e) {
33802	  var tick = gsap.ticker.frame,
33803	      matches = [],
33804	      i = 0,
33805	      index;
33806
33807	  if (_lastMediaTick !== tick || _startup) {
33808	    _revertAll();
33809
33810	    for (; i < _media.length; i += 4) {
33811	      index = _win.matchMedia(_media[i]).matches;
33812
33813	      if (index !== _media[i + 3]) {
33814	        _media[i + 3] = index;
33815	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
33816	      }
33817	    }
33818
33819	    _revertRecorded();
33820
33821	    for (i = 0; i < matches.length; i++) {
33822	      index = matches[i];
33823	      _creatingMedia = _media[index];
33824	      _media[index + 2] = _media[index + 1](e);
33825	    }
33826
33827	    _creatingMedia = 0;
33828	    _coreInitted && _refreshAll(0, 1);
33829	    _lastMediaTick = tick;
33830
33831	    _dispatch("matchMedia");
33832	  }
33833	},
33834	    _softRefresh = function _softRefresh() {
33835	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
33836	},
33837	    _dispatch = function _dispatch(type) {
33838	  return _listeners[type] && _listeners[type].map(function (f) {
33839	    return f();
33840	  }) || _emptyArray;
33841	},
33842	    _savedStyles = [],
33843	    _revertRecorded = function _revertRecorded(media) {
33844	  for (var i = 0; i < _savedStyles.length; i += 5) {
33845	    if (!media || _savedStyles[i + 4] === media) {
33846	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
33847	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
33848	      _savedStyles[i + 3].uncache = 1;
33849	    }
33850	  }
33851	},
33852	    _revertAll = function _revertAll(kill, media) {
33853	  var trigger;
33854
33855	  for (_i = 0; _i < _triggers.length; _i++) {
33856	    trigger = _triggers[_i];
33857
33858	    if (!media || trigger.media === media) {
33859	      if (kill) {
33860	        trigger.kill(1);
33861	      } else {
33862	        trigger.revert();
33863	      }
33864	    }
33865	  }
33866
33867	  media && _revertRecorded(media);
33868	  media || _dispatch("revert");
33869	},
33870	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 33871-34205
33871	  return _scrollers.forEach(function (obj) {
33872	    return typeof obj === "function" && (obj.rec = 0);
33873	  });
33874	},
33875	    _refreshingAll,
33876	    _refreshAll = function _refreshAll(force, skipRevert) {
33877	  if (_lastScrollTime && !force) {
33878	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
33879
33880	    return;
33881	  }
33882
33883	  _refreshingAll = true;
33884
33885	  var refreshInits = _dispatch("refreshInit");
33886
33887	  _sort && ScrollTrigger.sort();
33888	  skipRevert || _revertAll();
33889
33890	  _triggers.forEach(function (t) {
33891	    return t.refresh();
33892	  });
33893
33894	  refreshInits.forEach(function (result) {
33895	    return result && result.render && result.render(-1);
33896	  });
33897
33898	  _clearScrollMemory();
33899
33900	  _resizeDelay.pause();
33901
33902	  _refreshingAll = false;
33903
33904	  _dispatch("refresh");
33905	},
33906	    _lastScroll = 0,
33907	    _direction = 1,
33908	    _updateAll = function _updateAll() {
33909	  if (!_refreshingAll) {
33910	    var l = _triggers.length,
33911	        time = _getTime(),
33912	        recordVelocity = time - _time1 >= 50,
33913	        scroll = l && _triggers[0].scroll();
33914
33915	    _direction = _lastScroll > scroll ? -1 : 1;
33916	    _lastScroll = scroll;
33917
33918	    if (recordVelocity) {
33919	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
33920	        _lastScrollTime = 0;
33921
33922	        _dispatch("scrollEnd");
33923	      }
33924
33925	      _time2 = _time1;
33926	      _time1 = time;
33927	    }
33928
33929	    if (_direction < 0) {
33930	      _i = l;
33931
33932	      while (_i-- > 0) {
33933	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
33934	      }
33935
33936	      _direction = 1;
33937	    } else {
33938	      for (_i = 0; _i < l; _i++) {
33939	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
33940	      }
33941	    }
33942
33943	    _request = 0;
33944	  }
33945	},
33946	    _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"],
33947	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
33948	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
33949	  _setState(state);
33950
33951	  var cache = pin._gsap;
33952
33953	  if (cache.spacerIsNative) {
33954	    _setState(cache.spacerState);
33955	  } else if (pin.parentNode === spacer) {
33956	    var parent = spacer.parentNode;
33957
33958	    if (parent) {
33959	      parent.insertBefore(pin, spacer);
33960	      parent.removeChild(spacer);
33961	    }
33962	  }
33963	},
33964	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
33965	  if (pin.parentNode !== spacer) {
33966	    var i = _propNamesToCopy.length,
33967	        spacerStyle = spacer.style,
33968	        pinStyle = pin.style,
33969	        p;
33970
33971	    while (i--) {
33972	      p = _propNamesToCopy[i];
33973	      spacerStyle[p] = cs[p];
33974	    }
33975
33976	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
33977	    cs.display === "inline" && (spacerStyle.display = "inline-block");
33978	    pinStyle[_bottom] = pinStyle[_right] = "auto";
33979	    spacerStyle.overflow = "visible";
33980	    spacerStyle.boxSizing = "border-box";
33981	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
33982	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
33983	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
33984
33985	    _setState(spacerState);
33986
33987	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
33988	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
33989	    pinStyle[_padding] = cs[_padding];
33990	    pin.parentNode.insertBefore(spacer, pin);
33991	    spacer.appendChild(pin);
33992	  }
33993	},
33994	    _capsExp = /([A-Z])/g,
33995	    _setState = function _setState(state) {
33996	  if (state) {
33997	    var style = state.t.style,
33998	        l = state.length,
33999	        i = 0,
34000	        p,
34001	        value;
34002	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34003
34004	    for (; i < l; i += 2) {
34005	      value = state[i + 1];
34006	      p = state[i];
34007
34008	      if (value) {
34009	        style[p] = value;
34010	      } else if (style[p]) {
34011	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34012	      }
34013	    }
34014	  }
34015	},
34016	    _getState = function _getState(element) {
34017	  var l = _stateProps.length,
34018	      style = element.style,
34019	      state = [],
34020	      i = 0;
34021
34022	  for (; i < l; i++) {
34023	    state.push(_stateProps[i], style[_stateProps[i]]);
34024	  }
34025
34026	  state.t = element;
34027	  return state;
34028	},
34029	    _copyState = function _copyState(state, override, omitOffsets) {
34030	  var result = [],
34031	      l = state.length,
34032	      i = omitOffsets ? 8 : 0,
34033	      p;
34034
34035	  for (; i < l; i += 2) {
34036	    p = state[i];
34037	    result.push(p, p in override ? override[p] : state[i + 1]);
34038	  }
34039
34040	  result.t = state.t;
34041	  return result;
34042	},
34043	    _winOffsets = {
34044	  left: 0,
34045	  top: 0
34046	},
34047	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34048	  _isFunction(value) && (value = value(self));
34049
34050	  if (_isString(value) && value.substr(0, 3) === "max") {
34051	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34052	  }
34053
34054	  var time = containerAnimation ? containerAnimation.time() : 0,
34055	      p1,
34056	      p2,
34057	      element;
34058	  containerAnimation && containerAnimation.seek(0);
34059
34060	  if (!_isNumber(value)) {
34061	    _isFunction(trigger) && (trigger = trigger(self));
34062	    var offsets = value.split(" "),
34063	        bounds,
34064	        localOffset,
34065	        globalOffset,
34066	        display;
34067	    element = _getTarget(trigger) || _body;
34068	    bounds = _getBounds(element) || {};
34069
34070	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34071	      display = element.style.display;
34072	      element.style.display = "block";
34073	      bounds = _getBounds(element);
34074	      display ? element.style.display = display : element.style.removeProperty("display");
34075	    }
34076
34077	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
34078	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
34079	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
34080	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
34081	    scrollerSize -= scrollerSize - globalOffset;
34082	  } else if (markerScroller) {
34083	    _positionMarker(markerScroller, scrollerSize, direction, true);
34084	  }
34085
34086	  if (marker) {
34087	    var position = value + scrollerSize,
34088	        isStart = marker._isStart;
34089	    p1 = "scroll" + direction.d2;
34090
34091	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
34092
34093	    if (useFixedPosition) {
34094	      scrollerBounds = _getBounds(markerScroller);
34095	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
34096	    }
34097	  }
34098
34099	  if (containerAnimation && element) {
34100	    p1 = _getBounds(element);
34101	    containerAnimation.seek(scrollerMax);
34102	    p2 = _getBounds(element);
34103	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
34104	    value = value / containerAnimation._caScrollDist * scrollerMax;
34105	  }
34106
34107	  containerAnimation && containerAnimation.seek(time);
34108	  return containerAnimation ? value : Math.round(value);
34109	},
34110	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
34111	    _reparent = function _reparent(element, parent, top, left) {
34112	  if (element.parentNode !== parent) {
34113	    var style = element.style,
34114	        p,
34115	        cs;
34116
34117	    if (parent === _body) {
34118	      element._stOrig = style.cssText;
34119	      cs = _getComputedStyle(element);
34120
34121	      for (p in cs) {
34122	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
34123	          style[p] = cs[p];
34124	        }
34125	      }
34126
34127	      style.top = top;
34128	      style.left = left;
34129	    } else {
34130	      style.cssText = element._stOrig;
34131	    }
34132
34133	    gsap.core.getCache(element).uncache = 1;
34134	    parent.appendChild(element);
34135	  }
34136	},
34137	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
34138	  var getScroll = _getScrollFunc(scroller, direction),
34139	      prop = "_scroll" + direction.p2,
34140	      lastScroll1,
34141	      lastScroll2,
34142	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
34143	    var tween = getTween.tween,
34144	        onComplete = vars.onComplete,
34145	        modifiers = {};
34146	    tween && tween.kill();
34147	    lastScroll1 = Math.round(initialValue);
34148	    vars[prop] = scrollTo;
34149	    vars.modifiers = modifiers;
34150
34151	    modifiers[prop] = function (value) {
34152	      value = _round(getScroll());
34153
34154	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
34155	        tween.kill();
34156	        getTween.tween = 0;
34157	      } else {
34158	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
34159	      }
34160
34161	      lastScroll2 = lastScroll1;
34162	      return lastScroll1 = _round(value);
34163	    };
34164
34165	    vars.onComplete = function () {
34166	      getTween.tween = 0;
34167	      onComplete && onComplete.call(tween);
34168	    };
34169
34170	    tween = getTween.tween = gsap.to(scroller, vars);
34171	    return tween;
34172	  };
34173
34174	  scroller[prop] = getScroll;
34175	  scroller.addEventListener("wheel", function () {
34176	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
34177	  }, {
34178	    passive: true
34179	  });
34180	  return getTween;
34181	};
34182
34183	_horizontal.op = _vertical;
34184	var ScrollTrigger = function () {
34185	  function ScrollTrigger(vars, animation) {
34186	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
34187	    this.init(vars, animation);
34188	  }
34189
34190	  var _proto = ScrollTrigger.prototype;
34191
34192	  _proto.init = function init(vars, animation) {
34193	    this.progress = this.start = 0;
34194	    this.vars && this.kill(1);
34195
34196	    if (!_enabled) {
34197	      this.update = this.refresh = this.kill = _passThrough;
34198	      return;
34199	    }
34200
34201	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
34202	      trigger: vars
34203	    } : vars, _defaults);
34204
34205	    var _vars = vars,
34206	        onUpdate = _vars.onUpdate,
34207	        toggleClass = _vars.toggleClass,
34208	        id = _vars.id,
34209	        onToggle = _vars.onToggle,
34210	        onRefresh = _vars.onRefresh,
34211	        scrub = _vars.scrub,
34212	        trigger = _vars.trigger,
34213	        pin = _vars.pin,
34214	        pinSpacing = _vars.pinSpacing,
34215	        invalidateOnRefresh = _vars.invalidateOnRefresh,
34216	        anticipatePin = _vars.anticipatePin,
34217	        onScrubComplete = _vars.onScrubComplete,
34218	        onSnapComplete = _vars.onSnapComplete,
34219	        once = _vars.once,
34220	        snap = _vars.snap,
34221	        pinReparent = _vars.pinReparent,
34222	        pinSpacer = _vars.pinSpacer,
34223	        containerAnimation = _vars.containerAnimation,
34224	        fastScrollEnd = _vars.fastScrollEnd,
34225	        preventOverlaps = _vars.preventOverlaps,
34226	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
34227	        isToggle = !scrub && scrub !== 0,
34228	        scroller = _getTarget(vars.scroller || _win),
34229	        scrollerCache = gsap.core.getCache(scroller),
34230	        isViewport = _isViewport(scroller),
34231	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
34232	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
34233	        toggleActions = isToggle && vars.toggleActions.split(" "),
34234	        markers = "markers" in vars ? vars.markers : _defaults.markers,
34235	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
34236	        self = this,
34237	        onRefreshInit = vars.onRefreshInit && function () {
34238	      return vars.onRefreshInit(self);
34239	    },
34240	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
34241	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
34242	        lastSnap = 0,
34243	        scrollFunc = _getScrollFunc(scroller, direction),
34244	        tweenTo,
34245	        pinCache,
34246	        snapFunc,
34247	        scroll1,
34248	        scroll2,
34249	        start,
34250	        end,
34251	        markerStart,
34252	        markerEnd,
34253	        markerStartTrigger,
34254	        markerEndTrigger,
34255	        markerVars,
34256	        change,
34257	        pinOriginalState,
34258	        pinActiveState,
34259	        pinState,
34260	        spacer,
34261	        offset,
34262	        pinGetter,
34263	        pinSetter,
34264	        pinStart,
34265	        pinChange,
34266	        spacingStart,
34267	        spacerState,
34268	        markerStartSetter,
34269	        markerEndSetter,
34270	        cs,
34271	        snap1,
34272	        snap2,
34273	        scrubTween,
34274	        scrubSmooth,
34275	        snapDurClamp,
34276	        snapDelayedCall,
34277	        prevProgress,
34278	        prevScroll,
34279	        prevAnimProgress,
34280	        caMarkerSetter;
34281
34282	    self.media = _creatingMedia;
34283	    anticipatePin *= 45;
34284	    self.scroller = scroller;
34285	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
34286	    scroll1 = scrollFunc();
34287	    self.vars = vars;
34288	    animation = animation || vars.animation;
34289	    "refreshPriority" in vars && (_sort = 1);
34290	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
34291	      top: _getTweenCreator(scroller, _vertical),
34292	      left: _getTweenCreator(scroller, _horizontal)
34293	    };
34294	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
34295
34296	    if (animation) {
34297	      animation.vars.lazy = false;
34298	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
34299	      self.animation = animation.pause();
34300	      animation.scrollTrigger = self;
34301	      scrubSmooth = _isNumber(scrub) && scrub;
34302	      scrubSmooth && (scrubTween = gsap.to(animation, {
34303	        ease: "power3",
34304	        duration: scrubSmooth,
34305	        onComplete: function onComplete() {
34306	          return onScrubComplete && onScrubComplete(self);
34307	        }
34308	      }));
34309	      snap1 = 0;
34310	      id || (id = animation.vars.id);
34311	    }
34312
34313	    _triggers.push(self);
34314
34315	    if (snap) {
34316	      if (!_isObject(snap) || snap.push) {
34317	        snap = {
34318	          snapTo: snap
34319	        };
34320	      }
34321
34322	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
34323	        scrollBehavior: "auto"
34324	      });
34325	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
34326	        return _snapDirectional(snap.snapTo)(value, st.direction);
34327	      } : gsap.utils.snap(snap.snapTo);
34328	      snapDurClamp = snap.duration || {
34329	        min: 0.1,
34330	        max: 2
34331	      };
34332	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
34333	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
34334	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
34335	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
34336	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
34337	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
34338	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
34339	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
34340	              scroll = scrollFunc(),
34341	              endScroll = Math.round(start + endValue * change),
34342	              _snap = snap,
34343	              onStart = _snap.onStart,
34344	              _onInterrupt = _snap.onInterrupt,
34345	              _onComplete = _snap.onComplete,
34346	              tween = tweenTo.tween;
34347
34348	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
34349	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
34350	              return;
34351	            }
34352
34353	            if (snap.inertia === false) {
34354	              change1 = endValue - self.progress;
34355	            }
34356
34357	            tweenTo(endScroll, {
34358	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
34359	              ease: snap.ease || "power3",
34360	              data: _abs(endScroll - scroll),
34361	              onInterrupt: function onInterrupt() {
34362	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
34363	              },
34364	              onComplete: function onComplete() {
34365	                lastSnap = scrollFunc();
34366	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
34367	                onSnapComplete && onSnapComplete(self);
34368	                _onComplete && _onComplete(self);
34369	              }
34370	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
34371	            onStart && onStart(self, tweenTo.tween);
34372	          }
34373	        } else if (self.isActive) {
34374	          snapDelayedCall.restart(true);
34375	        }
34376	      }).pause();
34377	    }
34378
34379	    id && (_ids[id] = self);
34380	    trigger = self.trigger = _getTarget(trigger || pin);
34381	    pin = pin === true ? trigger : _getTarget(pin);
34382	    _isString(toggleClass) && (toggleClass = {
34383	      targets: trigger,
34384	      className: toggleClass
34385	    });
34386
34387	    if (pin) {
34388	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
34389	      self.pin = pin;
34390	      vars.force3D !== false && gsap.set(pin, {
34391	        force3D: true
34392	      });
34393	      pinCache = gsap.core.getCache(pin);
34394
34395	      if (!pinCache.spacer) {
34396	        if (pinSpacer) {
34397	          pinSpacer = _getTarget(pinSpacer);
34398	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
34399	          pinCache.spacerIsNative = !!pinSpacer;
34400	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
34401	        }
34402
34403	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
34404	        spacer.classList.add("pin-spacer");
34405	        id && spacer.classList.add("pin-spacer-" + id);
34406	        pinCache.pinState = pinOriginalState = _getState(pin);
34407	      } else {
34408	        pinOriginalState = pinCache.pinState;
34409	      }
34410
34411	      self.spacer = spacer = pinCache.spacer;
34412	      cs = _getComputedStyle(pin);
34413	      spacingStart = cs[pinSpacing + direction.os2];
34414	      pinGetter = gsap.getProperty(pin);
34415	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
34416
34417	      _swapPinIn(pin, spacer, cs);
34418
34419	      pinState = _getState(pin);
34420	    }
34421
34422	    if (markers) {
34423	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
34424	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
34425	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
34426	      offset = markerStartTrigger["offset" + direction.op.d2];
34427	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
34428	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
34429	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
34430
34431	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
34432	        _makePositionable(isViewport ? _body : scroller);
34433
34434	        gsap.set([markerStartTrigger, markerEndTrigger], {
34435	          force3D: true
34436	        });
34437	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
34438	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
34439	      }
34440	    }
34441
34442	    if (containerAnimation) {
34443	      var oldOnUpdate = containerAnimation.vars.onUpdate,
34444	          oldParams = containerAnimation.vars.onUpdateParams;
34445	      containerAnimation.eventCallback("onUpdate", function () {
34446	        self.update(0, 0, 1);
34447	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
34448	      });
34449	    }
34450
34451	    self.previous = function () {
34452	      return _triggers[_triggers.indexOf(self) - 1];
34453	    };
34454
34455	    self.next = function () {
34456	      return _triggers[_triggers.indexOf(self) + 1];
34457	    };
34458
34459	    self.revert = function (revert) {
34460	      var r = revert !== false || !self.enabled,
34461	          prevRefreshing = _refreshing;
34462
34463	      if (r !== self.isReverted) {
34464	        if (r) {
34465	          self.scroll.rec || (self.scroll.rec = scrollFunc());
34466	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
34467	          prevProgress = self.progress;
34468	          prevAnimProgress = animation && animation.progress();
34469	        }
34470
34471	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
34472	          return m.style.display = r ? "none" : "block";
34473	        });
34474	        r && (_refreshing = 1);
34475	        self.update(r);
34476	        _refreshing = prevRefreshing;
34477	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
34478	        self.isReverted = r;
34479	      }
34480	    };
34481
34482	    self.refresh = function (soft, force) {
34483	      if ((_refreshing || !self.enabled) && !force) {
34484	        return;
34485	      }
34486
34487	      if (pin && soft && _lastScrollTime) {
34488	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34489
34490	        return;
34491	      }
34492
34493	      _refreshing = 1;
34494	      scrubTween && scrubTween.pause();
34495	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
34496	      self.isReverted || self.revert();
34497
34498	      var size = getScrollerSize(),
34499	          scrollerBounds = getScrollerOffsets(),
34500	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
34501	          offset = 0,
34502	          otherPinOffset = 0,
34503	          parsedEnd = vars.end,
34504	          parsedEndTrigger = vars.endTrigger || trigger,
34505	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
34506	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
34507	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
34508	          i = triggerIndex,
34509	          cs,
34510	          bounds,
34511	          scroll,
34512	          isVertical,
34513	          override,
34514	          curTrigger,
34515	          curPin,
34516	          oppositeScroll,
34517	          initted,
34518	          revertedPins;
34519
34520	      while (i--) {
34521	        curTrigger = _triggers[i];
34522	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
34523	        curPin = curTrigger.pin;
34524
34525	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
34526	          revertedPins || (revertedPins = []);
34527	          revertedPins.unshift(curTrigger);
34528	          curTrigger.revert();
34529	        }
34530	      }
34531
34532	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
34533	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
34534	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
34535
34536	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
34537	        if (~parsedEnd.indexOf(" ")) {
34538	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
34539	        } else {
34540	          offset = _offsetToPx(parsedEnd.substr(2), size);
34541	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
34542	          parsedEndTrigger = trigger;
34543	        }
34544	      }
34545
34546	      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;
34547	      change = end - start || (start -= 0.01) && 0.001;
34548	      offset = 0;
34549	      i = triggerIndex;
34550
34551	      while (i--) {
34552	        curTrigger = _triggers[i];
34553	        curPin = curTrigger.pin;
34554
34555	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
34556	          cs = curTrigger.end - curTrigger.start;
34557	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
34558	          curPin === pin && (otherPinOffset += cs);
34559	        }
34560	      }
34561
34562	      start += offset;
34563	      end += offset;
34564	      self._pinPush = otherPinOffset;
34565
34566	      if (markerStart && offset) {
34567	        cs = {};
34568	        cs[direction.a] = "+=" + offset;
34569	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
34570	        gsap.set([markerStart, markerEnd], cs);
34571	      }
34572
34573	      if (pin) {
34574	        cs = _getComputedStyle(pin);
34575	        isVertical = direction === _vertical;
34576	        scroll = scrollFunc();
34577	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
34578	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
34579
34580	        _swapPinIn(pin, spacer, cs);
34581
34582	        pinState = _getState(pin);
34583	        bounds = _getBounds(pin, true);
34584	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
34585
34586	        if (pinSpacing) {
34587	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
34588	          spacerState.t = spacer;
34589	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
34590	          i && spacerState.push(direction.d, i + _px);
34591
34592	          _setState(spacerState);
34593
34594	          useFixedPosition && scrollFunc(prevScroll);
34595	        }
34596
34597	        if (useFixedPosition) {
34598	          override = {
34599	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
34600	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
34601	            boxSizing: "border-box",
34602	            position: "fixed"
34603	          };
34604	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
34605	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
34606	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
34607	          override[_padding] = cs[_padding];
34608	          override[_padding + _Top] = cs[_padding + _Top];
34609	          override[_padding + _Right] = cs[_padding + _Right];
34610	          override[_padding + _Bottom] = cs[_padding + _Bottom];
34611	          override[_padding + _Left] = cs[_padding + _Left];
34612	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
34613	        }
34614
34615	        if (animation) {
34616	          initted = animation._initted;
34617
34618	          _suppressOverwrites(1);
34619
34620	          animation.render(animation.duration(), true, true);
34621	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
34622	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
34623	          animation.render(0, true, true);
34624	          initted || animation.invalidate();
34625
34626	          _suppressOverwrites(0);
34627	        } else {
34628	          pinChange = change;
34629	        }
34630	      } else if (trigger && scrollFunc() && !containerAnimation) {
34631	        bounds = trigger.parentNode;
34632
34633	        while (bounds && bounds !== _body) {
34634	          if (bounds._pinOffset) {
34635	            start -= bounds._pinOffset;
34636	            end -= bounds._pinOffset;
34637	          }
34638
34639	          bounds = bounds.parentNode;
34640	        }
34641	      }
34642
34643	      revertedPins && revertedPins.forEach(function (t) {
34644	        return t.revert(false);
34645	      });
34646	      self.start = start;
34647	      self.end = end;
34648	      scroll1 = scroll2 = scrollFunc();
34649
34650	      if (!containerAnimation) {
34651	        scroll1 < prevScroll && scrollFunc(prevScroll);
34652	        self.scroll.rec = 0;
34653	      }
34654
34655	      self.revert(false);
34656	      _refreshing = 0;
34657	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
34658
34659	      if (prevProgress !== self.progress) {
34660	        animation && !isToggle && animation.totalProgress(prevProgress, true);
34661	        self.progress = prevProgress;
34662	        self.update(0, 0, 1);
34663	      }
34664
34665	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
34666	      onRefresh && onRefresh(self);
34667	    };
34668
34669	    self.getVelocity = function () {
34670	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
34671	    };
34672
34673	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 34674-34912
34674	      _endAnimation(self.callbackAnimation);
34675
34676	      if (animation) {
34677	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
34678	      }
34679	    };
34680
34681	    self.getTrailing = function (name) {
34682	      var i = _triggers.indexOf(self),
34683	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
34684
34685	      return _isString(name) ? a.filter(function (t) {
34686	        return t.vars.preventOverlaps === name;
34687	      }) : a;
34688	    };
34689
34690	    self.update = function (reset, recordVelocity, forceFake) {
34691	      if (containerAnimation && !forceFake && !reset) {
34692	        return;
34693	      }
34694
34695	      var scroll = self.scroll(),
34696	          p = reset ? 0 : (scroll - start) / change,
34697	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
34698	          prevProgress = self.progress,
34699	          isActive,
34700	          wasActive,
34701	          toggleState,
34702	          action,
34703	          stateChanged,
34704	          toggled,
34705	          isAtMax,
34706	          isTakingAction;
34707
34708	      if (recordVelocity) {
34709	        scroll2 = scroll1;
34710	        scroll1 = containerAnimation ? scrollFunc() : scroll;
34711
34712	        if (snap) {
34713	          snap2 = snap1;
34714	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
34715	        }
34716	      }
34717
34718	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
34719
34720	      if (clipped !== prevProgress && self.enabled) {
34721	        isActive = self.isActive = !!clipped && clipped < 1;
34722	        wasActive = !!prevProgress && prevProgress < 1;
34723	        toggled = isActive !== wasActive;
34724	        stateChanged = toggled || !!clipped !== !!prevProgress;
34725	        self.direction = clipped > prevProgress ? 1 : -1;
34726	        self.progress = clipped;
34727
34728	        if (stateChanged && !_refreshing) {
34729	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
34730
34731	          if (isToggle) {
34732	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
34733	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
34734	          }
34735	        }
34736
34737	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
34738	          return t.endAnimation();
34739	        }));
34740
34741	        if (!isToggle) {
34742	          if (scrubTween && !_refreshing && !_startup) {
34743	            scrubTween.vars.totalProgress = clipped;
34744	            scrubTween.invalidate().restart();
34745	          } else if (animation) {
34746	            animation.totalProgress(clipped, !!_refreshing);
34747	          }
34748	        }
34749
34750	        if (pin) {
34751	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
34752
34753	          if (!useFixedPosition) {
34754	            pinSetter(pinStart + pinChange * clipped);
34755	          } else if (stateChanged) {
34756	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
34757
34758	            if (pinReparent) {
34759	              if (!reset && (isActive || isAtMax)) {
34760	                var bounds = _getBounds(pin, true),
34761	                    _offset = scroll - start;
34762
34763	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
34764	              } else {
34765	                _reparent(pin, spacer);
34766	              }
34767	            }
34768
34769	            _setState(isActive || isAtMax ? pinActiveState : pinState);
34770
34771	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
34772	          }
34773	        }
34774
34775	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
34776	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
34777	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
34778	        });
34779	        onUpdate && !isToggle && !reset && onUpdate(self);
34780
34781	        if (stateChanged && !_refreshing) {
34782	          if (isToggle) {
34783	            if (isTakingAction) {
34784	              if (action === "complete") {
34785	                animation.pause().totalProgress(1);
34786	              } else if (action === "reset") {
34787	                animation.restart(true).pause();
34788	              } else if (action === "restart") {
34789	                animation.restart(true);
34790	              } else {
34791	                animation[action]();
34792	              }
34793	            }
34794
34795	            onUpdate && onUpdate(self);
34796	          }
34797
34798	          if (toggled || !_limitCallbacks) {
34799	            onToggle && toggled && _callback(self, onToggle);
34800	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
34801	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
34802
34803	            if (!toggled) {
34804	              toggleState = clipped === 1 ? 1 : 3;
34805	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
34806	            }
34807	          }
34808
34809	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
34810	            _endAnimation(self.callbackAnimation);
34811
34812	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
34813	          }
34814	        } else if (isToggle && onUpdate && !_refreshing) {
34815	          onUpdate(self);
34816	        }
34817	      }
34818
34819	      if (markerEndSetter) {
34820	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
34821	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
34822	        markerEndSetter(n);
34823	      }
34824
34825	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
34826	    };
34827
34828	    self.enable = function (reset, refresh) {
34829	      if (!self.enabled) {
34830	        self.enabled = true;
34831
34832	        _addListener(scroller, "resize", _onResize);
34833
34834	        _addListener(scroller, "scroll", _onScroll);
34835
34836	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
34837
34838	        if (reset !== false) {
34839	          self.progress = prevProgress = 0;
34840	          scroll1 = scroll2 = lastSnap = scrollFunc();
34841	        }
34842
34843	        refresh !== false && self.refresh();
34844	      }
34845	    };
34846
34847	    self.getTween = function (snap) {
34848	      return snap && tweenTo ? tweenTo.tween : scrubTween;
34849	    };
34850
34851	    self.disable = function (reset, allowAnimation) {
34852	      if (self.enabled) {
34853	        reset !== false && self.revert();
34854	        self.enabled = self.isActive = false;
34855	        allowAnimation || scrubTween && scrubTween.pause();
34856	        prevScroll = 0;
34857	        pinCache && (pinCache.uncache = 1);
34858	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
34859
34860	        if (snapDelayedCall) {
34861	          snapDelayedCall.pause();
34862	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
34863	        }
34864
34865	        if (!isViewport) {
34866	          var i = _triggers.length;
34867
34868	          while (i--) {
34869	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
34870	              return;
34871	            }
34872	          }
34873
34874	          _removeListener(scroller, "resize", _onResize);
34875
34876	          _removeListener(scroller, "scroll", _onScroll);
34877	        }
34878	      }
34879	    };
34880
34881	    self.kill = function (revert, allowAnimation) {
34882	      self.disable(revert, allowAnimation);
34883	      scrubTween && scrubTween.kill();
34884	      id && delete _ids[id];
34885
34886	      var i = _triggers.indexOf(self);
34887
34888	      _triggers.splice(i, 1);
34889
34890	      i === _i && _direction > 0 && _i--;
34891	      i = 0;
34892
34893	      _triggers.forEach(function (t) {
34894	        return t.scroller === self.scroller && (i = 1);
34895	      });
34896
34897	      i || (self.scroll.rec = 0);
34898
34899	      if (animation) {
34900	        animation.scrollTrigger = null;
34901	        revert && animation.render(-1);
34902	        allowAnimation || animation.kill();
34903	      }
34904
34905	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
34906	        return m.parentNode && m.parentNode.removeChild(m);
34907	      });
34908
34909	      if (pin) {
34910	        pinCache && (pinCache.uncache = 1);
34911	        i = 0;
34912
34913	        _triggers.forEach(function (t) {
34914	          return t.pin === pin && i++;
34915	        });
34916
34917	        i || (pinCache.spacer = 0);
34918	      }
34919	    };
34920
34921	    self.enable(false, false);
34922	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
34923	      return start || end || self.refresh();
34924	    }) && (change = 0.01) && (start = end = 0);
34925	  };
34926
34927	  ScrollTrigger.register = function register(core) {
34928	    if (!_coreInitted) {
34929	      gsap = core || _getGSAP();
34930
34931	      if (_windowExists() && window.document) {
34932	        _win = window;
34933	        _doc = document;
34934	        _docEl = _doc.documentElement;
34935	        _body = _doc.body;
34936	      }
34937
34938	      if (gsap) {
34939	        _toArray = gsap.utils.toArray;
34940	        _clamp = gsap.utils.clamp;
34941	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
34942	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
34943
34944	        if (_body) {
34945	          _raf = _win.requestAnimationFrame || function (f) {
34946	            return setTimeout(f, 16);
34947	          };
34948
34949	          _addListener(_win, "wheel", _onScroll);
34950
34951	          _root = [_win, _doc, _docEl, _body];
34952
34953	          _addListener(_doc, "scroll", _onScroll);
34954
34955	          var bodyStyle = _body.style,
34956	              border = bodyStyle.borderTopStyle,
34957	              bounds;
34958	          bodyStyle.borderTopStyle = "solid";
34959	          bounds = _getBounds(_body);
34960	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
34961	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
34962	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
34963	          _syncInterval = setInterval(_sync, 200);
34964	          gsap.delayedCall(0.5, function () {
34965	            return _startup = 0;
34966	          });
34967
34968	          _addListener(_doc, "touchcancel", _passThrough);
34969
34970	          _addListener(_body, "touchstart", _passThrough);
34971
34972	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
34973	            return _pointerIsDown = 1;
34974	          });
34975
34976	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
34977	            return _pointerIsDown = 0;
34978	          });
34979
34980	          _transformProp = gsap.utils.checkPrefix("transform");
34981
34982	          _stateProps.push(_transformProp);
34983
34984	          _coreInitted = _getTime();
34985	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
34986	          _autoRefresh = [_doc, "visibilitychange", function () {
34987	            var w = _win.innerWidth,
34988	                h = _win.innerHeight;
34989
34990	            if (_doc.hidden) {
34991	              _prevWidth = w;
34992	              _prevHeight = h;
34993	            } else if (_prevWidth !== w || _prevHeight !== h) {
34994	              _onResize();
34995	            }
34996	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
34997	            return _lastScrollTime || _refreshAll();
34998	          }, _win, "resize", _onResize];
34999
35000	          _iterateAutoRefresh(_addListener);
35001	        }
35002	      }
35003	    }
35004
35005	    return _coreInitted;
35006	  };
35007
35008	  ScrollTrigger.defaults = function defaults(config) {
35009	    for (var p in config) {
35010	      _defaults[p] = config[p];
35011	    }
35012	  };
35013
35014	  ScrollTrigger.kill = function kill() {
35015	    _enabled = 0;
35016
35017	    _triggers.slice(0).forEach(function (trigger) {
35018	      return trigger.kill(1);
35019	    });
35020	  };
35021
35022	  ScrollTrigger.config = function config(vars) {
35023	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35024	    var ms = vars.syncInterval;
35025	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35026
35027	    if ("autoRefreshEvents" in vars) {
35028	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35029	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35030	    }
35031	  };
35032
35033	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35034	    var t = _getTarget(target),
35035	        i = _scrollers.indexOf(t),
35036	        isViewport = _isViewport(t);
35037
35038	    if (~i) {
35039	      _scrollers.splice(i, isViewport ? 6 : 2);
35040	    }
35041
35042	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35043	  };
35044
35045	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35046	    var mq, p, i, func, result;
35047
35048	    for (p in vars) {
35049	      i = _media.indexOf(p);
35050	      func = vars[p];
35051	      _creatingMedia = p;
35052
35053	      if (p === "all") {
35054	        func();
35055	      } else {
35056	        mq = _win.matchMedia(p);
35057
35058	        if (mq) {
35059	          mq.matches && (result = func());
35060
35061	          if (~i) {
35062	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35063	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35064	          } else {
35065	            i = _media.length;
35066
35067	            _media.push(p, func, result);
35068
35069	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35070	          }
35071
35072	          _media[i + 3] = mq.matches;
35073	        }
35074	      }
35075
35076	      _creatingMedia = 0;
35077	    }
35078
35079	    return _media;
35080	  };
35081
35082	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
35083	    query || (_media.length = 0);
35084	    query = _media.indexOf(query);
35085	    query >= 0 && _media.splice(query, 4);
35086	  };
35087
35088	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
35089	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
35090	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
35091	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
35092	  };
35093
35094	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
35095	    _isString(element) && (element = _getTarget(element));
35096	    var bounds = element.getBoundingClientRect(),
35097	        size = bounds[horizontal ? _width : _height],
35098	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
35099	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
35100	  };
35101
35102	  return ScrollTrigger;
35103	}();
35104	ScrollTrigger.version = "3.8.0";
35105
35106	ScrollTrigger.saveStyles = function (targets) {
35107	  return targets ? _toArray(targets).forEach(function (target) {
35108	    if (target && target.style) {
35109	      var i = _savedStyles.indexOf(target);
35110
35111	      i >= 0 && _savedStyles.splice(i, 5);
35112
35113	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
35114	    }
35115	  }) : _savedStyles;
35116	};
35117
35118	ScrollTrigger.revert = function (soft, media) {
35119	  return _revertAll(!soft, media);
35120	};
35121
35122	ScrollTrigger.create = function (vars, animation) {
35123	  return new ScrollTrigger(vars, animation);
35124	};
35125
35126	ScrollTrigger.refresh = function (safe) {
35127	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
35128	};
35129
35130	ScrollTrigger.update = _updateAll;
35131	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
35132
35133	ScrollTrigger.maxScroll = function (element, horizontal) {
35134	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
35135	};
35136
35137	ScrollTrigger.getScrollFunc = function (element, horizontal) {
35138	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
35139	};
35140
35141	ScrollTrigger.getById = function (id) {
35142	  return _ids[id];
35143	};
35144
35145	ScrollTrigger.getAll = function () {
35146	  return _triggers.slice(0);
35147	};
35148
35149	ScrollTrigger.isScrolling = function () {
35150	  return !!_lastScrollTime;
35151	};
35152
35153	ScrollTrigger.snapDirectional = _snapDirectional;
35154
35155	ScrollTrigger.addEventListener = function (type, callback) {
35156	  var a = _listeners[type] || (_listeners[type] = []);
35157	  ~a.indexOf(callback) || a.push(callback);
35158	};
35159
35160	ScrollTrigger.removeEventListener = function (type, callback) {
35161	  var a = _listeners[type],
35162	      i = a && a.indexOf(callback);
35163	  i >= 0 && a.splice(i, 1);
35164	};
35165
35166	ScrollTrigger.batch = function (targets, vars) {
35167	  var result = [],
35168	      varsCopy = {},
35169	      interval = vars.interval || 0.016,
35170	      batchMax = vars.batchMax || 1e9,
35171	      proxyCallback = function proxyCallback(type, callback) {
35172	    var elements = [],
35173	        triggers = [],
35174	        delay = gsap.delayedCall(interval, function () {
35175	      callback(elements, triggers);
35176	      elements = [];
35177	      triggers = [];
35178	    }).pause();
35179	    return function (self) {
35180	      elements.length || delay.restart(true);
35181	      elements.push(self.trigger);
35182	      triggers.push(self);
35183	      batchMax <= elements.length && delay.progress(1);
35184	    };
35185	  },
35186	      p;
35187
35188	  for (p in vars) {
35189	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
35190	  }
35191
35192	  if (_isFunction(batchMax)) {
35193	    batchMax = batchMax();
35194
35195	    _addListener(ScrollTrigger, "refresh", function () {
35196	      return batchMax = vars.batchMax();
35197	    });
35198	  }
35199
35200	  _toArray(targets).forEach(function (target) {
35201	    var config = {};
35202
35203	    for (p in varsCopy) {
35204	      config[p] = varsCopy[p];
35205	    }
35206
35207	    config.trigger = target;
35208	    result.push(ScrollTrigger.create(config));
35209	  });
35210
35211	  return result;
35212	};
35213
35214	ScrollTrigger.sort = function (func) {
35215	  return _triggers.sort(func || function (a, b) {
35216	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
35217	  });
35218	};
35219
35220	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
35221
35222	exports.ScrollTrigger = ScrollTrigger;
35223	exports.default = ScrollTrigger;
35224
35225	Object.defineProperty(exports, '__esModule', { value: true });
35226
35227})));
35228
35229/* ========================================================================
35230 * Bootstrap: collapse.js v3.1.1
35231 * http://getbootstrap.com/javascript/#collapse
35232 * ========================================================================
35233 * Copyright 2011-2014 Twitter, Inc.
35234 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35235 * ======================================================================== */
35236
35237
35238+function ($) {
35239	'use strict';
35240
35241	// COLLAPSE PUBLIC CLASS DEFINITION
35242	// ================================
35243
35244	var Collapse = function (element, options) {
35245		this.$element      = $(element)
35246		this.options       = $.extend({}, Collapse.DEFAULTS, options)
35247		this.transitioning = null
35248
35249		if (this.options.parent) this.$parent = $(this.options.parent)
35250		if (this.options.toggle) this.toggle()
35251	}
35252
35253	Collapse.DEFAULTS = {
35254		toggle: true
35255	}
35256
35257	Collapse.prototype.dimension = function () {
35258		var hasWidth = this.$element.hasClass('width')
35259		return hasWidth ? 'width' : 'height'
35260	}
35261
35262	Collapse.prototype.show = function () {
35263		if (this.transitioning || this.$element.hasClass('in')) return
35264
35265		var startEvent = $.Event('show.bs.collapse')
35266		this.$element.trigger(startEvent)
35267		if (startEvent.isDefaultPrevented()) return
35268
35269		var actives = this.$parent && this.$parent.find('> .panel > .in')
35270
35271		if (actives && actives.length) {
35272			var hasData = actives.data('bs.collapse')
35273			if (hasData && hasData.transitioning) return
35274			actives.collapse('hide')
35275			hasData || actives.data('bs.collapse', null)
35276		}
35277
35278		var dimension = this.dimension()
35279
35280		this.$element
35281			.removeClass('collapse')
35282			.addClass('collapsing')[dimension](0)
35283
35284		this.transitioning = 1
35285
35286		var complete = function (e) {
35287			if (e && e.target != this.$element[0]) return
35288			this.$element
35289				.removeClass('collapsing')
35290				.addClass('collapse in')[dimension]('auto')
35291			this.transitioning = 0
35292			this.$element.trigger('shown.bs.collapse')
35293		}
35294
35295		if (!$.support.transition) return complete.call(this)
35296
35297		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
35298
35299		this.$element
35300			.one($.support.transition.end, $.proxy(complete, this))
35301			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
35302	}
35303
35304	Collapse.prototype.hide = function () {
35305		if (this.transitioning || !this.$element.hasClass('in')) return
35306
35307		var startEvent = $.Event('hide.bs.collapse')
35308		this.$element.trigger(startEvent)
35309		if (startEvent.isDefaultPrevented()) return
35310
35311		var dimension = this.dimension()
35312
35313		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
35314
35315		this.$element
35316			.addClass('collapsing')
35317			.removeClass('collapse')
35318			.removeClass('in')
35319
35320		this.transitioning = 1
35321
35322		var complete = function (e) {
35323			if (e && e.target != this.$element[0]) return
35324			this.transitioning = 0
35325			this.$element
35326				.trigger('hidden.bs.collapse')
35327				.removeClass('collapsing')
35328				.addClass('collapse')
35329		}
35330
35331		if (!$.support.transition) return complete.call(this)
35332
35333		this.$element
35334			[dimension](0)
35335			.one($.support.transition.end, $.proxy(complete, this))
35336			.emulateTransitionEnd(350)
35337	}
35338
35339	Collapse.prototype.toggle = function () {
35340		this[this.$element.hasClass('in') ? 'hide' : 'show']()
35341	}
35342
35343
35344	// COLLAPSE PLUGIN DEFINITION
35345	// ==========================
35346
35347	var old = $.fn.collapse
35348
35349	$.fn.collapse = function (option) {
35350		return this.each(function () {
35351			var $this   = $(this)
35352			var data    = $this.data('bs.collapse')
35353			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
35354
35355			if (!data && options.toggle && option == 'show') option = !option
35356			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
35357			if (typeof option == 'string') data[option]()
35358		})
35359	}
35360
35361	$.fn.collapse.Constructor = Collapse
35362
35363
35364	// COLLAPSE NO CONFLICT
35365	// ====================
35366
35367	$.fn.collapse.noConflict = function () {
35368		$.fn.collapse = old
35369		return this
35370	}
35371
35372
35373	// COLLAPSE DATA-API
35374	// =================
35375
35376	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
35377		var $this   = $(this), href
35378		var target  = $this.attr('data-target')
35379				|| e.preventDefault()
35380				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
35381		//Edited by Uncode to replace ID in panel [START]
35382		var _target = href.replace(/^#/, "");
35383		if ( $('[data-id="' + _target + '"]').length ) {
35384			var $target = $('[data-id="' + _target + '"]')
35385		} else {
35386			var $target = $(target)
35387		}
35388		//Edited by Uncode to replace ID in panel [END]
35389		var data    = $target.data('bs.collapse')
35390		var option  = data ? 'toggle' : $this.data()
35391		var parent  = $this.attr('data-parent')
35392		var $parent = parent && $(parent)
35393
35394		if (!data || !data.transitioning) {
35395			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
35396			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
35397		}
35398
35399		$target.collapse(option)
35400	})
35401
35402}(jQuery);
35403
35404/* ========================================================================
35405 * Bootstrap: tab.js v3.1.1
35406 * http://getbootstrap.com/javascript/#tabs
35407 * ========================================================================
35408 * Copyright 2011-2014 Twitter, Inc.
35409 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35410 * ======================================================================== */
35411
35412
35413+function ($) {
35414  'use strict';
35415
35416  // TAB CLASS DEFINITION
35417  // ====================
35418
35419  var Tab = function (element) {
35420    this.element = $(element)
35421  }
35422
35423  Tab.prototype.show = function () {
35424    var $this    = this.element
35425    var $ul      = $this.closest('ul:not(.dropdown-menu)')
35426    var selector = $this.data('target')
35427
35428    if (!selector) {
35429      selector = $this.attr('href')
35430      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
35431    }
35432
35433    if ($this.parent('li').hasClass('active')) return
35434
35435    var previous = $ul.find('.active:last a')[0]
35436    var e        = $.Event('show.bs.tab', {
35437      relatedTarget: previous
35438    })
35439
35440    $this.trigger(e)
35441
35442    if (e.isDefaultPrevented()) return
35443
35444    //Edited by Uncode to replace ID in panel [START]
35445    var _target = selector.replace(/^#/, "");
35446    if ( $('[data-id="' + _target + '"]').length )
35447      var $target = $('[data-id="' + _target + '"]')
35448    else
35449      var $target = $(selector)
35450    //Edited by Uncode to replace ID in panel [END]
35451
35452    this.activate($this.parent('li'), $ul)
35453    this.activate($target, $target.parent(), function () {
35454      $this.trigger({
35455        type: 'shown.bs.tab',
35456        relatedTarget: previous
35457      })
35458    })
35459  }
35460
35461  Tab.prototype.activate = function (element, container, callback) {
35462    var $active    = container.find('> .active')
35463    var transition = callback
35464      && $.support.transition
35465      && $active.hasClass('fade')
35466
35467    function next() {
35468      $active
35469        .removeClass('active')
35470        .find('> .dropdown-menu > .active')
35471        .removeClass('active')
35472
35473      element.addClass('active')
35474
35475      if (transition) {
35476        element[0].offsetWidth // reflow for transition
35477        element.addClass('in')
35478      } else {
35479        element.removeClass('fade')
35480      }
35481
35482      if (element.parent('.dropdown-menu')) {
35483        element.closest('li.dropdown').addClass('active')
35484      }
35485
35486      callback && callback()
35487    }
35488
35489    transition ?
35490      $active
35491        .one($.support.transition.end, next)
35492        .emulateTransitionEnd(150) :
35493      next()
35494
35495    $active.removeClass('in')
35496  }
35497
35498
35499  // TAB PLUGIN DEFINITION
35500  // =====================
35501
35502  var old = $.fn.tab
35503
35504  $.fn.tab = function ( option ) {
35505    return this.each(function () {
35506      var $this = $(this)
35507      var data  = $this.data('bs.tab')
35508
35509      if (!data) $this.data('bs.tab', (data = new Tab(this)))
35510      if (typeof option == 'string') data[option]()
35511    })
35512  }
35513
35514  $.fn.tab.Constructor = Tab
35515
35516
35517  // TAB NO CONFLICT
35518  // ===============
35519
35520  $.fn.tab.noConflict = function () {
35521    $.fn.tab = old
35522    return this
35523  }
35524
35525
35526  // TAB DATA-API
35527  // ============
35528
35529  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
35530    e.preventDefault()
35531    $(this).tab('show')
35532  })
35533
35534}(jQuery);
35535
35536/* ========================================================================
35537 * Bootstrap: tooltip.js v3.1.1
35538 * http://getbootstrap.com/javascript/#tooltip
35539 * Inspired by the original jQuery.tipsy by Jason Frame
35540 * ========================================================================
35541 * Copyright 2011-2014 Twitter, Inc.
35542 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35543 * ======================================================================== */
35544
35545
35546+function ($) {
35547  'use strict';
35548
35549  // TOOLTIP PUBLIC CLASS DEFINITION
35550  // ===============================
35551
35552  var Tooltip = function (element, options) {
35553    this.type       =
35554    this.options    =
35555    this.enabled    =
35556    this.timeout    =
35557    this.hoverState =
35558    this.$element   = null
35559
35560    this.init('tooltip', element, options)
35561  }
35562
35563  Tooltip.DEFAULTS = {
35564    animation: true,
35565    placement: 'top',
35566    selector: false,
35567    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
35568    trigger: 'hover focus',
35569    title: '',
35570    delay: 0,
35571    html: false,
35572    container: false,
35573    viewport: {
35574      selector: 'body',
35575      padding: 0
35576    }
35577  }
35578
35579  Tooltip.prototype.init = function (type, element, options) {
35580    this.enabled   = true
35581    this.type      = type
35582    this.$element  = $(element)
35583    this.options   = this.getOptions(options)
35584    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
35585
35586    var triggers = this.options.trigger.split(' ')
35587
35588    for (var i = triggers.length; i--;) {
35589      var trigger = triggers[i]
35590
35591      if (trigger == 'click') {
35592        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
35593      } else if (trigger != 'manual') {
35594        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
35595        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
35596
35597        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
35598        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
35599      }
35600    }
35601
35602    this.options.selector ?
35603      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
35604      this.fixTitle()
35605  }
35606
35607  Tooltip.prototype.getDefaults = function () {
35608    return Tooltip.DEFAULTS
35609  }
35610
35611  Tooltip.prototype.getOptions = function (options) {
35612    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
35613
35614    if (options.delay && typeof options.delay == 'number') {
35615      options.delay = {
35616        show: options.delay,
35617        hide: options.delay
35618      }
35619    }
35620
35621    return options
35622  }
35623
35624  Tooltip.prototype.getDelegateOptions = function () {
35625    var options  = {}
35626    var defaults = this.getDefaults()
35627
35628    this._options && $.each(this._options, function (key, value) {
35629      if (defaults[key] != value) options[key] = value
35630    })
35631
35632    return options
35633  }
35634
35635  Tooltip.prototype.enter = function (obj) {
35636    var self = obj instanceof this.constructor ?
35637      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
35638
35639    clearTimeout(self.timeout)
35640
35641    self.hoverState = 'in'
35642
35643    if (!self.options.delay || !self.options.delay.show) return self.show()
35644
35645    self.timeout = setTimeout(function () {
35646      if (self.hoverState == 'in') self.show()
35647    }, self.options.delay.show)
35648  }
35649
35650  Tooltip.prototype.leave = function (obj) {
35651    var self = obj instanceof this.constructor ?
35652      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
35653
35654    clearTimeout(self.timeout)
35655
35656    self.hoverState = 'out'
35657
35658    if (!self.options.delay || !self.options.delay.hide) return self.hide()
35659
35660    self.timeout = setTimeout(function () {
35661      if (self.hoverState == 'out') self.hide()
35662    }, self.options.delay.hide)
35663  }
35664
35665  Tooltip.prototype.show = function () {
35666    var e = $.Event('show.bs.' + this.type)
35667
35668    if (this.hasContent() && this.enabled) {
35669      this.$element.trigger(e)
35670
35671      if (e.isDefaultPrevented()) return
35672      var that = this;
35673
35674      var $tip = this.tip()
35675
35676      this.setContent()
35677
35678      if (this.options.animation) $tip.addClass('fade')
35679
35680      var placement = typeof this.options.placement == 'function' ?
35681        this.options.placement.call(this, $tip[0], this.$element[0]) :
35682        this.options.placement
35683
35684      var autoToken = /\s?auto?\s?/i
35685      var autoPlace = autoToken.test(placement)
35686      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
35687
35688      $tip
35689        .detach()
35690        .css({ top: 0, left: 0, display: 'block' })
35691        .addClass(placement)
35692
35693      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
35694
35695      var pos          = this.getPosition()
35696      var actualWidth  = $tip[0].offsetWidth
35697      var act
35697ualHeight = $tip[0].offsetHeight
35698
35699      if (autoPlace) {
35700        var orgPlacement = placement
35701        var $parent      = this.$element.parent()
35702        var parentDim    = this.getPosition($parent)
35703
35704        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
35705                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
35706                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
35707                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
35708                    placement
35709
35710        $tip
35711          .removeClass(orgPlacement)
35712          .addClass(placement)
35713      }
35714
35715      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
35716
35717      this.applyPlacement(calculatedOffset, placement)
35718      this.hoverState = null
35719
35720      var complete = function() {
35721        that.$element.trigger('shown.bs.' + that.type)
35722      }
35723
35724      $.support.transition && this.$tip.hasClass('fade') ?
35725        $tip
35726          .one($.support.transition.end, complete)
35727          .emulateTransitionEnd(150) :
35728        complete()
35729    }
35730  }
35731
35732  Tooltip.prototype.applyPlacement = function (offset, placement) {
35733    var $tip   = this.tip()
35734    var width  = $tip[0].offsetWidth
35735    var height = $tip[0].offsetHeight
35736
35737    // manually read margins because getBoundingClientRect includes difference
35738    var marginTop = parseInt($tip.css('margin-top'), 10)
35739    var marginLeft = parseInt($tip.css('margin-left'), 10)
35740
35741    // we must check for NaN for ie 8/9
35742    if (isNaN(marginTop))  marginTop  = 0
35743    if (isNaN(marginLeft)) marginLeft = 0
35744
35745    offset.top  = offset.top  + marginTop
35746    offset.left = offset.left + marginLeft
35747
35748    // $.fn.offset doesn't round pixel values
35749    // so we use setOffset directly with our own function B-0
35750    $.offset.setOffset($tip[0], $.extend({
35751      using: function (props) {
35752        $tip.css({
35753          top: Math.round(props.top),
35754          left: Math.round(props.left)
35755        })
35756      }
35757    }, offset), 0)
35758
35759    $tip.addClass('in')
35760
35761    // check to see if placing tip in new offset caused the tip to resize itself
35762    var actualWidth  = $tip[0].offsetWidth
35763    var actualHeight = $tip[0].offsetHeight
35764
35765    if (placement == 'top' && actualHeight != height) {
35766      offset.top = offset.top + height - actualHeight
35767    }
35768
35769    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
35770
35771    if (delta.left) offset.left += delta.left
35772    else offset.top += delta.top
35773
35774    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
35775    var arrowPosition       = delta.left ? 'left'        : 'top'
35776    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
35777
35778    $tip.offset(offset)
35779    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
35780  }
35781
35782  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
35783    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
35784  }
35785
35786  Tooltip.prototype.setContent = function () {
35787    var $tip  = this.tip()
35788    var title = this.getTitle()
35789
35790    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
35791    $tip.removeClass('fade in top bottom left right')
35792  }
35793
35794  Tooltip.prototype.hide = function () {
35795    var that = this
35796    var $tip = this.tip()
35797    var e    = $.Event('hide.bs.' + this.type)
35798
35799    function complete() {
35800      if (that.hoverState != 'in') $tip.detach()
35801      that.$element.trigger('hidden.bs.' + that.type)
35802    }
35803
35804    this.$element.trigger(e)
35805
35806    if (e.isDefaultPrevented()) return
35807
35808    $tip.removeClass('in')
35809
35810    $.support.transition && this.$tip.hasClass('fade') ?
35811      $tip
35812        .one($.support.transition.end, complete)
35813        .emulateTransitionEnd(150) :
35814      complete()
35815
35816    this.hoverState = null
35817
35818    return this
35819  }
35820
35821  Tooltip.prototype.fixTitle = function () {
35822    var $e = this.$element
35823    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
35824      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
35825    }
35826  }
35827
35828  Tooltip.prototype.hasContent = function () {
35829    return this.getTitle()
35830  }
35831
35832  Tooltip.prototype.getPosition = function ($element) {
35833    $element   = $element || this.$element
35834    var el     = $element[0]
35835    var isBody = el.tagName == 'BODY'
35836    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
35837      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
35838      width:  isBody ? $(window).width()  : $element.outerWidth(),
35839      height: isBody ? $(window).height() : $element.outerHeight()
35840    }, isBody ? {top: 0, left: 0} : $element.offset())
35841  }
35842
35843  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
35844    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
35845           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
35846           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
35847        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
35848
35849  }
35850
35851  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
35852    var delta = { top: 0, left: 0 }
35853    if (!this.$viewport) return delta
35854
35855    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
35856    var viewportDimensions = this.getPosition(this.$viewport)
35857
35858    if (/right|left/.test(placement)) {
35859      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
35860      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
35861      if (topEdgeOffset < viewportDimensions.top) { // top overflow
35862        delta.top = viewportDimensions.top - topEdgeOffset
35863      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
35864        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
35864EdgeOffset
35865      }
35866    } else {
35867      var leftEdgeOffset  = pos.left - viewportPadding
35868      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
35869      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
35870        delta.left = viewportDimensions.left - leftEdgeOffset
35871      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
35872        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
35873      }
35874    }
35875
35876    return delta
35877  }
35878
35879  Tooltip.prototype.getTitle = function () {
35880    var title
35881    var $e = this.$element
35882    var o  = this.options
35883
35884    title = $e.attr('data-original-title')
35885      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
35886
35887    return title
35888  }
35889
35890  Tooltip.prototype.tip = function () {
35891    return this.$tip = this.$tip || $(this.options.template)
35892  }
35893
35894  Tooltip.prototype.arrow = function () {
35895    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
35896  }
35897
35898  Tooltip.prototype.validate = function () {
35899    if (!this.$element[0].parentNode) {
35900      this.hide()
35901      this.$element = null
35902      this.options  = null
35903    }
35904  }
35905
35906  Tooltip.prototype.enable = function () {
35907    this.enabled = true
35908  }
35909
35910  Tooltip.prototype.disable = function () {
35911    this.enabled = false
35912  }
35913
35914  Tooltip.prototype.toggleEnabled = function () {
35915    this.enabled = !this.enabled
35916  }
35917
35918  Tooltip.prototype.toggle = function (e) {
35919    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
35920    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
35921  }
35922
35923  Tooltip.prototype.destroy = function () {
35924    clearTimeout(this.timeout)
35925    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
35926  }
35927
35928
35929  // TOOLTIP PLUGIN DEFINITION
35930  // =========================
35931
35932  var old = $.fn.tooltip
35933
35934  $.fn.tooltip = function (option) {
35935    return this.each(function () {
35936      var $this   = $(this)
35937      var data    = $this.data('bs.tooltip')
35938      var options = typeof option == 'object' && option
35939
35940      if (!data && option == 'destroy') return
35941      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
35942      if (typeof option == 'string') data[option]()
35943    })
35944  }
35945
35946  $.fn.tooltip.Constructor = Tooltip
35947
35948
35949  // TOOLTIP NO CONFLICT
35950  // ===================
35951
35952  $.fn.tooltip.noConflict = function () {
35953    $.fn.tooltip = old
35954    return this
35955  }
35956
35957}(jQuery);
35958
35959/* ========================================================================
35960 * Bootstrap: transition.js v3.1.1
35961 * http://getbootstrap.com/javascript/#transitions
35962 * ========================================================================
35963 * Copyright 2011-2014 Twitter, Inc.
35964 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
35965 * ======================================================================== */
35966
35967
35968+function ($) {
35969  'use strict';
35970
35971  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
35972  // ============================================================
35973
35974  function transitionEnd() {
35975    var el = document.createElement('bootstrap')
35976
35977    var transEndEventNames = {
35978      WebkitTransition : 'webkitTransitionEnd',
35979      MozTransition    : 'transitionend',
35980      OTransition      : 'oTransitionEnd otransitionend',
35981      transition       : 'transitionend'
35982    }
35983
35984    for (var name in transEndEventNames) {
35985      if (el.style[name] !== undefined) {
35986        return { end: transEndEventNames[name] }
35987      }
35988    }
35989
35990    return false // explicit for ie8 (  ._.)
35991  }
35992
35993  // http://blog.alexmaccaw.com/css-transitions
35994  $.fn.emulateTransitionEnd = function (duration) {
35995    var called = false, $el = this
35996    $(this).one($.support.transition.end, function () { called = true })
35997    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
35998    setTimeout(callback, duration)
35999    return this
36000  }
36001
36002  $(function () {
36003    $.support.transition = transitionEnd()
36004  })
36005
36006}(jQuery);
36007
36008
36009// ------------------------------------------
36010// Rellax.js
36011// Buttery smooth parallax library
36012// Copyright (c) 2016 Moe Amaya (@moeamaya)
36013// MIT license
36014//
36015// Thanks to Paraxify.js and Jaime Cabllero
36016// for parallax concepts
36017// ------------------------------------------
36018
36019(function (root, factory) {
36020	if (typeof define === 'function' && define.amd) {
36021		// AMD. Register as an anonymous module.
36022		define([], factory);
36023	} else if (typeof module === 'object' && module.exports) {
36024		// Node. Does not work with strict CommonJS, but
36025		// only CommonJS-like environments that support module.exports,
36026		// like Node.
36027		module.exports = factory();
36028	} else {
36029		// Browser globals (root is window)
36030		root.Rellax = factory();
36031	}
36032}(typeof window !== "undefined" ? window : global, function () {
36033	var Rellax = function(el, options){
36034		"use strict";
36035
36036		var self = Object.create(Rellax.prototype);
36037
36038		var posY = 0;
36039		var screenY = 0;
36040		var posX = 0;
36041		var screenX = 0;
36042		var blocks = [];
36043		var pause = true;
36044
36045		// check what requestAnimationFrame to use, and if
36046		// it's not supported, use the onscroll event
36047		var loop = window.requestAnimationFrame ||
36048			window.webkitRequestAnimationFrame ||
36049			window.mozRequestAnimationFrame ||
36050			window.msRequestAnimationFrame ||
36051			window.oRequestAnimationFrame ||
36052			function(callback){ return setTimeout(callback, 1000 / 60); };
36053
36054		// store the id for later use
36055		var loopId = null;
36056
36057		// Test via a getter in the options object to see if the passive property is accessed
36058		var supportsPassive = false;
vendor: 10,724 bytes, lines 36059-36360
36059		try {
36060			var opts = Object.defineProperty({}, 'passive', {
36061				get: function() {
36062					supportsPassive = true;
36063				}
36064			});
36065			window.addEventListener("testPassive", null, opts);
36066			window.removeEventListener("testPassive", null, opts);
36067		} catch (e) {}
36068
36069		// check what cancelAnimation method to use
36070		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
36071
36072		// check which transform property to use
36073		var transformProp = window.transformProp || (function(){
36074				var testEl = document.createElement('div');
36075				if (testEl.style.transform === null) {
36076					var vendors = ['Webkit', 'Moz', 'ms'];
36077					for (var vendor in vendors) {
36078						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
36079							return vendors[vendor] + 'Transform';
36080						}
36081					}
36082				}
36083				return 'transform';
36084			})();
36085
36086		// Default Settings
36087		self.options = {
36088			speed: -2,
36089			verticalSpeed: null,
36090			horizontalSpeed: null,
36091			breakpoints: [576, 768, 1201],
36092			center: false,
36093			wrapper: null,
36094			relativeToWrapper: false,
36095			round: true,
36096			vertical: true,
36097			horizontal: false,
36098			verticalScrollAxis: "y",
36099			horizontalScrollAxis: "x",
36100			callback: function() {},
36101		};
36102
36103		// User defined options (might have more in the future)
36104		if (options){
36105			Object.keys(options).forEach(function(key){
36106				self.options[key] = options[key];
36107			});
36108		}
36109
36110		function validateCustomBreakpoints () {
36111			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
36112				var isAscending = true;
36113				var isNumerical = true;
36114				var lastVal;
36115				self.options.breakpoints.forEach(function (i) {
36116					if (typeof i !== 'number') isNumerical = false;
36117					if (lastVal !== null) {
36118						if (i < lastVal) isAscending = false;
36119					}
36120					lastVal = i;
36121				});
36122				if (isAscending && isNumerical) return;
36123			}
36124			// revert defaults if set incorrectly
36125			self.options.breakpoints = [576, 768, 1201];
36126			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
36127		}
36128
36129		if (options && options.breakpoints) {
36130			validateCustomBreakpoints();
36131		}
36132
36133		// By default, rellax class
36134		if (!el) {
36135			el = '.rellax';
36136		}
36137
36138		// check if el is a className or a node
36139		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
36140
36141		// Now query selector
36142		if (elements.length > 0) {
36143			self.elems = elements;
36144		}
36145
36146		// The elements don't exist
36147		else {
36148			console.warn("Rellax: The elements you're trying to select don't exist.");
36149			return;
36150		}
36151
36152		// Has a wrapper and it exists
36153		if (self.options.wrapper) {
36154			if (!self.options.wrapper.nodeType) {
36155				var wrapper = document.querySelector(self.options.wrapper);
36156
36157				if (wrapper) {
36158					self.options.wrapper = wrapper;
36159				} else {
36160					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
36161					return;
36162				}
36163			}
36164		}
36165
36166		// set a placeholder for the current breakpoint
36167		var currentBreakpoint;
36168
36169		// helper to determine current breakpoint
36170		var getCurrentBreakpoint = function (w) {
36171			var bp = self.options.breakpoints;
36172			if (w < bp[0]) return 'xs';
36173			if (w >= bp[0] && w < bp[1]) return 'sm';
36174			if (w >= bp[1] && w < bp[2]) return 'md';
36175			return 'lg';
36176		};
36177
36178		// Get and cache initial position of all elements
36179		var cacheBlocks = function() {
36180			for (var i = 0; i < self.elems.length; i++){
36181				var block = createBlock(self.elems[i]);
36182				blocks.push(block);
36183			}
36184		};
36185
36186
36187		// Let's kick this script off
36188		// Build array for cached element values
36189		var init = function() {
36190			for (var i = 0; i < blocks.length; i++){
36191				self.elems[i].style.cssText = blocks[i].style;
36192			}
36193
36194			blocks = [];
36195
36196			screenY = window.innerHeight;
36197			screenX = window.innerWidth;
36198			currentBreakpoint = getCurrentBreakpoint(screenX);
36199
36200			setPosition();
36201
36202			cacheBlocks();
36203
36204			animate();
36205
36206			// If paused, unpause and set listener for window resizing events
36207			if (pause) {
36208				window.addEventListener('resize', init);
36209				pause = false;
36210				// Start the loop
36211				update();
36212			}
36213		};
36214
36215		// We want to cache the parallax blocks'
36216		// values: base, top, height, speed
36217		// el: is dom object, return: el cache values
36218		var createBlock = function(el) {
36219			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
36220			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
36221			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
36222			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
36223			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
36224			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
36225			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
36226			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
36227			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
36228			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
36229			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
36230			var dataMin = el.getAttribute( 'data-rellax-min' );
36231			var dataMax = el.getAttribute( 'data-rellax-max' );
36232			var dataMinX = el.getAttribute('data-rellax-min-x');
36233			var dataMaxX = el.getAttribute('data-rellax-max-x');
36234			var dataMinY = el.getAttribute('data-rellax-min-y');
36235			var dataMaxY = el.getAttribute('data-rellax-max-y');
36236			var mapBreakpoints;
36237			var breakpoints = true;
36238
36239			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
36240				breakpoints = false;
36241			} else {
36242				mapBreakpoints = {
36243					'xs': dataXsSpeed,
36244					'sm': dataMobileSpeed,
36245					'md': dataTabletSpeed,
36246					'lg': dataDesktopSpeed
36247				};
36248			}
36249
36250			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
36251			// ensures elements are positioned based on HTML layout.
36252			//
36253			// If the element has the percentage attribute, the posY and posX needs to be
36254			// the current scroll position's value, so that the elements are still positioned based on HTML layout
36255			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
36256			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
36257			if (self.options.relativeToWrapper) {
36258				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
36259				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
36260			}
36261			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
36262			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;
36263
36264			var blockTop = posY + el.getBoundingClientRect().top;
36265			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
36266
36267			var blockLeft = posX + el.getBoundingClientRect().left;
36268			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
36269
36270			// apparently parallax equation everyone uses
36271			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
36272			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
36273			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
36274
36275			// Optional individual block speed as data attr, otherwise global speed
36276			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
36277			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
36278			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
36279
36280			// Optional individual block movement axis direction as data attr, otherwise global movement direction
36281			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
36282			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
36283
36284			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
36285
36286			// ~~Store non-translate3d transforms~~
36287			// Store inline styles and extract transforms
36288			var style = el.style.cssText;
36289			var transform = '';
36290
36291			// Check if there's an inline styled transform
36292			var searchResult = /transform\s*:/i.exec(style);
36293			if (searchResult) {
36294				// Get the index of the transform
36295				var index = searchResult.index;
36296
36297				// Trim the style to the transform point and get the following semi-colon index
36298				var trimmedStyle = style.slice(index);
36299				var delimiter = trimmedStyle.indexOf(';');
36300
36301				// Remove "transform" string and save the attribute
36302				if (delimiter) {
36303					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
36304				} else {
36305					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
36306				}
36307			}
36308
36309			return {
36310				baseX: bases.x,
36311				baseY: bases.y,
36312				top: blockTop,
36313				left: blockLeft,
36314				height: blockHeight,
36315				width: blockWidth,
36316				speed: speed,
36317				verticalSpeed: verticalSpeed,
36318				horizontalSpeed: horizontalSpeed,
36319				verticalScrollAxis: verticalScrollAxis,
36320				horizontalScrollAxis: horizontalScrollAxis,
36321				style: style,
36322				transform: transform,
36323				zindex: dataZindex,
36324				min: dataMin,
36325				max: dataMax,
36326				minX: dataMinX,
36327				maxX: dataMaxX,
36328				minY: dataMinY,
36329				maxY: dataMaxY
36330			};
36331		};
36332
36333		// set scroll position (posY, posX)
36334		// side effect method is not ideal, but okay for now
36335		// returns true if the scroll changed, false if nothing happened
36336		var setPosition = function() {
36337			var oldY = posY;
36338			var oldX = posX;
36339
36340			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
36341			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
36342			// If option relativeToWrapper is true, use relative wrapper value instead.
36343			if (self.options.relativeToWrapper) {
36344				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
36345				posY = scrollPosY - self.options.wrapper.offsetTop;
36346			}
36347
36348
36349			if (oldY != posY && self.options.vertical) {
36350				// scroll changed, return true
36351				return true;
36352			}
36353
36354			if (oldX != posX && self.options.horizontal) {
36355				// scroll changed, return true
36356				return true;
36357			}
36358
36359			// scroll did not change
36360			return false;
36361		};
36362
36363		// Ahh a pure function, gets new transform value
36364		// based on scrollPosition and speed
36365		// Allow for decimal pixel values
36366		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
36367			var result = {};
36368			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
36369			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
36370
36371			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
36372			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
36373
36374			return result;
36375		};
36376
36377		// Remove event listeners and loop again
36378		var deferredUpdate = function() {
36379			window.removeEventListener('resize', deferredUpdate);
36380			window.removeEventListener('orientationchange', deferredUpdate);
36381			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
36382			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
36383
36384			// loop again
36385			loopId = loop(update);
36386		};
36387
36388		// Loop
36389		var update = function() {
36390			if (setPosition() && pause === false) {
36391				animate();
36392
36393				// loop again
36394				loopId = loop(update);
36395			} else {
36396				loopId = null;
36397
36398				// Don't animate until we get a position updating event
36399				window.addEventListener('resize', deferredUpdate);
36400				window.addEventListener('orientationchange', deferredUpdate);
36401				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
36402				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
36403			}
36404		};
36405
36406		// Transform3d on parallax element
36407		var animate = function() {
36408			var positions;
36409			for (var i = 0; i < self.elems.length; i++){
36410				// Determine relevant movement directions
36411				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
36412				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
36413				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
36414				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
36415				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
36416				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
36417
36418				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
36419				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
36420
36421				// Subtracting initialize value, so element stays in same spot as HTML
36422				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
36423				var positionY = positions.y - blocks[i].baseY;
36424				var positionX = positions.x - blocks[i].baseX;
36425
36426				// The next two "if" blocks go like this:
36427				// Check if a limit is defined (first "min", then "max");
36428				// Check if we need to change the Y or the X
36429				// (Currently working only if just one of the axes is enabled)
36430				// Then, check if the new position is inside the allowed limit
36431				// If so, use new position. If not, set position to limit.
36432
36433				// Check if a min limit is defined
36434				if (blocks[i].min !== null) {
36435					if (self.options.vertical && !self.options.horizontal) {
36436						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
36437					}
36438					if (self.options.horizontal && !self.options.vertical) {
36439						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
36440					}
36441				}
36442
36443				// Check if directional min limits are defined
36444				if (blocks[i].minY != null) {
36445						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
36446				}
36447				if (blocks[i].minX != null) {
36448						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
36449				}
36450
36451				// Check if a max limit is defined
36452				if (blocks[i].max !== null) {
36453					if (self.options.vertical && !self.options.horizontal) {
36454						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
36455					}
36456					if (self.options.horizontal && !self.options.vertical) {
36457						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
36458					}
36459				}
36460
36461				// Check if directional max limits are defined
36462				if (blocks[i].maxY != null) {
36463						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
36464				}
36465				if (blocks[i].maxX != null) {
36466						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
36467				}
36468
36469				var zindex = blocks[i].zindex;
36470
36471				// Move that element
36472				// (Set the new translation and append initial inline transforms.)
36473				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
36474				self.elems[i].style[transformProp] = translate;
36475			}
36476			self.options.callback(positions);
36477		};
36478
36479		self.destroy = function() {
36480			for (var i = 0; i < self.elems.length; i++){
36481				self.elems[i].style.cssText = blocks[i].style;
36482			}
36483
36484			// Remove resize event listener if not pause, and pause
36485			if (!pause) {
36486				window.removeEventListener('resize', init);
36487				pause = true;
36488			}
36489
36490			// Clear the animation loop to prevent possible memory leak
36491			clearLoop(loopId);
36492			loopId = null;
36493		};
36494
36495		// Init
36496		init();
36497
36498		// Allow to recalculate the initial values whenever we want
36499		self.refresh = init;
36500
36501		return self;
36502	};
36503	return Rellax;
36504}));
36505
36506/*
36507 * OKVideo by OKFocus v2.3.2
36508 * http://okfoc.us
36509 *
36510 * Copyright 2014, OKFocus
36511 * Licensed under the MIT license.
36512 *
36513 */
36514var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
36515// youtube player ready
36516function onYouTubeIframeAPIReady() {
36517	YTplayers = new Array();
36518	jQuery('.no-touch .uncode-video-container.video').each(function() {
36519		var playerY;
36520		if (jQuery(this).attr('data-provider') == 'youtube') {
36521			var id = jQuery(this).attr('data-id');
36522			options = jQuery(window).data('okoptions-' + id);
36523			options.time = jQuery(this).attr('data-t');
36524			playerY = new YT.Player('okplayer-' + id, {
36525				videoId: options.video ? options.video.id : null,
36526				playerVars: {
36527					'autohide': 1,
36528					'autoplay': 0, //options.autoplay,
36529					'disablekb': 1,
36530					'cc_load_policy': options.captions,
36531					'controls': 0,
36532					'enablejsapi': 1,
36533					'fs': 0,
36534					'modestbranding': 1,
36535					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
36536					'iv_load_policy': options.annotations,
36537					'loop': options.loop,
36538					'showinfo': 0,
36539					'rel': 0,
36540					'wmode': 'opaque',
36541					'hd': options.hd,
36542					'mute': 1
36543				},
36544				events: {
36545					'onReady': OKEvents.yt.ready,
36546					'onStateChange': OKEvents.yt.onStateChange,
36547					'onError': OKEvents.yt.error
36548				}
36549			});
36550			YTplayers[id] = playerY;
36551			playerY.videoId = id;
36552		}
36553
36554	});
36555}
36556// vimeo player ready
36557function vimeoPlayerReady(id) {
36558	options = jQuery(window).data('okoptions-' + id);
36559	var jIframe = options.jobject,
36560		iframe = jIframe[0];
36561
36562	jIframe.attr('src', jIframe.data('src'));
36563	var playerV = $f(iframe); // `$f` is froogaloop, assumed is loaded
36564	// hide player until Vimeo hides controls...
36565	playerV.addEvent('ready', function(e) {
36566		OKEvents.v.onReady(iframe);
36567		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
36568		if (carouselContainer.length) {
36569			UNCODE.owlPlayVideo(carouselContainer);
36570		}
36571		// "Do not try to add listeners or call functions before receiving this event."
36572		if (OKEvents.utils.isMobile()) {
36573			// mobile devices cannot listen for play event
36574			OKEvents.v.onPlay(playerV);
36575		} else {
36576			playerV.addEvent('play', OKEvents.v.onPlay(playerV));
36577			playerV.addEvent('pause', OKEvents.v.onPause);
36578			playerV.addEvent('finish', OKEvents.v.onFinish);
36579		}
36580		if (options.time != null) {
36581			var optsTimeStr = (options.time).replace('t=', ''),
36582				timeV = '';
36583
36584			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
36585				var timeArr = optsTimeStr.split(/([^\d.-])/);
36586				for ( var i = 0; i < timeArr.length; i++ ) {
36587					if ( timeArr[i] === 'h' ) {
36588						timeV += parseFloat(timeArr[i-1]) * 3600;
36589					} else if ( timeArr[i] === 'm' ) {
36590						timeV += parseFloat(timeArr[i-1]) * 60;
36591					} else if ( timeArr[i] === 's' ) {
36592						timeV += parseFloat(timeArr[i-1]);
36593					}
36594				}
36595			} else {
36596				timeV = optsTimeStr;
36597			}
36598
36599			playerV.api('seekTo', timeV);
36600		}
36601
36602		playerV.api('play');
36603		jQuery(iframe).css({
36604			visibility: 'visible',
36605			opacity: 1
36606		});
36607		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
36608		jQuery(iframe).closest('#page-header').addClass('video-started');
36609		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
36610
36611	});
36612}
36613OKEvents = {
36614	yt: {
36615		ready: function(event) {
36616			var id = event.target.videoId;
36617			youtubePlayers[id] = event.target;
36618			event.target.setVolume(options.volume);
36619			if (options.autoplay === 1) {
36620				if (options.playlist.list) {
36621					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
36622				} else {
36623					var inCarousel = jQuery('#okplayer-' + id).closest('.owl-item');
36624					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
36625						if (options.time != null) {
36626							event.target.seekTo(parseInt(options.time));
36627						}
36628						event.target.playVideo();
36629					} else {
36630						event.target.pauseVideo();
36631					}
36632				}
36633			}
36634			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
36635
36636			jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-resume', function(){
36637				if (options.time != null) {
36638					event.target.seekTo(parseInt(options.time)).playVideo();
36639				} else {
36640					event.target.seekTo(0).playVideo();
36641				}
36642			});
36643
36644			jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-pause', function(){
36645				if (options.time != null) {
36646					event.target.seekTo(parseInt(options.time)).pauseVideo();
36647				} else {
36648					event.target.seekTo(0).pauseVideo();
36649				}
36650			});
36651		},
36652		onStateChange: function(event) {
36653			var id = event.target.videoId;
36654			switch (event.data) {
36655				case -1:
36656					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
36657					break;
36658				case 0:
36659					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
36660					options.loop && event.target.playVideo();
36661					break;
36662				case 1:
36663					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
36664					setTimeout(function() {
36665						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
36666						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
36667						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
36668						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
36669					}, 300);
36670					break;
36671				case 2:
36672					OKEvents.utils.isFunction(options.onPause) && options.onPause();
36673					break;
36674				case 3:
36675					OKEvents.utils.isFunction(options.buffering) && options.buffering();
36676					break;
36677				case 5:
36678					OKEvents.utils.isFunction(options.cued) && options.cued();
36679					break;
36680				default:
36681					throw "OKVideo: received invalid data from YT player.";
36682			}
36683		},
36684		error: function(event) {
36685			throw event;
36686		}
36687	},
36688	v: {
36689		onReady: function(target) {
36690			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
36691		},
36692		onPlay: function(player) {
36693			if (!OKEvents.utils.isMobile()) player.api('setVolume', options.volume);
36694			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
36695			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
36696			jQuery(player.element).closest('#page-header').addClass('video-started');
36697			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
36698		},
36699		onPause: function() {
36700			OKEvents.utils.isFunction(options.onPause) && options.onPause();
36701		},
36702		onFinish: function() {
36703			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
36704		}
36705	},
36706	utils: {
36707		isFunction: function(func) {
36708			if (typeof func === 'function') {
36709				return true;
36710			} else {
36711				return false;
36712			}
36713		},
36714		isMobile: function() {
36715			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
36716				return true;
36717			} else {
36718				return false;
36719			}
36720		}
36721	}
36722};
36723
36724/**
36725 * vivus - JavaScript library to make drawing animation on SVG
36726 * @version v0.4.4
36727 * @link https://github.com/maxwellito/vivus
36728 * @license MIT
36729 */
36730
36731'use strict';
36732
36733(function () {
36734
36735  'use strict';
36736
36737/**
36738 * Pathformer
36739 * Beta version
36740 *
36741 * Take any SVG version 1.1 and transform
36742 * child elements to 'path' elements
36743 *
36744 * This code is purely forked from
36745 * https://github.com/Waest/SVGPathConverter
36746 */
36747
36748/**
36749 * Class constructor
36750 *
36751 * @param {DOM|String} element Dom element of the SVG or id of it
36752 */
36753function Pathformer(element) {
36754  // Test params
36755  if (typeof element === 'undefined') {
36756	throw new Error('Pathformer [constructor]: "element" parameter is required');
36757  }
36758
36759  // Set the element
36760  if (element.constructor === String) {
36761	element = document.getElementById(element);
36762	if (!element) {
36763	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
36764	}
36765  }
36766  if (element instanceof window.SVGElement ||
36767	  element instanceof window.SVGGElement ||
36768	  /^svg$/i.test(element.nodeName)) {
36769	this.el = element;
36770  } else {
36771	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
36772  }
36773
36774  // Start
36775  this.scan(element);
36776}
36777
36778/**
36779 * List of tags which can be transformed
36780 * to path elements
36781 *
36782 * @type {Array}
36783 */
36784Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
36785
36786/**
36787 * List of attribute names which contain
36788 * data. This array list them to check if
36789 * they contain bad values, like percentage.
36790 *
36791 * @type {Array}
36792 */
36793Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 36793-37591
36793y1', 'y2'];
36794
36795/**
36796 * Finds the elements compatible for transform
36797 * and apply the liked method
36798 *
36799 * @param  {object} options Object from the constructor
36800 */
36801Pathformer.prototype.scan = function (svg) {
36802  var fn, element, pathData, pathDom,
36803	  elements = svg.querySelectorAll(this.TYPES.join(','));
36804
36805  for (var i = 0; i < elements.length; i++) {
36806	element = elements[i];
36807	fn = this[element.tagName.toLowerCase() + 'ToPath'];
36808	pathData = fn(this.parseAttr(element.attributes));
36809	pathDom = this.pathMaker(element, pathData);
36810	element.parentNode.replaceChild(pathDom, element);
36811  }
36812};
36813
36814
36815/**
36816 * Read `line` element to extract and transform
36817 * data, to make it ready for a `path` object.
36818 *
36819 * @param  {DOMelement} element Line element to transform
36820 * @return {object}			 Data for a `path` element
36821 */
36822Pathformer.prototype.lineToPath = function (element) {
36823  var newElement = {},
36824	  x1 = element.x1 || 0,
36825	  y1 = element.y1 || 0,
36826	  x2 = element.x2 || 0,
36827	  y2 = element.y2 || 0;
36828
36829  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
36830  return newElement;
36831};
36832
36833/**
36834 * Read `rect` element to extract and transform
36835 * data, to make it ready for a `path` object.
36836 * The radius-border is not taken in charge yet.
36837 * (your help is more than welcomed)
36838 *
36839 * @param  {DOMelement} element Rect element to transform
36840 * @return {object}             Data for a `path` element
36841 */
36842Pathformer.prototype.rectToPath = function (element) {
36843  var newElement = {},
36844      x      = parseFloat(element.x)      || 0,
36845      y      = parseFloat(element.y)      || 0,
36846      width  = parseFloat(element.width)  || 0,
36847      height = parseFloat(element.height) || 0;
36848
36849  if (element.rx || element.ry) {
36850    var rx = parseInt(element.rx, 10) || -1,
36851        ry = parseInt(element.ry, 10) || -1;
36852    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
36853    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
36854
36855    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
36856                   'L ' + (x + width - rx) + ',' + y + ' ' +
36857                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
36858                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
36859                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
36860                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
36861                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
36862                   'L ' + x + ',' + (y + ry) + ' ' +
36863                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
36864  }
36865  else {
36866    newElement.d = 'M' + x + ' ' + y + ' ' +
36867                   'L' + (x + width) + ' ' + y + ' ' +
36868                   'L' + (x + width) + ' ' + (y + height) + ' ' +
36869                   'L' + x + ' ' + (y + height) + ' Z';
36870  }
36871  return newElement;
36872};
36873
36874/**
36875 * Read `polyline` element to extract and transform
36876 * data, to make it ready for a `path` object.
36877 *
36878 * @param  {DOMelement} element Polyline element to transform
36879 * @return {object}             Data for a `path` element
36880 */
36881Pathformer.prototype.polylineToPath = function (element) {
36882  var newElement = {},
36883      points = element.points.trim().split(' '),
36884      i, path;
36885
36886  // Reformatting if points are defined without commas
36887  if (element.points.indexOf(',') === -1) {
36888    var formattedPoints = [];
36889    for (i = 0; i < points.length; i+=2) {
36890      formattedPoints.push(points[i] + ',' + points[i+1]);
36891    }
36892    points = formattedPoints;
36893  }
36894
36895  // Generate the path.d value
36896  path = 'M' + points[0];
36897  for(i = 1; i < points.length; i++) {
36898    if (points[i].indexOf(',') !== -1) {
36899      path += 'L' + points[i];
36900    }
36901  }
36902  newElement.d = path;
36903  return newElement;
36904};
36905
36906/**
36907 * Read `polygon` element to extract and transform
36908 * data, to make it ready for a `path` object.
36909 * This method rely on polylineToPath, because the
36910 * logic is similar. The path created is just closed,
36911 * so it needs an 'Z' at the end.
36912 *
36913 * @param  {DOMelement} element Polygon element to transform
36914 * @return {object}             Data for a `path` element
36915 */
36916Pathformer.prototype.polygonToPath = function (element) {
36917  var newElement = Pathformer.prototype.polylineToPath(element);
36918
36919  newElement.d += 'Z';
36920  return newElement;
36921};
36922
36923/**
36924 * Read `ellipse` element to extract and transform
36925 * data, to make it ready for a `path` object.
36926 *
36927 * @param  {DOMelement} element ellipse element to transform
36928 * @return {object}             Data for a `path` element
36929 */
36930Pathformer.prototype.ellipseToPath = function (element) {
36931  var newElement = {},
36932      rx = parseFloat(element.rx) || 0,
36933      ry = parseFloat(element.ry) || 0,
36934      cx = parseFloat(element.cx) || 0,
36935      cy = parseFloat(element.cy) || 0,
36936      startX = cx - rx,
36937      startY = cy,
36938      endX = parseFloat(cx) + parseFloat(rx),
36939      endY = cy;
36940
36941  newElement.d = 'M' + startX + ',' + startY +
36942                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
36943                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
36944  return newElement;
36945};
36946
36947/**
36948 * Read `circle` element to extract and transform
36949 * data, to make it ready for a `path` object.
36950 *
36951 * @param  {DOMelement} element Circle element to transform
36952 * @return {object}             Data for a `path` element
36953 */
36954Pathformer.prototype.circleToPath = function (element) {
36955  var newElement = {},
36956      r  = parseFloat(element.r)  || 0,
36957      cx = parseFloat(element.cx) || 0,
36958      cy = parseFloat(element.cy) || 0,
36959      startX = cx - r,
36960      startY = cy,
36961      endX = parseFloat(cx) + parseFloat(r),
36962      endY = cy;
36963
36964  newElement.d =  'M' + startX + ',' + startY +
36965                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
36966                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
36967  return newElement;
36968};
36969
36970/**
36971 * Create `path` elements form original element
36972 * and prepared objects
36973 *
36974 * @param  {DOMelement} element  Original element to transform
36975 * @param  {object} pathData     Path data (from `toPath` methods)
36976 * @return {DOMelement}          Path element
36977 */
36978Pathformer.prototype.pathMaker = function (element, pathData) {
36979  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
36980  for(i = 0; i < element.attributes.length; i++) {
36981    attr = element.attributes[i];
36982    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
36983      pathTag.setAttribute(attr.name, attr.value);
36984    }
36985  }
36986  for(i in pathData) {
36987    pathTag.setAttribute(i, pathData[i]);
36988  }
36989  return pathTag;
36990};
36991
36992/**
36993 * Parse attributes of a DOM element to
36994 * get an object of attribute => value
36995 *
36996 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
36997 * @return {object}                  Object of attributes
36998 */
36999Pathformer.prototype.parseAttr = function (element) {
37000  var attr, output = {};
37001  for (var i = 0; i < element.length; i++) {
37002    attr = element[i];
37003    // Check if no data attribute contains '%', or the transformation is impossible
37004    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37005      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37006    }
37007    output[attr.name] = attr.value;
37008  }
37009  return output;
37010};
37011
37012  'use strict';
37013
37014var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37015
37016/**
37017 * Vivus
37018 * Beta version
37019 *
37020 * Take any SVG and make the animation
37021 * to give give the impression of live drawing
37022 *
37023 * This in more than just inspired from codrops
37024 * At that point, it's a pure fork.
37025 */
37026
37027/**
37028 * Class constructor
37029 * option structure
37030 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
37031 *   duration: <int> (in frames)
37032 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
37033 *   delay: <int> (delay between the drawing of first and last path)
37034 *   dashGap <integer> whitespace extra margin between dashes
37035 *   pathTimingFunction <function> timing animation function for each path element of the SVG
37036 *   animTimingFunction <function> timing animation function for the complete SVG
37037 *   forceRender <boolean> force the browser to re-render all updated path items
37038 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
37039 *
37040 * The attribute 'type' is by default on 'delayed'.
37041 *  - 'delayed'
37042 *    all paths are draw at the same time but with a
37043 *    little delay between them before start
37044 *  - 'sync'
37045 *    all path are start and finish at the same time
37046 *  - 'oneByOne'
37047 *    only one path is draw at the time
37048 *    the end of the first one will trigger the draw
37049 *    of the next one
37050 *
37051 * All these values can be overwritten individually
37052 * for each path item in the SVG
37053 * The value of frames will always take the advantage of
37054 * the duration value.
37055 * If you fail somewhere, an error will be thrown.
37056 * Good luck.
37057 *
37058 * @constructor
37059 * @this {Vivus}
37060 * @param {DOM|String}   element  Dom element of the SVG or id of it
37061 * @param {Object}       options  Options about the animation
37062 * @param {Function}     callback Callback for the end of the animation
37063 */
37064function Vivus (element, options, callback) {
37065
37066  setupEnv();
37067
37068  // Setup
37069  this.isReady = false;
37070  this.setElement(element, options);
37071  this.setOptions(options);
37072  this.setCallback(callback);
37073
37074  if (this.isReady) {
37075    this.init();
37076  }
37077}
37078
37079/**
37080 * Timing functions
37081 **************************************
37082 *
37083 * Default functions to help developers.
37084 * It always take a number as parameter (between 0 to 1) then
37085 * return a number (between 0 and 1)
37086 */
37087Vivus.LINEAR          = function (x) {return x;};
37088Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
37089Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
37090Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
37091Vivus.EASE_OUT_BOUNCE = function (x) {
37092  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
37093    rate = Math.pow(base,1.5),
37094    rateR = Math.pow(1 - x, 2),
37095    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
37096  return (1- rateR) + (progress * rateR);
37097};
37098
37099
37100/**
37101 * Setters
37102 **************************************
37103 */
37104
37105/**
37106 * Check and set the element in the instance
37107 * The method will not return anything, but will throw an
37108 * error if the parameter is invalid
37109 *
37110 * @param {DOM|String}   element  SVG Dom element or id of it
37111 */
37112Vivus.prototype.setElement = function (element, options) {
37113  var onLoad, self;
37114
37115  // Basic check
37116  if (typeof element === 'undefined') {
37117    throw new Error('Vivus [constructor]: "element" parameter is required');
37118  }
37119
37120  // Set the element
37121  if (element.constructor === String) {
37122    element = document.getElementById(element);
37123    if (!element) {
37124      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
37125    }
37126  }
37127  this.parentEl = element;
37128
37129  // Load the SVG with XMLHttpRequest and extract the SVG
37130  if (options && options.file) {
37131    var self = this;
37132    onLoad = function (e) {
37133      var domSandbox = document.createElement('div');
37134      domSandbox.innerHTML = this.responseText;
37135
37136      var svgTag = domSandbox.querySelector('svg');
37137      if (!svgTag) {
37138        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
37139      }
37140
37141      self.el = svgTag
37142      self.el.setAttribute('width', '100%');
37143      self.el.setAttribute('height', '100%');
37144      self.parentEl.appendChild(self.el)
37145      self.isReady = true;
37146      self.init();
37147      self = null;
37148    }
37149
37150    var oReq = new window.XMLHttpRequest();
37151    oReq.addEventListener('load', onLoad);
37152    oReq.open('GET', options.file);
37153    oReq.send();
37154    return;
37155  }
37156
37157  switch (element.constructor) {
37158  case window.SVGSVGElement:
37159  case window.SVGElement:
37160  case window.SVGGElement:
37161    this.el = element;
37162    this.isReady = true;
37163    break;
37164
37165  case window.HTMLObjectElement:
37166    self = this;
37167    onLoad = function (e) {
37168      if (self.isReady) {
37169        return;
37170      }
37171      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
37172      if (!self.el && e) {
37173        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
37174      }
37175      else if (self.el) {
37176        if (element.getAttribute('built-by-vivus')) {
37177          self.parentEl.insertBefore(self.el, element);
37178          self.parentEl.removeChild(element);
37179          self.el.setAttribute('width', '100%');
37180          self.el.setAttribute('height', '100%');
37181        }
37182        self.isReady = true;
37183        self.init();
37184        self = null;
37185      }
37186    };
37187
37188    if (!onLoad()) {
37189      element.addEventListener('load', onLoad);
37190    }
37191    break;
37192
37193  default:
37194    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
37195  }
37196};
37197
37198/**
37199 * Set up user option to the instance
37200 * The method will not return anything, but will throw an
37201 * error if the parameter is invalid
37202 *
37203 * @param  {object} options Object from the constructor
37204 */
37205Vivus.prototype.setOptions = function (options) {
37206  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
37207  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
37208
37209  // Basic check
37210  if (options !== undefined && options.constructor !== Object) {
37211    throw new Error('Vivus [constructor]: "options" parameter must be an object');
37212  }
37213  else {
37214    options = options || {};
37215  }
37216
37217  // Set the animation type
37218  if (options.type && allowedTypes.indexOf(options.type) === -1) {
37219    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
37220  }
37221  else {
37222    this.type = options.type || allowedTypes[0];
37223  }
37224
37225  // Set the start type
37226  if (options.start && allowedStarts.indexOf(options.start) === -1) {
37227    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
37228  }
37229  else {
37230    this.start = options.start || allowedStarts[0];
37231  }
37232
37233  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
37234  this.duration     = parsePositiveInt(options.duration, 120);
37235  this.delay        = parsePositiveInt(options.delay, null);
37236  //Uncode addition
37237  this.delayStart   = parsePositiveInt(options.delayStart, null);
37238  //#END
37239  this.dashGap      = parsePositiveInt(options.dashGap, 1);
37240  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
37241  this.reverseStack = !!options.reverseStack;
37242  this.selfDestroy  = !!options.selfDestroy;
37243  this.onReady      = options.onReady;
37244  this.map          = [];
37245  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
37246
37247  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
37248
37249  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
37250  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
37251
37252  if (this.delay >= this.duration) {
37253    throw new Error('Vivus [constructor]: delay must be shorter than duration');
37254  }
37255};
37256
37257/**
37258 * Set up callback to the instance
37259 * The method will not return enything, but will throw an
37260 * error if the parameter is invalid
37261 *
37262 * @param  {Function} callback Callback for the animation end
37263 */
37264Vivus.prototype.setCallback = function (callback) {
37265  // Basic check
37266  if (!!callback && callback.constructor !== Function) {
37267    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
37268  }
37269  this.callback = callback || function () {};
37270};
37271
37272
37273/**
37274 * Core
37275 **************************************
37276 */
37277
37278/**
37279 * Map the svg, path by path.
37280 * The method return nothing, it just fill the
37281 * `map` array. Each item in this array represent
37282 * a path element from the SVG, with informations for
37283 * the animation.
37284 *
37285 * ```
37286 * [
37287 *   {
37288 *     el: <DOMobj> the path element
37289 *     length: <number> length of the path line
37290 *     startAt: <number> time start of the path animation (in frames)
37291 *     duration: <number> path animation duration (in frames)
37292 *   },
37293 *   ...
37294 * ]
37295 * ```
37296 *
37297 */
37298Vivus.prototype.mapping = function () {
37299  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
37300  timePoint = totalLength = lengthMeter = 0;
37301  paths = this.el.querySelectorAll('path');
37302
37303  for (i = 0; i < paths.length; i++) {
37304    path = paths[i];
37305    if (this.isInvisible(path)) {
37306      continue;
37307    }
37308    pathObj = {
37309      el: path,
37310      length: Math.ceil(path.getTotalLength())
37311    };
37312    // Test if the path length is correct
37313    if (isNaN(pathObj.length)) {
37314      if (window.console && console.warn) {
37315        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
37316      }
37317      continue;
37318    }
37319    this.map.push(pathObj);
37320    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
37321    path.style.strokeDashoffset = pathObj.length + this.dashGap;
37322    pathObj.length += this.dashGap;
37323    totalLength += pathObj.length;
37324
37325    this.renderPath(i);
37326  }
37327
37328  totalLength = totalLength === 0 ? 1 : totalLength;
37329  this.delay = this.delay === null ? this.duration / 3 : this.delay;
37330  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
37331
37332  // Reverse stack if asked
37333  if (this.reverseStack) {
37334    this.map.reverse();
37335  }
37336
37337  for (i = 0; i < this.map.length; i++) {
37338    pathObj = this.map[i];
37339
37340    switch (this.type) {
37341    case 'delayed':
37342      pathObj.startAt = this.delayUnit * i;
37343      pathObj.duration = this.duration - this.delay;
37344      break;
37345
37346    case 'oneByOne':
37347      pathObj.startAt = lengthMeter / totalLength * this.duration;
37348      pathObj.duration = pathObj.length / totalLength * this.duration;
37349      break;
37350
37351    case 'sync':
37352    case 'async':
37353    case 'nsync':
37354      pathObj.startAt = 0;
37355      pathObj.duration = this.duration;
37356      break;
37357
37358    case 'scenario-sync':
37359      path = pathObj.el;
37360      pAttrs = this.parseAttr(path);
37361      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
37362      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
37363      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
37364      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
37365      break;
37366
37367    case 'scenario':
37368      path = pathObj.el;
37369      pAttrs = this.parseAttr(path);
37370      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
37371      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
37372      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
37373      break;
37374    }
37375    lengthMeter += pathObj.length;
37376    this.frameLength = this.frameLength || this.duration;
37377  }
37378};
37379
37380/**
37381 * Interval method to draw the SVG from current
37382 * position of the animation. It update the value of
37383 * `currentFrame` and re-trace the SVG.
37384 *
37385 * It use this.handle to store the requestAnimationFrame
37386 * and clear it one the animation is stopped. So this
37387 * attribute can be used to know if the animation is
37388 * playing.
37389 *
37390 * Once the animation at the end, this method will
37391 * trigger the Vivus callback.
37392 *
37393 */
37394Vivus.prototype.drawer = function () {
37395  var self = this;
37396  this.currentFrame += this.speed;
37397
37398  if (this.currentFrame <= 0) {
37399    this.stop();
37400    this.reset();
37401  } else if (this.currentFrame >= this.frameLength) {
37402    this.stop();
37403    this.currentFrame = this.frameLength;
37404    this.trace();
37405    if (this.selfDestroy) {
37406      this.destroy();
37407    }
37408  } else {
37409    this.trace();
37410    this.handle = requestAnimFrame(function () {
37411      self.drawer();
37412    });
37413    return;
37414  }
37415
37416  this.callback(this);
37417  if (this.instanceCallback) {
37418    this.instanceCallback(this);
37419    this.instanceCallback = null;
37420  }
37421};
37422
37423/**
37424 * Draw the SVG at the current instant from the
37425 * `currentFrame` value. Here is where most of the magic is.
37426 * The trick is to use the `strokeDashoffset` style property.
37427 *
37428 * For optimisation reasons, a new property called `progress`
37429 * is added in each item of `map`. This one contain the current
37430 * progress of the path element. Only if the new value is different
37431 * the new value will be applied to the DOM element. This
37432 * method save a lot of resources to re-render the SVG. And could
37433 * be improved if the animation couldn't be played forward.
37434 *
37435 */
37436Vivus.prototype.trace = function () {
37437  var i, progress, path, currentFrame;
37438  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
37439  for (i = 0; i < this.map.length; i++) {
37440    path = this.map[i];
37441    progress = (currentFrame - path.startAt) / path.duration;
37442    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
37443    if (path.progress !== progress) {
37444      path.progress = progress;
37445      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
37446      this.renderPath(i);
37447    }
37448  }
37449};
37450
37451/**
37452 * Method forcing the browser to re-render a path element
37453 * from it's index in the map. Depending on the `forceRender`
37454 * value.
37455 * The trick is to replace the path element by it's clone.
37456 * This practice is not recommended because it's asking more
37457 * ressources, too much DOM manupulation..
37458 * but it's the only way to let the magic happen on IE.
37459 * By default, this fallback is only applied on IE.
37460 *
37461 * @param  {Number} index Path index
37462 */
37463Vivus.prototype.renderPath = function (index) {
37464  if (this.forceRender && this.map && this.map[index]) {
37465    var pathObj = this.map[index],
37466        newPath = pathObj.el.cloneNode(true);
37467    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
37468    pathObj.el = newPath;
37469  }
37470};
37471
37472/**
37473 * When the SVG object is loaded and ready,
37474 * this method will continue the initialisation.
37475 *
37476 * This this mainly due to the case of passing an
37477 * object tag in the constructor. It will wait
37478 * the end of the loading to initialise.
37479 *
37480 */
37481Vivus.prototype.init = function () {
37482  // Set object variables
37483  this.frameLength = 0;
37484  this.currentFrame = 0;
37485  this.map = [];
37486
37487  // Start
37488  new Pathformer(this.el);
37489  this.mapping();
37490  this.starter();
37491
37492  if (this.onReady) {
37493    this.onReady(this);
37494  }
37495};
37496
37497/**
37498 * Trigger to start of the animation.
37499 * Depending on the `start` value, a different script
37500 * will be applied.
37501 *
37502 * If the `start` value is not valid, an error will be thrown.
37503 * Even if technically, this is impossible.
37504 *
37505 */
37506Vivus.prototype.starter = function () {
37507  switch (this.start) {
37508  case 'manual':
37509    return;
37510
37511  case 'autostart':
37512    this.play();
37513    break;
37514
37515  case 'inViewport':
37516    var self = this,
37517    listener = function () {
37518      if (self.isInViewport(self.parentEl, 1)) {
37519        self.play();
37520        window.removeEventListener('scroll', listener);
37521        //Uncode addition
37522        window.removeEventListener('fp-slide-changed', listener);
37523        window.removeEventListener('fp-slide-scroll', listener);
37524        //#END
37525      }
37526    };
37527    window.addEventListener('scroll', listener);
37528    //Uncode addition
37529    window.addEventListener('fp-slide-changed', listener);
37530    window.addEventListener('fp-slide-scroll', listener);
37531    //#END
37532    listener();
37533    break;
37534  }
37535};
37536
37537
37538/**
37539 * Controls
37540 **************************************
37541 */
37542
37543/**
37544 * Get the current status of the animation between
37545 * three different states: 'start', 'progress', 'end'.
37546 * @return {string} Instance status
37547 */
37548Vivus.prototype.getStatus = function () {
37549  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
37550};
37551
37552/**
37553 * Reset the instance to the initial state : undraw
37554 * Be careful, it just reset the animation, if you're
37555 * playing the animation, this won't stop it. But just
37556 * make it start from start.
37557 *
37558 */
37559Vivus.prototype.reset = function () {
37560  return this.setFrameProgress(0);
37561};
37562
37563/**
37564 * Set the instance to the final state : drawn
37565 * Be careful, it just set the animation, if you're
37566 * playing the animation on rewind, this won't stop it.
37567 * But just make it start from the end.
37568 *
37569 */
37570Vivus.prototype.finish = function () {
37571  return this.setFrameProgress(1);
37572};
37573
37574/**
37575 * Set the level of progress of the drawing.
37576 *
37577 * @param {number} progress Level of progress to set
37578 */
37579Vivus.prototype.setFrameProgress = function (progress) {
37580  progress = Math.min(1, Math.max(0, progress));
37581  this.currentFrame = Math.round(this.frameLength * progress);
37582  this.trace();
37583  return this;
37584};
37585
37586/**
37587 * Play the animation at the desired speed.
37588 * Speed must be a valid number (no zero).
37589 * By default, the speed value is 1.
37590 * But a negative value is accepted to go forward.
37591 *
37592 * And works with float too.
37593 * But don't forget we are in JavaScript, se be nice
37594 * with him and give him a 1/2^x value.
37595 *
37596 * @param  {number} speed Animation speed [optional]
37597 */
37598Vivus.prototype.play = function (speed, callback) {
37599  this.instanceCallback = null;
37600
37601  if (speed && typeof speed === 'function') {
37602    this.instanceCallback = speed; // first parameter is actually the callback function
37603    speed = null;
37604  }
37605  else if (speed && typeof speed !== 'number') {
37606    throw new Error('Vivus [play]: invalid speed');
37607  }
37608  // if the first parameter wasn't the callback, check if the seconds was
37609  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
37610    this.instanceCallback = callback;
37611  }
37612
37613
37614  this.speed = speed || 1;
37615  //Uncode addition
37616  if (!this.handle) {
37617    var $this = this,
37618    delay = (this.delayStart != null) ? this.delayStart : 0;
37619    setTimeout(function() {
37620      $this.drawer();
37621    }, delay);
37622  }
37623  //#END
37624  return this;
37625};
37626
37627/**
37628 * Stop the current animation, if on progress.
37629 * Should not trigger any error.
37630 *
37631 */
37632Vivus.prototype.stop = function () {
37633  if (this.handle) {
37634    cancelAnimFrame(this.handle);
37635    this.handle = null;
37636  }
37637  return this;
37638};
37639
37640/**
37641 * Destroy the instance.
37642 * Remove all bad styling attributes on all
37643 * path tags
37644 *
37645 */
37646Vivus.prototype.destroy = function () {
37647  this.stop();
37648  var i, path;
37649  for (i = 0; i < this.map.length; i++) {
37650    path = this.map[i];
37651    path.el.style.strokeDashoffset = null;
37652    path.el.style.strokeDasharray = null;
37653    this.renderPath(i);
37654  }
37655};
37656
37657
37658/**
37659 * Utils methods
37660 * include methods from Codrops
37661 **************************************
37662 */
37663
37664/**
37665 * Method to best guess if a path should added into
37666 * the animation or not.
37667 *
37668 * 1. Use the `data-vivus-ignore` attribute if set
37669 * 2. Check if the instance must ignore invisible paths
37670 * 3. Check if the path is visible
37671 *
37672 * For now the visibility checking is unstable.
37673 * It will be used for a beta phase.
37674 *
37675 * Other improvments are planned. Like detecting
37676 * is the path got a stroke or a valid opacity.
37677 */
37678Vivus.prototype.isInvisible = function (el) {
37679  var rect,
37680    ignoreAttr = el.getAttribute('data-ignore');
37681
37682  if (ignoreAttr !== null) {
37683    return ignoreAttr !== 'false';
37684  }
37685
37686  if (this.ignoreInvisible) {
37687    rect = el.getBoundingClientRect();
37688    return !rect.width && !rect.height;
37689  }
37690  else {
37691    return false;
37692  }
37693};
37694
37695/**
37696 * Parse attributes of a DOM element to
37697 * get an object of {attributeName => attributeValue}
37698 *
37699 * @param  {object} element DOM element to parse
37700 * @return {object}         Object of attributes
37701 */
37702Vivus.prototype.parseAttr = function (element) {
37703  var attr, output = {};
37704  if (element && element.attributes) {
37705    for (var i = 0; i < element.attributes.length; i++) {
37706      attr = element.attributes[i];
37707      output[attr.name] = attr.value;
37708    }
37709  }
37710  return output;
37711};
37712
37713/**
37714 * Reply if an element is in the page viewport
37715 *
37716 * @param  {object} el Element to observe
37717 * @param  {number} h  Percentage of height
37718 * @return {boolean}
37719 */
37720Vivus.prototype.isInViewport = function (el, h) {
37721  var scrolled   = this.scrollY(),
37722    viewed       = scrolled + this.getViewportH(),
37723    elBCR        = el.getBoundingClientRect(),
37724    elHeight     = elBCR.height,
37725    elTop        = scrolled + elBCR.top,
37726    elBottom     = elTop + elHeight;
37727
37728  // if 0, the element is considered in the viewport as soon as it enters.
37729  // if 1, the element is considered in the viewport only when it's fully inside
37730  // value in percentage (1 >= h >= 0)
37731  h = h || 0;
37732
37733  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
37734};
37735
37736
37737/**
37738 * Get the viewport height in pixels
37739 *
37740 * @return {integer} Viewport height
37741 */
37742Vivus.prototype.getViewportH = function () {
37743  var client = this.docElem.clientHeight,
37744    inner = window.innerHeight;
37745
37746  if (client < inner) {
37747    return inner;
37748  }
37749  else {
37750    return client;
37751  }
37752};
37753
37754/**
37755 * Get the page Y offset
37756 *
37757 * @return {integer} Page Y offset
37758 */
37759Vivus.prototype.scrollY = function () {
37760  return window.pageYOffset || this.docElem.scrollTop;
37761};
37762
37763setupEnv = function () {
37764
37765  if (Vivus.prototype.docElem) {
37766    return;
37767  }
37768
37769  /**
37770   * Alias for document element
37771   *
37772   * @type {DOMelement}
37773   */
37774  Vivus.prototype.docElem = window.document.documentElement;
37775
37776  /**
37777   * Alias for `requestAnimationFrame` or
37778   * `setTimeout` function for deprecated browsers.
37779   *
37780   */
37781  requestAnimFrame = (function () {
37782    return (
37783      window.requestAnimationFrame       ||
37784      window.webkitRequestAnimationFrame ||
37785      window.mozRequestAnimationFrame    ||
37786      window.oRequestAnimationFrame      ||
37787      window.msRequestAnimationFrame     ||
37788      function(/* function */ callback){
37789        return window.setTimeout(callback, 1000 / 60);
37790      }
37791    );
37792  })();
37793
37794  /**
37795   * Alias for `cancelAnimationFrame` or
37796   * `cancelTimeout` function for deprecated browsers.
37797   *
37798   */
37799  cancelAnimFrame = (function () {
37800    return (
37801      window.cancelAnimationFrame       ||
37802      window.webkitCancelAnimationFrame ||
37803      window.mozCancelAnimationFrame    ||
37804      window.oCancelAnimationFrame      ||
37805      window.msCancelAnimationFrame     ||
37806      function(id){
37807        return window.clearTimeout(id);
37808      }
37809    );
37810  })();
37811};
37812
37813/**
37814 * Parse string to integer.
37815 * If the number is not positive or null
37816 * the method will return the default value
37817 * or 0 if undefined
37818 *
37819 * @param {string} value String to parse
37820 * @param {*}
37820 defaultValue Value to return if the result parsed is invalid
37821 * @return {number}
37822 *
37823 */
37824parsePositiveInt = function (value, defaultValue) {
37825  var output = parseInt(value, 10);
37826  return (output >= 0) ? output : defaultValue;
37827};
37828
37829
37830  if (typeof define === 'function' && define.amd) {
37831    // AMD. Register as an anonymous module.
37832    define([], function() {
37833      return Vivus;
37834    });
37835  } else if (typeof exports === 'object') {
37836    // Node. Does not work with strict CommonJS, but
37837    // only CommonJS-like environments that support module.exports,
37838    // like Node.
37839    module.exports = Vivus;
37840  } else {
37841    // Browser globals
37842    window.Vivus = Vivus;
37843  }
37844
37845}());

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.