PageSourceSearch

https://retinart.net/wp-content/themes/uncode/library/js/plugins.js?ver=338603913

js retinart.net collected 2026-10-02 09:58:17 UTC 1,288,627 bytes, 38,783 lines download raw bytes

vendor: 4,985 bytes, lines 1-161
1/* ----------------------------------------------------------
2 * Plugins
3 * ---------------------------------------------------------- */
4
5(function (global, factory) {
6  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
7  typeof define === 'function' && define.amd ? define(['exports'], factory) :
8  (global = global || self, factory(global.window = global.window || {}));
9}(this, (function (exports) { 'use strict';
10
11  function _inheritsLoose(subClass, superClass) {
12    subClass.prototype = Object.create(superClass.prototype);
13    subClass.prototype.constructor = subClass;
14    subClass.__proto__ = superClass;
15  }
16
17  function _assertThisInitialized(self) {
18    if (self === void 0) {
19      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
20    }
21
22    return self;
23  }
24
25  /*!
26   * GSAP 3.11.3
27   * https://greensock.com
28   *
29   * @license Copyright 2008-2022, 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      _reverting,
49      _context,
50      _bigNum = 1e8,
51      _tinyNum = 1 / _bigNum,
52      _2PI = Math.PI * 2,
53      _HALF_PI = _2PI / 4,
54      _gsID = 0,
55      _sqrt = Math.sqrt,
56      _cos = Math.cos,
57      _sin = Math.sin,
58      _isString = function _isString(value) {
59    return typeof value === "string";
60  },
61      _isFunction = function _isFunction(value) {
62    return typeof value === "function";
63  },
64      _isNumber = function _isNumber(value) {
65    return typeof value === "number";
66  },
67      _isUndefined = function _isUndefined(value) {
68    return typeof value === "undefined";
69  },
70      _isObject = function _isObject(value) {
71    return typeof value === "object";
72  },
73      _isNotFalse = function _isNotFalse(value) {
74    return value !== false;
75  },
76      _windowExists = function _windowExists() {
77    return typeof window !== "undefined";
78  },
79      _isFuncOrString = function _isFuncOrString(value) {
80    return _isFunction(value) || _isString(value);
81  },
82      _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {},
83      _isArray = Array.isArray,
84      _strictNumExp = /(?:-?\.?\d|\.)+/gi,
85      _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g,
86      _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g,
87      _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi,
88      _relExp = /[+-]=-?[.\d]+/,
89      _delimitedValueExp = /[^,'"\[\]\s]+/gi,
90      _unitExp = /^[+\-=e\s\d]*\d+[.\d]*([a-z]*|%)\s*$/i,
91      _globalTimeline,
92      _win,
93      _coreInitted,
94      _doc,
95      _globals = {},
96      _installScope = {},
97      _coreReady,
98      _install = function _install(scope) {
99    return (_installScope = _merge(scope, _globals)) && gsap;
100  },
101      _missingPlugin = function _missingPlugin(property, value) {
102    return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()");
103  },
104      _warn = function _warn(message, suppress) {
105    return !suppress && console.warn(message);
106  },
107      _addGlobal = function _addGlobal(name, obj) {
108    return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals;
109  },
110      _emptyFunc = function _emptyFunc() {
111    return 0;
112  },
113      _startAtRevertConfig = {
114    suppressEvents: true,
115    isStart: true,
116    kill: false
117  },
118      _revertConfigNoKill = {
119    suppressEvents: true,
120    kill: false
121  },
122      _revertConfig = {
123    suppressEvents: true
124  },
125      _reservedProps = {},
126      _lazyTweens = [],
127      _lazyLookup = {},
128      _lastRenderedFrame,
129      _plugins = {},
130      _effects = {},
131      _nextGCFrame = 30,
132      _harnessPlugins = [],
133      _callbackNames = "",
134      _harness = function _harness(targets) {
135    var target = targets[0],
136        harnessPlugin,
137        i;
138    _isObject(target) || _isFunction(target) || (targets = [targets]);
139
140    if (!(harnessPlugin = (target._gsap || {}).harness)) {
141      i = _harnessPlugins.length;
142
143      while (i-- && !_harnessPlugins[i].targetTest(target)) {}
144
145      harnessPlugin = _harnessPlugins[i];
146    }
147
148    i = targets.length;
149
150    while (i--) {
151      targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1);
152    }
153
154    return targets;
155  },
156      _getCache = function _getCache(target) {
157    return target._gsap || _harness(toArray(target))[0]._gsap;
158  },
159      _getProperty = function _getProperty(target, property, v) {
160    return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v;
161  },
vendor: 7,375 bytes, lines 162-396
162      _forEachName = function _forEachName(names, func) {
163    return (names = names.split(",")).forEach(func) || names;
164  },
165      _round = function _round(value) {
166    return Math.round(value * 100000) / 100000 || 0;
167  },
168      _roundPrecise = function _roundPrecise(value) {
169    return Math.round(value * 10000000) / 10000000 || 0;
170  },
171      _parseRelative = function _parseRelative(start, value) {
172    var operator = value.charAt(0),
173        end = parseFloat(value.substr(2));
174    start = parseFloat(start);
175    return operator === "+" ? start + end : operator === "-" ? start - end : operator === "*" ? start * end : start / end;
176  },
177      _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) {
178    var l = toFind.length,
179        i = 0;
180
181    for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {}
182
183    return i < l;
184  },
185      _lazyRender = function _lazyRender() {
186    var l = _lazyTweens.length,
187        a = _lazyTweens.slice(0),
188        i,
189        tween;
190
191    _lazyLookup = {};
192    _lazyTweens.length = 0;
193
194    for (i = 0; i < l; i++) {
195      tween = a[i];
196      tween && tween._lazy && (tween.render(tween._lazy[0], tween._lazy[1], true)._lazy = 0);
197    }
198  },
199      _lazySafeRender = function _lazySafeRender(animation, time, suppressEvents, force) {
200    _lazyTweens.length && _lazyRender();
201    animation.render(time, suppressEvents, force || _reverting && time < 0 && (animation._initted || animation._startAt));
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(excludeDuration) {
219    return function (obj, defaults) {
220      for (var p in defaults) {
221        p in obj || p === "duration" && excludeDuration || p === "ease" || (obj[p] = defaults[p]);
222      }
223    };
224  },
225      _merge = function _merge(base, toMerge) {
226    for (var p in toMerge) {
227      base[p] = toMerge[p];
228    }
229
230    return base;
231  },
232      _mergeDeep = function _mergeDeep(base, toMerge) {
233    for (var p in toMerge) {
234      p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]);
235    }
236
237    return base;
238  },
239      _copyExcluding = function _copyExcluding(obj, excluding) {
240    var copy = {},
241        p;
242
243    for (p in obj) {
244      p in excluding || (copy[p] = obj[p]);
245    }
246
247    return copy;
248  },
249      _inheritDefaults = function _inheritDefaults(vars) {
250    var parent = vars.parent || _globalTimeline,
251        func = vars.keyframes ? _setKeyframeDefaults(_isArray(vars.keyframes)) : _setDefaults;
252
253    if (_isNotFalse(vars.inherit)) {
254      while (parent) {
255        func(vars, parent.vars.defaults);
256        parent = parent.parent || parent._dp;
257      }
258    }
259
260    return vars;
261  },
262      _arraysMatch = function _arraysMatch(a1, a2) {
263    var i = a1.length,
264        match = i === a2.length;
265
266    while (match && i-- && a1[i] === a2[i]) {}
267
268    return i < 0;
269  },
270      _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) {
271    if (firstProp === void 0) {
272      firstProp = "_first";
273    }
274
275    if (lastProp === void 0) {
276      lastProp = "_last";
277    }
278
279    var prev = parent[lastProp],
280        t;
281
282    if (sortBy) {
283      t = child[sortBy];
284
285      while (prev && prev[sortBy] > t) {
286        prev = prev._prev;
287      }
288    }
289
290    if (prev) {
291      child._next = prev._next;
292      prev._next = child;
293    } else {
294      child._next = parent[firstProp];
295      parent[firstProp] = child;
296    }
297
298    if (child._next) {
299      child._next._prev = child;
300    } else {
301      parent[lastProp] = child;
302    }
303
304    child._prev = prev;
305    child.parent = child._dp = parent;
306    return child;
307  },
308      _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) {
309    if (firstProp === void 0) {
310      firstProp = "_first";
311    }
312
313    if (lastProp === void 0) {
314      lastProp = "_last";
315    }
316
317    var prev = child._prev,
318        next = child._next;
319
320    if (prev) {
321      prev._next = next;
322    } else if (parent[firstProp] === child) {
323      parent[firstProp] = next;
324    }
325
326    if (next) {
327      next._prev = prev;
328    } else if (parent[lastProp] === child) {
329      parent[lastProp] = prev;
330    }
331
332    child._next = child._prev = child.parent = null;
333  },
334      _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) {
335    child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove(child);
336    child._act = 0;
337  },
338      _uncache = function _uncache(animation, child) {
339    if (animation && (!child || child._end > animation._dur || child._start < 0)) {
340      var a = animation;
341
342      while (a) {
343        a._dirty = 1;
344        a = a.parent;
345      }
346    }
347
348    return animation;
349  },
350      _recacheAncestors = function _recacheAncestors(animation) {
351    var parent = animation.parent;
352
353    while (parent && parent.parent) {
354      parent._dirty = 1;
355      parent.totalDuration();
356      parent = parent.parent;
357    }
358
359    return animation;
360  },
361      _rewindStartAt = function _rewindStartAt(tween, totalTime, suppressEvents, force) {
362    return tween._startAt && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween.vars.immediateRender && !tween.vars.autoRevert || tween._startAt.render(totalTime, true, force));
363  },
364      _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) {
365    return !animation || animation._ts && _hasNoPausedAncestors(animation.parent);
366  },
367      _elapsedCycleDuration = function _elapsedCycleDuration(animation) {
368    return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0;
369  },
370      _animationCycle = function _animationCycle(tTime, cycleDuration) {
371    var whole = Math.floor(tTime /= cycleDuration);
372    return tTime && whole === tTime ? whole - 1 : whole;
373  },
374      _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) {
375    return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur);
376  },
377      _setEnd = function _setEnd(animation) {
378    return animation._end = _roundPrecise(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0));
379  },
380      _alignPlayhead = function _alignPlayhead(animation, totalTime) {
381    var parent = animation._dp;
382
383    if (parent && parent.smoothChildTiming && animation._ts) {
384      animation._start = _roundPrecise(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts));
385
386      _setEnd(animation);
387
388      parent._dirty || _uncache(parent, animation);
389    }
390
391    return animation;
392  },
393      _postAddChecks = function _postAddChecks(timeline, child) {
394    var t;
395
396    if (child._time || child._initted && !child._dur
vendor: 11,458 bytes, lines 396-708
396) {
397      t = _parentToChildTotalTime(timeline.rawTime(), child);
398
399      if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) {
400        child.render(t, true);
401      }
402    }
403
404    if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) {
405      if (timeline._dur < timeline.duration()) {
406        t = timeline;
407
408        while (t._dp) {
409          t.rawTime() >= 0 && t.totalTime(t._tTime);
410          t = t._dp;
411        }
412      }
413
414      timeline._zTime = -_tinyNum;
415    }
416  },
417      _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) {
418    child.parent && _removeFromParent(child);
419    child._start = _roundPrecise((_isNumber(position) ? position : position || timeline !== _globalTimeline ? _parsePosition(timeline, position, child) : timeline._time) + child._delay);
420    child._end = _roundPrecise(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0));
421
422    _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0);
423
424    _isFromOrFromStart(child) || (timeline._recent = child);
425    skipChecks || _postAddChecks(timeline, child);
426    timeline._ts < 0 && _alignPlayhead(timeline, timeline._tTime);
427    return timeline;
428  },
429      _scrollTrigger = function _scrollTrigger(animation, trigger) {
430    return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation);
431  },
432      _attemptInitTween = function _attemptInitTween(tween, time, force, suppressEvents, tTime) {
433    _initTween(tween, time, tTime);
434
435    if (!tween._initted) {
436      return 1;
437    }
438
439    if (!force && tween._pt && !_reverting && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) {
440      _lazyTweens.push(tween);
441
442      tween._lazy = [tTime, suppressEvents];
443      return 1;
444    }
445  },
446      _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) {
447    var parent = _ref.parent;
448    return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent));
449  },
450      _isFromOrFromStart = function _isFromOrFromStart(_ref2) {
451    var data = _ref2.data;
452    return data === "isFromStart" || data === "isStart";
453  },
454      _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) {
455    var prevRatio = tween.ratio,
456        ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) && !(!tween._initted && _isFromOrFromStart(tween)) || (tween._ts < 0 || tween._dp._ts < 0) && !_isFromOrFromStart(tween)) ? 0 : 1,
457        repeatDelay = tween._rDelay,
458        tTime = 0,
459        pt,
460        iteration,
461        prevIteration;
462
463    if (repeatDelay && tween._repeat) {
464      tTime = _clamp(0, tween._tDur, totalTime);
465      iteration = _animationCycle(tTime, repeatDelay);
466      tween._yoyo && iteration & 1 && (ratio = 1 - ratio);
467
468      if (iteration !== _animationCycle(tween._tTime, repeatDelay)) {
469        prevRatio = 1 - ratio;
470        tween.vars.repeatRefresh && tween._initted && tween.invalidate();
471      }
472    }
473
474    if (ratio !== prevRatio || _reverting || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) {
475      if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents, tTime)) {
476        return;
477      }
478
479      prevIteration = tween._zTime;
480      tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0);
481      suppressEvents || (suppressEvents = totalTime && !prevIteration);
482      tween.ratio = ratio;
483      tween._from && (ratio = 1 - ratio);
484      tween._time = 0;
485      tween._tTime = tTime;
486      pt = tween._pt;
487
488      while (pt) {
489        pt.r(ratio, pt.d);
490        pt = pt._next;
491      }
492
493      totalTime < 0 && _rewindStartAt(tween, totalTime, suppressEvents, true);
494      tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate");
495      tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat");
496
497      if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) {
498        ratio && _removeFromParent(tween, 1);
499
500        if (!suppressEvents && !_reverting) {
501          _callback(tween, ratio ? "onComplete" : "onReverseComplete", true);
502
503          tween._prom && tween._prom();
504        }
505      }
506    } else if (!tween._zTime) {
507      tween._zTime = totalTime;
508    }
509  },
510      _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) {
511    var child;
512
513    if (time > prevTime) {
514      child = animation._first;
515
516      while (child && child._start <= time) {
517        if (child.data === "isPause" && child._start > prevTime) {
518          return child;
519        }
520
521        child = child._next;
522      }
523    } else {
524      child = animation._last;
525
526      while (child && child._start >= time) {
527        if (child.data === "isPause" && child._start < prevTime) {
528          return child;
529        }
530
531        child = child._prev;
532      }
533    }
534  },
535      _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) {
536    var repeat = animation._repeat,
537        dur = _roundPrecise(duration) || 0,
538        totalProgress = animation._tTime / animation._tDur;
539    totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur);
540    animation._dur = dur;
541    animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _roundPrecise(dur * (repeat + 1) + animation._rDelay * repeat);
542    totalProgress > 0 && !leavePlayhead && _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress);
543    animation.parent && _setEnd(animation);
544    skipUncache || _uncache(animation.parent, animation);
545    return animation;
546  },
547      _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) {
548    return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur);
549  },
550      _zeroPosition = {
551    _start: 0,
552    endTime: _emptyFunc,
553    totalDuration: _emptyFunc
554  },
555      _parsePosition = function _parsePosition(animation, position, percentAnimation) {
556    var labels = animation.labels,
557        recent = animation._recent || _zeroPosition,
558        clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur,
559        i,
560        offset,
561        isPercent;
562
563    if (_isString(position) && (isNaN(position) || position in labels)) {
564      offset = position.charAt(0);
565      isPercent = position.substr(-1) === "%";
566      i = position.indexOf("=");
567
568      if (offset === "<" || offset === ">") {
569        i >= 0 && (position = position.replace(/=/, ""));
570        return (offset === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0) * (isPercent ? (i < 0 ? recent : percentAnimation).totalDuration() / 100 : 1);
571      }
572
573      if (i < 0) {
574        position in labels || (labels[position] = clippedDuration);
575        return labels[position];
576      }
577
578      offset = parseFloat(position.charAt(i - 1) + position.substr(i + 1));
579
580      if (isPercent && percentAnimation) {
581        offset = offset / 100 * (_isArray(percentAnimation) ? percentAnimation[0] : percentAnimation).totalDuration();
582      }
583
584      return i > 1 ? _parsePosition(animation, position.substr(0, i - 1), percentAnimation) + offset : clippedDuration + offset;
585    }
586
587    return position == null ? clippedDuration : +position;
588  },
589      _createTweenType = function _createTweenType(type, params, timeline) {
590    var isLegacy = _isNumber(params[1]),
591        varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1),
592        vars = params[varsIndex],
593        irVars,
594        parent;
595
596    isLegacy && (vars.duration = params[1]);
597    vars.parent = timeline;
598
599    if (type) {
600      irVars = vars;
601      parent = timeline;
602
603      while (parent && !("immediateRender" in irVars)) {
604        irVars = parent.vars.defaults || {};
605        parent = _isNotFalse(parent.vars.inherit) && parent.parent;
606      }
607
608      vars.immediateRender = _isNotFalse(irVars.immediateRender);
609      type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1];
610    }
611
612    return new Tween(params[0], vars, params[varsIndex + 1]);
613  },
614      _conditionalReturn = function _conditionalReturn(value, func) {
615    return value || value === 0 ? func(value) : func;
616  },
617      _clamp = function _clamp(min, max, value) {
618    return value < min ? min : value > max ? max : value;
619  },
620      getUnit = function getUnit(value, v) {
621    return !_isString(value) || !(v = _unitExp.exec(value)) ? "" : v[1];
622  },
623      clamp = function clamp(min, max, value) {
624    return _conditionalReturn(value, function (v) {
625      return _clamp(min, max, v);
626    });
627  },
628      _slice = [].slice,
629      _isArrayLike = function _isArrayLike(value, nonEmpty) {
630    return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win;
631  },
632      _flatten = function _flatten(ar, leaveStrings, accumulator) {
633    if (accumulator === void 0) {
634      accumulator = [];
635    }
636
637    return ar.forEach(function (value) {
638      var _accumulator;
639
640      return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value);
641    }) || accumulator;
642  },
643      toArray = function toArray(value, scope, leaveStrings) {
644    return _context && !scope && _context.selector ? _context.selector(value) : _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call((scope || _doc).querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : [];
645  },
646      selector = function selector(value) {
647    value = toArray(value)[0] || _warn("Invalid scope") || {};
648    return function (v) {
649      var el = value.current || value.nativeElement || value;
650      return toArray(v, el.querySelectorAll ? el : el === value ? _warn("Invalid scope") || _doc.createElement("div") : value);
651    };
652  },
653      shuffle = function shuffle(a) {
654    return a.sort(function () {
655      return .5 - Math.random();
656    });
657  },
658      distribute = function distribute(v) {
659    if (_isFunction(v)) {
660      return v;
661    }
662
663    var vars = _isObject(v) ? v : {
664      each: v
665    },
666        ease = _parseEase(vars.ease),
667        from = vars.from || 0,
668        base = parseFloat(vars.base) || 0,
669        cache = {},
670        isDecimal = from > 0 && from < 1,
671        ratios = isNaN(from) || isDecimal,
672        axis = vars.axis,
673        ratioX = from,
674        ratioY = from;
675
676    if (_isString(from)) {
677      ratioX = ratioY = {
678        center: .5,
679        edges: .5,
680        end: 1
681      }[from] || 0;
682    } else if (!isDecimal && ratios) {
683      ratioX = from[0];
684      ratioY = from[1];
685    }
686
687    return function (i, target, a) {
688      var l = (a || vars).length,
689          distances = cache[l],
690          originX,
691          originY,
692          x,
693          y,
694          d,
695          j,
696          max,
697          min,
698          wrapAt;
699
700      if (!distances) {
701        wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1];
702
703        if (!wrapAt) {
704          max = -_bigNum;
705
706          while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {}
707
708          wrapAt
vendor: 3,154 bytes, lines 708-798
708--;
709        }
710
711        distances = cache[l] = [];
712        originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt;
713        originY = wrapAt === _bigNum ? 0 : ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0;
714        max = 0;
715        min = _bigNum;
716
717        for (j = 0; j < l; j++) {
718          x = j % wrapAt - originX;
719          y = originY - (j / wrapAt | 0);
720          distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x);
721          d > max && (max = d);
722          d < min && (min = d);
723        }
724
725        from === "random" && shuffle(distances);
726        distances.max = max - min;
727        distances.min = min;
728        distances.v = l = (parseFloat(vars.amount) || parseFloat(vars.each) * (wrapAt > l ? l - 1 : !axis ? Math.max(wrapAt, l / wrapAt) : axis === "y" ? l / wrapAt : wrapAt) || 0) * (from === "edges" ? -1 : 1);
729        distances.b = l < 0 ? base - l : base;
730        distances.u = getUnit(vars.amount || vars.each) || 0;
731        ease = ease && l < 0 ? _invertEase(ease) : ease;
732      }
733
734      l = (distances[i] - distances.min) / distances.max || 0;
735      return _roundPrecise(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u;
736    };
737  },
738      _roundModifier = function _roundModifier(v) {
739    var p = Math.pow(10, ((v + "").split(".")[1] || "").length);
740    return function (raw) {
741      var n = _roundPrecise(Math.round(parseFloat(raw) / v) * v * p);
742
743      return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw));
744    };
745  },
746      snap = function snap(snapTo, value) {
747    var isArray = _isArray(snapTo),
748        radius,
749        is2D;
750
751    if (!isArray && _isObject(snapTo)) {
752      radius = isArray = snapTo.radius || _bigNum;
753
754      if (snapTo.values) {
755        snapTo = toArray(snapTo.values);
756
757        if (is2D = !_isNumber(snapTo[0])) {
758          radius *= radius;
759        }
760      } else {
761        snapTo = _roundModifier(snapTo.increment);
762      }
763    }
764
765    return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) {
766      is2D = snapTo(raw);
767      return Math.abs(is2D - raw) <= radius ? is2D : raw;
768    } : function (raw) {
769      var x = parseFloat(is2D ? raw.x : raw),
770          y = parseFloat(is2D ? raw.y : 0),
771          min = _bigNum,
772          closest = 0,
773          i = snapTo.length,
774          dx,
775          dy;
776
777      while (i--) {
778        if (is2D) {
779          dx = snapTo[i].x - x;
780          dy = snapTo[i].y - y;
781          dx = dx * dx + dy * dy;
782        } else {
783          dx = Math.abs(snapTo[i] - x);
784        }
785
786        if (dx < min) {
787          min = dx;
788          closest = i;
789        }
790      }
791
792      closest = !radius || min <= radius ? snapTo[closest] : raw;
793      return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw);
794    });
795  },
796      random = function random(min, max, roundingIncrement, returnFunction) {
797    return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () {
798      return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e
vendor: 4,891 bytes, lines 798-960
798-5) && (returnFunction = roundingIncrement < 1 ? Math.pow(10, (roundingIncrement + "").length - 2) : 1) && Math.floor(Math.round((min - roundingIncrement / 2 + Math.random() * (max - min + roundingIncrement * .99)) / roundingIncrement) * roundingIncrement * returnFunction) / returnFunction;
799    });
800  },
801      pipe = function pipe() {
802    for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) {
803      functions[_key] = arguments[_key];
804    }
805
806    return function (value) {
807      return functions.reduce(function (v, f) {
808        return f(v);
809      }, value);
810    };
811  },
812      unitize = function unitize(func, unit) {
813    return function (value) {
814      return func(parseFloat(value)) + (unit || getUnit(value));
815    };
816  },
817      normalize = function normalize(min, max, value) {
818    return mapRange(min, max, 0, 1, value);
819  },
820      _wrapArray = function _wrapArray(a, wrapper, value) {
821    return _conditionalReturn(value, function (index) {
822      return a[~~wrapper(index)];
823    });
824  },
825      wrap = function wrap(min, max, value) {
826    var range = max - min;
827    return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) {
828      return (range + (value - min) % range) % range + min;
829    });
830  },
831      wrapYoyo = function wrapYoyo(min, max, value) {
832    var range = max - min,
833        total = range * 2;
834    return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) {
835      value = (total + (value - min) % total) % total || 0;
836      return min + (value > range ? total - value : value);
837    });
838  },
839      _replaceRandom = function _replaceRandom(value) {
840    var prev = 0,
841        s = "",
842        i,
843        nums,
844        end,
845        isArray;
846
847    while (~(i = value.indexOf("random(", prev))) {
848      end = value.indexOf(")", i);
849      isArray = value.charAt(i + 7) === "[";
850      nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp);
851      s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5);
852      prev = end + 1;
853    }
854
855    return s + value.substr(prev, value.length - prev);
856  },
857      mapRange = function mapRange(inMin, inMax, outMin, outMax, value) {
858    var inRange = inMax - inMin,
859        outRange = outMax - outMin;
860    return _conditionalReturn(value, function (value) {
861      return outMin + ((value - inMin) / inRange * outRange || 0);
862    });
863  },
864      interpolate = function interpolate(start, end, progress, mutate) {
865    var func = isNaN(start + end) ? 0 : function (p) {
866      return (1 - p) * start + p * end;
867    };
868
869    if (!func) {
870      var isString = _isString(start),
871          master = {},
872          p,
873          i,
874          interpolators,
875          l,
876          il;
877
878      progress === true && (mutate = 1) && (progress = null);
879
880      if (isString) {
881        start = {
882          p: start
883        };
884        end = {
885          p: end
886        };
887      } else if (_isArray(start) && !_isArray(end)) {
888        interpolators = [];
889        l = start.length;
890        il = l - 2;
891
892        for (i = 1; i < l; i++) {
893          interpolators.push(interpolate(start[i - 1], start[i]));
894        }
895
896        l--;
897
898        func = function func(p) {
899          p *= l;
900          var i = Math.min(il, ~~p);
901          return interpolators[i](p - i);
902        };
903
904        progress = end;
905      } else if (!mutate) {
906        start = _merge(_isArray(start) ? [] : {}, start);
907      }
908
909      if (!interpolators) {
910        for (p in end) {
911          _addPropTween.call(master, start, p, "get", end[p]);
912        }
913
914        func = function func(p) {
915          return _renderPropTweens(p, master) || (isString ? start.p : start);
916        };
917      }
918    }
919
920    return _conditionalReturn(progress, func);
921  },
922      _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) {
923    var labels = timeline.labels,
924        min = _bigNum,
925        p,
926        distance,
927        label;
928
929    for (p in labels) {
930      distance = labels[p] - fromTime;
931
932      if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) {
933        label = p;
934        min = distance;
935      }
936    }
937
938    return label;
939  },
940      _callback = function _callback(animation, type, executeLazyFirst) {
941    var v = animation.vars,
942        callback = v[type],
943        prevContext = _context,
944        context = animation._ctx,
945        params,
946        scope,
947        result;
948
949    if (!callback) {
950      return;
951    }
952
953    params = v[type + "Params"];
954    scope = v.callbackScope || animation;
955    executeLazyFirst && _lazyTweens.length && _lazyRender();
956    context && (_context = context);
957    result = params ? callback.apply(scope, params) : callback.call(scope);
958    _context = prevContext;
959    return result;
960  },
vendor: 7,656 bytes, lines 961-1246
961      _interrupt = function _interrupt(animation) {
962    _removeFromParent(animation);
963
964    animation.scrollTrigger && animation.scrollTrigger.kill(!!_reverting);
965    animation.progress() < 1 && _callback(animation, "onInterrupt");
966    return animation;
967  },
968      _quickTween,
969      _createPlugin = function _createPlugin(config) {
970    config = !config.name && config["default"] || config;
971
972    var name = config.name,
973        isFunc = _isFunction(config),
974        Plugin = name && !isFunc && config.init ? function () {
975      this._props = [];
976    } : config,
977        instanceDefaults = {
978      init: _emptyFunc,
979      render: _renderPropTweens,
980      add: _addPropTween,
981      kill: _killPropTweensOf,
982      modifier: _addPluginModifier,
983      rawVars: 0
984    },
985        statics = {
986      targetTest: 0,
987      get: 0,
988      getSetter: _getSetter,
989      aliases: {},
990      register: 0
991    };
992
993    _wake();
994
995    if (config !== Plugin) {
996      if (_plugins[name]) {
997        return;
998      }
999
1000      _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics));
1001
1002      _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics)));
1003
1004      _plugins[Plugin.prop = name] = Plugin;
1005
1006      if (config.targetTest) {
1007        _harnessPlugins.push(Plugin);
1008
1009        _reservedProps[name] = 1;
1010      }
1011
1012      name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin";
1013    }
1014
1015    _addGlobal(name, Plugin);
1016
1017    config.register && config.register(gsap, Plugin, PropTween);
1018  },
1019      _255 = 255,
1020      _colorLookup = {
1021    aqua: [0, _255, _255],
1022    lime: [0, _255, 0],
1023    silver: [192, 192, 192],
1024    black: [0, 0, 0],
1025    maroon: [128, 0, 0],
1026    teal: [0, 128, 128],
1027    blue: [0, 0, _255],
1028    navy: [0, 0, 128],
1029    white: [_255, _255, _255],
1030    olive: [128, 128, 0],
1031    yellow: [_255, _255, 0],
1032    orange: [_255, 165, 0],
1033    gray: [128, 128, 128],
1034    purple: [128, 0, 128],
1035    green: [0, 128, 0],
1036    red: [_255, 0, 0],
1037    pink: [_255, 192, 203],
1038    cyan: [0, _255, _255],
1039    transparent: [_255, _255, _255, 0]
1040  },
1041      _hue = function _hue(h, m1, m2) {
1042    h += h < 0 ? 1 : h > 1 ? -1 : 0;
1043    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;
1044  },
1045      splitColor = function splitColor(v, toHSL, forceAlpha) {
1046    var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0,
1047        r,
1048        g,
1049        b,
1050        h,
1051        s,
1052        l,
1053        max,
1054        min,
1055        d,
1056        wasHSL;
1057
1058    if (!a) {
1059      if (v.substr(-1) === ",") {
1060        v = v.substr(0, v.length - 1);
1061      }
1062
1063      if (_colorLookup[v]) {
1064        a = _colorLookup[v];
1065      } else if (v.charAt(0) === "#") {
1066        if (v.length < 6) {
1067          r = v.charAt(1);
1068          g = v.charAt(2);
1069          b = v.charAt(3);
1070          v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : "");
1071        }
1072
1073        if (v.length === 9) {
1074          a = parseInt(v.substr(1, 6), 16);
1075          return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255];
1076        }
1077
1078        v = parseInt(v.substr(1), 16);
1079        a = [v >> 16, v >> 8 & _255, v & _255];
1080      } else if (v.substr(0, 3) === "hsl") {
1081        a = wasHSL = v.match(_strictNumExp);
1082
1083        if (!toHSL) {
1084          h = +a[0] % 360 / 360;
1085          s = +a[1] / 100;
1086          l = +a[2] / 100;
1087          g = l <= .5 ? l * (s + 1) : l + s - l * s;
1088          r = l * 2 - g;
1089          a.length > 3 && (a[3] *= 1);
1090          a[0] = _hue(h + 1 / 3, r, g);
1091          a[1] = _hue(h, r, g);
1092          a[2] = _hue(h - 1 / 3, r, g);
1093        } else if (~v.indexOf("=")) {
1094          a = v.match(_numExp);
1095          forceAlpha && a.length < 4 && (a[3] = 1);
1096          return a;
1097        }
1098      } else {
1099        a = v.match(_strictNumExp) || _colorLookup.transparent;
1100      }
1101
1102      a = a.map(Number);
1103    }
1104
1105    if (toHSL && !wasHSL) {
1106      r = a[0] / _255;
1107      g = a[1] / _255;
1108      b = a[2] / _255;
1109      max = Math.max(r, g, b);
1110      min = Math.min(r, g, b);
1111      l = (max + min) / 2;
1112
1113      if (max === min) {
1114        h = s = 0;
1115      } else {
1116        d = max - min;
1117        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1118        h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
1119        h *= 60;
1120      }
1121
1122      a[0] = ~~(h + .5);
1123      a[1] = ~~(s * 100 + .5);
1124      a[2] = ~~(l * 100 + .5);
1125    }
1126
1127    forceAlpha && a.length < 4 && (a[3] = 1);
1128    return a;
1129  },
1130      _colorOrderData = function _colorOrderData(v) {
1131    var values = [],
1132        c = [],
1133        i = -1;
1134    v.split(_colorExp).forEach(function (v) {
1135      var a = v.match(_numWithUnitExp) || [];
1136      values.push.apply(values, a);
1137      c.push(i += a.length + 1);
1138    });
1139    values.c = c;
1140    return values;
1141  },
1142      _formatColors = function _formatColors(s, toHSL, orderMatchData) {
1143    var result = "",
1144        colors = (s + result).match(_colorExp),
1145        type = toHSL ? "hsla(" : "rgba(",
1146        i = 0,
1147        c,
1148        shell,
1149        d,
1150        l;
1151
1152    if (!colors) {
1153      return s;
1154    }
1155
1156    colors = colors.map(function (color) {
1157      return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")";
1158    });
1159
1160    if (orderMatchData) {
1161      d = _colorOrderData(s);
1162      c = orderMatchData.c;
1163
1164      if (c.join(result) !== d.c.join(result)) {
1165        shell = s.replace(_colorExp, "1").split(_numWithUnitExp);
1166        l = shell.length - 1;
1167
1168        for (; i < l; i++) {
1169          result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift());
1170        }
1171      }
1172    }
1173
1174    if (!shell) {
1175      shell = s.split(_colorExp);
1176      l = shell.length - 1;
1177
1178      for (; i < l; i++) {
1179        result += shell[i] + colors[i];
1180      }
1181    }
1182
1183    return result + shell[l];
1184  },
1185      _colorExp = function () {
1186    var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b",
1187        p;
1188
1189    for (p in _colorLookup) {
1190      s += "|" + p + "\\b";
1191    }
1192
1193    return new RegExp(s + ")", "gi");
1194  }(),
1195      _hslExp = /hsl[a]?\(/,
1196      _colorStringFilter = function _colorStringFilter(a) {
1197    var combined = a.join(" "),
1198        toHSL;
1199    _colorExp.lastIndex = 0;
1200
1201    if (_colorExp.test(combined)) {
1202      toHSL = _hslExp.test(combined);
1203      a[1] = _formatColors(a[1], toHSL);
1204      a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1]));
1205      return true;
1206    }
1207  },
1208      _tickerActive,
1209      _ticker = function () {
1210    var _getTime = Date.now,
1211        _lagThreshold = 500,
1212        _adjustedLag = 33,
1213        _startTime = _getTime(),
1214        _lastUpdate = _startTime,
1215        _gap = 1000 / 240,
1216        _nextTime = _gap,
1217        _listeners = [],
1218        _id,
1219        _req,
1220        _raf,
1221        _self,
1222        _delta,
1223        _i,
1224        _tick = function _tick(v) {
1225      var elapsed = _getTime() - _lastUpdate,
1226          manual = v === true,
1227          overlap,
1228          dispatch,
1229          time,
1230          frame;
1231
1232      elapsed > _lagThreshold && (_startTime += elapsed - _adjustedLag);
1233      _lastUpdate += elapsed;
1234      time = _lastUpdate - _startTime;
1235      overlap = time - _nextTime;
1236
1237      if (overlap > 0 || manual) {
1238        frame = ++_self.frame;
1239        _delta = time - _self.time * 1000;
1240        _self.time = time = time / 1000;
1241        _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap);
1242        dispatch = 1;
1243      }
1244
1245      manual || (_id = _req(_tick));
1246
vendor: 4,239 bytes, lines 1247-1383
1247      if (dispatch) {
1248        for (_i = 0; _i < _listeners.length; _i++) {
1249          _listeners[_i](time, _delta, frame, v);
1250        }
1251      }
1252    };
1253
1254    _self = {
1255      time: 0,
1256      frame: 0,
1257      tick: function tick() {
1258        _tick(true);
1259      },
1260      deltaRatio: function deltaRatio(fps) {
1261        return _delta / (1000 / (fps || 60));
1262      },
1263      wake: function wake() {
1264        if (_coreReady) {
1265          if (!_coreInitted && _windowExists()) {
1266            _win = _coreInitted = window;
1267            _doc = _win.document || {};
1268            _globals.gsap = gsap;
1269            (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version);
1270
1271            _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {});
1272
1273            _raf = _win.requestAnimationFrame;
1274          }
1275
1276          _id && _self.sleep();
1277
1278          _req = _raf || function (f) {
1279            return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0);
1280          };
1281
1282          _tickerActive = 1;
1283
1284          _tick(2);
1285        }
1286      },
1287      sleep: function sleep() {
1288        (_raf ? _win.cancelAnimationFrame : clearTimeout)(_id);
1289        _tickerActive = 0;
1290        _req = _emptyFunc;
1291      },
1292      lagSmoothing: function lagSmoothing(threshold, adjustedLag) {
1293        _lagThreshold = threshold || 1 / _tinyNum;
1294        _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
1295      },
1296      fps: function fps(_fps) {
1297        _gap = 1000 / (_fps || 240);
1298        _nextTime = _self.time * 1000 + _gap;
1299      },
1300      add: function add(callback, once, prioritize) {
1301        var func = once ? function (t, d, f, v) {
1302          callback(t, d, f, v);
1303
1304          _self.remove(func);
1305        } : callback;
1306
1307        _self.remove(callback);
1308
1309        _listeners[prioritize ? "unshift" : "push"](func);
1310
1311        _wake();
1312
1313        return func;
1314      },
1315      remove: function remove(callback, i) {
1316        ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--;
1317      },
1318      _listeners: _listeners
1319    };
1320    return _self;
1321  }(),
1322      _wake = function _wake() {
1323    return !_tickerActive && _ticker.wake();
1324  },
1325      _easeMap = {},
1326      _customEaseExp = /^[\d.\-M][\d.\-,\s]/,
1327      _quotesExp = /["']/g,
1328      _parseObjectInString = function _parseObjectInString(value) {
1329    var obj = {},
1330        split = value.substr(1, value.length - 3).split(":"),
1331        key = split[0],
1332        i = 1,
1333        l = split.length,
1334        index,
1335        val,
1336        parsedVal;
1337
1338    for (; i < l; i++) {
1339      val = split[i];
1340      index = i !== l - 1 ? val.lastIndexOf(",") : val.length;
1341      parsedVal = val.substr(0, index);
1342      obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal;
1343      key = val.substr(index + 1).trim();
1344    }
1345
1346    return obj;
1347  },
1348      _valueInParentheses = function _valueInParentheses(value) {
1349    var open = value.indexOf("(") + 1,
1350        close = value.indexOf(")"),
1351        nested = value.indexOf("(", open);
1352    return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close);
1353  },
1354      _configEaseFromString = function _configEaseFromString(name) {
1355    var split = (name + "").split("("),
1356        ease = _easeMap[split[0]];
1357    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;
1358  },
1359      _invertEase = function _invertEase(ease) {
1360    return function (p) {
1361      return 1 - ease(1 - p);
1362    };
1363  },
1364      _propagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) {
1365    var child = timeline._first,
1366        ease;
1367
1368    while (child) {
1369      if (child instanceof Timeline) {
1370        _propagateYoyoEase(child, isYoyo);
1371      } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) {
1372        if (child.timeline) {
1373          _propagateYoyoEase(child.timeline, isYoyo);
1374        } else {
1375          ease = child._ease;
1376          child._ease = child._yEase;
1377          child._yEase = ease;
1378          child._yoyo = isYoyo;
1379        }
1380      }
1381
1382      child = child._next;
1383    }
vendor: 3,445 bytes, lines 1383-1494
1383
1384  },
1385      _parseEase = function _parseEase(ease, defaultEase) {
1386    return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase;
1387  },
1388      _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) {
1389    if (easeOut === void 0) {
1390      easeOut = function easeOut(p) {
1391        return 1 - easeIn(1 - p);
1392      };
1393    }
1394
1395    if (easeInOut === void 0) {
1396      easeInOut = function easeInOut(p) {
1397        return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2;
1398      };
1399    }
1400
1401    var ease = {
1402      easeIn: easeIn,
1403      easeOut: easeOut,
1404      easeInOut: easeInOut
1405    },
1406        lowercaseName;
1407
1408    _forEachName(names, function (name) {
1409      _easeMap[name] = _globals[name] = ease;
1410      _easeMap[lowercaseName = name.toLowerCase()] = easeOut;
1411
1412      for (var p in ease) {
1413        _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p];
1414      }
1415    });
1416
1417    return ease;
1418  },
1419      _easeInOutFromOut = function _easeInOutFromOut(easeOut) {
1420    return function (p) {
1421      return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2;
1422    };
1423  },
1424      _configElastic = function _configElastic(type, amplitude, period) {
1425    var p1 = amplitude >= 1 ? amplitude : 1,
1426        p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1),
1427        p3 = p2 / _2PI * (Math.asin(1 / p1) || 0),
1428        easeOut = function easeOut(p) {
1429      return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1;
1430    },
1431        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1432      return 1 - easeOut(1 - p);
1433    } : _easeInOutFromOut(easeOut);
1434
1435    p2 = _2PI / p2;
1436
1437    ease.config = function (amplitude, period) {
1438      return _configElastic(type, amplitude, period);
1439    };
1440
1441    return ease;
1442  },
1443      _configBack = function _configBack(type, overshoot) {
1444    if (overshoot === void 0) {
1445      overshoot = 1.70158;
1446    }
1447
1448    var easeOut = function easeOut(p) {
1449      return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0;
1450    },
1451        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1452      return 1 - easeOut(1 - p);
1453    } : _easeInOutFromOut(easeOut);
1454
1455    ease.config = function (overshoot) {
1456      return _configBack(type, overshoot);
1457    };
1458
1459    return ease;
1460  };
1461
1462  _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) {
1463    var power = i < 5 ? i + 1 : i;
1464
1465    _insertEase(name + ",Power" + (power - 1), i ? function (p) {
1466      return Math.pow(p, power);
1467    } : function (p) {
1468      return p;
1469    }, function (p) {
1470      return 1 - Math.pow(1 - p, power);
1471    }, function (p) {
1472      return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2;
1473    });
1474  });
1475
1476  _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn;
1477
1478  _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic());
1479
1480  (function (n, c) {
1481    var n1 = 1 / c,
1482        n2 = 2 * n1,
1483        n3 = 2.5 * n1,
1484        easeOut = function easeOut(p) {
1485      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;
1486    };
1487
1488    _insertEase("Bounce", function (p) {
1489      return 1 - easeOut(1 - p);
1490    }, easeOut);
1491  })(7.5625, 2.75);
1492
1493  _insertEase("Expo", function (p) {
1494    return 
vendor: 6,314 bytes, lines 1494-1684
1494p ? Math.pow(2, 10 * (p - 1)) : 0;
1495  });
1496
1497  _insertEase("Circ", function (p) {
1498    return -(_sqrt(1 - p * p) - 1);
1499  });
1500
1501  _insertEase("Sine", function (p) {
1502    return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1;
1503  });
1504
1505  _insertEase("Back", _configBack("in"), _configBack("out"), _configBack());
1506
1507  _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = {
1508    config: function config(steps, immediateStart) {
1509      if (steps === void 0) {
1510        steps = 1;
1511      }
1512
1513      var p1 = 1 / steps,
1514          p2 = steps + (immediateStart ? 0 : 1),
1515          p3 = immediateStart ? 1 : 0,
1516          max = 1 - _tinyNum;
1517      return function (p) {
1518        return ((p2 * _clamp(0, max, p) | 0) + p3) * p1;
1519      };
1520    }
1521  };
1522  _defaults.ease = _easeMap["quad.out"];
1523
1524  _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) {
1525    return _callbackNames += name + "," + name + "Params,";
1526  });
1527
1528  var GSCache = function GSCache(target, harness) {
1529    this.id = _gsID++;
1530    target._gsap = this;
1531    this.target = target;
1532    this.harness = harness;
1533    this.get = harness ? harness.get : _getProperty;
1534    this.set = harness ? harness.getSetter : _getSetter;
1535  };
1536  var Animation = function () {
1537    function Animation(vars) {
1538      this.vars = vars;
1539      this._delay = +vars.delay || 0;
1540
1541      if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) {
1542        this._rDelay = vars.repeatDelay || 0;
1543        this._yoyo = !!vars.yoyo || !!vars.yoyoEase;
1544      }
1545
1546      this._ts = 1;
1547
1548      _setDuration(this, +vars.duration, 1, 1);
1549
1550      this.data = vars.data;
1551
1552      if (_context) {
1553        this._ctx = _context;
1554
1555        _context.data.push(this);
1556      }
1557
1558      _tickerActive || _ticker.wake();
1559    }
1560
1561    var _proto = Animation.prototype;
1562
1563    _proto.delay = function delay(value) {
1564      if (value || value === 0) {
1565        this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay);
1566        this._delay = value;
1567        return this;
1568      }
1569
1570      return this._delay;
1571    };
1572
1573    _proto.duration = function duration(value) {
1574      return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur;
1575    };
1576
1577    _proto.totalDuration = function totalDuration(value) {
1578      if (!arguments.length) {
1579        return this._tDur;
1580      }
1581
1582      this._dirty = 0;
1583      return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1));
1584    };
1585
1586    _proto.totalTime = function totalTime(_totalTime, suppressEvents) {
1587      _wake();
1588
1589      if (!arguments.length) {
1590        return this._tTime;
1591      }
1592
1593      var parent = this._dp;
1594
1595      if (parent && parent.smoothChildTiming && this._ts) {
1596        _alignPlayhead(this, _totalTime);
1597
1598        !parent._dp || parent.parent || _postAddChecks(parent, this);
1599
1600        while (parent && parent.parent) {
1601          if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) {
1602            parent.totalTime(parent._tTime, true);
1603          }
1604
1605          parent = parent.parent;
1606        }
1607
1608        if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) {
1609          _addToTimeline(this._dp, this, this._start - this._delay);
1610        }
1611      }
1612
1613      if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) {
1614        this._ts || (this._pTime = _totalTime);
1615
1616        _lazySafeRender(this, _totalTime, suppressEvents);
1617      }
1618
1619      return this;
1620    };
1621
1622    _proto.time = function time(value, suppressEvents) {
1623      return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % (this._dur + this._rDelay) || (value ? this._dur : 0), suppressEvents) : this._time;
1624    };
1625
1626    _proto.totalProgress = function totalProgress(value, suppressEvents) {
1627      return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.ratio;
1628    };
1629
1630    _proto.progress = function progress(value, suppressEvents) {
1631      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;
1632    };
1633
1634    _proto.iteration = function iteration(value, suppressEvents) {
1635      var cycleDuration = this.duration() + this._rDelay;
1636
1637      return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1;
1638    };
1639
1640    _proto.timeScale = function timeScale(value) {
1641      if (!arguments.length) {
1642        return this._rts === -_tinyNum ? 0 : this._rts;
1643      }
1644
1645      if (this._rts === value) {
1646        return this;
1647      }
1648
1649      var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime;
1650      this._rts = +value || 0;
1651      this._ts = this._ps || value === -_tinyNum ? 0 : this._rts;
1652      this.totalTime(_clamp(-this._delay, this._tDur, tTime), true);
1653
1654      _setEnd(this);
1655
1656      return _recacheAncestors(this);
1657    };
1658
1659    _proto.paused = function paused(value) {
1660      if (!arguments.length) {
1661        return this._ps;
1662      }
1663
1664      if (this._ps !== value) {
1665        this._ps = value;
1666
1667        if (value) {
1668          this._pTime = this._tTime || Math.max(-this._delay, this.rawTime());
1669          this._ts = this._act = 0;
1670        } else {
1671          _wake();
1672
1673          this._ts = this._rts;
1674          this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && Math.abs(this._zTime) !== _tinyNum && (this._tTime -= _tinyNum));
1675        }
1676      }
1677
1678      return this;
1679    };
1680
1681    _proto.startTime = function startTime(value) {
1682      if (arguments.length) {
1683        this._start = value;
1684        var parent = this.parent || this._dp;
vendor: 3,424 bytes, lines 1685-1797
1685        parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay);
1686        return this;
1687      }
1688
1689      return this._start;
1690    };
1691
1692    _proto.endTime = function endTime(includeRepeats) {
1693      return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts || 1);
1694    };
1695
1696    _proto.rawTime = function rawTime(wrapRepeats) {
1697      var parent = this.parent || this._dp;
1698      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);
1699    };
1700
1701    _proto.revert = function revert(config) {
1702      if (config === void 0) {
1703        config = _revertConfig;
1704      }
1705
1706      var prevIsReverting = _reverting;
1707      _reverting = config;
1708
1709      if (this._initted || this._startAt) {
1710        this.timeline && this.timeline.revert(config);
1711        this.totalTime(-0.01, config.suppressEvents);
1712      }
1713
1714      this.data !== "nested" && config.kill !== false && this.kill();
1715      _reverting = prevIsReverting;
1716      return this;
1717    };
1718
1719    _proto.globalTime = function globalTime(rawTime) {
1720      var animation = this,
1721          time = arguments.length ? rawTime : animation.rawTime();
1722
1723      while (animation) {
1724        time = animation._start + time / (animation._ts || 1);
1725        animation = animation._dp;
1726      }
1727
1728      return !this.parent && this.vars.immediateRender ? -1 : time;
1729    };
1730
1731    _proto.repeat = function repeat(value) {
1732      if (arguments.length) {
1733        this._repeat = value === Infinity ? -2 : value;
1734        return _onUpdateTotalDuration(this);
1735      }
1736
1737      return this._repeat === -2 ? Infinity : this._repeat;
1738    };
1739
1740    _proto.repeatDelay = function repeatDelay(value) {
1741      if (arguments.length) {
1742        var time = this._time;
1743        this._rDelay = value;
1744
1745        _onUpdateTotalDuration(this);
1746
1747        return time ? this.time(time) : this;
1748      }
1749
1750      return this._rDelay;
1751    };
1752
1753    _proto.yoyo = function yoyo(value) {
1754      if (arguments.length) {
1755        this._yoyo = value;
1756        return this;
1757      }
1758
1759      return this._yoyo;
1760    };
1761
1762    _proto.seek = function seek(position, suppressEvents) {
1763      return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents));
1764    };
1765
1766    _proto.restart = function restart(includeDelay, suppressEvents) {
1767      return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents));
1768    };
1769
1770    _proto.play = function play(from, suppressEvents) {
1771      from != null && this.seek(from, suppressEvents);
1772      return this.reversed(false).paused(false);
1773    };
1774
1775    _proto.reverse = function reverse(from, suppressEvents) {
1776      from != null && this.seek(from || this.totalDuration(), suppressEvents);
1777      return this.reversed(true).paused(false);
1778    };
1779
1780    _proto.pause = function pause(atTime, suppressEvents) {
1781      atTime != null && this.seek(atTime, suppressEvents);
1782      return this.paused(true);
1783    };
1784
1785    _proto.resume = function resume() {
1786      return this.paused(false);
1787    };
1788
1789    _proto.reversed = function reversed(value) {
1790      if (arguments.length) {
1791        !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0));
1792        return this;
1793      }
1794
1795      return this._rts < 0;
1796    };
1797
vendor: 8,586 bytes, lines 1798-2069
1798    _proto.invalidate = function invalidate() {
1799      this._initted = this._act = 0;
1800      this._zTime = -_tinyNum;
1801      return this;
1802    };
1803
1804    _proto.isActive = function isActive() {
1805      var parent = this.parent || this._dp,
1806          start = this._start,
1807          rawTime;
1808      return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum);
1809    };
1810
1811    _proto.eventCallback = function eventCallback(type, callback, params) {
1812      var vars = this.vars;
1813
1814      if (arguments.length > 1) {
1815        if (!callback) {
1816          delete vars[type];
1817        } else {
1818          vars[type] = callback;
1819          params && (vars[type + "Params"] = params);
1820          type === "onUpdate" && (this._onUpdate = callback);
1821        }
1822
1823        return this;
1824      }
1825
1826      return vars[type];
1827    };
1828
1829    _proto.then = function then(onFulfilled) {
1830      var self = this;
1831      return new Promise(function (resolve) {
1832        var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough,
1833            _resolve = function _resolve() {
1834          var _then = self.then;
1835          self.then = null;
1836          _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then);
1837          resolve(f);
1838          self.then = _then;
1839        };
1840
1841        if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) {
1842          _resolve();
1843        } else {
1844          self._prom = _resolve;
1845        }
1846      });
1847    };
1848
1849    _proto.kill = function kill() {
1850      _interrupt(this);
1851    };
1852
1853    return Animation;
1854  }();
1855
1856  _setDefaults(Animation.prototype, {
1857    _time: 0,
1858    _start: 0,
1859    _end: 0,
1860    _tTime: 0,
1861    _tDur: 0,
1862    _dirty: 0,
1863    _repeat: 0,
1864    _yoyo: false,
1865    parent: null,
1866    _initted: false,
1867    _rDelay: 0,
1868    _ts: 1,
1869    _dp: 0,
1870    ratio: 0,
1871    _zTime: -_tinyNum,
1872    _prom: 0,
1873    _ps: false,
1874    _rts: 1
1875  });
1876
1877  var Timeline = function (_Animation) {
1878    _inheritsLoose(Timeline, _Animation);
1879
1880    function Timeline(vars, position) {
1881      var _this;
1882
1883      if (vars === void 0) {
1884        vars = {};
1885      }
1886
1887      _this = _Animation.call(this, vars) || this;
1888      _this.labels = {};
1889      _this.smoothChildTiming = !!vars.smoothChildTiming;
1890      _this.autoRemoveChildren = !!vars.autoRemoveChildren;
1891      _this._sort = _isNotFalse(vars.sortChildren);
1892      _globalTimeline && _addToTimeline(vars.parent || _globalTimeline, _assertThisInitialized(_this), position);
1893      vars.reversed && _this.reverse();
1894      vars.paused && _this.paused(true);
1895      vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger);
1896      return _this;
1897    }
1898
1899    var _proto2 = Timeline.prototype;
1900
1901    _proto2.to = function to(targets, vars, position) {
1902      _createTweenType(0, arguments, this);
1903
1904      return this;
1905    };
1906
1907    _proto2.from = function from(targets, vars, position) {
1908      _createTweenType(1, arguments, this);
1909
1910      return this;
1911    };
1912
1913    _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) {
1914      _createTweenType(2, arguments, this);
1915
1916      return this;
1917    };
1918
1919    _proto2.set = function set(targets, vars, position) {
1920      vars.duration = 0;
1921      vars.parent = this;
1922      _inheritDefaults(vars).repeatDelay || (vars.repeat = 0);
1923      vars.immediateRender = !!vars.immediateRender;
1924      new Tween(targets, vars, _parsePosition(this, position), 1);
1925      return this;
1926    };
1927
1928    _proto2.call = function call(callback, params, position) {
1929      return _addToTimeline(this, Tween.delayedCall(0, callback, params), position);
1930    };
1931
1932    _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1933      vars.duration = duration;
1934      vars.stagger = vars.stagger || stagger;
1935      vars.onComplete = onCompleteAll;
1936      vars.onCompleteParams = onCompleteAllParams;
1937      vars.parent = this;
1938      new Tween(targets, vars, _parsePosition(this, position));
1939      return this;
1940    };
1941
1942    _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1943      vars.runBackwards = 1;
1944      _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender);
1945      return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams);
1946    };
1947
1948    _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) {
1949      toVars.startAt = fromVars;
1950      _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender);
1951      return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams);
1952    };
1953
1954    _proto2.render = function render(totalTime, suppressEvents, force) {
1955      var prevTime = this._time,
1956          tDur = this._dirty ? this.totalDuration() : this._tDur,
1957          dur = this._dur,
1958          tTime = totalTime <= 0 ? 0 : _roundPrecise(totalTime),
1959          crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur),
1960          time,
1961          child,
1962          next,
1963          iteration,
1964          cycleDuration,
1965          prevPaused,
1966          pauseTween,
1967          timeScale,
1968          prevStart,
1969          prevIteration,
1970          yoyo,
1971          isYoyo;
1972      this !== _globalTimeline && tTime > tDur && totalTime >= 0 && (tTime = tDur);
1973
1974      if (tTime !== this._tTime || force || crossingStart) {
1975        if (prevTime !== this._time && dur) {
1976          tTime += this._time - prevTime;
1977          totalTime += this._time - prevTime;
1978        }
1979
1980        time = tTime;
1981        prevStart = this._start;
1982        timeScale = this._ts;
1983        prevPaused = !timeScale;
1984
1985        if (crossingStart) {
1986          dur || (prevTime = this._zTime);
1987          (totalTime || !suppressEvents) && (this._zTime = totalTime);
1988        }
1989
1990        if (this._repeat) {
1991          yoyo = this._yoyo;
1992          cycleDuration = dur + this._rDelay;
1993
1994          if (this._repeat < -1 && totalTime < 0) {
1995            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
1996          }
1997
1998          time = _roundPrecise(tTime % cycleDuration);
1999
2000          if (tTime === tDur) {
2001            iteration = this._repeat;
2002            time = dur;
2003          } else {
2004            iteration = ~~(tTime / cycleDuration);
2005
2006            if (iteration && iteration === tTime / cycleDuration) {
2007              time = dur;
2008              iteration--;
2009            }
2010
2011            time > dur && (time = dur);
2012          }
2013
2014          prevIteration = _animationCycle(this._tTime, cycleDuration);
2015          !prevTime && this._tTime && prevIteration !== iteration && (prevIteration = iteration);
2016
2017          if (yoyo && iteration & 1) {
2018            time = dur - time;
2019            isYoyo = 1;
2020          }
2021
2022          if (iteration !== prevIteration && !this._lock) {
2023            var rewinding = yoyo && prevIteration & 1,
2024                doesWrap = rewinding === (yoyo && iteration & 1);
2025            iteration < prevIteration && (rewinding = !rewinding);
2026            prevTime = rewinding ? 0 : dur;
2027            this._lock = 1;
2028            this.render(prevTime || (isYoyo ? 0 : _roundPrecise(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0;
2029            this._tTime = tTime;
2030            !suppressEvents && this.parent && _callback(this, "onRepeat");
2031            this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1);
2032
2033            if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) {
2034              return this;
2035            }
2036
2037            dur = this._dur;
2038            tDur = this._tDur;
2039
2040            if (doesWrap) {
2041              this._lock = 2;
2042              prevTime = rewinding ? dur : -0.0001;
2043              this.render(prevTime, true);
2044              this.vars.repeatRefresh && !isYoyo && this.invalidate();
2045            }
2046
2047            this._lock = 0;
2048
2049            if (!this._ts && !prevPaused) {
2050              return this;
2051            }
2052
2053            _propagateYoyoEase(this, isYoyo);
2054          }
2055        }
2056
2057        if (this._hasPause && !this._forcing && this._lock < 2) {
2058          pauseTween = _findNextPauseTween(this, _roundPrecise(prevTime), _roundPrecise(time));
2059
2060          if (pauseTween) {
2061            tTime -= time - (time = pauseTween._start);
2062          }
2063        }
2064
2065        this._tTime = tTime;
2066        this._time = time;
2067        this._act = !timeScale;
2068
2069        if (!this._initted) {
vendor: 15,188 bytes, lines 2070-2602
2070          this._onUpdate = this.vars.onUpdate;
2071          this._initted = 1;
2072          this._zTime = totalTime;
2073          prevTime = 0;
2074        }
2075
2076        if (!prevTime && time && !suppressEvents) {
2077          _callback(this, "onStart");
2078
2079          if (this._tTime !== tTime) {
2080            return this;
2081          }
2082        }
2083
2084        if (time >= prevTime && totalTime >= 0) {
2085          child = this._first;
2086
2087          while (child) {
2088            next = child._next;
2089
2090            if ((child._act || time >= child._start) && child._ts && pauseTween !== child) {
2091              if (child.parent !== this) {
2092                return this.render(totalTime, suppressEvents, force);
2093              }
2094
2095              child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force);
2096
2097              if (time !== this._time || !this._ts && !prevPaused) {
2098                pauseTween = 0;
2099                next && (tTime += this._zTime = -_tinyNum);
2100                break;
2101              }
2102            }
2103
2104            child = next;
2105          }
2106        } else {
2107          child = this._last;
2108          var adjustedTime = totalTime < 0 ? totalTime : time;
2109
2110          while (child) {
2111            next = child._prev;
2112
2113            if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) {
2114              if (child.parent !== this) {
2115                return this.render(totalTime, suppressEvents, force);
2116              }
2117
2118              child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force || _reverting && (child._initted || child._startAt));
2119
2120              if (time !== this._time || !this._ts && !prevPaused) {
2121                pauseTween = 0;
2122                next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum);
2123                break;
2124              }
2125            }
2126
2127            child = next;
2128          }
2129        }
2130
2131        if (pauseTween && !suppressEvents) {
2132          this.pause();
2133          pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1;
2134
2135          if (this._ts) {
2136            this._start = prevStart;
2137
2138            _setEnd(this);
2139
2140            return this.render(totalTime, suppressEvents, force);
2141          }
2142        }
2143
2144        this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true);
2145        if (tTime === tDur && this._tTime >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) {
2146          (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
2147
2148          if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime || !tDur)) {
2149            _callback(this, tTime === tDur && totalTime >= 0 ? "onComplete" : "onReverseComplete", true);
2150
2151            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
2152          }
2153        }
2154      }
2155
2156      return this;
2157    };
2158
2159    _proto2.add = function add(child, position) {
2160      var _this2 = this;
2161
2162      _isNumber(position) || (position = _parsePosition(this, position, child));
2163
2164      if (!(child instanceof Animation)) {
2165        if (_isArray(child)) {
2166          child.forEach(function (obj) {
2167            return _this2.add(obj, position);
2168          });
2169          return this;
2170        }
2171
2172        if (_isString(child)) {
2173          return this.addLabel(child, position);
2174        }
2175
2176        if (_isFunction(child)) {
2177          child = Tween.delayedCall(0, child);
2178        } else {
2179          return this;
2180        }
2181      }
2182
2183      return this !== child ? _addToTimeline(this, child, position) : this;
2184    };
2185
2186    _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) {
2187      if (nested === void 0) {
2188        nested = true;
2189      }
2190
2191      if (tweens === void 0) {
2192        tweens = true;
2193      }
2194
2195      if (timelines === void 0) {
2196        timelines = true;
2197      }
2198
2199      if (ignoreBeforeTime === void 0) {
2200        ignoreBeforeTime = -_bigNum;
2201      }
2202
2203      var a = [],
2204          child = this._first;
2205
2206      while (child) {
2207        if (child._start >= ignoreBeforeTime) {
2208          if (child instanceof Tween) {
2209            tweens && a.push(child);
2210          } else {
2211            timelines && a.push(child);
2212            nested && a.push.apply(a, child.getChildren(true, tweens, timelines));
2213          }
2214        }
2215
2216        child = child._next;
2217      }
2218
2219      return a;
2220    };
2221
2222    _proto2.getById = function getById(id) {
2223      var animations = this.getChildren(1, 1, 1),
2224          i = animations.length;
2225
2226      while (i--) {
2227        if (animations[i].vars.id === id) {
2228          return animations[i];
2229        }
2230      }
2231    };
2232
2233    _proto2.remove = function remove(child) {
2234      if (_isString(child)) {
2235        return this.removeLabel(child);
2236      }
2237
2238      if (_isFunction(child)) {
2239        return this.killTweensOf(child);
2240      }
2241
2242      _removeLinkedListItem(this, child);
2243
2244      if (child === this._recent) {
2245        this._recent = this._last;
2246      }
2247
2248      return _uncache(this);
2249    };
2250
2251    _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) {
2252      if (!arguments.length) {
2253        return this._tTime;
2254      }
2255
2256      this._forcing = 1;
2257
2258      if (!this._dp && this._ts) {
2259        this._start = _roundPrecise(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts));
2260      }
2261
2262      _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents);
2263
2264      this._forcing = 0;
2265      return this;
2266    };
2267
2268    _proto2.addLabel = function addLabel(label, position) {
2269      this.labels[label] = _parsePosition(this, position);
2270      return this;
2271    };
2272
2273    _proto2.removeLabel = function removeLabel(label) {
2274      delete this.labels[label];
2275      return this;
2276    };
2277
2278    _proto2.addPause = function addPause(position, callback, params) {
2279      var t = Tween.delayedCall(0, callback || _emptyFunc, params);
2280      t.data = "isPause";
2281      this._hasPause = 1;
2282      return _addToTimeline(this, t, _parsePosition(this, position));
2283    };
2284
2285    _proto2.removePause = function removePause(position) {
2286      var child = this._first;
2287      position = _parsePosition(this, position);
2288
2289      while (child) {
2290        if (child._start === position && child.data === "isPause") {
2291          _removeFromParent(child);
2292        }
2293
2294        child = child._next;
2295      }
2296    };
2297
2298    _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) {
2299      var tweens = this.getTweensOf(targets, onlyActive),
2300          i = tweens.length;
2301
2302      while (i--) {
2303        _overwritingTween !== tweens[i] && tweens[i].kill(targets, props);
2304      }
2305
2306      return this;
2307    };
2308
2309    _proto2.getTweensOf = function getTweensOf(targets, onlyActive) {
2310      var a = [],
2311          parsedTargets = toArray(targets),
2312          child = this._first,
2313          isGlobalTime = _isNumber(onlyActive),
2314          children;
2315
2316      while (child) {
2317        if (child instanceof Tween) {
2318          if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) {
2319            a.push(child);
2320          }
2321        } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) {
2322          a.push.apply(a, children);
2323        }
2324
2325        child = child._next;
2326      }
2327
2328      return a;
2329    };
2330
2331    _proto2.tweenTo = function tweenTo(position, vars) {
2332      vars = vars || {};
2333
2334      var tl = this,
2335          endTime = _parsePosition(tl, position),
2336          _vars = vars,
2337          startAt = _vars.startAt,
2338          _onStart = _vars.onStart,
2339          onStartParams = _vars.onStartParams,
2340          immediateRender = _vars.immediateRender,
2341          initted,
2342          tween = Tween.to(tl, _setDefaults({
2343        ease: vars.ease || "none",
2344        lazy: false,
2345        immediateRender: false,
2346        time: endTime,
2347        overwrite: "auto",
2348        duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum,
2349        onStart: function onStart() {
2350          tl.pause();
2351
2352          if (!initted) {
2353            var duration = vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale());
2354            tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true);
2355            initted = 1;
2356          }
2357
2358          _onStart && _onStart.apply(tween, onStartParams || []);
2359        }
2360      }, vars));
2361
2362      return immediateRender ? tween.render(0) : tween;
2363    };
2364
2365    _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) {
2366      return this.tweenTo(toPosition, _setDefaults({
2367        startAt: {
2368          time: _parsePosition(this, fromPosition)
2369        }
2370      }, vars));
2371    };
2372
2373    _proto2.recent = function recent() {
2374      return this._recent;
2375    };
2376
2377    _proto2.nextLabel = function nextLabel(afterTime) {
2378      if (afterTime === void 0) {
2379        afterTime = this._time;
2380      }
2381
2382      return _getLabelInDirection(this, _parsePosition(this, afterTime));
2383    };
2384
2385    _proto2.previousLabel = function previousLabel(beforeTime) {
2386      if (beforeTime === void 0) {
2387        beforeTime = this._time;
2388      }
2389
2390      return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1);
2391    };
2392
2393    _proto2.currentLabel = function currentLabel(value) {
2394      return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum);
2395    };
2396
2397    _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) {
2398      if (ignoreBeforeTime === void 0) {
2399        ignoreBeforeTime = 0;
2400      }
2401
2402      var child = this._first,
2403          labels = this.labels,
2404          p;
2405
2406      while (child) {
2407        if (child._start >= ignoreBeforeTime) {
2408          child._start += amount;
2409          child._end += amount;
2410        }
2411
2412        child = child._next;
2413      }
2414
2415      if (adjustLabels) {
2416        for (p in labels) {
2417          if (labels[p] >= ignoreBeforeTime) {
2418            labels[p] += amount;
2419          }
2420        }
2421      }
2422
2423      return _uncache(this);
2424    };
2425
2426    _proto2.invalidate = function invalidate(soft) {
2427      var child = this._first;
2428      this._lock = 0;
2429
2430      while (child) {
2431        child.invalidate(soft);
2432        child = child._next;
2433      }
2434
2435      return _Animation.prototype.invalidate.call(this, soft);
2436    };
2437
2438    _proto2.clear = function clear(includeLabels) {
2439      if (includeLabels === void 0) {
2440        includeLabels = true;
2441      }
2442
2443      var child = this._first,
2444          next;
2445
2446      while (child) {
2447        next = child._next;
2448        this.remove(child);
2449        child = next;
2450      }
2451
2452      this._dp && (this._time = this._tTime = this._pTime = 0);
2453      includeLabels && (this.labels = {});
2454      return _uncache(this);
2455    };
2456
2457    _proto2.totalDuration = function totalDuration(value) {
2458      var max = 0,
2459          self = this,
2460          child = self._last,
2461          prevStart = _bigNum,
2462          prev,
2463          start,
2464          parent;
2465
2466      if (arguments.length) {
2467        return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value));
2468      }
2469
2470      if (self._dirty) {
2471        parent = self.parent;
2472
2473        while (child) {
2474          prev = child._prev;
2475          child._dirty && child.totalDuration();
2476          start = child._start;
2477
2478          if (start > prevStart && self._sort && child._ts && !self._lock) {
2479            self._lock = 1;
2480            _addToTimeline(self, child, start - child._delay, 1)._lock = 0;
2481          } else {
2482            prevStart = start;
2483          }
2484
2485          if (start < 0 && child._ts) {
2486            max -= start;
2487
2488            if (!parent && !self._dp || parent && parent.smoothChildTiming) {
2489              self._start += start / self._ts;
2490              self._time -= start;
2491              self._tTime -= start;
2492            }
2493
2494            self.shiftChildren(-start, false, -1e999);
2495            prevStart = 0;
2496          }
2497
2498          child._end > max && child._ts && (max = child._end);
2499          child = prev;
2500        }
2501
2502        _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1);
2503
2504        self._dirty = 0;
2505      }
2506
2507      return self._tDur;
2508    };
2509
2510    Timeline.updateRoot = function updateRoot(time) {
2511      if (_globalTimeline._ts) {
2512        _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline));
2513
2514        _lastRenderedFrame = _ticker.frame;
2515      }
2516
2517      if (_ticker.frame >= _nextGCFrame) {
2518        _nextGCFrame += _config.autoSleep || 120;
2519        var child = _globalTimeline._first;
2520        if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) {
2521          while (child && !child._ts) {
2522            child = child._next;
2523          }
2524
2525          child || _ticker.sleep();
2526        }
2527      }
2528    };
2529
2530    return Timeline;
2531  }(Animation);
2532
2533  _setDefaults(Timeline.prototype, {
2534    _lock: 0,
2535    _hasPause: 0,
2536    _forcing: 0
2537  });
2538
2539  var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) {
2540    var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter),
2541        index = 0,
2542        matchIndex = 0,
2543        result,
2544        startNums,
2545        color,
2546        endNum,
2547        chunk,
2548        startNum,
2549        hasRandom,
2550        a;
2551    pt.b = start;
2552    pt.e = end;
2553    start += "";
2554    end += "";
2555
2556    if (hasRandom = ~end.indexOf("random(")) {
2557      end = _replaceRandom(end);
2558    }
2559
2560    if (stringFilter) {
2561      a = [start, end];
2562      stringFilter(a, target, prop);
2563      start = a[0];
2564      end = a[1];
2565    }
2566
2567    startNums = start.match(_complexStringNumExp) || [];
2568
2569    while (result = _complexStringNumExp.exec(end)) {
2570      endNum = result[0];
2571      chunk = end.substring(index, result.index);
2572
2573      if (color) {
2574        color = (color + 1) % 5;
2575      } else if (chunk.substr(-5) === "rgba(") {
2576        color = 1;
2577      }
2578
2579      if (endNum !== startNums[matchIndex++]) {
2580        startNum = parseFloat(startNums[matchIndex - 1]) || 0;
2581        pt._pt = {
2582          _next: pt._pt,
2583          p: chunk || matchIndex === 1 ? chunk : ",",
2584          s: startNum,
2585          c: endNum.charAt(1) === "=" ? _parseRelative(startNum, endNum) - startNum : parseFloat(endNum) - startNum,
2586          m: color && color < 4 ? Math.round : 0
2587        };
2588        index = _complexStringNumExp.lastIndex;
2589      }
2590    }
2591
2592    pt.c = index < end.length ? end.substring(index, end.length) : "";
2593    pt.fp = funcParam;
2594
2595    if (_relExp.test(end) || hasRandom) {
2596      pt.e = 0;
2597    }
2598
2599    this._pt = pt;
2600    return pt;
2601  },
2602      _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam, optional) {
vendor: 9,749 bytes, lines 2603-2889
2603    _isFunction(end) && (end = end(index || 0, target, targets));
2604    var currentValue = target[prop],
2605        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](),
2606        setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc,
2607        pt;
2608
2609    if (_isString(end)) {
2610      if (~end.indexOf("random(")) {
2611        end = _replaceRandom(end);
2612      }
2613
2614      if (end.charAt(1) === "=") {
2615        pt = _parseRelative(parsedStart, end) + (getUnit(parsedStart) || 0);
2616
2617        if (pt || pt === 0) {
2618          end = pt;
2619        }
2620      }
2621    }
2622
2623    if (!optional || parsedStart !== end || _forceAllPropTweens) {
2624      if (!isNaN(parsedStart * end) && end !== "") {
2625        pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter);
2626        funcParam && (pt.fp = funcParam);
2627        modifier && pt.modifier(modifier, this, target);
2628        return this._pt = pt;
2629      }
2630
2631      !currentValue && !(prop in target) && _missingPlugin(prop, end);
2632      return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam);
2633    }
2634  },
2635      _processVars = function _processVars(vars, index, target, targets, tween) {
2636    _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets));
2637
2638    if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) {
2639      return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars;
2640    }
2641
2642    var copy = {},
2643        p;
2644
2645    for (p in vars) {
2646      copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets);
2647    }
2648
2649    return copy;
2650  },
2651      _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) {
2652    var plugin, pt, ptLookup, i;
2653
2654    if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) {
2655      tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority);
2656
2657      if (tween !== _quickTween) {
2658        ptLookup = tween._ptLookup[tween._targets.indexOf(target)];
2659        i = plugin._props.length;
2660
2661        while (i--) {
2662          ptLookup[plugin._props[i]] = pt;
2663        }
2664      }
2665    }
2666
2667    return plugin;
2668  },
2669      _overwritingTween,
2670      _forceAllPropTweens,
2671      _initTween = function _initTween(tween, time, tTime) {
2672    var vars = tween.vars,
2673        ease = vars.ease,
2674        startAt = vars.startAt,
2675        immediateRender = vars.immediateRender,
2676        lazy = vars.lazy,
2677        onUpdate = vars.onUpdate,
2678        onUpdateParams = vars.onUpdateParams,
2679        callbackScope = vars.callbackScope,
2680        runBackwards = vars.runBackwards,
2681        yoyoEase = vars.yoyoEase,
2682        keyframes = vars.keyframes,
2683        autoRevert = vars.autoRevert,
2684        dur = tween._dur,
2685        prevStartAt = tween._startAt,
2686        targets = tween._targets,
2687        parent = tween.parent,
2688        fullTargets = parent && parent.data === "nested" ? parent.vars.targets : targets,
2689        autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites,
2690        tl = tween.timeline,
2691        cleanVars,
2692        i,
2693        p,
2694        pt,
2695        target,
2696        hasPriority,
2697        gsData,
2698        harness,
2699        plugin,
2700        ptLookup,
2701        index,
2702        harnessVars,
2703        overwritten;
2704    tl && (!keyframes || !ease) && (ease = "none");
2705    tween._ease = _parseEase(ease, _defaults.ease);
2706    tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0;
2707
2708    if (yoyoEase && tween._yoyo && !tween._repeat) {
2709      yoyoEase = tween._yEase;
2710      tween._yEase = tween._ease;
2711      tween._ease = yoyoEase;
2712    }
2713
2714    tween._from = !tl && !!vars.runBackwards;
2715
2716    if (!tl || keyframes && !vars.stagger) {
2717      harness = targets[0] ? _getCache(targets[0]).harness : 0;
2718      harnessVars = harness && vars[harness.prop];
2719      cleanVars = _copyExcluding(vars, _reservedProps);
2720
2721      if (prevStartAt) {
2722        prevStartAt._zTime < 0 && prevStartAt.progress(1);
2723        time < 0 && runBackwards && immediateRender && !autoRevert ? prevStartAt.render(-1, true) : prevStartAt.revert(runBackwards && dur ? _revertConfigNoKill : _startAtRevertConfig);
2724        prevStartAt._lazy = 0;
2725      }
2726
2727      if (startAt) {
2728        _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({
2729          data: "isStart",
2730          overwrite: false,
2731          parent: parent,
2732          immediateRender: true,
2733          lazy: _isNotFalse(lazy),
2734          startAt: null,
2735          delay: 0,
2736          onUpdate: onUpdate,
2737          onUpdateParams: onUpdateParams,
2738          callbackScope: callbackScope,
2739          stagger: 0
2740        }, startAt)));
2741
2742        tween._startAt._dp = 0;
2743        time < 0 && (_reverting || !immediateRender && !autoRevert) && tween._startAt.revert(_revertConfigNoKill);
2744
2745        if (immediateRender) {
2746          if (dur && time <= 0 && tTime <= 0) {
2747            time && (tween._zTime = time);
2748            return;
2749          }
2750        }
2751      } else if (runBackwards && dur) {
2752        if (!prevStartAt) {
2753          time && (immediateRender = false);
2754          p = _setDefaults({
2755            overwrite: false,
2756            data: "isFromStart",
2757            lazy: immediateRender && _isNotFalse(lazy),
2758            immediateRender: immediateRender,
2759            stagger: 0,
2760            parent: parent
2761          }, cleanVars);
2762          harnessVars && (p[harness.prop] = harnessVars);
2763
2764          _removeFromParent(tween._startAt = Tween.set(targets, p));
2765
2766          tween._startAt._dp = 0;
2767          time < 0 && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween._startAt.render(-1, true));
2768          tween._zTime = time;
2769
2770          if (!immediateRender) {
2771            _initTween(tween._startAt, _tinyNum, _tinyNum);
2772          } else if (!time) {
2773            return;
2774          }
2775        }
2776      }
2777
2778      tween._pt = tween._ptCache = 0;
2779      lazy = dur && _isNotFalse(lazy) || lazy && !dur;
2780
2781      for (i = 0; i < targets.length; i++) {
2782        target = targets[i];
2783        gsData = target._gsap || _harness(targets)[i]._gsap;
2784        tween._ptLookup[i] = ptLookup = {};
2785        _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender();
2786        index = fullTargets === targets ? i : fullTargets.indexOf(target);
2787
2788        if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) {
2789          tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority);
2790
2791          plugin._props.forEach(function (name) {
2792            ptLookup[name] = pt;
2793          });
2794
2795          plugin.priority && (hasPriority = 1);
2796        }
2797
2798        if (!harness || harnessVars) {
2799          for (p in cleanVars) {
2800            if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) {
2801              plugin.priority && (hasPriority = 1);
2802            } else {
2803              ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter);
2804            }
2805          }
2806        }
2807
2808        tween._op && tween._op[i] && tween.kill(target, tween._op[i]);
2809
2810        if (autoOverwrite && tween._pt) {
2811          _overwritingTween = tween;
2812
2813          _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(time));
2814
2815          overwritten = !tween.parent;
2816          _overwritingTween = 0;
2817        }
2818
2819        tween._pt && lazy && (_lazyLookup[gsData.id] = 1);
2820      }
2821
2822      hasPriority && _sortPropTweensByPriority(tween);
2823      tween._onInit && tween._onInit(tween);
2824    }
2825
2826    tween._onUpdate = onUpdate;
2827    tween._initted = (!tween._op || tween._pt) && !overwritten;
2828    keyframes && time <= 0 && tl.render(_bigNum, true, true);
2829  },
2830      _updatePropTweens = function _updatePropTweens(tween, property, value, start, startIsRelative, ratio, time) {
2831    var ptCache = (tween._pt && tween._ptCache || (tween._ptCache = {}))[property],
2832        pt,
2833        rootPT,
2834        lookup,
2835        i;
2836
2837    if (!ptCache) {
2838      ptCache = tween._ptCache[property] = [];
2839      lookup = tween._ptLookup;
2840      i = tween._targets.length;
2841
2842      while (i--) {
2843        pt = lookup[i][property];
2844
2845        if (pt && pt.d && pt.d._pt) {
2846          pt = pt.d._pt;
2847
2848          while (pt && pt.p !== property && pt.fp !== property) {
2849            pt = pt._next;
2850          }
2851        }
2852
2853        if (!pt) {
2854          _forceAllPropTweens = 1;
2855          tween.vars[property] = "+=0";
2856
2857          _initTween(tween, time);
2858
2859          _forceAllPropTweens = 0;
2860          return 1;
2861        }
2862
2863        ptCache.push(pt);
2864      }
2865    }
2866
2867    i = ptCache.length;
2868
2869    while (i--) {
2870      rootPT = ptCache[i];
2871      pt = rootPT._pt || rootPT;
2872      pt.s = (start || start === 0) && !startIsRelative ? start : pt.s + (start || 0) + ratio * pt.c;
2873      pt.c = value - pt.s;
2874      rootPT.e && (rootPT.e = _round(value) + getUnit(rootPT.e));
2875      rootPT.b && (rootPT.b = pt.s + getUnit(rootPT.b));
2876    }
2877  },
2878      _addAliasesToVars = function _addAliasesToVars(targets, vars) {
2879    var harness = targets[0] ? _getCache(targets[0]).harness : 0,
2880        propertyAliases = harness && harness.aliases,
2881        copy,
2882        p,
2883        i,
2884        aliases;
2885
2886    if (!propertyAliases) {
2887      return vars;
2888    }
2889
vendor: 4,989 bytes, lines 2890-3032
2890    copy = _merge({}, vars);
2891
2892    for (p in propertyAliases) {
2893      if (p in copy) {
2894        aliases = propertyAliases[p].split(",");
2895        i = aliases.length;
2896
2897        while (i--) {
2898          copy[aliases[i]] = copy[p];
2899        }
2900      }
2901    }
2902
2903    return copy;
2904  },
2905      _parseKeyframe = function _parseKeyframe(prop, obj, allProps, easeEach) {
2906    var ease = obj.ease || easeEach || "power1.inOut",
2907        p,
2908        a;
2909
2910    if (_isArray(obj)) {
2911      a = allProps[prop] || (allProps[prop] = []);
2912      obj.forEach(function (value, i) {
2913        return a.push({
2914          t: i / (obj.length - 1) * 100,
2915          v: value,
2916          e: ease
2917        });
2918      });
2919    } else {
2920      for (p in obj) {
2921        a = allProps[p] || (allProps[p] = []);
2922        p === "ease" || a.push({
2923          t: parseFloat(prop),
2924          v: obj[p],
2925          e: ease
2926        });
2927      }
2928    }
2929  },
2930      _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) {
2931    return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value;
2932  },
2933      _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase,autoRevert",
2934      _staggerPropsToSkip = {};
2935
2936  _forEachName(_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger", function (name) {
2937    return _staggerPropsToSkip[name] = 1;
2938  });
2939
2940  var Tween = function (_Animation2) {
2941    _inheritsLoose(Tween, _Animation2);
2942
2943    function Tween(targets, vars, position, skipInherit) {
2944      var _this3;
2945
2946      if (typeof vars === "number") {
2947        position.duration = vars;
2948        vars = position;
2949        position = null;
2950      }
2951
2952      _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars)) || this;
2953      var _this3$vars = _this3.vars,
2954          duration = _this3$vars.duration,
2955          delay = _this3$vars.delay,
2956          immediateRender = _this3$vars.immediateRender,
2957          stagger = _this3$vars.stagger,
2958          overwrite = _this3$vars.overwrite,
2959          keyframes = _this3$vars.keyframes,
2960          defaults = _this3$vars.defaults,
2961          scrollTrigger = _this3$vars.scrollTrigger,
2962          yoyoEase = _this3$vars.yoyoEase,
2963          parent = vars.parent || _globalTimeline,
2964          parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets),
2965          tl,
2966          i,
2967          copy,
2968          l,
2969          p,
2970          curTarget,
2971          staggerFunc,
2972          staggerVarsToMerge;
2973      _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://greensock.com", !_config.nullTargetWarn) || [];
2974      _this3._ptLookup = [];
2975      _this3._overwrite = overwrite;
2976
2977      if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2978        vars = _this3.vars;
2979        tl = _this3.timeline = new Timeline({
2980          data: "nested",
2981          defaults: defaults || {},
2982          targets: parent && parent.data === "nested" ? parent.vars.targets : parsedTargets
2983        });
2984        tl.kill();
2985        tl.parent = tl._dp = _assertThisInitialized(_this3);
2986        tl._start = 0;
2987
2988        if (stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2989          l = parsedTargets.length;
2990          staggerFunc = stagger && distribute(stagger);
2991
2992          if (_isObject(stagger)) {
2993            for (p in stagger) {
2994              if (~_staggerTweenProps.indexOf(p)) {
2995                staggerVarsToMerge || (staggerVarsToMerge = {});
2996                staggerVarsToMerge[p] = stagger[p];
2997              }
2998            }
2999          }
3000
3001          for (i = 0; i < l; i++) {
3002            copy = _copyExcluding(vars, _staggerPropsToSkip);
3003            copy.stagger = 0;
3004            yoyoEase && (copy.yoyoEase = yoyoEase);
3005            staggerVarsToMerge && _merge(copy, staggerVarsToMerge);
3006            curTarget = parsedTargets[i];
3007            copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets);
3008            copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay;
3009
3010            if (!stagger && l === 1 && copy.delay) {
3011              _this3._delay = delay = copy.delay;
3012              _this3._start += delay;
3013              copy.delay = 0;
3014            }
3015
3016            tl.to(curTarget, copy, staggerFunc ? staggerFunc(i, curTarget, parsedTargets) : 0);
3017            tl._ease = _easeMap.none;
3018          }
3019
3020          tl.duration() ? duration = delay = 0 : _this3.timeline = 0;
3021        } else if (keyframes) {
3022          _inheritDefaults(_setDefaults(tl.vars.defaults, {
3023            ease: "none"
3024          }));
3025
3026          tl._ease = _parseEase(keyframes.ease || vars.ease || "none");
3027          var time = 0,
3028              a,
3029              kf,
3030              v;
3031
3032          if (_isArray(keyframes)) {
vendor: 6,328 bytes, lines 3033-3239
3033            keyframes.forEach(function (frame) {
3034              return tl.to(parsedTargets, frame, ">");
3035            });
3036            tl.duration();
3037          } else {
3038            copy = {};
3039
3040            for (p in keyframes) {
3041              p === "ease" || p === "easeEach" || _parseKeyframe(p, keyframes[p], copy, keyframes.easeEach);
3042            }
3043
3044            for (p in copy) {
3045              a = copy[p].sort(function (a, b) {
3046                return a.t - b.t;
3047              });
3048              time = 0;
3049
3050              for (i = 0; i < a.length; i++) {
3051                kf = a[i];
3052                v = {
3053                  ease: kf.e,
3054                  duration: (kf.t - (i ? a[i - 1].t : 0)) / 100 * duration
3055                };
3056                v[p] = kf.v;
3057                tl.to(parsedTargets, v, time);
3058                time += v.duration;
3059              }
3060            }
3061
3062            tl.duration() < duration && tl.to({}, {
3063              duration: duration - tl.duration()
3064            });
3065          }
3066        }
3067
3068        duration || _this3.duration(duration = tl.duration());
3069      } else {
3070        _this3.timeline = 0;
3071      }
3072
3073      if (overwrite === true && !_suppressOverwrites) {
3074        _overwritingTween = _assertThisInitialized(_this3);
3075
3076        _globalTimeline.killTweensOf(parsedTargets);
3077
3078        _overwritingTween = 0;
3079      }
3080
3081      _addToTimeline(parent, _assertThisInitialized(_this3), position);
3082
3083      vars.reversed && _this3.reverse();
3084      vars.paused && _this3.paused(true);
3085
3086      if (immediateRender || !duration && !keyframes && _this3._start === _roundPrecise(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") {
3087        _this3._tTime = -_tinyNum;
3088
3089        _this3.render(Math.max(0, -delay) || 0);
3090      }
3091
3092      scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger);
3093      return _this3;
3094    }
3095
3096    var _proto3 = Tween.prototype;
3097
3098    _proto3.render = function render(totalTime, suppressEvents, force) {
3099      var prevTime = this._time,
3100          tDur = this._tDur,
3101          dur = this._dur,
3102          isNegative = totalTime < 0,
3103          tTime = totalTime > tDur - _tinyNum && !isNegative ? tDur : totalTime < _tinyNum ? 0 : totalTime,
3104          time,
3105          pt,
3106          iteration,
3107          cycleDuration,
3108          prevIteration,
3109          isYoyo,
3110          ratio,
3111          timeline,
3112          yoyoEase;
3113
3114      if (!dur) {
3115        _renderZeroDurationTween(this, totalTime, suppressEvents, force);
3116      } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== isNegative) {
3117        time = tTime;
3118        timeline = this.timeline;
3119
3120        if (this._repeat) {
3121          cycleDuration = dur + this._rDelay;
3122
3123          if (this._repeat < -1 && isNegative) {
3124            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
3125          }
3126
3127          time = _roundPrecise(tTime % cycleDuration);
3128
3129          if (tTime === tDur) {
3130            iteration = this._repeat;
3131            time = dur;
3132          } else {
3133            iteration = ~~(tTime / cycleDuration);
3134
3135            if (iteration && iteration === tTime / cycleDuration) {
3136              time = dur;
3137              iteration--;
3138            }
3139
3140            time > dur && (time = dur);
3141          }
3142
3143          isYoyo = this._yoyo && iteration & 1;
3144
3145          if (isYoyo) {
3146            yoyoEase = this._yEase;
3147            time = dur - time;
3148          }
3149
3150          prevIteration = _animationCycle(this._tTime, cycleDuration);
3151
3152          if (time === prevTime && !force && this._initted) {
3153            this._tTime = tTime;
3154            return this;
3155          }
3156
3157          if (iteration !== prevIteration) {
3158            timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo);
3159
3160            if (this.vars.repeatRefresh && !isYoyo && !this._lock) {
3161              this._lock = force = 1;
3162              this.render(_roundPrecise(cycleDuration * iteration), true).invalidate()._lock = 0;
3163            }
3164          }
3165        }
3166
3167        if (!this._initted) {
3168          if (_attemptInitTween(this, isNegative ? totalTime : time, force, suppressEvents, tTime)) {
3169            this._tTime = 0;
3170            return this;
3171          }
3172
3173          if (prevTime !== this._time) {
3174            return this;
3175          }
3176
3177          if (dur !== this._dur) {
3178            return this.render(totalTime, suppressEvents, force);
3179          }
3180        }
3181
3182        this._tTime = tTime;
3183        this._time = time;
3184
3185        if (!this._act && this._ts) {
3186          this._act = 1;
3187          this._lazy = 0;
3188        }
3189
3190        this.ratio = ratio = (yoyoEase || this._ease)(time / dur);
3191
3192        if (this._from) {
3193          this.ratio = ratio = 1 - ratio;
3194        }
3195
3196        if (time && !prevTime && !suppressEvents) {
3197          _callback(this, "onStart");
3198
3199          if (this._tTime !== tTime) {
3200            return this;
3201          }
3202        }
3203
3204        pt = this._pt;
3205
3206        while (pt) {
3207          pt.r(ratio, pt.d);
3208          pt = pt._next;
3209        }
3210
3211        timeline && timeline.render(totalTime < 0 ? totalTime : !time && isYoyo ? -_tinyNum : timeline._dur * timeline._ease(time / this._dur), suppressEvents, force) || this._startAt && (this._zTime = totalTime);
3212
3213        if (this._onUpdate && !suppressEvents) {
3214          isNegative && _rewindStartAt(this, totalTime, suppressEvents, force);
3215
3216          _callback(this, "onUpdate");
3217        }
3218
3219        this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat");
3220
3221        if ((tTime === this._tDur || !tTime) && this._tTime === tTime) {
3222          isNegative && !this._onUpdate && _rewindStartAt(this, totalTime, true, true);
3223          (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
3224
3225          if (!suppressEvents && !(isNegative && !prevTime) && (tTime || prevTime || isYoyo)) {
3226            _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true);
3227
3228            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
3229          }
3230        }
3231      }
3232
3233      return this;
3234    };
3235
3236    _proto3.targets = function targets() {
3237      return this._targets;
3238    };
3239
vendor: 1,277 bytes, lines 3240-3273
3240    _proto3.invalidate = function invalidate(soft) {
3241      (!soft || !this.vars.runBackwards) && (this._startAt = 0);
3242      this._pt = this._op = this._onUpdate = this._lazy = this.ratio = 0;
3243      this._ptLookup = [];
3244      this.timeline && this.timeline.invalidate(soft);
3245      return _Animation2.prototype.invalidate.call(this, soft);
3246    };
3247
3248    _proto3.resetTo = function resetTo(property, value, start, startIsRelative) {
3249      _tickerActive || _ticker.wake();
3250      this._ts || this.play();
3251      var time = Math.min(this._dur, (this._dp._time - this._start) * this._ts),
3252          ratio;
3253      this._initted || _initTween(this, time);
3254      ratio = this._ease(time / this._dur);
3255
3256      if (_updatePropTweens(this, property, value, start, startIsRelative, ratio, time)) {
3257        return this.resetTo(property, value, start, startIsRelative);
3258      }
3259
3260      _alignPlayhead(this, 0);
3261
3262      this.parent || _addLinkedListItem(this._dp, this, "_first", "_last", this._dp._sort ? "_start" : 0);
3263      return this.render(0);
3264    };
3265
3266    _proto3.kill = function kill(targets, vars) {
3267      if (vars === void 0) {
3268        vars = "all";
3269      }
3270
3271      if (!targets && (!vars || vars === "all")) {
3272        this._lazy = this._pt = 0;
3273        return this.parent ? _interrupt(this) :
vendor: 7,709 bytes, lines 3273-3553
3273 this;
3274      }
3275
3276      if (this.timeline) {
3277        var tDur = this.timeline.totalDuration();
3278        this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this);
3279        this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1);
3280        return this;
3281      }
3282
3283      var parsedTargets = this._targets,
3284          killingTargets = targets ? toArray(targets) : parsedTargets,
3285          propTweenLookup = this._ptLookup,
3286          firstPT = this._pt,
3287          overwrittenProps,
3288          curLookup,
3289          curOverwriteProps,
3290          props,
3291          p,
3292          pt,
3293          i;
3294
3295      if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) {
3296        vars === "all" && (this._pt = 0);
3297        return _interrupt(this);
3298      }
3299
3300      overwrittenProps = this._op = this._op || [];
3301
3302      if (vars !== "all") {
3303        if (_isString(vars)) {
3304          p = {};
3305
3306          _forEachName(vars, function (name) {
3307            return p[name] = 1;
3308          });
3309
3310          vars = p;
3311        }
3312
3313        vars = _addAliasesToVars(parsedTargets, vars);
3314      }
3315
3316      i = parsedTargets.length;
3317
3318      while (i--) {
3319        if (~killingTargets.indexOf(parsedTargets[i])) {
3320          curLookup = propTweenLookup[i];
3321
3322          if (vars === "all") {
3323            overwrittenProps[i] = vars;
3324            props = curLookup;
3325            curOverwriteProps = {};
3326          } else {
3327            curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {};
3328            props = vars;
3329          }
3330
3331          for (p in props) {
3332            pt = curLookup && curLookup[p];
3333
3334            if (pt) {
3335              if (!("kill" in pt.d) || pt.d.kill(p) === true) {
3336                _removeLinkedListItem(this, pt, "_pt");
3337              }
3338
3339              delete curLookup[p];
3340            }
3341
3342            if (curOverwriteProps !== "all") {
3343              curOverwriteProps[p] = 1;
3344            }
3345          }
3346        }
3347      }
3348
3349      this._initted && !this._pt && firstPT && _interrupt(this);
3350      return this;
3351    };
3352
3353    Tween.to = function to(targets, vars) {
3354      return new Tween(targets, vars, arguments[2]);
3355    };
3356
3357    Tween.from = function from(targets, vars) {
3358      return _createTweenType(1, arguments);
3359    };
3360
3361    Tween.delayedCall = function delayedCall(delay, callback, params, scope) {
3362      return new Tween(callback, 0, {
3363        immediateRender: false,
3364        lazy: false,
3365        overwrite: false,
3366        delay: delay,
3367        onComplete: callback,
3368        onReverseComplete: callback,
3369        onCompleteParams: params,
3370        onReverseCompleteParams: params,
3371        callbackScope: scope
3372      });
3373    };
3374
3375    Tween.fromTo = function fromTo(targets, fromVars, toVars) {
3376      return _createTweenType(2, arguments);
3377    };
3378
3379    Tween.set = function set(targets, vars) {
3380      vars.duration = 0;
3381      vars.repeatDelay || (vars.repeat = 0);
3382      return new Tween(targets, vars);
3383    };
3384
3385    Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) {
3386      return _globalTimeline.killTweensOf(targets, props, onlyActive);
3387    };
3388
3389    return Tween;
3390  }(Animation);
3391
3392  _setDefaults(Tween.prototype, {
3393    _targets: [],
3394    _lazy: 0,
3395    _startAt: 0,
3396    _op: 0,
3397    _onInit: 0
3398  });
3399
3400  _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) {
3401    Tween[name] = function () {
3402      var tl = new Timeline(),
3403          params = _slice.call(arguments, 0);
3404
3405      params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0);
3406      return tl[name].apply(tl, params);
3407    };
3408  });
3409
3410  var _setterPlain = function _setterPlain(target, property, value) {
3411    return target[property] = value;
3412  },
3413      _setterFunc = function _setterFunc(target, property, value) {
3414    return target[property](value);
3415  },
3416      _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) {
3417    return target[property](data.fp, value);
3418  },
3419      _setterAttribute = function _setterAttribute(target, property, value) {
3420    return target.setAttribute(property, value);
3421  },
3422      _getSetter = function _getSetter(target, property) {
3423    return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain;
3424  },
3425      _renderPlain = function _renderPlain(ratio, data) {
3426    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 1000000) / 1000000, data);
3427  },
3428      _renderBoolean = function _renderBoolean(ratio, data) {
3429    return data.set(data.t, data.p, !!(data.s + data.c * ratio), data);
3430  },
3431      _renderComplexString = function _renderComplexString(ratio, data) {
3432    var pt = data._pt,
3433        s = "";
3434
3435    if (!ratio && data.b) {
3436      s = data.b;
3437    } else if (ratio === 1 && data.e) {
3438      s = data.e;
3439    } else {
3440      while (pt) {
3441        s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s;
3442        pt = pt._next;
3443      }
3444
3445      s += data.c;
3446    }
3447
3448    data.set(data.t, data.p, s, data);
3449  },
3450      _renderPropTweens = function _renderPropTweens(ratio, data) {
3451    var pt = data._pt;
3452
3453    while (pt) {
3454      pt.r(ratio, pt.d);
3455      pt = pt._next;
3456    }
3457  },
3458      _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) {
3459    var pt = this._pt,
3460        next;
3461
3462    while (pt) {
3463      next = pt._next;
3464      pt.p === property && pt.modifier(modifier, tween, target);
3465      pt = next;
3466    }
3467  },
3468      _killPropTweensOf = function _killPropTweensOf(property) {
3469    var pt = this._pt,
3470        hasNonDependentRemaining,
3471        next;
3472
3473    while (pt) {
3474      next = pt._next;
3475
3476      if (pt.p === property && !pt.op || pt.op === property) {
3477        _removeLinkedListItem(this, pt, "_pt");
3478      } else if (!pt.dep) {
3479        hasNonDependentRemaining = 1;
3480      }
3481
3482      pt = next;
3483    }
3484
3485    return !hasNonDependentRemaining;
3486  },
3487      _setterWithModifier = function _setterWithModifier(target, property, value, data) {
3488    data.mSet(target, property, data.m.call(data.tween, value, data.mt), data);
3489  },
3490      _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) {
3491    var pt = parent._pt,
3492        next,
3493        pt2,
3494        first,
3495        last;
3496
3497    while (pt) {
3498      next = pt._next;
3499      pt2 = first;
3500
3501      while (pt2 && pt2.pr > pt.pr) {
3502        pt2 = pt2._next;
3503      }
3504
3505      if (pt._prev = pt2 ? pt2._prev : last) {
3506        pt._prev._next = pt;
3507      } else {
3508        first = pt;
3509      }
3510
3511      if (pt._next = pt2) {
3512        pt2._prev = pt;
3513      } else {
3514        last = pt;
3515      }
3516
3517      pt = next;
3518    }
3519
3520    parent._pt = first;
3521  };
3522
3523  var PropTween = function () {
3524    function PropTween(next, target, prop, start, change, renderer, data, setter, priority) {
3525      this.t = target;
3526      this.s = start;
3527      this.c = change;
3528      this.p = prop;
3529      this.r = renderer || _renderPlain;
3530      this.d = data || this;
3531      this.set = setter || _setterPlain;
3532      this.pr = priority || 0;
3533      this._next = next;
3534
3535      if (next) {
3536        next._prev = this;
3537      }
3538    }
3539
3540    var _proto4 = PropTween.prototype;
3541
3542    _proto4.modifier = function modifier(func, tween, target) {
3543      this.mSet = this.mSet || this.set;
3544      this.set = _setterWithModifier;
3545      this.m = func;
3546      this.mt = target;
3547      this.tween = tween;
3548    };
3549
3550    return PropTween;
3551  }();
3552
3553  _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
vendor: 3,674 bytes, lines 3553-3696
3553", function (name) {
3554    return _reservedProps[name] = 1;
3555  });
3556
3557  _globals.TweenMax = _globals.TweenLite = Tween;
3558  _globals.TimelineLite = _globals.TimelineMax = Timeline;
3559  _globalTimeline = new Timeline({
3560    sortChildren: false,
3561    defaults: _defaults,
3562    autoRemoveChildren: true,
3563    id: "root",
3564    smoothChildTiming: true
3565  });
3566  _config.stringFilter = _colorStringFilter;
3567
3568  var _media = [],
3569      _listeners = {},
3570      _emptyArray = [],
3571      _lastMediaTime = 0,
3572      _dispatch = function _dispatch(type) {
3573    return (_listeners[type] || _emptyArray).map(function (f) {
3574      return f();
3575    });
3576  },
3577      _onMediaChange = function _onMediaChange() {
3578    var time = Date.now(),
3579        matches = [];
3580
3581    if (time - _lastMediaTime > 2) {
3582      _dispatch("matchMediaInit");
3583
3584      _media.forEach(function (c) {
3585        var queries = c.queries,
3586            conditions = c.conditions,
3587            match,
3588            p,
3589            anyMatch,
3590            toggled;
3591
3592        for (p in queries) {
3593          match = _win.matchMedia(queries[p]).matches;
3594          match && (anyMatch = 1);
3595
3596          if (match !== conditions[p]) {
3597            conditions[p] = match;
3598            toggled = 1;
3599          }
3600        }
3601
3602        if (toggled) {
3603          c.revert();
3604          anyMatch && matches.push(c);
3605        }
3606      });
3607
3608      _dispatch("matchMediaRevert");
3609
3610      matches.forEach(function (c) {
3611        return c.onMatch(c);
3612      });
3613      _lastMediaTime = time;
3614
3615      _dispatch("matchMedia");
3616    }
3617  };
3618
3619  var Context = function () {
3620    function Context(func, scope) {
3621      this.selector = scope && selector(scope);
3622      this.data = [];
3623      this._r = [];
3624      this.isReverted = false;
3625      func && this.add(func);
3626    }
3627
3628    var _proto5 = Context.prototype;
3629
3630    _proto5.add = function add(name, func, scope) {
3631      if (_isFunction(name)) {
3632        scope = func;
3633        func = name;
3634        name = _isFunction;
3635      }
3636
3637      var self = this,
3638          f = function f() {
3639        var prev = _context,
3640            prevSelector = self.selector,
3641            result;
3642        prev && prev !== self && prev.data.push(self);
3643        scope && (self.selector = selector(scope));
3644        _context = self;
3645        result = func.apply(self, arguments);
3646        _isFunction(result) && self._r.push(result);
3647        _context = prev;
3648        self.selector = prevSelector;
3649        self.isReverted = false;
3650        return result;
3651      };
3652
3653      self.last = f;
3654      return name === _isFunction ? f(self) : name ? self[name] = f : f;
3655    };
3656
3657    _proto5.ignore = function ignore(func) {
3658      var prev = _context;
3659      _context = null;
3660      func(this);
3661      _context = prev;
3662    };
3663
3664    _proto5.getTweens = function getTweens() {
3665      var a = [];
3666      this.data.forEach(function (e) {
3667        return e instanceof Context ? a.push.apply(a, e.getTweens()) : e instanceof Tween && !(e.parent && e.parent.data === "nested") && a.push(e);
3668      });
3669      return a;
3670    };
3671
3672    _proto5.clear = function clear() {
3673      this._r.length = this.data.length = 0;
3674    };
3675
3676    _proto5.kill = function kill(revert, matchMedia) {
3677      var _this4 = this;
3678
3679      if (revert) {
3680        var tweens = this.getTweens();
3681        this.data.forEach(function (t) {
3682          if (t.data === "isFlip") {
3683            t.revert();
3684            t.getChildren(true, true, false).forEach(function (tween) {
3685              return tweens.splice(tweens.indexOf(tween), 1);
3686            });
3687          }
3688        });
3689        tweens.map(function (t) {
3690          return {
3691            g: t.globalTime(0),
3692            t: t
3693          };
3694        }).sort(function (a, b) {
3695          return b.g - a.g || -1;
3696        }
3696).forEach(function (o) {
3697          return o.t.revert(revert);
3698        });
3699        this.data.forEach(function (e) {
3700          return !(e instanceof Animation) && e.revert && e.revert(revert);
3701        });
3702
3703        this._r.forEach(function (f) {
3704          return f(revert, _this4);
3705        });
3706
3707        this.isReverted = true;
3708      } else {
3709        this.data.forEach(function (e) {
3710          return e.kill && e.kill();
3711        });
3712      }
3713
3714      this.clear();
3715
3716      if (matchMedia) {
3717        var i = _media.indexOf(this);
3718
3719        !!~i && _media.splice(i, 1);
3720      }
3721    };
3722
3723    _proto5.revert = function revert(config) {
3724      this.kill(config || {});
3725    };
3726
3727    return Context;
3728  }();
3729
3730  var MatchMedia = function () {
3731    function MatchMedia(scope) {
3732      this.contexts = [];
3733      this.scope = scope;
3734    }
3735
3736    var _proto6 = MatchMedia.prototype;
3737
3738    _proto6.add = function add(conditions, func, scope) {
3739      _isObject(conditions) || (conditions = {
3740        matches: conditions
3741      });
3742      var context = new Context(0, scope || this.scope),
3743          cond = context.conditions = {},
3744          mq,
3745          p,
3746          active;
3747      this.contexts.push(context);
3748      func = context.add("onMatch", func);
3749      context.queries = conditions;
3750
3751      for (p in conditions) {
3752        if (p === "all") {
3753          active = 1;
3754        } else {
3755          mq = _win.matchMedia(conditions[p]);
3756
3757          if (mq) {
3758            _media.indexOf(context) < 0 && _media.push(context);
3759            (cond[p] = mq.matches) && (active = 1);
3760            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
3761          }
3762        }
3763      }
3764
3765      active && func(context);
3766      return this;
3767    };
3768
3769    _proto6.revert = function revert(config) {
3770      this.kill(config || {});
3771    };
3772
3773    _proto6.kill = function kill(revert) {
vendor: 2,486 bytes, lines 3774-3846
3774      this.contexts.forEach(function (c) {
3775        return c.kill(revert, true);
3776      });
3777    };
3778
3779    return MatchMedia;
3780  }();
3781
3782  var _gsap = {
3783    registerPlugin: function registerPlugin() {
3784      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
3785        args[_key2] = arguments[_key2];
3786      }
3787
3788      args.forEach(function (config) {
3789        return _createPlugin(config);
3790      });
3791    },
3792    timeline: function timeline(vars) {
3793      return new Timeline(vars);
3794    },
3795    getTweensOf: function getTweensOf(targets, onlyActive) {
3796      return _globalTimeline.getTweensOf(targets, onlyActive);
3797    },
3798    getProperty: function getProperty(target, property, unit, uncache) {
3799      _isString(target) && (target = toArray(target)[0]);
3800
3801      var getter = _getCache(target || {}).get,
3802          format = unit ? _passThrough : _numericIfPossible;
3803
3804      unit === "native" && (unit = "");
3805      return !target ? target : !property ? function (property, unit, uncache) {
3806        return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3807      } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3808    },
3809    quickSetter: function quickSetter(target, property, unit) {
3810      target = toArray(target);
3811
3812      if (target.length > 1) {
3813        var setters = target.map(function (t) {
3814          return gsap.quickSetter(t, property, unit);
3815        }),
3816            l = setters.length;
3817        return function (value) {
3818          var i = l;
3819
3820          while (i--) {
3821            setters[i](value);
3822          }
3823        };
3824      }
3825
3826      target = target[0] || {};
3827
3828      var Plugin = _plugins[property],
3829          cache = _getCache(target),
3830          p = cache.harness && (cache.harness.aliases || {})[property] || property,
3831          setter = Plugin ? function (value) {
3832        var p = new Plugin();
3833        _quickTween._pt = 0;
3834        p.init(target, unit ? value + unit : value, _quickTween, 0, [target]);
3835        p.render(1, p);
3836        _quickTween._pt && _renderPropTweens(1, _quickTween);
3837      } : cache.set(target, p);
3838
3839      return Plugin ? setter : function (value) {
3840        return setter(target, p, unit ? value + unit : value, cache, 1);
3841      };
3842    },
3843    quickTo: function quickTo(target, property, vars) {
3844      var _merge2;
3845
3846      var tween = gsap.to(target, _merge((_merge2 = {}, _merge2[property] = "+=0.1", _merge2.paused = true, _merge
vendor: 5,649 bytes, lines 3846-4048
38462), vars || {})),
3847          func = function func(value, start, startIsRelative) {
3848        return tween.resetTo(property, value, start, startIsRelative);
3849      };
3850
3851      func.tween = tween;
3852      return func;
3853    },
3854    isTweening: function isTweening(targets) {
3855      return _globalTimeline.getTweensOf(targets, true).length > 0;
3856    },
3857    defaults: function defaults(value) {
3858      value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease));
3859      return _mergeDeep(_defaults, value || {});
3860    },
3861    config: function config(value) {
3862      return _mergeDeep(_config, value || {});
3863    },
3864    registerEffect: function registerEffect(_ref3) {
3865      var name = _ref3.name,
3866          effect = _ref3.effect,
3867          plugins = _ref3.plugins,
3868          defaults = _ref3.defaults,
3869          extendTimeline = _ref3.extendTimeline;
3870      (plugins || "").split(",").forEach(function (pluginName) {
3871        return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin.");
3872      });
3873
3874      _effects[name] = function (targets, vars, tl) {
3875        return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl);
3876      };
3877
3878      if (extendTimeline) {
3879        Timeline.prototype[name] = function (targets, vars, position) {
3880          return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position);
3881        };
3882      }
3883    },
3884    registerEase: function registerEase(name, ease) {
3885      _easeMap[name] = _parseEase(ease);
3886    },
3887    parseEase: function parseEase(ease, defaultEase) {
3888      return arguments.length ? _parseEase(ease, defaultEase) : _easeMap;
3889    },
3890    getById: function getById(id) {
3891      return _globalTimeline.getById(id);
3892    },
3893    exportRoot: function exportRoot(vars, includeDelayedCalls) {
3894      if (vars === void 0) {
3895        vars = {};
3896      }
3897
3898      var tl = new Timeline(vars),
3899          child,
3900          next;
3901      tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming);
3902
3903      _globalTimeline.remove(tl);
3904
3905      tl._dp = 0;
3906      tl._time = tl._tTime = _globalTimeline._time;
3907      child = _globalTimeline._first;
3908
3909      while (child) {
3910        next = child._next;
3911
3912        if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) {
3913          _addToTimeline(tl, child, child._start - child._delay);
3914        }
3915
3916        child = next;
3917      }
3918
3919      _addToTimeline(_globalTimeline, tl, 0);
3920
3921      return tl;
3922    },
3923    context: function context(func, scope) {
3924      return func ? new Context(func, scope) : _context;
3925    },
3926    matchMedia: function matchMedia(scope) {
3927      return new MatchMedia(scope);
3928    },
3929    matchMediaRefresh: function matchMediaRefresh() {
3930      return _media.forEach(function (c) {
3931        var cond = c.conditions,
3932            found,
3933            p;
3934
3935        for (p in cond) {
3936          if (cond[p]) {
3937            cond[p] = false;
3938            found = 1;
3939          }
3940        }
3941
3942        found && c.revert();
3943      }) || _onMediaChange();
3944    },
3945    addEventListener: function addEventListener(type, callback) {
3946      var a = _listeners[type] || (_listeners[type] = []);
3947      ~a.indexOf(callback) || a.push(callback);
3948    },
3949    removeEventListener: function removeEventListener(type, callback) {
3950      var a = _listeners[type],
3951          i = a && a.indexOf(callback);
3952      i >= 0 && a.splice(i, 1);
3953    },
3954    utils: {
3955      wrap: wrap,
3956      wrapYoyo: wrapYoyo,
3957      distribute: distribute,
3958      random: random,
3959      snap: snap,
3960      normalize: normalize,
3961      getUnit: getUnit,
3962      clamp: clamp,
3963      splitColor: splitColor,
3964      toArray: toArray,
3965      selector: selector,
3966      mapRange: mapRange,
3967      pipe: pipe,
3968      unitize: unitize,
3969      interpolate: interpolate,
3970      shuffle: shuffle
3971    },
3972    install: _install,
3973    effects: _effects,
3974    ticker: _ticker,
3975    updateRoot: Timeline.updateRoot,
3976    plugins: _plugins,
3977    globalTimeline: _globalTimeline,
3978    core: {
3979      PropTween: PropTween,
3980      globals: _addGlobal,
3981      Tween: Tween,
3982      Timeline: Timeline,
3983      Animation: Animation,
3984      getCache: _getCache,
3985      _removeLinkedListItem: _removeLinkedListItem,
3986      reverting: function reverting() {
3987        return _reverting;
3988      },
3989      context: function context(toAdd) {
3990        if (toAdd && _context) {
3991          _context.data.push(toAdd);
3992
3993          toAdd._ctx = _context;
3994        }
3995
3996        return _context;
3997      },
3998      suppressOverwrites: function suppressOverwrites(value) {
3999        return _suppressOverwrites = value;
4000      }
4001    }
4002  };
4003
4004  _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) {
4005    return _gsap[name] = Tween[name];
4006  });
4007
4008  _ticker.add(Timeline.updateRoot);
4009
4010  _quickTween = _gsap.to({}, {
4011    duration: 0
4012  });
4013
4014  var _getPluginPropTween = function _getPluginPropTween(plugin, prop) {
4015    var pt = plugin._pt;
4016
4017    while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) {
4018      pt = pt._next;
4019    }
4020
4021    return pt;
4022  },
4023      _addModifiers = function _addModifiers(tween, modifiers) {
4024    var targets = tween._targets,
4025        p,
4026        i,
4027        pt;
4028
4029    for (p in modifiers) {
4030      i = targets.length;
4031
4032      while (i--) {
4033        pt = tween._ptLookup[i][p];
4034
4035        if (pt && (pt = pt.d)) {
4036          if (pt._pt) {
4037            pt = _getPluginPropTween(pt, p);
4038          }
4039
4040          pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p);
4041        }
4042      }
4043    }
4044  },
4045      _buildModifierPlugin = function _buildModifierPlugin(name, modifier) {
4046    return {
4047      name: name,
4048      
vendor: 20,072 bytes, lines 4048-4675
4048rawVars: 1,
4049      init: function init(target, vars, tween) {
4050        tween._onInit = function (tween) {
4051          var temp, p;
4052
4053          if (_isString(vars)) {
4054            temp = {};
4055
4056            _forEachName(vars, function (name) {
4057              return temp[name] = 1;
4058            });
4059
4060            vars = temp;
4061          }
4062
4063          if (modifier) {
4064            temp = {};
4065
4066            for (p in vars) {
4067              temp[p] = modifier(vars[p]);
4068            }
4069
4070            vars = temp;
4071          }
4072
4073          _addModifiers(tween, vars);
4074        };
4075      }
4076    };
4077  };
4078
4079  var gsap = _gsap.registerPlugin({
4080    name: "attr",
4081    init: function init(target, vars, tween, index, targets) {
4082      var p, pt, v;
4083      this.tween = tween;
4084
4085      for (p in vars) {
4086        v = target.getAttribute(p) || "";
4087        pt = this.add(target, "setAttribute", (v || 0) + "", vars[p], index, targets, 0, 0, p);
4088        pt.op = p;
4089        pt.b = v;
4090
4091        this._props.push(p);
4092      }
4093    },
4094    render: function render(ratio, data) {
4095      var pt = data._pt;
4096
4097      while (pt) {
4098        _reverting ? pt.set(pt.t, pt.p, pt.b, pt) : pt.r(ratio, pt.d);
4099        pt = pt._next;
4100      }
4101    }
4102  }, {
4103    name: "endArray",
4104    init: function init(target, value) {
4105      var i = value.length;
4106
4107      while (i--) {
4108        this.add(target, i, target[i] || 0, value[i], 0, 0, 0, 0, 0, 1);
4109      }
4110    }
4111  }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap;
4112  Tween.version = Timeline.version = gsap.version = "3.11.3";
4113  _coreReady = 1;
4114  _windowExists() && _wake();
4115  var Power0 = _easeMap.Power0,
4116      Power1 = _easeMap.Power1,
4117      Power2 = _easeMap.Power2,
4118      Power3 = _easeMap.Power3,
4119      Power4 = _easeMap.Power4,
4120      Linear = _easeMap.Linear,
4121      Quad = _easeMap.Quad,
4122      Cubic = _easeMap.Cubic,
4123      Quart = _easeMap.Quart,
4124      Quint = _easeMap.Quint,
4125      Strong = _easeMap.Strong,
4126      Elastic = _easeMap.Elastic,
4127      Back = _easeMap.Back,
4128      SteppedEase = _easeMap.SteppedEase,
4129      Bounce = _easeMap.Bounce,
4130      Sine = _easeMap.Sine,
4131      Expo = _easeMap.Expo,
4132      Circ = _easeMap.Circ;
4133
4134  var _win$1,
4135      _doc$1,
4136      _docElement,
4137      _pluginInitted,
4138      _tempDiv,
4139      _tempDivStyler,
4140      _recentSetterPlugin,
4141      _reverting$1,
4142      _windowExists$1 = function _windowExists() {
4143    return typeof window !== "undefined";
4144  },
4145      _transformProps = {},
4146      _RAD2DEG = 180 / Math.PI,
4147      _DEG2RAD = Math.PI / 180,
4148      _atan2 = Math.atan2,
4149      _bigNum$1 = 1e8,
4150      _capsExp = /([A-Z])/g,
4151      _horizontalExp = /(left|right|width|margin|padding|x)/i,
4152      _complexExp = /[\s,\(]\S/,
4153      _propertyAliases = {
4154    autoAlpha: "opacity,visibility",
4155    scale: "scaleX,scaleY",
4156    alpha: "opacity"
4157  },
4158      _renderCSSProp = function _renderCSSProp(ratio, data) {
4159    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
4160  },
4161      _renderPropWithEnd = function _renderPropWithEnd(ratio, data) {
4162    return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
4163  },
4164      _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) {
4165    return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data);
4166  },
4167      _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) {
4168    var value = data.s + data.c * ratio;
4169    data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data);
4170  },
4171      _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) {
4172    return data.set(data.t, data.p, ratio ? data.e : data.b, data);
4173  },
4174      _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) {
4175    return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data);
4176  },
4177      _setterCSSStyle = function _setterCSSStyle(target, property, value) {
4178    return target.style[property] = value;
4179  },
4180      _setterCSSProp = function _setterCSSProp(target, property, value) {
4181    return target.style.setProperty(property, value);
4182  },
4183      _setterTransform = function _setterTransform(target, property, value) {
4184    return target._gsap[property] = value;
4185  },
4186      _setterScale = function _setterScale(target, property, value) {
4187    return target._gsap.scaleX = target._gsap.scaleY = value;
4188  },
4189      _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) {
4190    var cache = target._gsap;
4191    cache.scaleX = cache.scaleY = value;
4192    cache.renderTransform(ratio, cache);
4193  },
4194      _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) {
4195    var cache = target._gsap;
4196    cache[property] = value;
4197    cache.renderTransform(ratio, cache);
4198  },
4199      _transformProp = "transform",
4200      _transformOriginProp = _transformProp + "Origin",
4201      _saveStyle = function _saveStyle(property, isNotCSS) {
4202    var _this = this;
4203
4204    var target = this.target,
4205        style = target.style;
4206
4207    if (property in _transformProps) {
4208      this.tfm = this.tfm || {};
4209
4210      if (property !== "transform") {
4211        property = _propertyAliases[property] || property;
4212        ~property.indexOf(",") ? property.split(",").forEach(function (a) {
4213          return _this.tfm[a] = _get(target, a);
4214        }) : this.tfm[property] = target._gsap.x ? target._gsap[property] : _get(target, property);
4215      }
4216
4217      if (this.props.indexOf(_transformProp) >= 0) {
4218        return;
4219      }
4220
4221      if (target._gsap.svg) {
4222        this.svgo = target.getAttribute("data-svg-origin");
4223        this.props.push(_transformOriginProp, isNotCSS, "");
4224      }
4225
4226      property = _transformProp;
4227    }
4228
4229    (style || isNotCSS) && this.props.push(property, isNotCSS, style[property]);
4230  },
4231      _removeIndependentTransforms = function _removeIndependentTransforms(style) {
4232    if (style.translate) {
4233      style.removeProperty("translate");
4234      style.removeProperty("scale");
4235      style.removeProperty("rotate");
4236    }
4237  },
4238      _revertStyle = function _revertStyle() {
4239    var props = this.props,
4240        target = this.target,
4241        style = target.style,
4242        cache = target._gsap,
4243        i,
4244        p;
4245
4246    for (i = 0; i < props.length; i += 3) {
4247      props[i + 1] ? target[props[i]] = props[i + 2] : props[i + 2] ? style[props[i]] = props[i + 2] : style.removeProperty(props[i].replace(_capsExp, "-$1").toLowerCase());
4248    }
4249
4250    if (this.tfm) {
4251      for (p in this.tfm) {
4252        cache[p] = this.tfm[p];
4253      }
4254
4255      if (cache.svg) {
4256        cache.renderTransform();
4257        target.setAttribute("data-svg-origin", this.svgo || "");
4258      }
4259
4260      i = _reverting$1();
4261
4262      if (i && !i.isStart && !style[_transformProp]) {
4263        _removeIndependentTransforms(style);
4264
4265        cache.uncache = 1;
4266      }
4267    }
4268  },
4269      _getStyleSaver = function _getStyleSaver(target, properties) {
4270    var saver = {
4271      target: target,
4272      props: [],
4273      revert: _revertStyle,
4274      save: _saveStyle
4275    };
4276    properties && properties.split(",").forEach(function (p) {
4277      return saver.save(p);
4278    });
4279    return saver;
4280  },
4281      _supports3D,
4282      _createElement = function _createElement(type, ns) {
4283    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
4284    return e.style ? e : _doc$1.createElement(type);
4285  },
4286      _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) {
4287    var cs = getComputedStyle(target);
4288    return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || "";
4289  },
4290      _prefixes = "O,Moz,ms,Ms,Webkit".split(","),
4291      _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) {
4292    var e = element || _tempDiv,
4293        s = e.style,
4294        i = 5;
4295
4296    if (property in s && !preferPrefix) {
4297      return property;
4298    }
4299
4300    property = property.charAt(0).toUpperCase() + property.substr(1);
4301
4302    while (i-- && !(_prefixes[i] + property in s)) {}
4303
4304    return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property;
4305  },
4306      _initCore = function _initCore() {
4307    if (_windowExists$1() && window.document) {
4308      _win$1 = window;
4309      _doc$1 = _win$1.document;
4310      _docElement = _doc$1.documentElement;
4311      _tempDiv = _createElement("div") || {
4312        style: {}
4313      };
4314      _tempDivStyler = _createElement("div");
4315      _transformProp = _checkPropPrefix(_transformProp);
4316      _transformOriginProp = _transformProp + "Origin";
4317      _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0";
4318      _supports3D = !!_checkPropPrefix("perspective");
4319      _reverting$1 = gsap.core.reverting;
4320      _pluginInitted = 1;
4321    }
4322  },
4323      _getBBoxHack = function _getBBoxHack(swapIfPossible) {
4324    var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"),
4325        oldParent = this.parentNode,
4326        oldSibling = this.nextSibling,
4327        oldCSS = this.style.cssText,
4328        bbox;
4329
4330    _docElement.appendChild(svg);
4331
4332    svg.appendChild(this);
4333    this.style.display = "block";
4334
4335    if (swapIfPossible) {
4336      try {
4337        bbox = this.getBBox();
4338        this._gsapBBox = this.getBBox;
4339        this.getBBox = _getBBoxHack;
4340      } catch (e) {}
4341    } else if (this._gsapBBox) {
4342      bbox = this._gsapBBox();
4343    }
4344
4345    if (oldParent) {
4346      if (oldSibling) {
4347        oldParent.insertBefore(this, oldSibling);
4348      } else {
4349        oldParent.appendChild(this);
4350      }
4351    }
4352
4353    _docElement.removeChild(svg);
4354
4355    this.style.cssText = oldCSS;
4356    return bbox;
4357  },
4358      _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) {
4359    var i = attributesArray.length;
4360
4361    while (i--) {
4362      if (target.hasAttribute(attributesArray[i])) {
4363        return target.getAttribute(attributesArray[i]);
4364      }
4365    }
4366  },
4367      _getBBox = function _getBBox(target) {
4368    var bounds;
4369
4370    try {
4371      bounds = target.getBBox();
4372    } catch (error) {
4373      bounds = _getBBoxHack.call(target, true);
4374    }
4375
4376    bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true));
4377    return bounds && !bounds.width && !bounds.x && !bounds.y ? {
4378      x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0,
4379      y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0,
4380      width: 0,
4381      height: 0
4382    } : bounds;
4383  },
4384      _isSVG = function _isSVG(e) {
4385    return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e));
4386  },
4387      _removeProperty = function _removeProperty(target, property) {
4388    if (property) {
4389      var style = target.style;
4390
4391      if (property in _transformProps && property !== _transformOriginProp) {
4392        property = _transformProp;
4393      }
4394
4395      if (style.removeProperty) {
4396        if (property.substr(0, 2) === "ms" || property.substr(0, 6) === "webkit") {
4397          property = "-" + property;
4398        }
4399
4400        style.removeProperty(property.replace(_capsExp, "-$1").toLowerCase());
4401      } else {
4402        style.removeAttribute(property);
4403      }
4404    }
4405  },
4406      _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) {
4407    var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue);
4408    plugin._pt = pt;
4409    pt.b = beginning;
4410    pt.e = end;
4411
4412    plugin._props.push(property);
4413
4414    return pt;
4415  },
4416      _nonConvertibleUnits = {
4417    deg: 1,
4418    rad: 1,
4419    turn: 1
4420  },
4421      _nonStandardLayouts = {
4422    grid: 1,
4423    flex: 1
4424  },
4425      _convertToUnit = function _convertToUnit(target, property, value, unit) {
4426    var curValue = parseFloat(value) || 0,
4427        curUnit = (value + "").trim().substr((curValue + "").length) || "px",
4428        style = _tempDiv.style,
4429        horizontal = _horizontalExp.test(property),
4430        isRootSVG = target.tagName.toLowerCase() === "svg",
4431        measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"),
4432        amount = 100,
4433        toPixels = unit === "px",
4434        toPercent = unit === "%",
4435        px,
4436        parent,
4437        cache,
4438        isSVG;
4439
4440    if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) {
4441      return curValue;
4442    }
4443
4444    curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px"));
4445    isSVG = target.getCTM && _isSVG(target);
4446
4447    if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) {
4448      px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty];
4449      return _round(toPercent ? curValue / px * amount : curValue / 100 * px);
4450    }
4451
4452    style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit);
4453    parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode;
4454
4455    if (isSVG) {
4456      parent = (target.ownerSVGElement || {}).parentNode;
4457    }
4458
4459    if (!parent || parent === _doc$1 || !parent.appendChild) {
4460      parent = _doc$1.body;
4461    }
4462
4463    cache = parent._gsap;
4464
4465    if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time && !cache.uncache) {
4466      return _round(curValue / cache.width * amount);
4467    } else {
4468      (toPercent || curUnit === "%") && !_nonStandardLayouts[_getComputedProperty(parent, "display")] && (style.position = _getComputedProperty(target, "position"));
4469      parent === target && (style.position = "static");
4470      parent.appendChild(_tempDiv);
4471      px = _tempDiv[measureProperty];
4472      parent.removeChild(_tempDiv);
4473      style.position = "absolute";
4474
4475      if (horizontal && toPercent) {
4476        cache = _getCache(parent);
4477        cache.time = _ticker.time;
4478        cache.width = parent[measureProperty];
4479      }
4480    }
4481
4482    return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0);
4483  },
4484      _get = function _get(target, property, unit, uncache) {
4485    var value;
4486    _pluginInitted || _initCore();
4487
4488    if (property in _propertyAliases && property !== "transform") {
4489      property = _propertyAliases[property];
4490
4491      if (~property.indexOf(",")) {
4492        property = property.split(",")[0];
4493      }
4494    }
4495
4496    if (_transformProps[property] && property !== "transform") {
4497      value = _parseTransform(target, uncache);
4498      value = property !== "transformOrigin" ? value[property] : value.svg ? value.origin : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px";
4499    } else {
4500      value = target.style[property];
4501
4502      if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) {
4503        value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0);
4504      }
4505    }
4506
4507    return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value;
4508  },
4509      _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) {
4510    if (!start || start === "none") {
4511      var p = _checkPropPrefix(prop, target, 1),
4512          s = p && _getComputedProperty(target, p, 1);
4513
4514      if (s && s !== start) {
4515        prop = p;
4516        start = s;
4517      } else if (prop === "borderColor") {
4518        start = _getComputedProperty(target, "borderTopColor");
4519      }
4520    }
4521
4522    var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString),
4523        index = 0,
4524        matchIndex = 0,
4525        a,
4526        result,
4527        startValues,
4528        startNum,
4529        color,
4530        startValue,
4531        endValue,
4532        endNum,
4533        chunk,
4534        endUnit,
4535        startUnit,
4536        endValues;
4537    pt.b = start;
4538    pt.e = end;
4539    start += "";
4540    end += "";
4541
4542    if (end === "auto") {
4543      target.style[prop] = end;
4544      end = _getComputedProperty(target, prop) || end;
4545      target.style[prop] = start;
4546    }
4547
4548    a = [start, end];
4549
4550    _colorStringFilter(a);
4551
4552    start = a[0];
4553    end = a[1];
4554    startValues = start.match(_numWithUnitExp) || [];
4555    endValues = end.match(_numWithUnitExp) || [];
4556
4557    if (endValues.length) {
4558      while (result = _numWithUnitExp.exec(end)) {
4559        endValue = result[0];
4560        chunk = end.substring(index, result.index);
4561
4562        if (color) {
4563          color = (color + 1) % 5;
4564        } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") {
4565          color = 1;
4566        }
4567
4568        if (endValue !== (startValue = startValues[matchIndex++] || "")) {
4569          startNum = parseFloat(startValue) || 0;
4570          startUnit = startValue.substr((startNum + "").length);
4571          endValue.charAt(1) === "=" && (endValue = _parseRelative(startNum, endValue) + startUnit);
4572          endNum = parseFloat(endValue);
4573          endUnit = endValue.substr((endNum + "").length);
4574          index = _numWithUnitExp.lastIndex - endUnit.length;
4575
4576          if (!endUnit) {
4577            endUnit = endUnit || _config.units[prop] || startUnit;
4578
4579            if (index === end.length) {
4580              end += endUnit;
4581              pt.e += endUnit;
4582            }
4583          }
4584
4585          if (startUnit !== endUnit) {
4586            startNum = _convertToUnit(target, prop, startValue, endUnit) || 0;
4587          }
4588
4589          pt._pt = {
4590            _next: pt._pt,
4591            p: chunk || matchIndex === 1 ? chunk : ",",
4592            s: startNum,
4593            c: endNum - startNum,
4594            m: color && color < 4 || prop === "zIndex" ? Math.round : 0
4595          };
4596        }
4597      }
4598
4599      pt.c = index < end.length ? end.substring(index, end.length) : "";
4600    } else {
4601      pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue;
4602    }
4603
4604    _relExp.test(end) && (pt.e = 0);
4605    this._pt = pt;
4606    return pt;
4607  },
4608      _keywordToPercent = {
4609    top: "0%",
4610    bottom: "100%",
4611    left: "0%",
4612    right: "100%",
4613    center: "50%"
4614  },
4615      _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) {
4616    var split = value.split(" "),
4617        x = split[0],
4618        y = split[1] || "50%";
4619
4620    if (x === "top" || x === "bottom" || y === "left" || y === "right") {
4621      value = x;
4622      x = y;
4623      y = value;
4624    }
4625
4626    split[0] = _keywordToPercent[x] || x;
4627    split[1] = _keywordToPercent[y] || y;
4628    return split.join(" ");
4629  },
4630      _renderClearProps = function _renderClearProps(ratio, data) {
4631    if (data.tween && data.tween._time === data.tween._dur) {
4632      var target = data.t,
4633          style = target.style,
4634          props = data.u,
4635          cache = target._gsap,
4636          prop,
4637          clearTransforms,
4638          i;
4639
4640      if (props === "all" || props === true) {
4641        style.cssText = "";
4642        clearTransforms = 1;
4643      } else {
4644        props = props.split(",");
4645        i = props.length;
4646
4647        while (--i > -1) {
4648          prop = props[i];
4649
4650          if (_transformProps[prop]) {
4651            clearTransforms = 1;
4652            prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp;
4653          }
4654
4655          _removeProperty(target, prop);
4656        }
4657      }
4658
4659      if (clearTransforms) {
4660        _removeProperty(target, _transformProp);
4661
4662        if (cache) {
4663          cache.svg && target.removeAttribute("transform");
4664
4665          _parseTransform(target, 1);
4666
4667          cache.uncache = 1;
4668
4669          _removeIndependentTransforms(style);
4670        }
4671      }
4672    }
4673  },
4674      _specialProps = {
4675    clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 1,580 bytes, lines 4676-4716
4676      if (tween.data !== "isFromStart") {
4677        var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps);
4678        pt.u = endValue;
4679        pt.pr = -10;
4680        pt.tween = tween;
4681
4682        plugin._props.push(property);
4683
4684        return 1;
4685      }
4686    }
4687  },
4688      _identity2DMatrix = [1, 0, 0, 1, 0, 0],
4689      _rotationalProperties = {},
4690      _isNullTransform = function _isNullTransform(value) {
4691    return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value;
4692  },
4693      _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) {
4694    var matrixString = _getComputedProperty(target, _transformProp);
4695
4696    return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round);
4697  },
4698      _getMatrix = function _getMatrix(target, force2D) {
4699    var cache = target._gsap || _getCache(target),
4700        style = target.style,
4701        matrix = _getComputedTransformMatrixAsArray(target),
4702        parent,
4703        nextSibling,
4704        temp,
4705        addedToDOM;
4706
4707    if (cache.svg && target.getAttribute("transform")) {
4708      temp = target.transform.baseVal.consolidate().matrix;
4709      matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f];
4710      return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix;
4711    } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) {
4712      temp = style.display;
4713      style.display = "block";
4714      parent = target.parentNode;
4715
4716      if (!parent || !target.offsetParent
vendor: 18,897 bytes, lines 4716-5313
4716) {
4717        addedToDOM = 1;
4718        nextSibling = target.nextElementSibling;
4719
4720        _docElement.appendChild(target);
4721      }
4722
4723      matrix = _getComputedTransformMatrixAsArray(target);
4724      temp ? style.display = temp : _removeProperty(target, "display");
4725
4726      if (addedToDOM) {
4727        nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target);
4728      }
4729    }
4730
4731    return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix;
4732  },
4733      _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) {
4734    var cache = target._gsap,
4735        matrix = matrixArray || _getMatrix(target, true),
4736        xOriginOld = cache.xOrigin || 0,
4737        yOriginOld = cache.yOrigin || 0,
4738        xOffsetOld = cache.xOffset || 0,
4739        yOffsetOld = cache.yOffset || 0,
4740        a = matrix[0],
4741        b = matrix[1],
4742        c = matrix[2],
4743        d = matrix[3],
4744        tx = matrix[4],
4745        ty = matrix[5],
4746        originSplit = origin.split(" "),
4747        xOrigin = parseFloat(originSplit[0]) || 0,
4748        yOrigin = parseFloat(originSplit[1]) || 0,
4749        bounds,
4750        determinant,
4751        x,
4752        y;
4753
4754    if (!originIsAbsolute) {
4755      bounds = _getBBox(target);
4756      xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * bounds.width : xOrigin);
4757      yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin);
4758    } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) {
4759      x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant;
4760      y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant;
4761      xOrigin = x;
4762      yOrigin = y;
4763    }
4764
4765    if (smooth || smooth !== false && cache.smooth) {
4766      tx = xOrigin - xOriginOld;
4767      ty = yOrigin - yOriginOld;
4768      cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx;
4769      cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty;
4770    } else {
4771      cache.xOffset = cache.yOffset = 0;
4772    }
4773
4774    cache.xOrigin = xOrigin;
4775    cache.yOrigin = yOrigin;
4776    cache.smooth = !!smooth;
4777    cache.origin = origin;
4778    cache.originIsAbsolute = !!originIsAbsolute;
4779    target.style[_transformOriginProp] = "0px 0px";
4780
4781    if (pluginToAddPropTweensTo) {
4782      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin);
4783
4784      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin);
4785
4786      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset);
4787
4788      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset);
4789    }
4790
4791    target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin);
4792  },
4793      _parseTransform = function _parseTransform(target, uncache) {
4794    var cache = target._gsap || new GSCache(target);
4795
4796    if ("x" in cache && !uncache && !cache.uncache) {
4797      return cache;
4798    }
4799
4800    var style = target.style,
4801        invertedScaleX = cache.scaleX < 0,
4802        px = "px",
4803        deg = "deg",
4804        cs = getComputedStyle(target),
4805        origin = _getComputedProperty(target, _transformOriginProp) || "0",
4806        x,
4807        y,
4808        z,
4809        scaleX,
4810        scaleY,
4811        rotation,
4812        rotationX,
4813        rotationY,
4814        skewX,
4815        skewY,
4816        perspective,
4817        xOrigin,
4818        yOrigin,
4819        matrix,
4820        angle,
4821        cos,
4822        sin,
4823        a,
4824        b,
4825        c,
4826        d,
4827        a12,
4828        a22,
4829        t1,
4830        t2,
4831        t3,
4832        a13,
4833        a23,
4834        a33,
4835        a42,
4836        a43,
4837        a32;
4838    x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0;
4839    scaleX = scaleY = 1;
4840    cache.svg = !!(target.getCTM && _isSVG(target));
4841
4842    if (cs.translate) {
4843      if (cs.translate !== "none" || cs.scale !== "none" || cs.rotate !== "none") {
4844        style[_transformProp] = (cs.translate !== "none" ? "translate3d(" + (cs.translate + " 0 0").split(" ").slice(0, 3).join(", ") + ") " : "") + (cs.rotate !== "none" ? "rotate(" + cs.rotate + ") " : "") + (cs.scale !== "none" ? "scale(" + cs.scale.split(" ").join(",") + ") " : "") + (cs[_transformProp] !== "none" ? cs[_transformProp] : "");
4845      }
4846
4847      style.scale = style.rotate = style.translate = "none";
4848    }
4849
4850    matrix = _getMatrix(target, cache.svg);
4851
4852    if (cache.svg) {
4853      if (cache.uncache) {
4854        t2 = target.getBBox();
4855        origin = cache.xOrigin - t2.x + "px " + (cache.yOrigin - t2.y) + "px";
4856        t1 = "";
4857      } else {
4858        t1 = !uncache && target.getAttribute("data-svg-origin");
4859      }
4860
4861      _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix);
4862    }
4863
4864    xOrigin = cache.xOrigin || 0;
4865    yOrigin = cache.yOrigin || 0;
4866
4867    if (matrix !== _identity2DMatrix) {
4868      a = matrix[0];
4869      b = matrix[1];
4870      c = matrix[2];
4871      d = matrix[3];
4872      x = a12 = matrix[4];
4873      y = a22 = matrix[5];
4874
4875      if (matrix.length === 6) {
4876        scaleX = Math.sqrt(a * a + b * b);
4877        scaleY = Math.sqrt(d * d + c * c);
4878        rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0;
4879        skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0;
4880        skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD)));
4881
4882        if (cache.svg) {
4883          x -= xOrigin - (xOrigin * a + yOrigin * c);
4884          y -= yOrigin - (xOrigin * b + yOrigin * d);
4885        }
4886      } else {
4887        a32 = matrix[6];
4888        a42 = matrix[7];
4889        a13 = matrix[8];
4890        a23 = matrix[9];
4891        a33 = matrix[10];
4892        a43 = matrix[11];
4893        x = matrix[12];
4894        y = matrix[13];
4895        z = matrix[14];
4896        angle = _atan2(a32, a33);
4897        rotationX = angle * _RAD2DEG;
4898
4899        if (angle) {
4900          cos = Math.cos(-angle);
4901          sin = Math.sin(-angle);
4902          t1 = a12 * cos + a13 * sin;
4903          t2 = a22 * cos + a23 * sin;
4904          t3 = a32 * cos + a33 * sin;
4905          a13 = a12 * -sin + a13 * cos;
4906          a23 = a22 * -sin + a23 * cos;
4907          a33 = a32 * -sin + a33 * cos;
4908          a43 = a42 * -sin + a43 * cos;
4909          a12 = t1;
4910          a22 = t2;
4911          a32 = t3;
4912        }
4913
4914        angle = _atan2(-c, a33);
4915        rotationY = angle * _RAD2DEG;
4916
4917        if (angle) {
4918          cos = Math.cos(-angle);
4919          sin = Math.sin(-angle);
4920          t1 = a * cos - a13 * sin;
4921          t2 = b * cos - a23 * sin;
4922          t3 = c * cos - a33 * sin;
4923          a43 = d * sin + a43 * cos;
4924          a = t1;
4925          b = t2;
4926          c = t3;
4927        }
4928
4929        angle = _atan2(b, a);
4930        rotation = angle * _RAD2DEG;
4931
4932        if (angle) {
4933          cos = Math.cos(angle);
4934          sin = Math.sin(angle);
4935          t1 = a * cos + b * sin;
4936          t2 = a12 * cos + a22 * sin;
4937          b = b * cos - a * sin;
4938          a22 = a22 * cos - a12 * sin;
4939          a = t1;
4940          a12 = t2;
4941        }
4942
4943        if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) {
4944          rotationX = rotation = 0;
4945          rotationY = 180 - rotationY;
4946        }
4947
4948        scaleX = _round(Math.sqrt(a * a + b * b + c * c));
4949        scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32));
4950        angle = _atan2(a12, a22);
4951        skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0;
4952        perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0;
4953      }
4954
4955      if (cache.svg) {
4956        t1 = target.getAttribute("transform");
4957        cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp));
4958        t1 && target.setAttribute("transform", t1);
4959      }
4960    }
4961
4962    if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
4963      if (invertedScaleX) {
4964        scaleX *= -1;
4965        skewX += rotation <= 0 ? 180 : -180;
4966        rotation += rotation <= 0 ? 180 : -180;
4967      } else {
4968        scaleY *= -1;
4969        skewX += skewX <= 0 ? 180 : -180;
4970      }
4971    }
4972
4973    uncache = uncache || cache.uncache;
4974    cache.x = x - ((cache.xPercent = x && (!uncache && cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px;
4975    cache.y = y - ((cache.yPercent = y && (!uncache && cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px;
4976    cache.z = z + px;
4977    cache.scaleX = _round(scaleX);
4978    cache.scaleY = _round(scaleY);
4979    cache.rotation = _round(rotation) + deg;
4980    cache.rotationX = _round(rotationX) + deg;
4981    cache.rotationY = _round(rotationY) + deg;
4982    cache.skewX = skewX + deg;
4983    cache.skewY = skewY + deg;
4984    cache.transformPerspective = perspective + px;
4985
4986    if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || 0) {
4987      style[_transformOriginProp] = _firstTwoOnly(origin);
4988    }
4989
4990    cache.xOffset = cache.yOffset = 0;
4991    cache.force3D = _config.force3D;
4992    cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms;
4993    cache.uncache = 0;
4994    return cache;
4995  },
4996      _firstTwoOnly = function _firstTwoOnly(value) {
4997    return (value = value.split(" "))[0] + " " + value[1];
4998  },
4999      _addPxTranslate = function _addPxTranslate(target, start, value) {
5000    var unit = getUnit(start);
5001    return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit;
5002  },
5003      _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) {
5004    cache.z = "0px";
5005    cache.rotationY = cache.rotationX = "0deg";
5006    cache.force3D = 0;
5007
5008    _renderCSSTransforms(ratio, cache);
5009  },
5010      _zeroDeg = "0deg",
5011      _zeroPx = "0px",
5012      _endParenthesis = ") ",
5013      _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) {
5014    var _ref = cache || this,
5015        xPercent = _ref.xPercent,
5016        yPercent = _ref.yPercent,
5017        x = _ref.x,
5018        y = _ref.y,
5019        z = _ref.z,
5020        rotation = _ref.rotation,
5021        rotationY = _ref.rotationY,
5022        rotationX = _ref.rotationX,
5023        skewX = _ref.skewX,
5024        skewY = _ref.skewY,
5025        scaleX = _ref.scaleX,
5026        scaleY = _ref.scaleY,
5027        transformPerspective = _ref.transformPerspective,
5028        force3D = _ref.force3D,
5029        target = _ref.target,
5030        zOrigin = _ref.zOrigin,
5031        transforms = "",
5032        use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true;
5033
5034    if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) {
5035      var angle = parseFloat(rotationY) * _DEG2RAD,
5036          a13 = Math.sin(angle),
5037          a33 = Math.cos(angle),
5038          cos;
5039
5040      angle = parseFloat(rotationX) * _DEG2RAD;
5041      cos = Math.cos(angle);
5042      x = _addPxTranslate(target, x, a13 * cos * -zOrigin);
5043      y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin);
5044      z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin);
5045    }
5046
5047    if (transformPerspective !== _zeroPx) {
5048      transforms += "perspective(" + transformPerspective + _endParenthesis;
5049    }
5050
5051    if (xPercent || yPercent) {
5052      transforms += "translate(" + xPercent + "%, " + yPercent + "%) ";
5053    }
5054
5055    if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) {
5056      transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis;
5057    }
5058
5059    if (rotation !== _zeroDeg) {
5060      transforms += "rotate(" + rotation + _endParenthesis;
5061    }
5062
5063    if (rotationY !== _zeroDeg) {
5064      transforms += "rotateY(" + rotationY + _endParenthesis;
5065    }
5066
5067    if (rotationX !== _zeroDeg) {
5068      transforms += "rotateX(" + rotationX + _endParenthesis;
5069    }
5070
5071    if (skewX !== _zeroDeg || skewY !== _zeroDeg) {
5072      transforms += "skew(" + skewX + ", " + skewY + _endParenthesis;
5073    }
5074
5075    if (scaleX !== 1 || scaleY !== 1) {
5076      transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis;
5077    }
5078
5079    target.style[_transformProp] = transforms || "translate(0, 0)";
5080  },
5081      _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) {
5082    var _ref2 = cache || this,
5083        xPercent = _ref2.xPercent,
5084        yPercent = _ref2.yPercent,
5085        x = _ref2.x,
5086        y = _ref2.y,
5087        rotation = _ref2.rotation,
5088        skewX = _ref2.skewX,
5089        skewY = _ref2.skewY,
5090        scaleX = _ref2.scaleX,
5091        scaleY = _ref2.scaleY,
5092        target = _ref2.target,
5093        xOrigin = _ref2.xOrigin,
5094        yOrigin = _ref2.yOrigin,
5095        xOffset = _ref2.xOffset,
5096        yOffset = _ref2.yOffset,
5097        forceCSS = _ref2.forceCSS,
5098        tx = parseFloat(x),
5099        ty = parseFloat(y),
5100        a11,
5101        a21,
5102        a12,
5103        a22,
5104        temp;
5105
5106    rotation = parseFloat(rotation);
5107    skewX = parseFloat(skewX);
5108    skewY = parseFloat(skewY);
5109
5110    if (skewY) {
5111      skewY = parseFloat(skewY);
5112      skewX += skewY;
5113      rotation += skewY;
5114    }
5115
5116    if (rotation || skewX) {
5117      rotation *= _DEG2RAD;
5118      skewX *= _DEG2RAD;
5119      a11 = Math.cos(rotation) * scaleX;
5120      a21 = Math.sin(rotation) * scaleX;
5121      a12 = Math.sin(rotation - skewX) * -scaleY;
5122      a22 = Math.cos(rotation - skewX) * scaleY;
5123
5124      if (skewX) {
5125        skewY *= _DEG2RAD;
5126        temp = Math.tan(skewX - skewY);
5127        temp = Math.sqrt(1 + temp * temp);
5128        a12 *= temp;
5129        a22 *= temp;
5130
5131        if (skewY) {
5132          temp = Math.tan(skewY);
5133          temp = Math.sqrt(1 + temp * temp);
5134          a11 *= temp;
5135          a21 *= temp;
5136        }
5137      }
5138
5139      a11 = _round(a11);
5140      a21 = _round(a21);
5141      a12 = _round(a12);
5142      a22 = _round(a22);
5143    } else {
5144      a11 = scaleX;
5145      a22 = scaleY;
5146      a21 = a12 = 0;
5147    }
5148
5149    if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) {
5150      tx = _convertToUnit(target, "x", x, "px");
5151      ty = _convertToUnit(target, "y", y, "px");
5152    }
5153
5154    if (xOrigin || yOrigin || xOffset || yOffset) {
5155      tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset);
5156      ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset);
5157    }
5158
5159    if (xPercent || yPercent) {
5160      temp = target.getBBox();
5161      tx = _round(tx + xPercent / 100 * temp.width);
5162      ty = _round(ty + yPercent / 100 * temp.height);
5163    }
5164
5165    temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")";
5166    target.setAttribute("transform", temp);
5167    forceCSS && (target.style[_transformProp] = temp);
5168  },
5169      _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue) {
5170    var cap = 360,
5171        isString = _isString(endValue),
5172        endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1),
5173        change = endNum - startNum,
5174        finalValue = startNum + change + "deg",
5175        direction,
5176        pt;
5177
5178    if (isString) {
5179      direction = endValue.split("_")[1];
5180
5181      if (direction === "short") {
5182        change %= cap;
5183
5184        if (change !== change % (cap / 2)) {
5185          change += change < 0 ? cap : -cap;
5186        }
5187      }
5188
5189      if (direction === "cw" && change < 0) {
5190        change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap;
5191      } else if (direction === "ccw" && change > 0) {
5192        change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap;
5193      }
5194    }
5195
5196    plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd);
5197    pt.e = finalValue;
5198    pt.u = "deg";
5199
5200    plugin._props.push(property);
5201
5202    return pt;
5203  },
5204      _assign = function _assign(target, source) {
5205    for (var p in source) {
5206      target[p] = source[p];
5207    }
5208
5209    return target;
5210  },
5211      _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) {
5212    var startCache = _assign({}, target._gsap),
5213        exclude = "perspective,force3D,transformOrigin,svgOrigin",
5214        style = target.style,
5215        endCache,
5216        p,
5217        startValue,
5218        endValue,
5219        startNum,
5220        endNum,
5221        startUnit,
5222        endUnit;
5223
5224    if (startCache.svg) {
5225      startValue = target.getAttribute("transform");
5226      target.setAttribute("transform", "");
5227      style[_transformProp] = transforms;
5228      endCache = _parseTransform(target, 1);
5229
5230      _removeProperty(target, _transformProp);
5231
5232      target.setAttribute("transform", startValue);
5233    } else {
5234      startValue = getComputedStyle(target)[_transformProp];
5235      style[_transformProp] = transforms;
5236      endCache = _parseTransform(target, 1);
5237      style[_transformProp] = startValue;
5238    }
5239
5240    for (p in _transformProps) {
5241      startValue = startCache[p];
5242      endValue = endCache[p];
5243
5244      if (startValue !== endValue && exclude.indexOf(p) < 0) {
5245        startUnit = getUnit(startValue);
5246        endUnit = getUnit(endValue);
5247        startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue);
5248        endNum = parseFloat(endValue);
5249        plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp);
5250        plugin._pt.u = endUnit || 0;
5251
5252        plugin._props.push(p);
5253      }
5254    }
5255
5256    _assign(endCache, startCache);
5257  };
5258
5259  _forEachName("padding,margin,Width,Radius", function (name, index) {
5260    var t = "Top",
5261        r = "Right",
5262        b = "Bottom",
5263        l = "Left",
5264        props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) {
5265      return index < 2 ? name + side : "border" + side + name;
5266    });
5267
5268    _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) {
5269      var a, vars;
5270
5271      if (arguments.length < 4) {
5272        a = props.map(function (prop) {
5273          return _get(plugin, prop, property);
5274        });
5275        vars = a.join(" ");
5276        return vars.split(a[0]).length === 5 ? a[0] : vars;
5277      }
5278
5279      a = (endValue + "").split(" ");
5280      vars = {};
5281      props.forEach(function (prop, i) {
5282        return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0];
5283      });
5284      plugin.init(target, vars, tween);
5285    };
5286  });
5287
5288  var CSSPlugin = {
5289    name: "css",
5290    register: _initCore,
5291    targetTest: function targetTest(target) {
5292      return target.style && target.nodeType;
5293    },
5294    init: function init(target, vars, tween, index, targets) {
5295      var props = this._props,
5296          style = target.style,
5297          startAt = tween.vars.startAt,
5298          startValue,
5299          endValue,
5300          endNum,
5301          startNum,
5302          type,
5303          specialProp,
5304          p,
5305          startUnit,
5306          endUnit,
5307          relative,
5308          isTransformRelated,
5309          transformPropTween,
5310          cache,
5311          smooth,
5312          hasPriority,
5313          inlineProps
vendor: 7,960 bytes, lines 5313-5500
5313;
5314      _pluginInitted || _initCore();
5315      this.styles = this.styles || _getStyleSaver(target);
5316      inlineProps = this.styles.props;
5317      this.tween = tween;
5318
5319      for (p in vars) {
5320        if (p === "autoRound") {
5321          continue;
5322        }
5323
5324        endValue = vars[p];
5325
5326        if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) {
5327          continue;
5328        }
5329
5330        type = typeof endValue;
5331        specialProp = _specialProps[p];
5332
5333        if (type === "function") {
5334          endValue = endValue.call(tween, index, target, targets);
5335          type = typeof endValue;
5336        }
5337
5338        if (type === "string" && ~endValue.indexOf("random(")) {
5339          endValue = _replaceRandom(endValue);
5340        }
5341
5342        if (specialProp) {
5343          specialProp(this, target, p, endValue, tween) && (hasPriority = 1);
5344        } else if (p.substr(0, 2) === "--") {
5345          startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim();
5346          endValue += "";
5347          _colorExp.lastIndex = 0;
5348
5349          if (!_colorExp.test(startValue)) {
5350            startUnit = getUnit(startValue);
5351            endUnit = getUnit(endValue);
5352          }
5353
5354          endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit);
5355          this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p);
5356          props.push(p);
5357          inlineProps.push(p, 0, style[p]);
5358        } else if (type !== "undefined") {
5359          if (startAt && p in startAt) {
5360            startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p];
5361            _isString(startValue) && ~startValue.indexOf("random(") && (startValue = _replaceRandom(startValue));
5362            getUnit(startValue + "") || (startValue += _config.units[p] || getUnit(_get(target, p)) || "");
5363            (startValue + "").charAt(1) === "=" && (startValue = _get(target, p));
5364          } else {
5365            startValue = _get(target, p);
5366          }
5367
5368          startNum = parseFloat(startValue);
5369          relative = type === "string" && endValue.charAt(1) === "=" && endValue.substr(0, 2);
5370          relative && (endValue = endValue.substr(2));
5371          endNum = parseFloat(endValue);
5372
5373          if (p in _propertyAliases) {
5374            if (p === "autoAlpha") {
5375              if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) {
5376                startNum = 0;
5377              }
5378
5379              inlineProps.push("visibility", 0, style.visibility);
5380
5381              _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum);
5382            }
5383
5384            if (p !== "scale" && p !== "transform") {
5385              p = _propertyAliases[p];
5386              ~p.indexOf(",") && (p = p.split(",")[0]);
5387            }
5388          }
5389
5390          isTransformRelated = p in _transformProps;
5391
5392          if (isTransformRelated) {
5393            this.styles.save(p);
5394
5395            if (!transformPropTween) {
5396              cache = target._gsap;
5397              cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform);
5398              smooth = vars.smoothOrigin !== false && cache.smooth;
5399              transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1);
5400              transformPropTween.dep = 1;
5401            }
5402
5403            if (p === "scale") {
5404              this._pt = new PropTween(this._pt, cache, "scaleY", startNum, (relative ? _parseRelative(startNum, relative + endNum) : endNum) - startNum || 0, _renderCSSProp);
5405              this._pt.u = 0;
5406              props.push("scaleY", p);
5407              p += "X";
5408            } else if (p === "transformOrigin") {
5409              inlineProps.push(_transformOriginProp, 0, style[_transformOriginProp]);
5410              endValue = _convertKeywordsToPercentages(endValue);
5411
5412              if (cache.svg) {
5413                _applySVGOrigin(target, endValue, 0, smooth, 0, this);
5414              } else {
5415                endUnit = parseFloat(endValue.split(" ")[2]) || 0;
5416                endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit);
5417
5418                _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue));
5419              }
5420
5421              continue;
5422            } else if (p === "svgOrigin") {
5423              _applySVGOrigin(target, endValue, 1, smooth, 0, this);
5424
5425              continue;
5426            } else if (p in _rotationalProperties) {
5427              _addRotationalPropTween(this, cache, p, startNum, relative ? _parseRelative(startNum, relative + endValue) : endValue);
5428
5429              continue;
5430            } else if (p === "smoothOrigin") {
5431              _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue);
5432
5433              continue;
5434            } else if (p === "force3D") {
5435              cache[p] = endValue;
5436              continue;
5437            } else if (p === "transform") {
5438              _addRawTransformPTs(this, endValue, target);
5439
5440              continue;
5441            }
5442          } else if (!(p in style)) {
5443            p = _checkPropPrefix(p) || p;
5444          }
5445
5446          if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) {
5447            startUnit = (startValue + "").substr((startNum + "").length);
5448            endNum || (endNum = 0);
5449            endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit);
5450            startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit));
5451            this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, (relative ? _parseRelative(startNum, relative + endNum) : endNum) - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp);
5452            this._pt.u = endUnit || 0;
5453
5454            if (startUnit !== endUnit && endUnit !== "%") {
5455              this._pt.b = startValue;
5456              this._pt.r = _renderCSSPropWithBeginning;
5457            }
5458          } else if (!(p in style)) {
5459            if (p in target) {
5460              this.add(target, p, startValue || target[p], relative ? relative + endValue : endValue, index, targets);
5461            } else {
5462              _missingPlugin(p, endValue);
5463
5464              continue;
5465            }
5466          } else {
5467            _tweenComplexCSSString.call(this, target, p, startValue, relative ? relative + endValue : endValue);
5468          }
5469
5470          isTransformRelated || (p in style ? inlineProps.push(p, 0, style[p]) : inlineProps.push(p, 1, startValue || target[p]));
5471          props.push(p);
5472        }
5473      }
5474
5475      hasPriority && _sortPropTweensByPriority(this);
5476    },
5477    render: function render(ratio, data) {
5478      if (data.tween._time || !_reverting$1()) {
5479        var pt = data._pt;
5480
5481        while (pt) {
5482          pt.r(ratio, pt.d);
5483          pt = pt._next;
5484        }
5485      } else {
5486        data.styles.revert();
5487      }
5488    },
5489    get: _get,
5490    aliases: _propertyAliases,
5491    getSetter: function getSetter(target, property, plugin) {
5492      var p = _propertyAliases[property];
5493      p && p.indexOf(",") < 0 && (property = p);
5494      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);
5495    },
5496    core: {
5497      _removeProperty: _removeProperty,
5498      _getMatrix: _getMatrix
5499    }
5500  };
5501  gsap.utils.checkPrefix = _checkPropPrefix;
5502  gsap.core.getStyleSaver = _getStyleSaver;
5503
5504  (function (positionAndScale, rotation, others, aliases) {
5505    var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) {
5506      _transformProps[name] = 1;
5507    });
5508
5509    _forEachName(rotation, function (name) {
5510      _config.units[name] = "deg";
5511      _rotationalProperties[name] = 1;
5512    });
5513
5514    _propertyAliases[all[13]] = positionAndScale + "," + rotation;
5515
5516    _forEachName(aliases, function (name) {
5517      var split = name.split(":");
5518      _propertyAliases[split[1]] = all[split[0]];
5519    });
5520  })("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");
5521
5522  _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) {
5523    _config.units[name] = "px";
5524  });
5525
5526  gsap.registerPlugin(CSSPlugin);
5527
5528  var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap,
5529      TweenMaxWithCSS = gsapWithCSS.core.Tween;
5530
5531  exports.Back = Back;
5532  exports.Bounce = Bounce;
5533  exports.CSSPlugin = CSSPlugin;
5534  exports.Circ = Circ;
5535  exports.Cubic = Cubic;
5536  exports.Elastic = Elastic;
5537  exports.Expo = Expo;
5538  exports.Linear = Linear;
5539  exports.Power0 = Power0;
5540  exports.Power1 = Power1;
5541  exports.Power2 = Power2;
5542  exports.Power3 = Power3;
5543  exports.Power4 = Power4;
5544  exports.Quad = Quad;
5545  exports.Quart = Quart;
5546  exports.Quint = Quint;
5547  exports.Sine = Sine;
5548  exports.SteppedEase = SteppedEase;
5549  exports.Strong = Strong;
5550  exports.TimelineLite = Timeline;
5551  exports.TimelineMax = Timeline;
5552  exports.TweenLite = Tween;
5553  exports.TweenMax = TweenMaxWithCSS;
5554  exports.default = gsapWithCSS;
5555  exports.gsap = gsapWithCSS;
5556
5557  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
5558
5559})));
5560
5561(function(window, $) {
5562  'use strict';
5563  var counter = 0,
5564    $headCache = $('head'),
5565    oldBigText = window.BigText,
5566    oldjQueryMethod = $.fn.bigtext,
5567    BigText = {
5568      DEBUG_MODE: false,
5569      DEFAULT_MIN_FONT_SIZE_PX: null,
5570      DEFAULT_MAX_FONT_SIZE_PX: 528,
5571      GLOBAL_STYLE_ID: 'bigtext-style',
5572      STYLE_ID: 'bigtext-id',
5573      LINE_CLASS_PREFIX: 'bigtext-line',
5574      EXEMPT_CLASS: 'bigtext-exempt',
5575      noConflict: function(restore)
5576      {
5577        if(restore) {
5578          $.fn.bigtext = oldjQueryMethod;
5579          window.BigText = oldBigText;
5580        }
5581        return BigText;
5582      },
5583      supports: {
5584        wholeNumberFontSizeOnly: (function() {
5585          if( !( 'getComputedStyle' in window ) ) {
5586            return true;
5587          }
5588          var test = $('<div/>').css({
5589              position: 'absolute',
5590              'font-size': '14.1px'
5591            }).insertBefore( $('script').eq(0) ),
5592            computedStyle = window.getComputedStyle( test[0], null );
5593
5594          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
5595          test.remove();
5596          return ret;
5597        })()
5598      },
5599      init: function() {
5600        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
5601          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
5602                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
5603        }
5604      },
5605      bindResize: function(eventName, resizeFunction) {
5606        var timeoutId;
5607        $(window).unbind(eventName).bind(eventName, function() {
5608          if( timeoutId ) {
5609            clearTimeout( timeoutId );
5610          }
5611          timeoutId = setTimeout( resizeFunction, 300 );
5612        });
5613      },
5614      getStyleId: function(id)
5615      {
5616        return BigText.STYLE_ID + '-' + id;
5617      },
5618      generateStyleTag: function(id, css)
5619      {
5620        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
5621      },
5622      clearCss: function(id)
5623      {
5624        var styleId = BigText.getStyleId(id);
5625        $('#' + styleId).remove();
5626      },
5627      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
5628      {
5629        var css = [];
5630
5631        BigText.clearCss(id);
5632
5633        for(var j=0, k=linesFontSizes.length; j<k; j++) {
5634          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
5635            (minFontSizes[j] ? ' white-space: normal;' : '') +
5636            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
5637            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
5638            '}');
5639        }
5640
5641        return BigText.generateStyleTag(BigText.getStyleId(id), css);
5642      },
5643      jQueryMethod: function(options)
5644      {
5645        BigText.init();
5646
5647        options = $.extend({
5648          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
5649          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
5650          childSelector: '',
5651          resize: true
5652        }, options || {});
5653
5654        this.each(function()
5655        {
5656          var $t = $(this).addClass('bigtext'),
5657            maxWidth = $t.width(),
5658            id = $t.attr('id'),
5659            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
5660
5661          if(!id) {
5662            id = 'bigtext-id' + (counter++);
5663            $t.attr('id', id);
5664          }
5665
5666          if(options.resize) {
5667            BigText.bindResize('resize.bigtext-event-' + id, function()
5668            {
5669              // TODO only call this if the width has changed.
5670              BigText.jQueryMethod.call($('#' + id), options);
5671            });
5672          }
5673
5674          BigText.clearCss(id);
5675
5676          $children.addClass(function(lineNumber, className)
5677          {
5678            // remove existing line classes.
5679            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
5680                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
5681          });
5682
5683          var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
5684          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
5685        });
5686
5687        return this.trigger('bigtext:complete');
5688      }
5689    };
5690
5691  function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth)
5692  {
5693    var width;
5694    previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
5695    $line.css(property, size + units);
5696
5697    width = $line.width();
5698
5699    if(width >= maxWidth) {
5700
5701      $line.css(property, '');
5702
5703      if(width === maxWidth) {
5704        return {
5705          match: 'exact',
5706          size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
5707        };
5708      }
5709
5710      // Since this is an estimate, we calculate how far over the width we went with the new value.
5711      // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
5712      // Otherwise, we revert to the underestimate.
5713      var under = maxWidth - previousWidth,
5714        over = width - maxWidth;
5715
5716      return {
5717        match: 'estimate',
5718        size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
5719      };
5720    }
5721
5722    return width;
5723  }
5724
5725  function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize)
5726  {
5727    var $c = $t.clone(true)
5728      .addClass('bigtext-cloned')
5729      .css({
5730        fontFamily: $t.css('font-family'),
5731        textTransform: $t.css('text-transform'),
5732        wordSpacing: $t.css('word-spacing'),
5733        letterSpacing: $t.css('letter-spacing'),
5734        position: 'absolute',
5735        left: BigText.DEBUG_MODE ? 0 : -9999,
5736        top: BigText.DEBUG_MODE ? 0 : -9999
5737      })
5738      .appendTo(document.body);
5739
5740    // font-size isn't the only thing we can modify, we can also mess with:
5741    // word-spacing and letter-spacing. WebKit does not respect subpixel
5742    // letter-spacing, word-spacing, or font-size.
5743    // TODO try -webkit-transform: scale() as a workaround.
5744    var fontSizes = [],
5745      wordSpacings = [],
5746      minFontSizes = [],
5747      ratios = [];
5748
5749    $children.css('float', 'left').each(function() {
5750      var $line = $(this),
5751        // TODO replace 8, 4 with a proportional size to the calculated font-size.
5752        intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
5753        lineMax,
5754        newFontSize;
5755
5756      if($line.hasClass(BigText.EXEMPT_CLASS)) {
5757        fontSizes.push(null);
5758        ratios.push(null);
5759        minFontSizes.push(false);
5760        return;
5761      }
5762
5763      // TODO we can cache this ratio?
5764      var autoGuessSubtraction = 32, // font size in px
5765        currentFontSize = parseFloat($line.css('font-size')),
5766        ratio = ( $line.width() / currentFontSize ).toFixed(6);
5767
5768      newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
5769
5770      outer: for(var m=0, n=intervals.length; m<n; m++) {
5771        inner: for(var j=1, k=10; j<=k; j++) {
5772          if(newFontSize + j*intervals[m] > maxFontSize) {
5773            newFontSize = maxFontSize;
5774            break outer;
5775          }
5776
5777          lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
5778          if(typeof lineMax !== 'number') {
5779            newFontSize = lineMax.size;
5780
5781            if(lineMax.match === 'exact') {
5782              break outer;
5783            }
5784            break inner;
5785          }
5786        }
5787      }
5788
5789      ratios.push(maxWidth / newFontSize);
5790
5791      if(newFontSize > maxFontSize) {
5792        fontSizes.push(maxFontSize);
5793        minFontSizes.push(false);
5794      } else if(!!minFontSize && newFontSize < minFontSize) {
5795        fontSizes.push(minFontSize);
5796        minFontSizes.push(true);
5797      } else {
5798        fontSizes.push(newFontSize);
5799        minFontSizes.push(false);
5800      }
5801    }).each(function(lineNumber) {
5802      var $line = $(this),
5803        wordSpacing = 0,
5804        interval = 1,
5805        maxWordSpacing;
5806
5807      if($line.hasClass(BigText.EXEMPT_CLASS)) {
5808        wordSpacings.push(null);
5809        return;
5810      }
5811
5812      // must re-use font-size, even though it was removed above.
5813      $line.css('font-size', fontSizes[lineNumber] + 'px');
5814
5815      for(var m=1, n=3; m<n; m+=interval) {
5816        maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
5817        if(typeof maxWordSpacing !== 'number') {
5818          wordSpacing = maxWordSpacing.size;
5819          break;
5820        }
5821      }
5822
5823      $line.css('font-size', '');
5824      wordSpacings.push(wordSpacing);
5825    }).removeAttr('style');
5826
5827    if( !BigText.DEBUG_MODE ) {
5828      $c.remove();
5829    } else {
5830      $c.css({
5831        'background-color': 'rgba(255,255,255,.4)'
5832      });
5833    }
5834
5835    return {
5836      fontSizes: fontSizes,
5837      wordSpacings: wordSpacings,
5838      ratios: ratios,
5839      minFontSizes: minFontSizes
5840    };
5841  }
5842
5843  $.fn.bigtext = BigText.jQueryMethod;
5844  window.BigText = BigText;
5845
5846})(this, jQuery);
5847/*!
5848 * Isotope PACKAGED v3.0.6
5849 *
5850 * Licensed GPLv3 for open source use
5851 * or Isotope Commercial License for commercial use
5852 *
5853 * https://isotope.metafizzy.co
5854 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 5854-6504
5854
5855 */
5856
5857/**
5858 * Bridget makes jQuery widgets
5859 * v2.0.1
5860 * MIT license
5861 */
5862
5863/* jshint browser: true, strict: true, undef: true, unused: true */
5864
5865( function( window, factory ) {
5866  // universal module definition
5867  /*jshint strict: false */ /* globals define, module, require */
5868  if ( typeof define == 'function' && define.amd ) {
5869    // AMD
5870    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
5871      return factory( window, jQuery );
5872    });
5873  } else if ( typeof module == 'object' && module.exports ) {
5874    // CommonJS
5875    module.exports = factory(
5876      window,
5877      require('jquery')
5878    );
5879  } else {
5880    // browser global
5881    window.jQueryBridget = factory(
5882      window,
5883      window.jQuery
5884    );
5885  }
5886
5887}( window, function factory( window, jQuery ) {
5888'use strict';
5889
5890// ----- utils ----- //
5891
5892var arraySlice = Array.prototype.slice;
5893
5894// helper function for logging errors
5895// $.error breaks jQuery chaining
5896var console = window.console;
5897var logError = typeof console == 'undefined' ? function() {} :
5898  function( message ) {
5899    console.error( message );
5900  };
5901
5902// ----- jQueryBridget ----- //
5903
5904function jQueryBridget( namespace, PluginClass, $ ) {
5905  $ = $ || jQuery || window.jQuery;
5906  if ( !$ ) {
5907    return;
5908  }
5909
5910  // add option method -> $().plugin('option', {...})
5911  if ( !PluginClass.prototype.option ) {
5912    // option setter
5913    PluginClass.prototype.option = function( opts ) {
5914      // bail out if not an object
5915      if ( !$.isPlainObject( opts ) ){
5916        return;
5917      }
5918      this.options = $.extend( true, this.options, opts );
5919    };
5920  }
5921
5922  // make jQuery plugin
5923  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
5924    if ( typeof arg0 == 'string' ) {
5925      // method call $().plugin( 'methodName', { options } )
5926      // shift arguments by 1
5927      var args = arraySlice.call( arguments, 1 );
5928      return methodCall( this, arg0, args );
5929    }
5930    // just $().plugin({ options })
5931    plainCall( this, arg0 );
5932    return this;
5933  };
5934
5935  // $().plugin('methodName')
5936  function methodCall( $elems, methodName, args ) {
5937    var returnValue;
5938    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
5939
5940    $elems.each( function( i, elem ) {
5941      // get instance
5942      var instance = $.data( elem, namespace );
5943      if ( !instance ) {
5944        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
5945          pluginMethodStr );
5946        return;
5947      }
5948
5949      var method = instance[ methodName ];
5950      if ( !method || methodName.charAt(0) == '_' ) {
5951        logError( pluginMethodStr + ' is not a valid method' );
5952        return;
5953      }
5954
5955      // apply method, get return value
5956      var value = method.apply( instance, args );
5957      // set return value if value is returned, use only first value
5958      returnValue = returnValue === undefined ? value : returnValue;
5959    });
5960
5961    return returnValue !== undefined ? returnValue : $elems;
5962  }
5963
5964  function plainCall( $elems, options ) {
5965    $elems.each( function( i, elem ) {
5966      var instance = $.data( elem, namespace );
5967      if ( instance ) {
5968        // set options & init
5969        instance.option( options );
5970        instance._init();
5971      } else {
5972        // initialize new instance
5973        instance = new PluginClass( elem, options );
5974        $.data( elem, namespace, instance );
5975      }
5976    });
5977  }
5978
5979  updateJQuery( $ );
5980
5981}
5982
5983// ----- updateJQuery ----- //
5984
5985// set $.bridget for v1 backwards compatibility
5986function updateJQuery( $ ) {
5987  if ( !$ || ( $ && $.bridget ) ) {
5988    return;
5989  }
5990  $.bridget = jQueryBridget;
5991}
5992
5993updateJQuery( jQuery || window.jQuery );
5994
5995// -----  ----- //
5996
5997return jQueryBridget;
5998
5999}));
6000
6001/**
6002 * EvEmitter v1.1.0
6003 * Lil' event emitter
6004 * MIT License
6005 */
6006
6007/* jshint unused: true, undef: true, strict: true */
6008
6009( function( global, factory ) {
6010  // universal module definition
6011  /* jshint strict: false */ /* globals define, module, window */
6012  if ( typeof define == 'function' && define.amd ) {
6013    // AMD - RequireJS
6014    define( 'ev-emitter/ev-emitter',factory );
6015  } else if ( typeof module == 'object' && module.exports ) {
6016    // CommonJS - Browserify, Webpack
6017    module.exports = factory();
6018  } else {
6019    // Browser globals
6020    global.EvEmitter = factory();
6021  }
6022
6023}( typeof window != 'undefined' ? window : this, function() {
6024
6025
6026
6027function EvEmitter() {}
6028
6029var proto = EvEmitter.prototype;
6030
6031proto.on = function( eventName, listener ) {
6032  if ( !eventName || !listener ) {
6033    return;
6034  }
6035  // set events hash
6036  var events = this._events = this._events || {};
6037  // set listeners array
6038  var listeners = events[ eventName ] = events[ eventName ] || [];
6039  // only add once
6040  if ( listeners.indexOf( listener ) == -1 ) {
6041    listeners.push( listener );
6042  }
6043
6044  return this;
6045};
6046
6047proto.once = function( eventName, listener ) {
6048  if ( !eventName || !listener ) {
6049    return;
6050  }
6051  // add event
6052  this.on( eventName, listener );
6053  // set once flag
6054  // set onceEvents hash
6055  var onceEvents = this._onceEvents = this._onceEvents || {};
6056  // set onceListeners object
6057  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
6058  // set flag
6059  onceListeners[ listener ] = true;
6060
6061  return this;
6062};
6063
6064proto.off = function( eventName, listener ) {
6065  var listeners = this._events && this._events[ eventName ];
6066  if ( !listeners || !listeners.length ) {
6067    return;
6068  }
6069  var index = listeners.indexOf( listener );
6070  if ( index != -1 ) {
6071    listeners.splice( index, 1 );
6072  }
6073
6074  return this;
6075};
6076
6077proto.emitEvent = function( eventName, args ) {
6078  var listeners = this._events && this._events[ eventName ];
6079  if ( !listeners || !listeners.length ) {
6080    return;
6081  }
6082  // copy over to avoid interference if .off() in listener
6083  listeners = listeners.slice(0);
6084  args = args || [];
6085  // once stuff
6086  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
6087
6088  for ( var i=0; i < listeners.length; i++ ) {
6089    var listener = listeners[i]
6090    var isOnce = onceListeners && onceListeners[ listener ];
6091    if ( isOnce ) {
6092      // remove listener
6093      // remove before trigger to prevent recursion
6094      this.off( eventName, listener );
6095      // unset once flag
6096      delete onceListeners[ listener ];
6097    }
6098    // trigger listener
6099    listener.apply( this, args );
6100  }
6101
6102  return this;
6103};
6104
6105proto.allOff = function() {
6106  delete this._events;
6107  delete this._onceEvents;
6108};
6109
6110return EvEmitter;
6111
6112}));
6113
6114/*!
6115 * getSize v2.0.3
6116 * measure size of elements
6117 * MIT license
6118 */
6119
6120/* jshint browser: true, strict: true, undef: true, unused: true */
6121/* globals console: false */
6122
6123( function( window, factory ) {
6124  /* jshint strict: false */ /* globals define, module */
6125  if ( typeof define == 'function' && define.amd ) {
6126    // AMD
6127    define( 'get-size/get-size',factory );
6128  } else if ( typeof module == 'object' && module.exports ) {
6129    // CommonJS
6130    module.exports = factory();
6131  } else {
6132    // browser global
6133    window.getSize = factory();
6134  }
6135
6136})( window, function factory() {
6137'use strict';
6138
6139// -------------------------- helpers -------------------------- //
6140
6141// get a number from a string, not a percentage
6142function getStyleSize( value ) {
6143  var num = parseFloat( value );
6144  // not a percent like '100%', and a number
6145  var isValid = value.indexOf('%') == -1 && !isNaN( num );
6146  return isValid && num;
6147}
6148
6149function noop() {}
6150
6151var logError = typeof console == 'undefined' ? noop :
6152  function( message ) {
6153    console.error( message );
6154  };
6155
6156// -------------------------- measurements -------------------------- //
6157
6158var measurements = [
6159  'paddingLeft',
6160  'paddingRight',
6161  'paddingTop',
6162  'paddingBottom',
6163  'marginLeft',
6164  'marginRight',
6165  'marginTop',
6166  'marginBottom',
6167  'borderLeftWidth',
6168  'borderRightWidth',
6169  'borderTopWidth',
6170  'borderBottomWidth'
6171];
6172
6173var measurementsLength = measurements.length;
6174
6175function getZeroSize() {
6176  var size = {
6177    width: 0,
6178    height: 0,
6179    innerWidth: 0,
6180    innerHeight: 0,
6181    outerWidth: 0,
6182    outerHeight: 0
6183  };
6184  for ( var i=0; i < measurementsLength; i++ ) {
6185    var measurement = measurements[i];
6186    size[ measurement ] = 0;
6187  }
6188  return size;
6189}
6190
6191// -------------------------- getStyle -------------------------- //
6192
6193/**
6194 * getStyle, get style of element, check for Firefox bug
6195 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
6196 */
6197function getStyle( elem ) {
6198  var style = getComputedStyle( elem );
6199  if ( !style ) {
6200    logError( 'Style returned ' + style +
6201      '. Are you running this code in a hidden iframe on Firefox? ' +
6202      'See https://bit.ly/getsizebug1' );
6203  }
6204  return style;
6205}
6206
6207// -------------------------- setup -------------------------- //
6208
6209var isSetup = false;
6210
6211var isBoxSizeOuter;
6212
6213/**
6214 * setup
6215 * check isBoxSizerOuter
6216 * do on first getSize() rather than on page load for Firefox bug
6217 */
6218function setup() {
6219  // setup once
6220  if ( isSetup ) {
6221    return;
6222  }
6223  isSetup = true;
6224
6225  // -------------------------- box sizing -------------------------- //
6226
6227  /**
6228   * Chrome & Safari measure the outer-width on style.width on border-box elems
6229   * IE11 & Firefox<29 measures the inner-width
6230   */
6231  var div = document.createElement('div');
6232  div.style.width = '200px';
6233  div.style.padding = '1px 2px 3px 4px';
6234  div.style.borderStyle = 'solid';
6235  div.style.borderWidth = '1px 2px 3px 4px';
6236  div.style.boxSizing = 'border-box';
6237
6238  var body = document.body || document.documentElement;
6239  body.appendChild( div );
6240  var style = getStyle( div );
6241  // round value for browser zoom. desandro/masonry#928
6242  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
6243  getSize.isBoxSizeOuter = isBoxSizeOuter;
6244
6245  body.removeChild( div );
6246}
6247
6248// -------------------------- getSize -------------------------- //
6249
6250function getSize( elem ) {
6251  setup();
6252
6253  // use querySeletor if elem is string
6254  if ( typeof elem == 'string' ) {
6255    elem = document.querySelector( elem );
6256  }
6257
6258  // do not proceed on non-objects
6259  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
6260    return;
6261  }
6262
6263  var style = getStyle( elem );
6264
6265  // if hidden, everything is 0
6266  if ( style.display == 'none' ) {
6267    return getZeroSize();
6268  }
6269
6270  var size = {};
6271  size.width = elem.offsetWidth;
6272  size.height = elem.offsetHeight;
6273
6274  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
6275
6276  // get all measurements
6277  for ( var i=0; i < measurementsLength; i++ ) {
6278    var measurement = measurements[i];
6279    var value = style[ measurement ];
6280    var num = parseFloat( value );
6281    // any 'auto', 'medium' value will be 0
6282    size[ measurement ] = !isNaN( num ) ? num : 0;
6283  }
6284
6285  var paddingWidth = size.paddingLeft + size.paddingRight;
6286  var paddingHeight = size.paddingTop + size.paddingBottom;
6287  var marginWidth = size.marginLeft + size.marginRight;
6288  var marginHeight = size.marginTop + size.marginBottom;
6289  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
6290  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
6291
6292  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
6293
6294  // overwrite width and height if we can get it from style
6295  var styleWidth = getStyleSize( style.width );
6296  if ( styleWidth !== false ) {
6297    size.width = styleWidth +
6298      // add padding and border unless it's already including it
6299      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
6300  }
6301
6302  var styleHeight = getStyleSize( style.height );
6303  if ( styleHeight !== false ) {
6304    size.height = styleHeight +
6305      // add padding and border unless it's already including it
6306      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
6307  }
6308
6309  size.innerWidth = size.width - ( paddingWidth + borderWidth );
6310  size.innerHeight = size.height - ( paddingHeight + borderHeight );
6311
6312  size.outerWidth = size.width + marginWidth;
6313  size.outerHeight = size.height + marginHeight;
6314
6315  return size;
6316}
6317
6318return getSize;
6319
6320});
6321
6322/**
6323 * matchesSelector v2.0.2
6324 * matchesSelector( element, '.selector' )
6325 * MIT license
6326 */
6327
6328/*jshint browser: true, strict: true, undef: true, unused: true */
6329
6330( function( window, factory ) {
6331  /*global define: false, module: false */
6332  'use strict';
6333  // universal module definition
6334  if ( typeof define == 'function' && define.amd ) {
6335    // AMD
6336    define( 'desandro-matches-selector/matches-selector',factory );
6337  } else if ( typeof module == 'object' && module.exports ) {
6338    // CommonJS
6339    module.exports = factory();
6340  } else {
6341    // browser global
6342    window.matchesSelector = factory();
6343  }
6344
6345}( window, function factory() {
6346  'use strict';
6347
6348  var matchesMethod = ( function() {
6349    var ElemProto = window.Element.prototype;
6350    // check for the standard method name first
6351    if ( ElemProto.matches ) {
6352      return 'matches';
6353    }
6354    // check un-prefixed
6355    if ( ElemProto.matchesSelector ) {
6356      return 'matchesSelector';
6357    }
6358    // check vendor prefixes
6359    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
6360
6361    for ( var i=0; i < prefixes.length; i++ ) {
6362      var prefix = prefixes[i];
6363      var method = prefix + 'MatchesSelector';
6364      if ( ElemProto[ method ] ) {
6365        return method;
6366      }
6367    }
6368  })();
6369
6370  return function matchesSelector( elem, selector ) {
6371    return elem[ matchesMethod ]( selector );
6372  };
6373
6374}));
6375
6376/**
6377 * Fizzy UI utils v2.0.7
6378 * MIT license
6379 */
6380
6381/*jshint browser: true, undef: true, unused: true, strict: true */
6382
6383( function( window, factory ) {
6384  // universal module definition
6385  /*jshint strict: false */ /*globals define, module, require */
6386
6387  if ( typeof define == 'function' && define.amd ) {
6388    // AMD
6389    define( 'fizzy-ui-utils/utils',[
6390      'desandro-matches-selector/matches-selector'
6391    ], function( matchesSelector ) {
6392      return factory( window, matchesSelector );
6393    });
6394  } else if ( typeof module == 'object' && module.exports ) {
6395    // CommonJS
6396    module.exports = factory(
6397      window,
6398      require('desandro-matches-selector')
6399    );
6400  } else {
6401    // browser global
6402    window.fizzyUIUtils = factory(
6403      window,
6404      window.matchesSelector
6405    );
6406  }
6407
6408}( window, function factory( window, matchesSelector ) {
6409
6410
6411
6412var utils = {};
6413
6414// ----- extend ----- //
6415
6416// extends objects
6417utils.extend = function( a, b ) {
6418  for ( var prop in b ) {
6419    a[ prop ] = b[ prop ];
6420  }
6421  return a;
6422};
6423
6424// ----- modulo ----- //
6425
6426utils.modulo = function( num, div ) {
6427  return ( ( num % div ) + div ) % div;
6428};
6429
6430// ----- makeArray ----- //
6431
6432var arraySlice = Array.prototype.slice;
6433
6434// turn element or nodeList into an array
6435utils.makeArray = function( obj ) {
6436  if ( Array.isArray( obj ) ) {
6437    // use object if already an array
6438    return obj;
6439  }
6440  // return empty array if undefined or null. #6
6441  if ( obj === null || obj === undefined ) {
6442    return [];
6443  }
6444
6445  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
6446  if ( isArrayLike ) {
6447    // convert nodeList to array
6448    return arraySlice.call( obj );
6449  }
6450
6451  // array of single index
6452  return [ obj ];
6453};
6454
6455// ----- removeFrom ----- //
6456
6457utils.removeFrom = function( ary, obj ) {
6458  var index = ary.indexOf( obj );
6459  if ( index != -1 ) {
6460    ary.splice( index, 1 );
6461  }
6462};
6463
6464// ----- getParent ----- //
6465
6466utils.getParent = function( elem, selector ) {
6467  while ( elem.parentNode && elem != document.body ) {
6468    elem = elem.parentNode;
6469    if ( matchesSelector( elem, selector ) ) {
6470      return elem;
6471    }
6472  }
6473};
6474
6475// ----- getQueryElement ----- //
6476
6477// use element as selector string
6478utils.getQueryElement = function( elem ) {
6479  if ( typeof elem == 'string' ) {
6480    return document.querySelector( elem );
6481  }
6482  return elem;
6483};
6484
6485// ----- handleEvent ----- //
6486
6487// enable .ontype to trigger from .addEventListener( elem, 'type' )
6488utils.handleEvent = function( event ) {
6489  var method = 'on' + event.type;
6490  if ( this[ method ] ) {
6491    this[ method ]( event );
6492  }
6493};
6494
6495// ----- filterFindElements ----- //
6496
6497utils.filterFindElements = function( elems, selector ) {
6498  // make array of elems
6499  elems = utils.makeArray( elems );
6500  var ffElems = [];
6501
6502  elems.forEach( function( elem ) {
6503    // check that elem is an actual element
6504    
6504// START UNCODE EDIT
6505    // if ( !( elem instanceof HTMLElement ) ) {
6506    if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) {
6507    // END UNCODE EDIT
vendor: 23,480 bytes, lines 6507-7419
6507
6508      return;
6509    }
6510    // add elem if no selector
6511    if ( !selector ) {
6512      ffElems.push( elem );
6513      return;
6514    }
6515    // filter & find items if we have a selector
6516    // filter
6517    if ( matchesSelector( elem, selector ) ) {
6518      ffElems.push( elem );
6519    }
6520    // find children
6521    var childElems = elem.querySelectorAll( selector );
6522    // concat childElems to filterFound array
6523    for ( var i=0; i < childElems.length; i++ ) {
6524      ffElems.push( childElems[i] );
6525    }
6526  });
6527
6528  return ffElems;
6529};
6530
6531// ----- debounceMethod ----- //
6532
6533utils.debounceMethod = function( _class, methodName, threshold ) {
6534  threshold = threshold || 100;
6535  // original method
6536  var method = _class.prototype[ methodName ];
6537  var timeoutName = methodName + 'Timeout';
6538
6539  _class.prototype[ methodName ] = function() {
6540    var timeout = this[ timeoutName ];
6541    clearTimeout( timeout );
6542
6543    var args = arguments;
6544    var _this = this;
6545    this[ timeoutName ] = setTimeout( function() {
6546      method.apply( _this, args );
6547      delete _this[ timeoutName ];
6548    }, threshold );
6549  };
6550};
6551
6552// ----- docReady ----- //
6553
6554utils.docReady = function( callback ) {
6555  var readyState = document.readyState;
6556  if ( readyState == 'complete' || readyState == 'interactive' ) {
6557    // do async to allow for other scripts to run. metafizzy/flickity#441
6558    setTimeout( callback );
6559  } else {
6560    document.addEventListener( 'DOMContentLoaded', callback );
6561  }
6562};
6563
6564// ----- htmlInit ----- //
6565
6566// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
6567utils.toDashed = function( str ) {
6568  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
6569    return $1 + '-' + $2;
6570  }).toLowerCase();
6571};
6572
6573var console = window.console;
6574/**
6575 * allow user to initialize classes via [data-namespace] or .js-namespace class
6576 * htmlInit( Widget, 'widgetName' )
6577 * options are parsed from data-namespace-options
6578 */
6579utils.htmlInit = function( WidgetClass, namespace ) {
6580  utils.docReady( function() {
6581    var dashedNamespace = utils.toDashed( namespace );
6582    var dataAttr = 'data-' + dashedNamespace;
6583    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
6584    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
6585    var elems = utils.makeArray( dataAttrElems )
6586      .concat( utils.makeArray( jsDashElems ) );
6587    var dataOptionsAttr = dataAttr + '-options';
6588    var jQuery = window.jQuery;
6589
6590    elems.forEach( function( elem ) {
6591      var attr = elem.getAttribute( dataAttr ) ||
6592        elem.getAttribute( dataOptionsAttr );
6593      var options;
6594      try {
6595        options = attr && JSON.parse( attr );
6596      } catch ( error ) {
6597        // log error, do not initialize
6598        if ( console ) {
6599          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
6600          ': ' + error );
6601        }
6602        return;
6603      }
6604      // initialize
6605      var instance = new WidgetClass( elem, options );
6606      // make available via $().data('namespace')
6607      if ( jQuery ) {
6608        jQuery.data( elem, namespace, instance );
6609      }
6610    });
6611
6612  });
6613};
6614
6615// -----  ----- //
6616
6617return utils;
6618
6619}));
6620
6621/**
6622 * Outlayer Item
6623 */
6624
6625( function( window, factory ) {
6626  // universal module definition
6627  /* jshint strict: false */ /* globals define, module, require */
6628  if ( typeof define == 'function' && define.amd ) {
6629    // AMD - RequireJS
6630    define( 'outlayer/item',[
6631        'ev-emitter/ev-emitter',
6632        'get-size/get-size'
6633      ],
6634      factory
6635    );
6636  } else if ( typeof module == 'object' && module.exports ) {
6637    // CommonJS - Browserify, Webpack
6638    module.exports = factory(
6639      require('ev-emitter'),
6640      require('get-size')
6641    );
6642  } else {
6643    // browser global
6644    window.Outlayer = {};
6645    window.Outlayer.Item = factory(
6646      window.EvEmitter,
6647      window.getSize
6648    );
6649  }
6650
6651}( window, function factory( EvEmitter, getSize ) {
6652'use strict';
6653
6654// ----- helpers ----- //
6655
6656function isEmptyObj( obj ) {
6657  for ( var prop in obj ) {
6658    return false;
6659  }
6660  prop = null;
6661  return true;
6662}
6663
6664// -------------------------- CSS3 support -------------------------- //
6665
6666
6667var docElemStyle = document.documentElement.style;
6668
6669var transitionProperty = typeof docElemStyle.transition == 'string' ?
6670  'transition' : 'WebkitTransition';
6671var transformProperty = typeof docElemStyle.transform == 'string' ?
6672  'transform' : 'WebkitTransform';
6673
6674var transitionEndEvent = {
6675  WebkitTransition: 'webkitTransitionEnd',
6676  transition: 'transitionend'
6677}[ transitionProperty ];
6678
6679// cache all vendor properties that could have vendor prefix
6680var vendorProperties = {
6681  transform: transformProperty,
6682  transition: transitionProperty,
6683  transitionDuration: transitionProperty + 'Duration',
6684  transitionProperty: transitionProperty + 'Property',
6685  transitionDelay: transitionProperty + 'Delay'
6686};
6687
6688// -------------------------- Item -------------------------- //
6689
6690function Item( element, layout ) {
6691  if ( !element ) {
6692    return;
6693  }
6694
6695  this.element = element;
6696  // parent layout class, i.e. Masonry, Isotope, or Packery
6697  this.layout = layout;
6698  this.position = {
6699    x: 0,
6700    y: 0
6701  };
6702
6703  this._create();
6704}
6705
6706// inherit EvEmitter
6707var proto = Item.prototype = Object.create( EvEmitter.prototype );
6708proto.constructor = Item;
6709
6710proto._create = function() {
6711  // transition objects
6712  this._transn = {
6713    ingProperties: {},
6714    clean: {},
6715    onEnd: {}
6716  };
6717
6718  this.css({
6719    position: 'absolute'
6720  });
6721};
6722
6723// trigger specified handler for event type
6724proto.handleEvent = function( event ) {
6725  var method = 'on' + event.type;
6726  if ( this[ method ] ) {
6727    this[ method ]( event );
6728  }
6729};
6730
6731proto.getSize = function() {
6732  this.size = getSize( this.element );
6733};
6734
6735/**
6736 * apply CSS styles to element
6737 * @param {Object} style
6738 */
6739proto.css = function( style ) {
6740  var elemStyle = this.element.style;
6741
6742  for ( var prop in style ) {
6743    // use vendor property if available
6744    var supportedProp = vendorProperties[ prop ] || prop;
6745    elemStyle[ supportedProp ] = style[ prop ];
6746  }
6747};
6748
6749 // measure position, and sets it
6750proto.getPosition = function() {
6751  var style = getComputedStyle( this.element );
6752  var isOriginLeft = this.layout._getOption('originLeft');
6753  var isOriginTop = this.layout._getOption('originTop');
6754  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
6755  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
6756  var x = parseFloat( xValue );
6757  var y = parseFloat( yValue );
6758  // convert percent to pixels
6759  var layoutSize = this.layout.size;
6760  if ( xValue.indexOf('%') != -1 ) {
6761    x = ( x / 100 ) * layoutSize.width;
6762  }
6763  if ( yValue.indexOf('%') != -1 ) {
6764    y = ( y / 100 ) * layoutSize.height;
6765  }
6766  // clean up 'auto' or other non-integer values
6767  x = isNaN( x ) ? 0 : x;
6768  y = isNaN( y ) ? 0 : y;
6769  // remove padding from measurement
6770  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
6771  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
6772
6773  this.position.x = x;
6774  this.position.y = y;
6775};
6776
6777// set settled position, apply padding
6778proto.layoutPosition = function() {
6779  var layoutSize = this.layout.size;
6780  var style = {};
6781  var isOriginLeft = this.layout._getOption('originLeft');
6782  var isOriginTop = this.layout._getOption('originTop');
6783
6784  // x
6785  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
6786  var xProperty = isOriginLeft ? 'left' : 'right';
6787  var xResetProperty = isOriginLeft ? 'right' : 'left';
6788
6789  var x = this.position.x + layoutSize[ xPadding ];
6790  // set in percentage or pixels
6791  style[ xProperty ] = this.getXValue( x );
6792  // reset other property
6793  style[ xResetProperty ] = '';
6794
6795  // y
6796  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
6797  var yProperty = isOriginTop ? 'top' : 'bottom';
6798  var yResetProperty = isOriginTop ? 'bottom' : 'top';
6799
6800  var y = this.position.y + layoutSize[ yPadding ];
6801  // set in percentage or pixels
6802  style[ yProperty ] = this.getYValue( y );
6803  // reset other property
6804  style[ yResetProperty ] = '';
6805
6806  this.css( style );
6807  this.emitEvent( 'layout', [ this ] );
6808};
6809
6810proto.getXValue = function( x ) {
6811  var isHorizontal = this.layout._getOption('horizontal');
6812  return this.layout.options.percentPosition && !isHorizontal ?
6813    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
6814};
6815
6816proto.getYValue = function( y ) {
6817  var isHorizontal = this.layout._getOption('horizontal');
6818  return this.layout.options.percentPosition && isHorizontal ?
6819    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
6820};
6821
6822proto._transitionTo = function( x, y ) {
6823  this.getPosition();
6824  // get current x & y from top/left
6825  var curX = this.position.x;
6826  var curY = this.position.y;
6827
6828  var didNotMove = x == this.position.x && y == this.position.y;
6829
6830  // save end position
6831  this.setPosition( x, y );
6832
6833  // if did not move and not transitioning, just go to layout
6834  if ( didNotMove && !this.isTransitioning ) {
6835    this.layoutPosition();
6836    return;
6837  }
6838
6839  var transX = x - curX;
6840  var transY = y - curY;
6841  var transitionStyle = {};
6842  transitionStyle.transform = this.getTranslate( transX, transY );
6843
6844  this.transition({
6845    to: transitionStyle,
6846    onTransitionEnd: {
6847      transform: this.layoutPosition
6848    },
6849    isCleaning: true
6850  });
6851};
6852
6853proto.getTranslate = function( x, y ) {
6854  // flip cooridinates if origin on right or bottom
6855  var isOriginLeft = this.layout._getOption('originLeft');
6856  var isOriginTop = this.layout._getOption('originTop');
6857  x = isOriginLeft ? x : -x;
6858  y = isOriginTop ? y : -y;
6859  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
6860};
6861
6862// non transition + transform support
6863proto.goTo = function( x, y ) {
6864  this.setPosition( x, y );
6865  this.layoutPosition();
6866};
6867
6868proto.moveTo = proto._transitionTo;
6869
6870proto.setPosition = function( x, y ) {
6871  this.position.x = parseFloat( x );
6872  this.position.y = parseFloat( y );
6873};
6874
6875// ----- transition ----- //
6876
6877/**
6878 * @param {Object} style - CSS
6879 * @param {Function} onTransitionEnd
6880 */
6881
6882// non transition, just trigger callback
6883proto._nonTransition = function( args ) {
6884  this.css( args.to );
6885  if ( args.isCleaning ) {
6886    this._removeStyles( args.to );
6887  }
6888  for ( var prop in args.onTransitionEnd ) {
6889    args.onTransitionEnd[ prop ].call( this );
6890  }
6891};
6892
6893/**
6894 * proper transition
6895 * @param {Object} args - arguments
6896 *   @param {Object} to - style to transition to
6897 *   @param {Object} from - style to start transition from
6898 *   @param {Boolean} isCleaning - removes transition styles after transition
6899 *   @param {Function} onTransitionEnd - callback
6900 */
6901proto.transition = function( args ) {
6902  // redirect to nonTransition if no transition duration
6903  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
6904    this._nonTransition( args );
6905    return;
6906  }
6907
6908  var _transition = this._transn;
6909  // keep track of onTransitionEnd callback by css property
6910  for ( var prop in args.onTransitionEnd ) {
6911    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
6912  }
6913  // keep track of properties that are transitioning
6914  for ( prop in args.to ) {
6915    _transition.ingProperties[ prop ] = true;
6916    // keep track of properties to clean up when transition is done
6917    if ( args.isCleaning ) {
6918      _transition.clean[ prop ] = true;
6919    }
6920  }
6921
6922  // set from styles
6923  if ( args.from ) {
6924    this.css( args.from );
6925    // force redraw. http://blog.alexmaccaw.com/css-transitions
6926    var h = this.element.offsetHeight;
6927    // hack for JSHint to hush about unused var
6928    h = null;
6929  }
6930  // enable transition
6931  this.enableTransition( args.to );
6932  // set styles that are transitioning
6933  this.css( args.to );
6934
6935  this.isTransitioning = true;
6936
6937};
6938
6939// dash before all cap letters, including first for
6940// WebkitTransform => -webkit-transform
6941function toDashedAll( str ) {
6942  return str.replace( /([A-Z])/g, function( $1 ) {
6943    return '-' + $1.toLowerCase();
6944  });
6945}
6946
6947var transitionProps = 'opacity,' + toDashedAll( transformProperty );
6948
6949proto.enableTransition = function(/* style */) {
6950  // HACK changing transitionProperty during a transition
6951  // will cause transition to jump
6952  if ( this.isTransitioning ) {
6953    return;
6954  }
6955
6956  // make `transition: foo, bar, baz` from style object
6957  // HACK un-comment this when enableTransition can work
6958  // while a transition is happening
6959  // var transitionValues = [];
6960  // for ( var prop in style ) {
6961  //   // dash-ify camelCased properties like WebkitTransition
6962  //   prop = vendorProperties[ prop ] || prop;
6963  //   transitionValues.push( toDashedAll( prop ) );
6964  // }
6965  // munge number to millisecond, to match stagger
6966  var duration = this.layout.options.transitionDuration;
6967  duration = typeof duration == 'number' ? duration + 'ms' : duration;
6968  // enable transition styles
6969  this.css({
6970    transitionProperty: transitionProps,
6971    transitionDuration: duration,
6972    transitionDelay: this.staggerDelay || 0
6973  });
6974  // listen for transition end event
6975  this.element.addEventListener( transitionEndEvent, this, false );
6976};
6977
6978// ----- events ----- //
6979
6980proto.onwebkitTransitionEnd = function( event ) {
6981  this.ontransitionend( event );
6982};
6983
6984proto.onotransitionend = function( event ) {
6985  this.ontransitionend( event );
6986};
6987
6988// properties that I munge to make my life easier
6989var dashedVendorProperties = {
6990  '-webkit-transform': 'transform'
6991};
6992
6993proto.ontransitionend = function( event ) {
6994  // disregard bubbled events from children
6995  if ( event.target !== this.element ) {
6996    return;
6997  }
6998  var _transition = this._transn;
6999  // get property name of transitioned property, convert to prefix-free
7000  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
7001
7002  // remove property that has completed transitioning
7003  delete _transition.ingProperties[ propertyName ];
7004  // check if any properties are still transitioning
7005  if ( isEmptyObj( _transition.ingProperties ) ) {
7006    // all properties have completed transitioning
7007    this.disableTransition();
7008  }
7009  // clean style
7010  if ( propertyName in _transition.clean ) {
7011    // clean up style
7012    this.element.style[ event.propertyName ] = '';
7013    delete _transition.clean[ propertyName ];
7014  }
7015  // trigger onTransitionEnd callback
7016  if ( propertyName in _transition.onEnd ) {
7017    var onTransitionEnd = _transition.onEnd[ propertyName ];
7018    onTransitionEnd.call( this );
7019    delete _transition.onEnd[ propertyName ];
7020  }
7021
7022  this.emitEvent( 'transitionEnd', [ this ] );
7023};
7024
7025proto.disableTransition = function() {
7026  this.removeTransitionStyles();
7027  this.element.removeEventListener( transitionEndEvent, this, false );
7028  this.isTransitioning = false;
7029};
7030
7031/**
7032 * removes style property from element
7033 * @param {Object} style
7034**/
7035proto._removeStyles = function( style ) {
7036  // clean up transition styles
7037  var cleanStyle = {};
7038  for ( var prop in style ) {
7039    cleanStyle[ prop ] = '';
7040  }
7041  this.css( cleanStyle );
7042};
7043
7044var cleanTransitionStyle = {
7045  transitionProperty: '',
7046  transitionDuration: '',
7047  transitionDelay: ''
7048};
7049
7050proto.removeTransitionStyles = function() {
7051  // remove transition
7052  this.css( cleanTransitionStyle );
7053};
7054
7055// ----- stagger ----- //
7056
7057proto.stagger = function( delay ) {
7058  delay = isNaN( delay ) ? 0 : delay;
7059  this.staggerDelay = delay + 'ms';
7060};
7061
7062// ----- show/hide/remove ----- //
7063
7064// remove element from DOM
7065proto.removeElem = function() {
7066  this.element.parentNode.removeChild( this.element );
7067  // remove display: none
7068  this.css({ display: '' });
7069  this.emitEvent( 'remove', [ this ] );
7070};
7071
7072proto.remove = function() {
7073  // just remove element if no transition support or no transition
7074  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
7075    this.removeElem();
7076    return;
7077  }
7078
7079  // start transition
7080  this.once( 'transitionEnd', function() {
7081    this.removeElem();
7082  });
7083  this.hide();
7084};
7085
7086proto.reveal = function() {
7087  delete this.isHidden;
7088  // remove display: none
7089  this.css({ display: '' });
7090
7091  var options = this.layout.options;
7092
7093  var onTransitionEnd = {};
7094  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
7095  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
7096
7097  this.transition({
7098    from: options.hiddenStyle,
7099    to: options.visibleStyle,
7100    isCleaning: true,
7101    onTransitionEnd: onTransitionEnd
7102  });
7103};
7104
7105proto.onRevealTransitionEnd = function() {
7106  // check if still visible
7107  // during transition, item may have been hidden
7108  if ( !this.isHidden ) {
7109    this.emitEvent('reveal');
7110  }
7111};
7112
7113/**
7114 * get style property use for hide/reveal transition end
7115 * @param {String} styleProperty - hiddenStyle/visibleStyle
7116 * @returns {String}
7117 */
7118proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
7119  var optionStyle = this.layout.options[ styleProperty ];
7120  // use opacity
7121  if ( optionStyle.opacity ) {
7122    return 'opacity';
7123  }
7124  // get first property
7125  for ( var prop in optionStyle ) {
7126    return prop;
7127  }
7128};
7129
7130proto.hide = function() {
7131  // set flag
7132  this.isHidden = true;
7133  // remove display: none
7134  this.css({ display: '' });
7135
7136  var options = this.layout.options;
7137
7138  var onTransitionEnd = {};
7139  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
7140  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
7141
7142  this.transition({
7143    from: options.visibleStyle,
7144    to: options.hiddenStyle,
7145    // keep hidden stuff hidden
7146    isCleaning: true,
7147    onTransitionEnd: onTransitionEnd
7148  });
7149};
7150
7151proto.onHideTransitionEnd = function() {
7152  // check if still hidden
7153  // during transition, item may have been un-hidden
7154  if ( this.isHidden ) {
7155    this.css({ display: 'none' });
7156    this.emitEvent('hide');
7157  }
7158};
7159
7160proto.destroy = function() {
7161  this.css({
7162    position: '',
7163    left: '',
7164    right: '',
7165    top: '',
7166    bottom: '',
7167    transition: '',
7168    transform: ''
7169  });
7170};
7171
7172return Item;
7173
7174}));
7175
7176/*!
7177 * Outlayer v2.1.1
7178 * the brains and guts of a layout library
7179 * MIT license
7180 */
7181
7182( function( window, factory ) {
7183  'use strict';
7184  // universal module definition
7185  /* jshint strict: false */ /* globals define, module, require */
7186  if ( typeof define == 'function' && define.amd ) {
7187    // AMD - RequireJS
7188    define( 'outlayer/outlayer',[
7189        'ev-emitter/ev-emitter',
7190        'get-size/get-size',
7191        'fizzy-ui-utils/utils',
7192        './item'
7193      ],
7194      function( EvEmitter, getSize, utils, Item ) {
7195        return factory( window, EvEmitter, getSize, utils, Item);
7196      }
7197    );
7198  } else if ( typeof module == 'object' && module.exports ) {
7199    // CommonJS - Browserify, Webpack
7200    module.exports = factory(
7201      window,
7202      require('ev-emitter'),
7203      require('get-size'),
7204      require('fizzy-ui-utils'),
7205      require('./item')
7206    );
7207  } else {
7208    // browser global
7209    window.Outlayer = factory(
7210      window,
7211      window.EvEmitter,
7212      window.getSize,
7213      window.fizzyUIUtils,
7214      window.Outlayer.Item
7215    );
7216  }
7217
7218}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
7219'use strict';
7220
7221// ----- vars ----- //
7222
7223var console = window.console;
7224var jQuery = window.jQuery;
7225var noop = function() {};
7226
7227// -------------------------- Outlayer -------------------------- //
7228
7229// globally unique identifiers
7230var GUID = 0;
7231// internal store of all Outlayer intances
7232var instances = {};
7233
7234
7235/**
7236 * @param {Element, String} element
7237 * @param {Object} options
7238 * @constructor
7239 */
7240function Outlayer( element, options ) {
7241  var queryElement = utils.getQueryElement( element );
7242  if ( !queryElement ) {
7243    if ( console ) {
7244      console.error( 'Bad element for ' + this.constructor.namespace +
7245        ': ' + ( queryElement || element ) );
7246    }
7247    return;
7248  }
7249  this.element = queryElement;
7250  // add jQuery
7251  if ( jQuery ) {
7252    this.$element = jQuery( this.element );
7253  }
7254
7255  // options
7256  this.options = utils.extend( {}, this.constructor.defaults );
7257  this.option( options );
7258
7259  // add id for Outlayer.getFromElement
7260  var id = ++GUID;
7261  this.element.outlayerGUID = id; // expando
7262  instances[ id ] = this; // associate via id
7263
7264  // kick it off
7265  this._create();
7266
7267  var isInitLayout = this._getOption('initLayout');
7268  if ( isInitLayout ) {
7269    this.layout();
7270  }
7271}
7272
7273// settings are for internal use only
7274Outlayer.namespace = 'outlayer';
7275Outlayer.Item = Item;
7276
7277// default options
7278Outlayer.defaults = {
7279  containerStyle: {
7280    position: 'relative'
7281  },
7282  initLayout: true,
7283  originLeft: true,
7284  originTop: true,
7285  resize: true,
7286  resizeContainer: true,
7287  // item options
7288  transitionDuration: '0.4s',
7289  hiddenStyle: {
7290    opacity: 0,
7291    transform: 'scale(0.001)'
7292  },
7293  visibleStyle: {
7294    opacity: 1,
7295    transform: 'scale(1)'
7296  }
7297};
7298
7299var proto = Outlayer.prototype;
7300// inherit EvEmitter
7301utils.extend( proto, EvEmitter.prototype );
7302
7303/**
7304 * set options
7305 * @param {Object} opts
7306 */
7307proto.option = function( opts ) {
7308  utils.extend( this.options, opts );
7309};
7310
7311/**
7312 * get backwards compatible option value, check old name
7313 */
7314proto._getOption = function( option ) {
7315  var oldOption = this.constructor.compatOptions[ option ];
7316  return oldOption && this.options[ oldOption ] !== undefined ?
7317    this.options[ oldOption ] : this.options[ option ];
7318};
7319
7320Outlayer.compatOptions = {
7321  // currentName: oldName
7322  initLayout: 'isInitLayout',
7323  horizontal: 'isHorizontal',
7324  layoutInstant: 'isLayoutInstant',
7325  originLeft: 'isOriginLeft',
7326  originTop: 'isOriginTop',
7327  resize: 'isResizeBound',
7328  resizeContainer: 'isResizingContainer'
7329};
7330
7331proto._create = function() {
7332  // get items from children
7333  this.reloadItems();
7334  // elements that affect layout, but are not laid out
7335  this.stamps = [];
7336  this.stamp( this.options.stamp );
7337  // set container style
7338  utils.extend( this.element.style, this.options.containerStyle );
7339
7340  // bind resize method
7341  var canBindResize = this._getOption('resize');
7342  if ( canBindResize ) {
7343    this.bindResize();
7344  }
7345};
7346
7347// goes through all children again and gets bricks in proper order
7348proto.reloadItems = function() {
7349  // collection of item elements
7350  this.items = this._itemize( this.element.children );
7351};
7352
7353
7354/**
7355 * turn elements into Outlayer.Items to be used in layout
7356 * @param {Array or NodeList or HTMLElement} elems
7357 * @returns {Array} items - collection of new Outlayer Items
7358 */
7359proto._itemize = function( elems ) {
7360
7361  var itemElems = this._filterFindItemElements( elems );
7362  var Item = this.constructor.Item;
7363
7364  // create new Outlayer Items for collection
7365  var items = [];
7366  for ( var i=0; i < itemElems.length; i++ ) {
7367    var elem = itemElems[i];
7368    var item = new Item( elem, this );
7369    items.push( item );
7370  }
7371
7372  return items;
7373};
7374
7375/**
7376 * get item elements to be used in layout
7377 * @param {Array or NodeList or HTMLElement} elems
7378 * @returns {Array} items - item elements
7379 */
7380proto._filterFindItemElements = function( elems ) {
7381  return utils.filterFindElements( elems, this.options.itemSelector );
7382};
7383
7384/**
7385 * getter method for getting item elements
7386 * @returns {Array} elems - collection of item elements
7387 */
7388proto.getItemElements = function() {
7389  return this.items.map( function( item ) {
7390    return item.element;
7391  });
7392};
7393
7394// ----- init & layout ----- //
7395
7396/**
7397 * lays out all items
7398 */
7399proto.layout = function() {
7400  this._resetLayout();
7401  this._manageStamps();
7402
7403  // don't animate first layout
7404  var layoutInstant = this._getOption('layoutInstant');
7405  var isInstant = layoutInstant !== undefined ?
7406    layoutInstant : !this._isLayoutInited;
7407  this.layoutItems( this.items, isInstant );
7408
7409  // flag for initalized
7410  this._isLayoutInited = true;
7411};
7412
7413// _init is alias for layout
7414proto._init = proto.layout;
7415
7416/**
7417 * logic before any new layout
7418 */
7419proto._resetLayout = function() {
vendor: 13,499 bytes, lines 7420-7988
7420  this.getSize();
7421};
7422
7423
7424proto.getSize = function() {
7425  this.size = getSize( this.element );
7426};
7427
7428/**
7429 * get measurement from option, for columnWidth, rowHeight, gutter
7430 * if option is String -> get element from selector string, & get size of element
7431 * if option is Element -> get size of element
7432 * else use option as a number
7433 *
7434 * @param {String} measurement
7435 * @param {String} size - width or height
7436 * @private
7437 */
7438proto._getMeasurement = function( measurement, size ) {
7439  var option = this.options[ measurement ];
7440  var elem;
7441  if ( !option ) {
7442    // default to 0
7443    this[ measurement ] = 0;
7444  } else {
7445    // use option as an element
7446    if ( typeof option == 'string' ) {
7447      elem = this.element.querySelector( option );
7448    } else if ( option instanceof HTMLElement ) {
7449      elem = option;
7450    }
7451    // use size of element, if element
7452    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
7453  }
7454};
7455
7456/**
7457 * layout a collection of item elements
7458 * @api public
7459 */
7460proto.layoutItems = function( items, isInstant ) {
7461  items = this._getItemsForLayout( items );
7462
7463  this._layoutItems( items, isInstant );
7464
7465  this._postLayout();
7466};
7467
7468/**
7469 * get the items to be laid out
7470 * you may want to skip over some items
7471 * @param {Array} items
7472 * @returns {Array} items
7473 */
7474proto._getItemsForLayout = function( items ) {
7475  return items.filter( function( item ) {
7476    return !item.isIgnored;
7477  });
7478};
7479
7480/**
7481 * layout items
7482 * @param {Array} items
7483 * @param {Boolean} isInstant
7484 */
7485proto._layoutItems = function( items, isInstant ) {
7486  this._emitCompleteOnItems( 'layout', items );
7487
7488  if ( !items || !items.length ) {
7489    // no items, emit event with empty array
7490    return;
7491  }
7492
7493  var queue = [];
7494
7495  items.forEach( function( item ) {
7496    // get x/y object from method
7497    var position = this._getItemLayoutPosition( item );
7498    // enqueue
7499    position.item = item;
7500    position.isInstant = isInstant || item.isLayoutInstant;
7501    queue.push( position );
7502  }, this );
7503
7504  this._processLayoutQueue( queue );
7505};
7506
7507/**
7508 * get item layout position
7509 * @param {Outlayer.Item} item
7510 * @returns {Object} x and y position
7511 */
7512proto._getItemLayoutPosition = function( /* item */ ) {
7513  return {
7514    x: 0,
7515    y: 0
7516  };
7517};
7518
7519/**
7520 * iterate over array and position each item
7521 * Reason being - separating this logic prevents 'layout invalidation'
7522 * thx @paul_irish
7523 * @param {Array} queue
7524 */
7525proto._processLayoutQueue = function( queue ) {
7526  this.updateStagger();
7527  queue.forEach( function( obj, i ) {
7528    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
7529  }, this );
7530};
7531
7532// set stagger from option in milliseconds number
7533proto.updateStagger = function() {
7534  var stagger = this.options.stagger;
7535  if ( stagger === null || stagger === undefined ) {
7536    this.stagger = 0;
7537    return;
7538  }
7539  this.stagger = getMilliseconds( stagger );
7540  return this.stagger;
7541};
7542
7543/**
7544 * Sets position of item in DOM
7545 * @param {Outlayer.Item} item
7546 * @param {Number} x - horizontal position
7547 * @param {Number} y - vertical position
7548 * @param {Boolean} isInstant - disables transitions
7549 */
7550proto._positionItem = function( item, x, y, isInstant, i ) {
7551  if ( isInstant ) {
7552    // if not transition, just set CSS
7553    item.goTo( x, y );
7554  } else {
7555    item.stagger( i * this.stagger );
7556    item.moveTo( x, y );
7557  }
7558};
7559
7560/**
7561 * Any logic you want to do after each layout,
7562 * i.e. size the container
7563 */
7564proto._postLayout = function() {
7565  this.resizeContainer();
7566};
7567
7568proto.resizeContainer = function() {
7569  var isResizingContainer = this._getOption('resizeContainer');
7570  if ( !isResizingContainer ) {
7571    return;
7572  }
7573  var size = this._getContainerSize();
7574  if ( size ) {
7575    this._setContainerMeasure( size.width, true );
7576    this._setContainerMeasure( size.height, false );
7577  }
7578};
7579
7580/**
7581 * Sets width or height of container if returned
7582 * @returns {Object} size
7583 *   @param {Number} width
7584 *   @param {Number} height
7585 */
7586proto._getContainerSize = noop;
7587
7588/**
7589 * @param {Number} measure - size of width or height
7590 * @param {Boolean} isWidth
7591 */
7592proto._setContainerMeasure = function( measure, isWidth ) {
7593  if ( measure === undefined ) {
7594    return;
7595  }
7596
7597  var elemSize = this.size;
7598  // add padding and border width if border box
7599  if ( elemSize.isBorderBox ) {
7600    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
7601      elemSize.borderLeftWidth + elemSize.borderRightWidth :
7602      elemSize.paddingBottom + elemSize.paddingTop +
7603      elemSize.borderTopWidth + elemSize.borderBottomWidth;
7604  }
7605
7606  measure = Math.max( measure, 0 );
7607  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
7608};
7609
7610/**
7611 * emit eventComplete on a collection of items events
7612 * @param {String} eventName
7613 * @param {Array} items - Outlayer.Items
7614 */
7615proto._emitCompleteOnItems = function( eventName, items ) {
7616  var _this = this;
7617  function onComplete() {
7618    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
7619  }
7620
7621  var count = items.length;
7622  if ( !items || !count ) {
7623    onComplete();
7624    return;
7625  }
7626
7627  var doneCount = 0;
7628  function tick() {
7629    doneCount++;
7630    if ( doneCount == count ) {
7631      onComplete();
7632    }
7633  }
7634
7635  // bind callback
7636  items.forEach( function( item ) {
7637    item.once( eventName, tick );
7638  });
7639};
7640
7641/**
7642 * emits events via EvEmitter and jQuery events
7643 * @param {String} type - name of event
7644 * @param {Event} event - original event
7645 * @param {Array} args - extra arguments
7646 */
7647proto.dispatchEvent = function( type, event, args ) {
7648  // add original event to arguments
7649  var emitArgs = event ? [ event ].concat( args ) : args;
7650  this.emitEvent( type, emitArgs );
7651
7652  if ( jQuery ) {
7653    // set this.$element
7654    this.$element = this.$element || jQuery( this.element );
7655    if ( event ) {
7656      // create jQuery event
7657      var $event = jQuery.Event( event );
7658      $event.type = type;
7659      this.$element.trigger( $event, args );
7660    } else {
7661      // just trigger with type if no event available
7662      this.$element.trigger( type, args );
7663    }
7664  }
7665};
7666
7667// -------------------------- ignore & stamps -------------------------- //
7668
7669
7670/**
7671 * keep item in collection, but do not lay it out
7672 * ignored items do not get skipped in layout
7673 * @param {Element} elem
7674 */
7675proto.ignore = function( elem ) {
7676  var item = this.getItem( elem );
7677  if ( item ) {
7678    item.isIgnored = true;
7679  }
7680};
7681
7682/**
7683 * return item to layout collection
7684 * @param {Element} elem
7685 */
7686proto.unignore = function( elem ) {
7687  var item = this.getItem( elem );
7688  if ( item ) {
7689    delete item.isIgnored;
7690  }
7691};
7692
7693/**
7694 * adds elements to stamps
7695 * @param {NodeList, Array, Element, or String} elems
7696 */
7697proto.stamp = function( elems ) {
7698  elems = this._find( elems );
7699  if ( !elems ) {
7700    return;
7701  }
7702
7703  this.stamps = this.stamps.concat( elems );
7704  // ignore
7705  elems.forEach( this.ignore, this );
7706};
7707
7708/**
7709 * removes elements to stamps
7710 * @param {NodeList, Array, or Element} elems
7711 */
7712proto.unstamp = function( elems ) {
7713  elems = this._find( elems );
7714  if ( !elems ){
7715    return;
7716  }
7717
7718  elems.forEach( function( elem ) {
7719    // filter out removed stamp elements
7720    utils.removeFrom( this.stamps, elem );
7721    this.unignore( elem );
7722  }, this );
7723};
7724
7725/**
7726 * finds child elements
7727 * @param {NodeList, Array, Element, or String} elems
7728 * @returns {Array} elems
7729 */
7730proto._find = function( elems ) {
7731  if ( !elems ) {
7732    return;
7733  }
7734  // if string, use argument as selector string
7735  if ( typeof elems == 'string' ) {
7736    elems = this.element.querySelectorAll( elems );
7737  }
7738  elems = utils.makeArray( elems );
7739  return elems;
7740};
7741
7742proto._manageStamps = function() {
7743  if ( !this.stamps || !this.stamps.length ) {
7744    return;
7745  }
7746
7747  this._getBoundingRect();
7748
7749  this.stamps.forEach( this._manageStamp, this );
7750};
7751
7752// update boundingLeft / Top
7753proto._getBoundingRect = function() {
7754  // get bounding rect for container element
7755  var boundingRect = this.element.getBoundingClientRect();
7756  var size = this.size;
7757  this._boundingRect = {
7758    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
7759    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
7760    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
7761    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
7762  };
7763};
7764
7765/**
7766 * @param {Element} stamp
7767**/
7768proto._manageStamp = noop;
7769
7770/**
7771 * get x/y position of element relative to container element
7772 * @param {Element} elem
7773 * @returns {Object} offset - has left, top, right, bottom
7774 */
7775proto._getElementOffset = function( elem ) {
7776  var boundingRect = elem.getBoundingClientRect();
7777  var thisRect = this._boundingRect;
7778  var size = getSize( elem );
7779  var offset = {
7780    left: boundingRect.left - thisRect.left - size.marginLeft,
7781    top: boundingRect.top - thisRect.top - size.marginTop,
7782    right: thisRect.right - boundingRect.right - size.marginRight,
7783    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
7784  };
7785  return offset;
7786};
7787
7788// -------------------------- resize -------------------------- //
7789
7790// enable event handlers for listeners
7791// i.e. resize -> onresize
7792proto.handleEvent = utils.handleEvent;
7793
7794/**
7795 * Bind layout to window resizing
7796 */
7797proto.bindResize = function() {
7798  window.addEventListener( 'resize', this );
7799  this.isResizeBound = true;
7800};
7801
7802/**
7803 * Unbind layout to window resizing
7804 */
7805proto.unbindResize = function() {
7806  window.removeEventListener( 'resize', this );
7807  this.isResizeBound = false;
7808};
7809
7810proto.onresize = function() {
7811  this.resize();
7812};
7813
7814utils.debounceMethod( Outlayer, 'onresize', 100 );
7815
7816proto.resize = function() {
7817  // don't trigger if size did not change
7818  // or if resize was unbound. See #9
7819  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
7820    return;
7821  }
7822
7823  this.layout();
7824};
7825
7826/**
7827 * check if layout is needed post layout
7828 * @returns Boolean
7829 */
7830proto.needsResizeLayout = function() {
7831  var size = getSize( this.element );
7832  // check that this.size and size are there
7833  // IE8 triggers resize on body size change, so they might not be
7834  var hasSizes = this.size && size;
7835  return hasSizes && size.innerWidth !== this.size.innerWidth;
7836};
7837
7838// -------------------------- methods -------------------------- //
7839
7840/**
7841 * add items to Outlayer instance
7842 * @param {Array or NodeList or Element} elems
7843 * @returns {Array} items - Outlayer.Items
7844**/
7845proto.addItems = function( elems ) {
7846  var items = this._itemize( elems );
7847  // add items to collection
7848  if ( items.length ) {
7849    this.items = this.items.concat( items );
7850  }
7851  return items;
7852};
7853
7854/**
7855 * Layout newly-appended item elements
7856 * @param {Array or NodeList or Element} elems
7857 */
7858proto.appended = function( elems ) {
7859  var items = this.addItems( elems );
7860  if ( !items.length ) {
7861    return;
7862  }
7863  // layout and reveal just the new items
7864  this.layoutItems( items, true );
7865  this.reveal( items );
7866};
7867
7868/**
7869 * Layout prepended elements
7870 * @param {Array or NodeList or Element} elems
7871 */
7872proto.prepended = function( elems ) {
7873  var items = this._itemize( elems );
7874  if ( !items.length ) {
7875    return;
7876  }
7877  // add items to beginning of collection
7878  var previousItems = this.items.slice(0);
7879  this.items = items.concat( previousItems );
7880  // start new layout
7881  this._resetLayout();
7882  this._manageStamps();
7883  // layout new stuff without transition
7884  this.layoutItems( items, true );
7885  this.reveal( items );
7886  // layout previous items
7887  this.layoutItems( previousItems );
7888};
7889
7890/**
7891 * reveal a collection of items
7892 * @param {Array of Outlayer.Items} items
7893 */
7894proto.reveal = function( items ) {
7895  this._emitCompleteOnItems( 'reveal', items );
7896  if ( !items || !items.length ) {
7897    return;
7898  }
7899  var stagger = this.updateStagger();
7900  items.forEach( function( item, i ) {
7901    item.stagger( i * stagger );
7902    item.reveal();
7903  });
7904};
7905
7906/**
7907 * hide a collection of items
7908 * @param {Array of Outlayer.Items} items
7909 */
7910proto.hide = function( items ) {
7911  this._emitCompleteOnItems( 'hide', items );
7912  if ( !items || !items.length ) {
7913    return;
7914  }
7915  var stagger = this.updateStagger();
7916  items.forEach( function( item, i ) {
7917    item.stagger( i * stagger );
7918    item.hide();
7919  });
7920};
7921
7922/**
7923 * reveal item elements
7924 * @param {Array}, {Element}, {NodeList} items
7925 */
7926proto.revealItemElements = function( elems ) {
7927  var items = this.getItems( elems );
7928  this.reveal( items );
7929};
7930
7931/**
7932 * hide item elements
7933 * @param {Array}, {Element}, {NodeList} items
7934 */
7935proto.hideItemElements = function( elems ) {
7936  var items = this.getItems( elems );
7937  this.hide( items );
7938};
7939
7940/**
7941 * get Outlayer.Item, given an Element
7942 * @param {Element} elem
7943 * @param {Function} callback
7944 * @returns {Outlayer.Item} item
7945 */
7946proto.getItem = function( elem ) {
7947  // loop through items to get the one that matches
7948  for ( var i=0; i < this.items.length; i++ ) {
7949    var item = this.items[i];
7950    if ( item.element == elem ) {
7951      // return item
7952      return item;
7953    }
7954  }
7955};
7956
7957/**
7958 * get collection of Outlayer.Items, given Elements
7959 * @param {Array} elems
7960 * @returns {Array} items - Outlayer.Items
7961 */
7962proto.getItems = function( elems ) {
7963  elems = utils.makeArray( elems );
7964  var items = [];
7965  elems.forEach( function( elem ) {
7966    var item = this.getItem( elem );
7967    if ( item ) {
7968      items.push( item );
7969    }
7970  }, this );
7971
7972  return items;
7973};
7974
7975/**
7976 * remove element(s) from instance and DOM
7977 * @param {Array or NodeList or Element} elems
7978 */
7979proto.remove = function( elems ) {
7980  var removeItems = this.getItems( elems );
7981
7982  this._emitCompleteOnItems( 'remove', removeItems );
7983
7984  // bail if no items to remove
7985  if ( !removeItems || !removeItems.length ) {
7986    return;
7987  }
7988
vendor: 38,285 bytes, lines 7989-9412
7989  removeItems.forEach( function( item ) {
7990    item.remove();
7991    // remove item from collection
7992    utils.removeFrom( this.items, item );
7993  }, this );
7994};
7995
7996// ----- destroy ----- //
7997
7998// remove and disable Outlayer instance
7999proto.destroy = function() {
8000  // clean up dynamic styles
8001  var style = this.element.style;
8002  style.height = '';
8003  style.position = '';
8004  style.width = '';
8005  // destroy items
8006  this.items.forEach( function( item ) {
8007    item.destroy();
8008  });
8009
8010  this.unbindResize();
8011
8012  var id = this.element.outlayerGUID;
8013  delete instances[ id ]; // remove reference to instance by id
8014  delete this.element.outlayerGUID;
8015  // remove data for jQuery
8016  if ( jQuery ) {
8017    jQuery.removeData( this.element, this.constructor.namespace );
8018  }
8019
8020};
8021
8022// -------------------------- data -------------------------- //
8023
8024/**
8025 * get Outlayer instance from element
8026 * @param {Element} elem
8027 * @returns {Outlayer}
8028 */
8029Outlayer.data = function( elem ) {
8030  elem = utils.getQueryElement( elem );
8031  var id = elem && elem.outlayerGUID;
8032  return id && instances[ id ];
8033};
8034
8035
8036// -------------------------- create Outlayer class -------------------------- //
8037
8038/**
8039 * create a layout class
8040 * @param {String} namespace
8041 */
8042Outlayer.create = function( namespace, options ) {
8043  // sub-class Outlayer
8044  var Layout = subclass( Outlayer );
8045  // apply new options and compatOptions
8046  Layout.defaults = utils.extend( {}, Outlayer.defaults );
8047  utils.extend( Layout.defaults, options );
8048  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
8049
8050  Layout.namespace = namespace;
8051
8052  Layout.data = Outlayer.data;
8053
8054  // sub-class Item
8055  Layout.Item = subclass( Item );
8056
8057  // -------------------------- declarative -------------------------- //
8058
8059  utils.htmlInit( Layout, namespace );
8060
8061  // -------------------------- jQuery bridge -------------------------- //
8062
8063  // make into jQuery plugin
8064  if ( jQuery && jQuery.bridget ) {
8065    jQuery.bridget( namespace, Layout );
8066  }
8067
8068  return Layout;
8069};
8070
8071function subclass( Parent ) {
8072  function SubClass() {
8073    Parent.apply( this, arguments );
8074  }
8075
8076  SubClass.prototype = Object.create( Parent.prototype );
8077  SubClass.prototype.constructor = SubClass;
8078
8079  return SubClass;
8080}
8081
8082// ----- helpers ----- //
8083
8084// how many milliseconds are in each unit
8085var msUnits = {
8086  ms: 1,
8087  s: 1000
8088};
8089
8090// munge time-like parameter into millisecond number
8091// '0.4s' -> 40
8092function getMilliseconds( time ) {
8093  if ( typeof time == 'number' ) {
8094    return time;
8095  }
8096  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
8097  var num = matches && matches[1];
8098  var unit = matches && matches[2];
8099  if ( !num.length ) {
8100    return 0;
8101  }
8102  num = parseFloat( num );
8103  var mult = msUnits[ unit ] || 1;
8104  return num * mult;
8105}
8106
8107// ----- fin ----- //
8108
8109// back in global
8110Outlayer.Item = Item;
8111
8112return Outlayer;
8113
8114}));
8115
8116/**
8117 * Isotope Item
8118**/
8119
8120( function( window, factory ) {
8121  // universal module definition
8122  /* jshint strict: false */ /*globals define, module, require */
8123  if ( typeof define == 'function' && define.amd ) {
8124    // AMD
8125    define( 'isotope-layout/js/item',[
8126        'outlayer/outlayer'
8127      ],
8128      factory );
8129  } else if ( typeof module == 'object' && module.exports ) {
8130    // CommonJS
8131    module.exports = factory(
8132      require('outlayer')
8133    );
8134  } else {
8135    // browser global
8136    window.Isotope = window.Isotope || {};
8137    window.Isotope.Item = factory(
8138      window.Outlayer
8139    );
8140  }
8141
8142}( window, function factory( Outlayer ) {
8143'use strict';
8144
8145// -------------------------- Item -------------------------- //
8146
8147// sub-class Outlayer Item
8148function Item() {
8149  Outlayer.Item.apply( this, arguments );
8150}
8151
8152var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
8153
8154var _create = proto._create;
8155proto._create = function() {
8156  // assign id, used for original-order sorting
8157  this.id = this.layout.itemGUID++;
8158  _create.call( this );
8159  this.sortData = {};
8160};
8161
8162proto.updateSortData = function() {
8163  if ( this.isIgnored ) {
8164    return;
8165  }
8166  // default sorters
8167  this.sortData.id = this.id;
8168  // for backward compatibility
8169  this.sortData['original-order'] = this.id;
8170  this.sortData.random = Math.random();
8171  // go thru getSortData obj and apply the sorters
8172  var getSortData = this.layout.options.getSortData;
8173  var sorters = this.layout._sorters;
8174  for ( var key in getSortData ) {
8175    var sorter = sorters[ key ];
8176    this.sortData[ key ] = sorter( this.element, this );
8177  }
8178};
8179
8180var _destroy = proto.destroy;
8181proto.destroy = function() {
8182  // call super
8183  _destroy.apply( this, arguments );
8184  // reset display, #741
8185  this.css({
8186    display: ''
8187  });
8188};
8189
8190return Item;
8191
8192}));
8193
8194/**
8195 * Isotope LayoutMode
8196 */
8197
8198( function( window, factory ) {
8199  // universal module definition
8200  /* jshint strict: false */ /*globals define, module, require */
8201  if ( typeof define == 'function' && define.amd ) {
8202    // AMD
8203    define( 'isotope-layout/js/layout-mode',[
8204        'get-size/get-size',
8205        'outlayer/outlayer'
8206      ],
8207      factory );
8208  } else if ( typeof module == 'object' && module.exports ) {
8209    // CommonJS
8210    module.exports = factory(
8211      require('get-size'),
8212      require('outlayer')
8213    );
8214  } else {
8215    // browser global
8216    window.Isotope = window.Isotope || {};
8217    window.Isotope.LayoutMode = factory(
8218      window.getSize,
8219      window.Outlayer
8220    );
8221  }
8222
8223}( window, function factory( getSize, Outlayer ) {
8224  'use strict';
8225
8226  // layout mode class
8227  function LayoutMode( isotope ) {
8228    this.isotope = isotope;
8229    // link properties
8230    if ( isotope ) {
8231      this.options = isotope.options[ this.namespace ];
8232      this.element = isotope.element;
8233      this.items = isotope.filteredItems;
8234      this.size = isotope.size;
8235    }
8236  }
8237
8238  var proto = LayoutMode.prototype;
8239
8240  /**
8241   * some methods should just defer to default Outlayer method
8242   * and reference the Isotope instance as `this`
8243  **/
8244  var facadeMethods = [
8245    '_resetLayout',
8246    '_getItemLayoutPosition',
8247    '_manageStamp',
8248    '_getContainerSize',
8249    '_getElementOffset',
8250    'needsResizeLayout',
8251    '_getOption'
8252  ];
8253
8254  facadeMethods.forEach( function( methodName ) {
8255    proto[ methodName ] = function() {
8256      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
8257    };
8258  });
8259
8260  // -----  ----- //
8261
8262  // for horizontal layout modes, check vertical size
8263  proto.needsVerticalResizeLayout = function() {
8264    // don't trigger if size did not change
8265    var size = getSize( this.isotope.element );
8266    // check that this.size and size are there
8267    // IE8 triggers resize on body size change, so they might not be
8268    var hasSizes = this.isotope.size && size;
8269    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
8270  };
8271
8272  // ----- measurements ----- //
8273
8274  proto._getMeasurement = function() {
8275    this.isotope._getMeasurement.apply( this, arguments );
8276  };
8277
8278  proto.getColumnWidth = function() {
8279    this.getSegmentSize( 'column', 'Width' );
8280  };
8281
8282  proto.getRowHeight = function() {
8283    this.getSegmentSize( 'row', 'Height' );
8284  };
8285
8286  /**
8287   * get columnWidth or rowHeight
8288   * segment: 'column' or 'row'
8289   * size 'Width' or 'Height'
8290  **/
8291  proto.getSegmentSize = function( segment, size ) {
8292    var segmentName = segment + size;
8293    var outerSize = 'outer' + size;
8294    // columnWidth / outerWidth // rowHeight / outerHeight
8295    this._getMeasurement( segmentName, outerSize );
8296    // got rowHeight or columnWidth, we can chill
8297    if ( this[ segmentName ] ) {
8298      return;
8299    }
8300    // fall back to item of first element
8301    var firstItemSize = this.getFirstItemSize();
8302    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
8303      // or size of container
8304      this.isotope.size[ 'inner' + size ];
8305  };
8306
8307  proto.getFirstItemSize = function() {
8308    var firstItem = this.isotope.filteredItems[0];
8309    return firstItem && firstItem.element && getSize( firstItem.element );
8310  };
8311
8312  // ----- methods that should reference isotope ----- //
8313
8314  proto.layout = function() {
8315    this.isotope.layout.apply( this.isotope, arguments );
8316  };
8317
8318  proto.getSize = function() {
8319    this.isotope.getSize();
8320    this.size = this.isotope.size;
8321  };
8322
8323  // -------------------------- create -------------------------- //
8324
8325  LayoutMode.modes = {};
8326
8327  LayoutMode.create = function( namespace, options ) {
8328
8329    function Mode() {
8330      LayoutMode.apply( this, arguments );
8331    }
8332
8333    Mode.prototype = Object.create( proto );
8334    Mode.prototype.constructor = Mode;
8335
8336    // default options
8337    if ( options ) {
8338      Mode.options = options;
8339    }
8340
8341    Mode.prototype.namespace = namespace;
8342    // register in Isotope
8343    LayoutMode.modes[ namespace ] = Mode;
8344
8345    return Mode;
8346  };
8347
8348  return LayoutMode;
8349
8350}));
8351
8352/*!
8353 * Masonry v4.2.1
8354 * Cascading grid layout library
8355 * https://masonry.desandro.com
8356 * MIT License
8357 * by David DeSandro
8358 */
8359
8360( function( window, factory ) {
8361  // universal module definition
8362  /* jshint strict: false */ /*globals define, module, require */
8363  if ( typeof define == 'function' && define.amd ) {
8364    // AMD
8365    define( 'masonry-layout/masonry',[
8366        'outlayer/outlayer',
8367        'get-size/get-size'
8368      ],
8369      factory );
8370  } else if ( typeof module == 'object' && module.exports ) {
8371    // CommonJS
8372    module.exports = factory(
8373      require('outlayer'),
8374      require('get-size')
8375    );
8376  } else {
8377    // browser global
8378    window.Masonry = factory(
8379      window.Outlayer,
8380      window.getSize
8381    );
8382  }
8383
8384}( window, function factory( Outlayer, getSize ) {
8385
8386
8387
8388// -------------------------- masonryDefinition -------------------------- //
8389
8390  // create an Outlayer layout class
8391  var Masonry = Outlayer.create('masonry');
8392  // isFitWidth -> fitWidth
8393  Masonry.compatOptions.fitWidth = 'isFitWidth';
8394
8395  var proto = Masonry.prototype;
8396
8397  proto._resetLayout = function() {
8398    this.getSize();
8399    this._getMeasurement( 'columnWidth', 'outerWidth' );
8400    this._getMeasurement( 'gutter', 'outerWidth' );
8401    this.measureColumns();
8402
8403    // reset column Y
8404    this.colYs = [];
8405    for ( var i=0; i < this.cols; i++ ) {
8406      this.colYs.push( 0 );
8407    }
8408
8409    this.maxY = 0;
8410    this.horizontalColIndex = 0;
8411  };
8412
8413  proto.measureColumns = function() {
8414    this.getContainerWidth();
8415    // if columnWidth is 0, default to outerWidth of first item
8416    if ( !this.columnWidth ) {
8417      var firstItem = this.items[0];
8418      var firstItemElem = firstItem && firstItem.element;
8419      // columnWidth fall back to item of first element
8420      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
8421        // if first elem has no width, default to size of container
8422        this.containerWidth;
8423    }
8424
8425    var columnWidth = this.columnWidth += this.gutter;
8426
8427    // calculate columns
8428    var containerWidth = this.containerWidth + this.gutter;
8429    var cols = containerWidth / columnWidth;
8430    // fix rounding errors, typically with gutters
8431    var excess = columnWidth - containerWidth % columnWidth;
8432    // if overshoot is less than a pixel, round up, otherwise floor it
8433    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
8434    cols = Math[ mathMethod ]( cols );
8435    this.cols = Math.max( cols, 1 );
8436  };
8437
8438  proto.getContainerWidth = function() {
8439    // container is parent if fit width
8440    var isFitWidth = this._getOption('fitWidth');
8441    var container = isFitWidth ? this.element.parentNode : this.element;
8442    // check that this.size and size are there
8443    // IE8 triggers resize on body size change, so they might not be
8444    var size = getSize( container );
8445    this.containerWidth = size && size.innerWidth;
8446  };
8447
8448  proto._getItemLayoutPosition = function( item ) {
8449    item.getSize();
8450    // how many columns does this brick span
8451    var remainder = item.size.outerWidth % this.columnWidth;
8452    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
8453    // round if off by 1 pixel, otherwise use ceil
8454    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
8455    colSpan = Math.min( colSpan, this.cols );
8456    // use horizontal or top column position
8457    var colPosMethod = this.options.horizontalOrder ?
8458      '_getHorizontalColPosition' : '_getTopColPosition';
8459    var colPosition = this[ colPosMethod ]( colSpan, item );
8460    // position the brick
8461    var position = {
8462      x: this.columnWidth * colPosition.col,
8463      y: colPosition.y
8464    };
8465    // apply setHeight to necessary columns
8466    var setHeight = colPosition.y + item.size.outerHeight;
8467    var setMax = colSpan + colPosition.col;
8468    for ( var i = colPosition.col; i < setMax; i++ ) {
8469      this.colYs[i] = setHeight;
8470    }
8471
8472    return position;
8473  };
8474
8475  proto._getTopColPosition = function( colSpan ) {
8476    var colGroup = this._getTopColGroup( colSpan );
8477    // get the minimum Y value from the columns
8478    var minimumY = Math.min.apply( Math, colGroup );
8479
8480    return {
8481      col: colGroup.indexOf( minimumY ),
8482      y: minimumY,
8483    };
8484  };
8485
8486  /**
8487   * @param {Number} colSpan - number of columns the element spans
8488   * @returns {Array} colGroup
8489   */
8490  proto._getTopColGroup = function( colSpan ) {
8491    if ( colSpan < 2 ) {
8492      // if brick spans only one column, use all the column Ys
8493      return this.colYs;
8494    }
8495
8496    var colGroup = [];
8497    // how many different places could this brick fit horizontally
8498    var groupCount = this.cols + 1 - colSpan;
8499    // for each group potential horizontal position
8500    for ( var i = 0; i < groupCount; i++ ) {
8501      colGroup[i] = this._getColGroupY( i, colSpan );
8502    }
8503    return colGroup;
8504  };
8505
8506  proto._getColGroupY = function( col, colSpan ) {
8507    if ( colSpan < 2 ) {
8508      return this.colYs[ col ];
8509    }
8510    // make an array of colY values for that one group
8511    var groupColYs = this.colYs.slice( col, col + colSpan );
8512    // and get the max value of the array
8513    return Math.max.apply( Math, groupColYs );
8514  };
8515
8516  // get column position based on horizontal index. #873
8517  proto._getHorizontalColPosition = function( colSpan, item ) {
8518    var col = this.horizontalColIndex % this.cols;
8519    var isOver = colSpan > 1 && col + colSpan > this.cols;
8520    // shift to next row if item can't fit on current row
8521    col = isOver ? 0 : col;
8522    // don't let zero-size items take up space
8523    var hasSize = item.size.outerWidth && item.size.outerHeight;
8524    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
8525
8526    return {
8527      col: col,
8528      y: this._getColGroupY( col, colSpan ),
8529    };
8530  };
8531
8532  proto._manageStamp = function( stamp ) {
8533    var stampSize = getSize( stamp );
8534    var offset = this._getElementOffset( stamp );
8535    // get the columns that this stamp affects
8536    var isOriginLeft = this._getOption('originLeft');
8537    var firstX = isOriginLeft ? offset.left : offset.right;
8538    var lastX = firstX + stampSize.outerWidth;
8539    var firstCol = Math.floor( firstX / this.columnWidth );
8540    firstCol = Math.max( 0, firstCol );
8541    var lastCol = Math.floor( lastX / this.columnWidth );
8542    // lastCol should not go over if multiple of columnWidth #425
8543    lastCol -= lastX % this.columnWidth ? 0 : 1;
8544    lastCol = Math.min( this.cols - 1, lastCol );
8545    // set colYs to bottom of the stamp
8546
8547    var isOriginTop = this._getOption('originTop');
8548    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
8549      stampSize.outerHeight;
8550    for ( var i = firstCol; i <= lastCol; i++ ) {
8551      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
8552    }
8553  };
8554
8555  proto._getContainerSize = function() {
8556    this.maxY = Math.max.apply( Math, this.colYs );
8557    var size = {
8558      height: this.maxY
8559    };
8560
8561    if ( this._getOption('fitWidth') ) {
8562      size.width = this._getContainerFitWidth();
8563    }
8564
8565    return size;
8566  };
8567
8568  proto._getContainerFitWidth = function() {
8569    var unusedCols = 0;
8570    // count unused columns
8571    var i = this.cols;
8572    while ( --i ) {
8573      if ( this.colYs[i] !== 0 ) {
8574        break;
8575      }
8576      unusedCols++;
8577    }
8578    // fit container to columns that have been used
8579    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
8580  };
8581
8582  proto.needsResizeLayout = function() {
8583    var previousWidth = this.containerWidth;
8584    this.getContainerWidth();
8585    return previousWidth != this.containerWidth;
8586  };
8587
8588  return Masonry;
8589
8590}));
8591
8592/*!
8593 * Masonry layout mode
8594 * sub-classes Masonry
8595 * https://masonry.desandro.com
8596 */
8597
8598( function( window, factory ) {
8599  // universal module definition
8600  /* jshint strict: false */ /*globals define, module, require */
8601  if ( typeof define == 'function' && define.amd ) {
8602    // AMD
8603    define( 'isotope-layout/js/layout-modes/masonry',[
8604        '../layout-mode',
8605        'masonry-layout/masonry'
8606      ],
8607      factory );
8608  } else if ( typeof module == 'object' && module.exports ) {
8609    // CommonJS
8610    module.exports = factory(
8611      require('../layout-mode'),
8612      require('masonry-layout')
8613    );
8614  } else {
8615    // browser global
8616    factory(
8617      window.Isotope.LayoutMode,
8618      window.Masonry
8619    );
8620  }
8621
8622}( window, function factory( LayoutMode, Masonry ) {
8623'use strict';
8624
8625// -------------------------- masonryDefinition -------------------------- //
8626
8627  // create an Outlayer layout class
8628  var MasonryMode = LayoutMode.create('masonry');
8629
8630  var proto = MasonryMode.prototype;
8631
8632  var keepModeMethods = {
8633    _getElementOffset: true,
8634    layout: true,
8635    _getMeasurement: true
8636  };
8637
8638  // inherit Masonry prototype
8639  for ( var method in Masonry.prototype ) {
8640    // do not inherit mode methods
8641    if ( !keepModeMethods[ method ] ) {
8642      proto[ method ] = Masonry.prototype[ method ];
8643    }
8644  }
8645
8646  var measureColumns = proto.measureColumns;
8647  proto.measureColumns = function() {
8648    // set items, used if measuring first item
8649    this.items = this.isotope.filteredItems;
8650    measureColumns.call( this );
8651  };
8652
8653  // point to mode options for fitWidth
8654  var _getOption = proto._getOption;
8655  proto._getOption = function( option ) {
8656    if ( option == 'fitWidth' ) {
8657      return this.options.isFitWidth !== undefined ?
8658        this.options.isFitWidth : this.options.fitWidth;
8659    }
8660    return _getOption.apply( this.isotope, arguments );
8661  };
8662
8663  return MasonryMode;
8664
8665}));
8666
8667/**
8668 * fitRows layout mode
8669 */
8670
8671( function( window, factory ) {
8672  // universal module definition
8673  /* jshint strict: false */ /*globals define, module, require */
8674  if ( typeof define == 'function' && define.amd ) {
8675    // AMD
8676    define( 'isotope-layout/js/layout-modes/fit-rows',[
8677        '../layout-mode'
8678      ],
8679      factory );
8680  } else if ( typeof exports == 'object' ) {
8681    // CommonJS
8682    module.exports = factory(
8683      require('../layout-mode')
8684    );
8685  } else {
8686    // browser global
8687    factory(
8688      window.Isotope.LayoutMode
8689    );
8690  }
8691
8692}( window, function factory( LayoutMode ) {
8693'use strict';
8694
8695var FitRows = LayoutMode.create('fitRows');
8696
8697var proto = FitRows.prototype;
8698
8699proto._resetLayout = function() {
8700  this.x = 0;
8701  this.y = 0;
8702  this.maxY = 0;
8703  this._getMeasurement( 'gutter', 'outerWidth' );
8704};
8705
8706proto._getItemLayoutPosition = function( item ) {
8707  item.getSize();
8708
8709  var itemWidth = item.size.outerWidth + this.gutter;
8710  // if this element cannot fit in the current row
8711  var containerWidth = this.isotope.size.innerWidth + this.gutter;
8712  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
8713    this.x = 0;
8714    this.y = this.maxY;
8715  }
8716
8717  var position = {
8718    x: this.x,
8719    y: this.y
8720  };
8721
8722  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
8723  this.x += itemWidth;
8724
8725  return position;
8726};
8727
8728proto._getContainerSize = function() {
8729  return { height: this.maxY };
8730};
8731
8732return FitRows;
8733
8734}));
8735
8736/**
8737 * vertical layout mode
8738 */
8739
8740( function( window, factory ) {
8741  // universal module definition
8742  /* jshint strict: false */ /*globals define, module, require */
8743  if ( typeof define == 'function' && define.amd ) {
8744    // AMD
8745    define( 'isotope-layout/js/layout-modes/vertical',[
8746        '../layout-mode'
8747      ],
8748      factory );
8749  } else if ( typeof module == 'object' && module.exports ) {
8750    // CommonJS
8751    module.exports = factory(
8752      require('../layout-mode')
8753    );
8754  } else {
8755    // browser global
8756    factory(
8757      window.Isotope.LayoutMode
8758    );
8759  }
8760
8761}( window, function factory( LayoutMode ) {
8762'use strict';
8763
8764var Vertical = LayoutMode.create( 'vertical', {
8765  horizontalAlignment: 0
8766});
8767
8768var proto = Vertical.prototype;
8769
8770proto._resetLayout = function() {
8771  this.y = 0;
8772};
8773
8774proto._getItemLayoutPosition = function( item ) {
8775  item.getSize();
8776  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
8777    this.options.horizontalAlignment;
8778  var y = this.y;
8779  this.y += item.size.outerHeight;
8780  return { x: x, y: y };
8781};
8782
8783proto._getContainerSize = function() {
8784  return { height: this.y };
8785};
8786
8787return Vertical;
8788
8789}));
8790
8791/*!
8792 * Isotope v3.0.6
8793 *
8794 * Licensed GPLv3 for open source use
8795 * or Isotope Commercial License for commercial use
8796 *
8797 * https://isotope.metafizzy.co
8798 * Copyright 2010-2018 Metafizzy
8799 */
8800
8801( function( window, factory ) {
8802  // universal module definition
8803  /* jshint strict: false */ /*globals define, module, require */
8804  if ( typeof define == 'function' && define.amd ) {
8805    // AMD
8806    define( [
8807        'outlayer/outlayer',
8808        'get-size/get-size',
8809        'desandro-matches-selector/matches-selector',
8810        'fizzy-ui-utils/utils',
8811        'isotope-layout/js/item',
8812        'isotope-layout/js/layout-mode',
8813        // include default layout modes
8814        'isotope-layout/js/layout-modes/masonry',
8815        'isotope-layout/js/layout-modes/fit-rows',
8816        'isotope-layout/js/layout-modes/vertical'
8817      ],
8818      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
8819        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
8820      });
8821  } else if ( typeof module == 'object' && module.exports ) {
8822    // CommonJS
8823    module.exports = factory(
8824      window,
8825      require('outlayer'),
8826      require('get-size'),
8827      require('desandro-matches-selector'),
8828      require('fizzy-ui-utils'),
8829      require('isotope-layout/js/item'),
8830      require('isotope-layout/js/layout-mode'),
8831      // include default layout modes
8832      require('isotope-layout/js/layout-modes/masonry'),
8833      require('isotope-layout/js/layout-modes/fit-rows'),
8834      require('isotope-layout/js/layout-modes/vertical')
8835    );
8836  } else {
8837    // browser global
8838    window.Isotope = factory(
8839      window,
8840      window.Outlayer,
8841      window.getSize,
8842      window.matchesSelector,
8843      window.fizzyUIUtils,
8844      window.Isotope.Item,
8845      window.Isotope.LayoutMode
8846    );
8847  }
8848
8849}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
8850  Item, LayoutMode ) {
8851
8852
8853
8854// -------------------------- vars -------------------------- //
8855
8856var jQuery = window.jQuery;
8857
8858// -------------------------- helpers -------------------------- //
8859
8860var trim = String.prototype.trim ?
8861  function( str ) {
8862    return str.trim();
8863  } :
8864  function( str ) {
8865    return str.replace( /^\s+|\s+$/g, '' );
8866  };
8867
8868// -------------------------- isotopeDefinition -------------------------- //
8869
8870  // create an Outlayer layout class
8871  var Isotope = Outlayer.create( 'isotope', {
8872    layoutMode: 'masonry',
8873    isJQueryFiltering: true,
8874    sortAscending: true
8875  });
8876
8877  Isotope.Item = Item;
8878  Isotope.LayoutMode = LayoutMode;
8879
8880  var proto = Isotope.prototype;
8881
8882  proto._create = function() {
8883    this.itemGUID = 0;
8884    // functions that sort items
8885    this._sorters = {};
8886    this._getSorters();
8887    // call super
8888    Outlayer.prototype._create.call( this );
8889
8890    // create layout modes
8891    this.modes = {};
8892    // start filteredItems with all items
8893    this.filteredItems = this.items;
8894    // keep of track of sortBys
8895    this.sortHistory = [ 'original-order' ];
8896    // create from registered layout modes
8897    for ( var name in LayoutMode.modes ) {
8898      this._initLayoutMode( name );
8899    }
8900  };
8901
8902  proto.reloadItems = function() {
8903    // reset item ID counter
8904    this.itemGUID = 0;
8905    // call super
8906    Outlayer.prototype.reloadItems.call( this );
8907  };
8908
8909  proto._itemize = function() {
8910    var items = Outlayer.prototype._itemize.apply( this, arguments );
8911    // assign ID for original-order
8912    for ( var i=0; i < items.length; i++ ) {
8913      var item = items[i];
8914      item.id = this.itemGUID++;
8915    }
8916    this._updateItemsSortData( items );
8917    return items;
8918  };
8919
8920
8921  // -------------------------- layout -------------------------- //
8922
8923  proto._initLayoutMode = function( name ) {
8924    var Mode = LayoutMode.modes[ name ];
8925    // set mode options
8926    // HACK extend initial options, back-fill in default options
8927    var initialOpts = this.options[ name ] || {};
8928    this.options[ name ] = Mode.options ?
8929      utils.extend( Mode.options, initialOpts ) : initialOpts;
8930    // init layout mode instance
8931    this.modes[ name ] = new Mode( this );
8932  };
8933
8934
8935  proto.layout = function() {
8936    // if first time doing layout, do all magic
8937    if ( !this._isLayoutInited && this._getOption('initLayout') ) {
8938      this.arrange();
8939      return;
8940    }
8941    this._layout();
8942  };
8943
8944  // private method to be used in layout() & magic()
8945  proto._layout = function() {
8946    // don't animate first layout
8947    var isInstant = this._getIsInstant();
8948    // layout flow
8949    this._resetLayout();
8950    this._manageStamps();
8951    this.layoutItems( this.filteredItems, isInstant );
8952
8953    // flag for initalized
8954    this._isLayoutInited = true;
8955  };
8956
8957  // filter + sort + layout
8958  proto.arrange = function( opts ) {
8959    // set any options pass
8960    this.option( opts );
8961    this._getIsInstant();
8962    // filter, sort, and layout
8963
8964    // filter
8965    var filtered = this._filter( this.items );
8966    this.filteredItems = filtered.matches;
8967
8968    this._bindArrangeComplete();
8969
8970    if ( this._isInstant ) {
8971      this._noTransition( this._hideReveal, [ filtered ] );
8972    } else {
8973      this._hideReveal( filtered );
8974    }
8975
8976    this._sort();
8977    this._layout();
8978  };
8979  // alias to _init for main plugin method
8980  proto._init = proto.arrange;
8981
8982  proto._hideReveal = function( filtered ) {
8983    this.reveal( filtered.needReveal );
8984    this.hide( filtered.needHide );
8985  };
8986
8987  // HACK
8988  // Don't animate/transition first layout
8989  // Or don't animate/transition other layouts
8990  proto._getIsInstant = function() {
8991    var isLayoutInstant = this._getOption('layoutInstant');
8992    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
8993      !this._isLayoutInited;
8994    this._isInstant = isInstant;
8995    return isInstant;
8996  };
8997
8998  // listen for layoutComplete, hideComplete and revealComplete
8999  // to trigger arrangeComplete
9000  proto._bindArrangeComplete = function() {
9001    // listen for 3 events to trigger arrangeComplete
9002    var isLayoutComplete, isHideComplete, isRevealComplete;
9003    var _this = this;
9004    function arrangeParallelCallback() {
9005      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
9006        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
9007      }
9008    }
9009    this.once( 'layoutComplete', function() {
9010      isLayoutComplete = true;
9011      arrangeParallelCallback();
9012    });
9013    this.once( 'hideComplete', function() {
9014      isHideComplete = true;
9015      arrangeParallelCallback();
9016    });
9017    this.once( 'revealComplete', function() {
9018      isRevealComplete = true;
9019      arrangeParallelCallback();
9020    });
9021  };
9022
9023  // -------------------------- filter -------------------------- //
9024
9025  proto._filter = function( items ) {
9026    var filter = this.options.filter;
9027    filter = filter || '*';
9028    var matches = [];
9029    var hiddenMatched = [];
9030    var visibleUnmatched = [];
9031
9032    var test = this._getFilterTest( filter );
9033
9034    // test each item
9035    for ( var i=0; i < items.length; i++ ) {
9036      var item = items[i];
9037      if ( item.isIgnored ) {
9038        continue;
9039      }
9040      // add item to either matched or unmatched group
9041      var isMatched = test( item );
9042      // item.isFilterMatched = isMatched;
9043      // add to matches if its a match
9044      if ( isMatched ) {
9045        matches.push( item );
9046      }
9047      // add to additional group if item needs to be hidden or revealed
9048      if ( isMatched && item.isHidden ) {
9049        hiddenMatched.push( item );
9050      } else if ( !isMatched && !item.isHidden ) {
9051        visibleUnmatched.push( item );
9052      }
9053    }
9054
9055    // return collections of items to be manipulated
9056    return {
9057      matches: matches,
9058      needReveal: hiddenMatched,
9059      needHide: visibleUnmatched
9060    };
9061  };
9062
9063  // get a jQuery, function, or a matchesSelector test given the filter
9064  proto._getFilterTest = function( filter ) {
9065    if ( jQuery && this.options.isJQueryFiltering ) {
9066      // use jQuery
9067      return function( item ) {
9068        return jQuery( item.element ).is( filter );
9069      };
9070    }
9071    if ( typeof filter == 'function' ) {
9072      // use filter as function
9073      return function( item ) {
9074        return filter( item.element );
9075      };
9076    }
9077    // default, use filter as selector string
9078    return function( item ) {
9079      return matchesSelector( item.element, filter );
9080    };
9081  };
9082
9083  // -------------------------- sorting -------------------------- //
9084
9085  /**
9086   * @params {Array} elems
9087   * @public
9088   */
9089  proto.updateSortData = function( elems ) {
9090    // get items
9091    var items;
9092    if ( elems ) {
9093      elems = utils.makeArray( elems );
9094      items = this.getItems( elems );
9095    } else {
9096      // update all items if no elems provided
9097      items = this.items;
9098    }
9099
9100    this._getSorters();
9101    this._updateItemsSortData( items );
9102  };
9103
9104  proto._getSorters = function() {
9105    var getSortData = this.options.getSortData;
9106    for ( var key in getSortData ) {
9107      var sorter = getSortData[ key ];
9108      this._sorters[ key ] = mungeSorter( sorter );
9109    }
9110  };
9111
9112  /**
9113   * @params {Array} items - of Isotope.Items
9114   * @private
9115   */
9116  proto._updateItemsSortData = function( items ) {
9117    // do not update if no items
9118    var len = items && items.length;
9119
9120    for ( var i=0; len && i < len; i++ ) {
9121      var item = items[i];
9122      item.updateSortData();
9123    }
9124  };
9125
9126  // ----- munge sorter ----- //
9127
9128  // encapsulate this, as we just need mungeSorter
9129  // other functions in here are just for munging
9130  var mungeSorter = ( function() {
9131    // add a magic layer to sorters for convienent shorthands
9132    // `.foo-bar` will use the text of .foo-bar querySelector
9133    // `[foo-bar]` will use attribute
9134    // you can also add parser
9135    // `.foo-bar parseInt` will parse that as a number
9136    function mungeSorter( sorter ) {
9137      // if not a string, return function or whatever it is
9138      if ( typeof sorter != 'string' ) {
9139        return sorter;
9140      }
9141      // parse the sorter string
9142      var args = trim( sorter ).split(' ');
9143      var query = args[0];
9144      // check if query looks like [an-attribute]
9145      var attrMatch = query.match( /^\[(.+)\]$/ );
9146      var attr = attrMatch && attrMatch[1];
9147      var getValue = getValueGetter( attr, query );
9148      // use second argument as a parser
9149      var parser = Isotope.sortDataParsers[ args[1] ];
9150      // parse the value, if there was a parser
9151      sorter = parser ? function( elem ) {
9152        return elem && parser( getValue( elem ) );
9153      } :
9154      // otherwise just return value
9155      function( elem ) {
9156        return elem && getValue( elem );
9157      };
9158
9159      return sorter;
9160    }
9161
9162    // get an attribute getter, or get text of the querySelector
9163    function getValueGetter( attr, query ) {
9164      // if query looks like [foo-bar], get attribute
9165      if ( attr ) {
9166        return function getAttribute( elem ) {
9167          return elem.getAttribute( attr );
9168        };
9169      }
9170
9171      // otherwise, assume its a querySelector, and get its text
9172      return function getChildText( elem ) {
9173        var child = elem.querySelector( query );
9174        return child && child.textContent;
9175      };
9176    }
9177
9178    return mungeSorter;
9179  })();
9180
9181  // parsers used in getSortData shortcut strings
9182  Isotope.sortDataParsers = {
9183    'parseInt': function( val ) {
9184      return parseInt( val, 10 );
9185    },
9186    'parseFloat': function( val ) {
9187      return parseFloat( val );
9188    }
9189  };
9190
9191  // ----- sort method ----- //
9192
9193  // sort filteredItem order
9194  proto._sort = function() {
9195    if ( !this.options.sortBy ) {
9196      return;
9197    }
9198    // keep track of sortBy History
9199    var sortBys = utils.makeArray( this.options.sortBy );
9200    if ( !this._getIsSameSortBy( sortBys ) ) {
9201      // concat all sortBy and sortHistory, add to front, oldest goes in last
9202      this.sortHistory = sortBys.concat( this.sortHistory );
9203    }
9204    // sort magic
9205    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
9206    this.filteredItems.sort( itemSorter );
9207  };
9208
9209  // check if sortBys is same as start of sortHistory
9210  proto._getIsSameSortBy = function( sortBys ) {
9211    for ( var i=0; i < sortBys.length; i++ ) {
9212      if ( sortBys[i] != this.sortHistory[i] ) {
9213        return false;
9214      }
9215    }
9216    return true;
9217  };
9218
9219  // returns a function used for sorting
9220  function getItemSorter( sortBys, sortAsc ) {
9221    return function sorter( itemA, itemB ) {
9222      // cycle through all sortKeys
9223      for ( var i = 0; i < sortBys.length; i++ ) {
9224        var sortBy = sortBys[i];
9225        var a = itemA.sortData[ sortBy ];
9226        var b = itemB.sortData[ sortBy ];
9227        if ( a > b || a < b ) {
9228          // if sortAsc is an object, use the value given the sortBy key
9229          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
9230          var direction = isAscending ? 1 : -1;
9231          return ( a > b ? 1 : -1 ) * direction;
9232        }
9233      }
9234      return 0;
9235    };
9236  }
9237
9238  // -------------------------- methods -------------------------- //
9239
9240  // get layout mode
9241  proto._mode = function() {
9242    var layoutMode = this.options.layoutMode;
9243    var mode = this.modes[ layoutMode ];
9244    if ( !mode ) {
9245      // TODO console.error
9246      throw new Error( 'No layout mode: ' + layoutMode );
9247    }
9248    // HACK sync mode's options
9249    // any options set after init for layout mode need to be synced
9250    mode.options = this.options[ layoutMode ];
9251    return mode;
9252  };
9253
9254  proto._resetLayout = function() {
9255    // trigger original reset layout
9256    Outlayer.prototype._resetLayout.call( this );
9257    this._mode()._resetLayout();
9258  };
9259
9260  proto._getItemLayoutPosition = function( item  ) {
9261    return this._mode()._getItemLayoutPosition( item );
9262  };
9263
9264  proto._manageStamp = function( stamp ) {
9265    this._mode()._manageStamp( stamp );
9266  };
9267
9268  proto._getContainerSize = function() {
9269    return this._mode()._getContainerSize();
9270  };
9271
9272  proto.needsResizeLayout = function() {
9273    return this._mode().needsResizeLayout();
9274  };
9275
9276  // -------------------------- adding & removing -------------------------- //
9277
9278  // HEADS UP overwrites default Outlayer appended
9279  proto.appended = function( elems ) {
9280    var items = this.addItems( elems );
9281    if ( !items.length ) {
9282      return;
9283    }
9284    // filter, layout, reveal new items
9285    var filteredItems = this._filterRevealAdded( items );
9286    // add to filteredItems
9287    this.filteredItems = this.filteredItems.concat( filteredItems );
9288  };
9289
9290  // HEADS UP overwrites default Outlayer prepended
9291  proto.prepended = function( elems ) {
9292    var items = this._itemize( elems );
9293    if ( !items.length ) {
9294      return;
9295    }
9296    // start new layout
9297    this._resetLayout();
9298    this._manageStamps();
9299    // filter, layout, reveal new items
9300    var filteredItems = this._filterRevealAdded( items );
9301    // layout previous items
9302    this.layoutItems( this.filteredItems );
9303    // add to items and filteredItems
9304    this.filteredItems = filteredItems.concat( this.filteredItems );
9305    this.items = items.concat( this.items );
9306  };
9307
9308  proto._filterRevealAdded = function( items ) {
9309    var filtered = this._filter( items );
9310    this.hide( filtered.needHide );
9311    // reveal all new items
9312    this.reveal( filtered.matches );
9313    // layout new items, no transition
9314    this.layoutItems( filtered.matches, true );
9315    return filtered.matches;
9316  };
9317
9318  /**
9319   * Filter, sort, and layout newly-appended item elements
9320   * @param {Array or NodeList or Element} elems
9321   */
9322  proto.insert = function( elems ) {
9323    var items = this.addItems( elems );
9324    if ( !items.length ) {
9325      return;
9326    }
9327    // append item elements
9328    var i, item;
9329    var len = items.length;
9330    for ( i=0; i < len; i++ ) {
9331      item = items[i];
9332      this.element.appendChild( item.element );
9333    }
9334    // filter new stuff
9335    var filteredInsertItems = this._filter( items ).matches;
9336    // set flag
9337    for ( i=0; i < len; i++ ) {
9338      items[i].isLayoutInstant = true;
9339    }
9340    this.arrange();
9341    // reset flag
9342    for ( i=0; i < len; i++ ) {
9343      delete items[i].isLayoutInstant;
9344    }
9345    this.reveal( filteredInsertItems );
9346  };
9347
9348  var _remove = proto.remove;
9349  proto.remove = function( elems ) {
9350    elems = utils.makeArray( elems );
9351    var removeItems = this.getItems( elems );
9352    // do regular thing
9353    _remove.call( this, elems );
9354    // bail if no items to remove
9355    var len = removeItems && removeItems.length;
9356    // remove elems from filteredItems
9357    for ( var i=0; len && i < len; i++ ) {
9358      var item = removeItems[i];
9359      // remove item from collection
9360      utils.removeFrom( this.filteredItems, item );
9361    }
9362  };
9363
9364  proto.shuffle = function() {
9365    // update random sortData
9366    for ( var i=0; i < this.items.length; i++ ) {
9367      var item = this.items[i];
9368      item.sortData.random = Math.random();
9369    }
9370    this.options.sortBy = 'random';
9371    this._sort();
9372    this._layout();
9373  };
9374
9375  /**
9376   * trigger fn without transition
9377   * kind of hacky to have this in the first place
9378   * @param {Function} fn
9379   * @param {Array} args
9380   * @returns ret
9381   * @private
9382   */
9383  proto._noTransition = function( fn, args ) {
9384    // save transitionDuration before disabling
9385    var transitionDuration = this.options.transitionDuration;
9386    // disable transition
9387    this.options.transitionDuration = 0;
9388    // do it
9389    var returnValue = fn.apply( this, args );
9390    // re-enable transition for reveal
9391    this.options.transitionDuration = transitionDuration;
9392    return returnValue;
9393  };
9394
9395  // ----- helper methods ----- //
9396
9397  /**
9398   * getter method for getting filtered item elements
9399   * @returns {Array} elems - collection of item elements
9400   */
9401  proto.getFilteredItemElements = function() {
9402    return this.filteredItems.map( function( item ) {
9403      return item.element;
9404    });
9405  };
9406
9407  // -----  ----- //
9408
9409  return Isotope;
9410
9411}));
9412
vendor: 29,252 bytes, lines 9413-10569
9413/*!
9414 * Packery layout mode PACKAGED v2.0.1
9415 * sub-classes Packery
9416 */
9417
9418/**
9419 * Rect
9420 * low-level utility class for basic geometry
9421 */
9422
9423( function( window, factory ) {
9424  // universal module definition
9425  /* jshint strict: false */ /* globals define, module */
9426  if ( typeof define == 'function' && define.amd ) {
9427    // AMD
9428    define( 'packery/js/rect',factory );
9429  } else if ( typeof module == 'object' && module.exports ) {
9430    // CommonJS
9431    module.exports = factory();
9432  } else {
9433    // browser global
9434    window.Packery = window.Packery || {};
9435    window.Packery.Rect = factory();
9436  }
9437
9438}( window, function factory() {
9439
9440
9441// -------------------------- Rect -------------------------- //
9442
9443function Rect( props ) {
9444  // extend properties from defaults
9445  for ( var prop in Rect.defaults ) {
9446    this[ prop ] = Rect.defaults[ prop ];
9447  }
9448
9449  for ( prop in props ) {
9450    this[ prop ] = props[ prop ];
9451  }
9452
9453}
9454
9455Rect.defaults = {
9456  x: 0,
9457  y: 0,
9458  width: 0,
9459  height: 0
9460};
9461
9462var proto = Rect.prototype;
9463
9464/**
9465 * Determines whether or not this rectangle wholly encloses another rectangle or point.
9466 * @param {Rect} rect
9467 * @returns {Boolean}
9468**/
9469proto.contains = function( rect ) {
9470  // points don't have width or height
9471  var otherWidth = rect.width || 0;
9472  var otherHeight = rect.height || 0;
9473  return this.x <= rect.x &&
9474    this.y <= rect.y &&
9475    this.x + this.width >= rect.x + otherWidth &&
9476    this.y + this.height >= rect.y + otherHeight;
9477};
9478
9479/**
9480 * Determines whether or not the rectangle intersects with another.
9481 * @param {Rect} rect
9482 * @returns {Boolean}
9483**/
9484proto.overlaps = function( rect ) {
9485  var thisRight = this.x + this.width;
9486  var thisBottom = this.y + this.height;
9487  var rectRight = rect.x + rect.width;
9488  var rectBottom = rect.y + rect.height;
9489
9490  // http://stackoverflow.com/a/306332
9491  return this.x < rectRight &&
9492    thisRight > rect.x &&
9493    this.y < rectBottom &&
9494    thisBottom > rect.y;
9495};
9496
9497/**
9498 * @param {Rect} rect - the overlapping rect
9499 * @returns {Array} freeRects - rects representing the area around the rect
9500**/
9501proto.getMaximalFreeRects = function( rect ) {
9502
9503  // if no intersection, return false
9504  if ( !this.overlaps( rect ) ) {
9505    return false;
9506  }
9507
9508  var freeRects = [];
9509  var freeRect;
9510
9511  var thisRight = this.x + this.width;
9512  var thisBottom = this.y + this.height;
9513  var rectRight = rect.x + rect.width;
9514  var rectBottom = rect.y + rect.height;
9515
9516  // top
9517  if ( this.y < rect.y ) {
9518    freeRect = new Rect({
9519      x: this.x,
9520      y: this.y,
9521      width: this.width,
9522      height: rect.y - this.y
9523    });
9524    freeRects.push( freeRect );
9525  }
9526
9527  // right
9528  if ( thisRight > rectRight ) {
9529    freeRect = new Rect({
9530      x: rectRight,
9531      y: this.y,
9532      width: thisRight - rectRight,
9533      height: this.height
9534    });
9535    freeRects.push( freeRect );
9536  }
9537
9538  // bottom
9539  if ( thisBottom > rectBottom ) {
9540    freeRect = new Rect({
9541      x: this.x,
9542      y: rectBottom,
9543      width: this.width,
9544      height: thisBottom - rectBottom
9545    });
9546    freeRects.push( freeRect );
9547  }
9548
9549  // left
9550  if ( this.x < rect.x ) {
9551    freeRect = new Rect({
9552      x: this.x,
9553      y: this.y,
9554      width: rect.x - this.x,
9555      height: this.height
9556    });
9557    freeRects.push( freeRect );
9558  }
9559
9560  return freeRects;
9561};
9562
9563proto.canFit = function( rect ) {
9564  return this.width >= rect.width && this.height >= rect.height;
9565};
9566
9567return Rect;
9568
9569}));
9570
9571/**
9572 * Packer
9573 * bin-packing algorithm
9574 */
9575
9576( function( window, factory ) {
9577  // universal module definition
9578  /* jshint strict: false */ /* globals define, module, require */
9579  if ( typeof define == 'function' && define.amd ) {
9580    // AMD
9581    define( 'packery/js/packer',[ './rect' ], factory );
9582  } else if ( typeof module == 'object' && module.exports ) {
9583    // CommonJS
9584    module.exports = factory(
9585      require('./rect')
9586    );
9587  } else {
9588    // browser global
9589    var Packery = window.Packery = window.Packery || {};
9590    Packery.Packer = factory( Packery.Rect );
9591  }
9592
9593}( window, function factory( Rect ) {
9594
9595
9596// -------------------------- Packer -------------------------- //
9597
9598/**
9599 * @param {Number} width
9600 * @param {Number} height
9601 * @param {String} sortDirection
9602 *   topLeft for vertical, leftTop for horizontal
9603 */
9604function Packer( width, height, sortDirection ) {
9605  this.width = width || 0;
9606  this.height = height || 0;
9607  this.sortDirection = sortDirection || 'downwardLeftToRight';
9608
9609  this.reset();
9610}
9611
9612var proto = Packer.prototype;
9613
9614proto.reset = function() {
9615  this.spaces = [];
9616
9617  var initialSpace = new Rect({
9618    x: 0,
9619    y: 0,
9620    width: this.width,
9621    height: this.height
9622  });
9623
9624  this.spaces.push( initialSpace );
9625  // set sorter
9626  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
9627};
9628
9629// change x and y of rect to fit with in Packer's available spaces
9630proto.pack = function( rect ) {
9631  for ( var i=0; i < this.spaces.length; i++ ) {
9632    var space = this.spaces[i];
9633    if ( space.canFit( rect ) ) {
9634      this.placeInSpace( rect, space );
9635      break;
9636    }
9637  }
9638};
9639
9640proto.columnPack = function( rect ) {
9641  for ( var i=0; i < this.spaces.length; i++ ) {
9642    var space = this.spaces[i];
9643    var canFitInSpaceColumn = space.x <= rect.x &&
9644      space.x + space.width >= rect.x + rect.width &&
9645      space.height >= rect.height - 0.01; // fudge number for rounding error
9646    if ( canFitInSpaceColumn ) {
9647      rect.y = space.y;
9648      this.placed( rect );
9649      break;
9650    }
9651  }
9652};
9653
9654proto.rowPack = function( rect ) {
9655  for ( var i=0; i < this.spaces.length; i++ ) {
9656    var space = this.spaces[i];
9657    var canFitInSpaceRow = space.y <= rect.y &&
9658      space.y + space.height >= rect.y + rect.height &&
9659      space.width >= rect.width - 0.01; // fudge number for rounding error
9660    if ( canFitInSpaceRow ) {
9661      rect.x = space.x;
9662      this.placed( rect );
9663      break;
9664    }
9665  }
9666};
9667
9668proto.placeInSpace = function( rect, space ) {
9669  // place rect in space
9670  rect.x = space.x;
9671  rect.y = space.y;
9672
9673  this.placed( rect );
9674};
9675
9676// update spaces with placed rect
9677proto.placed = function( rect ) {
9678  // update spaces
9679  var revisedSpaces = [];
9680  for ( var i=0; i < this.spaces.length; i++ ) {
9681    var space = this.spaces[i];
9682    var newSpaces = space.getMaximalFreeRects( rect );
9683    // add either the original space or the new spaces to the revised spaces
9684    if ( newSpaces ) {
9685      revisedSpaces.push.apply( revisedSpaces, newSpaces );
9686    } else {
9687      revisedSpaces.push( space );
9688    }
9689  }
9690
9691  this.spaces = revisedSpaces;
9692
9693  this.mergeSortSpaces();
9694};
9695
9696proto.mergeSortSpaces = function() {
9697  // remove redundant spaces
9698  Packer.mergeRects( this.spaces );
9699  this.spaces.sort( this.sorter );
9700};
9701
9702// add a space back
9703proto.addSpace = function( rect ) {
9704  this.spaces.push( rect );
9705  this.mergeSortSpaces();
9706};
9707
9708// -------------------------- utility functions -------------------------- //
9709
9710/**
9711 * Remove redundant rectangle from array of rectangles
9712 * @param {Array} rects: an array of Rects
9713 * @returns {Array} rects: an array of Rects
9714**/
9715Packer.mergeRects = function( rects ) {
9716  var i = 0;
9717  var rect = rects[i];
9718
9719  rectLoop:
9720  while ( rect ) {
9721    var j = 0;
9722    var compareRect = rects[ i + j ];
9723
9724    while ( compareRect ) {
9725      if  ( compareRect == rect ) {
9726        j++; // next
9727      } else if ( compareRect.contains( rect ) ) {
9728        // remove rect
9729        rects.splice( i, 1 );
9730        rect = rects[i]; // set next rect
9731        continue rectLoop; // bail on compareLoop
9732      } else if ( rect.contains( compareRect ) ) {
9733        // remove compareRect
9734        rects.splice( i + j, 1 );
9735      } else {
9736        j++;
9737      }
9738      compareRect = rects[ i + j ]; // set next compareRect
9739    }
9740    i++;
9741    rect = rects[i];
9742  }
9743
9744  return rects;
9745};
9746
9747
9748// -------------------------- sorters -------------------------- //
9749
9750// functions for sorting rects in order
9751var sorters = {
9752  // top down, then left to right
9753  downwardLeftToRight: function( a, b ) {
9754    return a.y - b.y || a.x - b.x;
9755  },
9756  // left to right, then top down
9757  rightwardTopToBottom: function( a, b ) {
9758    return a.x - b.x || a.y - b.y;
9759  }
9760};
9761
9762
9763// --------------------------  -------------------------- //
9764
9765return Packer;
9766
9767}));
9768
9769/**
9770 * Packery Item Element
9771**/
9772
9773( function( window, factory ) {
9774  // universal module definition
9775  /* jshint strict: false */ /* globals define, module, require */
9776  if ( typeof define == 'function' && define.amd ) {
9777    // AMD
9778    define( 'packery/js/item',[
9779        'outlayer/outlayer',
9780        './rect'
9781      ],
9782      factory );
9783  } else if ( typeof module == 'object' && module.exports ) {
9784    // CommonJS
9785    module.exports = factory(
9786      require('outlayer'),
9787      require('./rect')
9788    );
9789  } else {
9790    // browser global
9791    window.Packery.Item = factory(
9792      window.Outlayer,
9793      window.Packery.Rect
9794    );
9795  }
9796
9797}( window, function factory( Outlayer, Rect ) {
9798
9799
9800// -------------------------- Item -------------------------- //
9801
9802var docElemStyle = document.documentElement.style;
9803
9804var transformProperty = typeof docElemStyle.transform == 'string' ?
9805  'transform' : 'WebkitTransform';
9806
9807// sub-class Item
9808var Item = function PackeryItem() {
9809  Outlayer.Item.apply( this, arguments );
9810};
9811
9812var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
9813
9814var __create = proto._create;
9815proto._create = function() {
9816  // call default _create logic
9817  __create.call( this );
9818  this.rect = new Rect();
9819};
9820
9821var _moveTo = proto.moveTo;
9822proto.moveTo = function( x, y ) {
9823  // don't shift 1px while dragging
9824  var dx = Math.abs( this.position.x - x );
9825  var dy = Math.abs( this.position.y - y );
9826
9827  var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&
9828    !this.isTransitioning && dx < 1 && dy < 1;
9829  if ( canHackGoTo ) {
9830    this.goTo( x, y );
9831    return;
9832  }
9833  _moveTo.apply( this, arguments );
9834};
9835
9836// -------------------------- placing -------------------------- //
9837
9838proto.enablePlacing = function() {
9839  this.removeTransitionStyles();
9840  // remove transform property from transition
9841  if ( this.isTransitioning && transformProperty ) {
9842    this.element.style[ transformProperty ] = 'none';
9843  }
9844  this.isTransitioning = false;
9845  this.getSize();
9846  this.layout._setRectSize( this.element, this.rect );
9847  this.isPlacing = true;
9848};
9849
9850proto.disablePlacing = function() {
9851  this.isPlacing = false;
9852};
9853
9854// -----  ----- //
9855
9856// remove element from DOM
9857proto.removeElem = function() {
9858  this.element.parentNode.removeChild( this.element );
9859  // add space back to packer
9860  this.layout.packer.addSpace( this.rect );
9861  this.emitEvent( 'remove', [ this ] );
9862};
9863
9864// ----- dropPlaceholder ----- //
9865
9866proto.showDropPlaceholder = function() {
9867  var dropPlaceholder = this.dropPlaceholder;
9868  if ( !dropPlaceholder ) {
9869    // create dropPlaceholder
9870    dropPlaceholder = this.dropPlaceholder = document.createElement('div');
9871    dropPlaceholder.className = 'packery-drop-placeholder';
9872    dropPlaceholder.style.position = 'absolute';
9873  }
9874
9875  dropPlaceholder.style.width = this.size.width + 'px';
9876  dropPlaceholder.style.height = this.size.height + 'px';
9877  this.positionDropPlaceholder();
9878  this.layout.element.appendChild( dropPlaceholder );
9879};
9880
9881proto.positionDropPlaceholder = function() {
9882  this.dropPlaceholder.style[ transformProperty ] = 'translate(' +
9883    this.rect.x + 'px, ' + this.rect.y + 'px)';
9884};
9885
9886proto.hideDropPlaceholder = function() {
9887  this.layout.element.removeChild( this.dropPlaceholder );
9888};
9889
9890// -----  ----- //
9891
9892return Item;
9893
9894}));
9895
9896/*!
9897 * Packery v2.0.0
9898 * Gapless, draggable grid layouts
9899 *
9900 * Licensed GPLv3 for open source use
9901 * or Packery Commercial License for commercial use
9902 *
9903 * http://packery.metafizzy.co
9904 * Copyright 2016 Metafizzy
9905 */
9906
9907( function( window, factory ) {
9908  // universal module definition
9909  /* jshint strict: false */ /* globals define, module, require */
9910  if ( typeof define == 'function' && define.amd ) {
9911    // AMD
9912    define( 'packery/js/packery',[
9913        'get-size/get-size',
9914        'outlayer/outlayer',
9915        './rect',
9916        './packer',
9917        './item'
9918      ],
9919      factory );
9920  } else if ( typeof module == 'object' && module.exports ) {
9921    // CommonJS
9922    module.exports = factory(
9923      require('get-size'),
9924      require('outlayer'),
9925      require('./rect'),
9926      require('./packer'),
9927      require('./item')
9928    );
9929  } else {
9930    // browser global
9931    window.Packery = factory(
9932      window.getSize,
9933      window.Outlayer,
9934      window.Packery.Rect,
9935      window.Packery.Packer,
9936      window.Packery.Item
9937    );
9938  }
9939
9940}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {
9941
9942
9943// ----- Rect ----- //
9944
9945// allow for pixel rounding errors IE8-IE11 & Firefox; #227
9946Rect.prototype.canFit = function( rect ) {
9947  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
9948};
9949
9950// -------------------------- Packery -------------------------- //
9951
9952// create an Outlayer layout class
9953var Packery = Outlayer.create('packery');
9954Packery.Item = Item;
9955
9956var proto = Packery.prototype;
9957
9958proto._create = function() {
9959  // call super
9960  Outlayer.prototype._create.call( this );
9961
9962  // initial properties
9963  this.packer = new Packer();
9964  // packer for drop targets
9965  this.shiftPacker = new Packer();
9966  this.isEnabled = true;
9967
9968  this.dragItemCount = 0;
9969
9970  // create drag handlers
9971  var _this = this;
9972  this.handleDraggabilly = {
9973    dragStart: function() {
9974      _this.itemDragStart( this.element );
9975    },
9976    dragMove: function() {
9977      _this.itemDragMove( this.element, this.position.x, this.position.y );
9978    },
9979    dragEnd: function() {
9980      _this.itemDragEnd( this.element );
9981    }
9982  };
9983
9984  this.handleUIDraggable = {
9985    start: function handleUIDraggableStart( event, ui ) {
9986      // HTML5 may trigger dragstart, dismiss HTML5 dragging
9987      if ( !ui ) {
9988        return;
9989      }
9990      _this.itemDragStart( event.currentTarget );
9991    },
9992    drag: function handleUIDraggableDrag( event, ui ) {
9993      if ( !ui ) {
9994        return;
9995      }
9996      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
9997    },
9998    stop: function handleUIDraggableStop( event, ui ) {
9999      if ( !ui ) {
10000        return;
10001      }
10002      _this.itemDragEnd( event.currentTarget );
10003    }
10004  };
10005
10006};
10007
10008
10009// ----- init & layout ----- //
10010
10011/**
10012 * logic before any new layout
10013 */
10014proto._resetLayout = function() {
10015  this.getSize();
10016
10017  this._getMeasurements();
10018
10019  // reset packer
10020  var width, height, sortDirection;
10021  // packer settings, if horizontal or vertical
10022  if ( this._getOption('horizontal') ) {
10023    width = Infinity;
10024    height = this.size.innerHeight + this.gutter;
10025    sortDirection = 'rightwardTopToBottom';
10026  } else {
10027    width = this.size.innerWidth + this.gutter;
10028    height = Infinity;
10029    sortDirection = 'downwardLeftToRight';
10030  }
10031
10032  this.packer.width = this.shiftPacker.width = width;
10033  this.packer.height = this.shiftPacker.height = height;
10034  this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;
10035
10036  this.packer.reset();
10037
10038  // layout
10039  this.maxY = 0;
10040  this.maxX = 0;
10041};
10042
10043/**
10044 * update columnWidth, rowHeight, & gutter
10045 * @private
10046 */
10047proto._getMeasurements = function() {
10048  this._getMeasurement( 'columnWidth', 'width' );
10049  this._getMeasurement( 'rowHeight', 'height' );
10050  this._getMeasurement( 'gutter', 'width' );
10051};
10052
10053proto._getItemLayoutPosition = function( item ) {
10054  this._setRectSize( item.element, item.rect );
10055  if ( this.isShifting || this.dragItemCount > 0 ) {
10056    var packMethod = this._getPackMethod();
10057    this.packer[ packMethod ]( item.rect );
10058  } else {
10059    this.packer.pack( item.rect );
10060  }
10061
10062  this._setMaxXY( item.rect );
10063  return item.rect;
10064};
10065
10066proto.shiftLayout = function() {
10067  this.isShifting = true;
10068  this.layout();
10069  delete this.isShifting;
10070};
10071
10072proto._getPackMethod = function() {
10073  return this._getOption('horizontal') ? 'rowPack' : 'columnPack';
10074};
10075
10076
10077/**
10078 * set max X and Y value, for size of container
10079 * @param {Packery.Rect} rect
10080 * @private
10081 */
10082proto._setMaxXY = function( rect ) {
10083  this.maxX = Math.max( rect.x + rect.width, this.maxX );
10084  this.maxY = Math.max( rect.y + rect.height, this.maxY );
10085};
10086
10087/**
10088 * set the width and height of a rect, applying columnWidth and rowHeight
10089 * @param {Element} elem
10090 * @param {Packery.Rect} rect
10091 */
10092proto._setRectSize = function( elem, rect ) {
10093  var size = getSize( elem );
10094  var w = size.outerWidth;
10095  var h = size.outerHeight;
10096  // size for columnWidth and rowHeight, if available
10097  // only check if size is non-zero, #177
10098  if ( w || h ) {
10099    w = this._applyGridGutter( w, this.columnWidth );
10100    h = this._applyGridGutter( h, this.rowHeight );
10101  }
10102  // rect must fit in packer
10103  rect.width = Math.min( w, this.packer.width );
10104  rect.height = Math.min( h, this.packer.height );
10105};
10106
10107/**
10108 * fits item to columnWidth/rowHeight and adds gutter
10109 * @param {Number} measurement - item width or height
10110 * @param {Number} gridSize - columnWidth or rowHeight
10111 * @returns measurement
10112 */
10113proto._applyGridGutter = function( measurement, gridSize ) {
10114  // just add gutter if no gridSize
10115  if ( !gridSize ) {
10116    return measurement + this.gutter;
10117  }
10118  gridSize += this.gutter;
10119  // fit item to columnWidth/rowHeight
10120  var remainder = measurement % gridSize;
10121  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
10122  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
10123  return measurement;
10124};
10125
10126proto._getContainerSize = function() {
10127  if ( this._getOption('horizontal') ) {
10128    return {
10129      width: this.maxX - this.gutter
10130    };
10131  } else {
10132    return {
10133      height: this.maxY - this.gutter
10134    };
10135  }
10136};
10137
10138
10139// -------------------------- stamp -------------------------- //
10140
10141/**
10142 * makes space for element
10143 * @param {Element} elem
10144 */
10145proto._manageStamp = function( elem ) {
10146
10147  var item = this.getItem( elem );
10148  var rect;
10149  if ( item && item.isPlacing ) {
10150    rect = item.rect;
10151  } else {
10152    var offset = this._getElementOffset( elem );
10153    rect = new Rect({
10154      x: this._getOption('originLeft') ? offset.left : offset.right,
10155      y: this._getOption('originTop') ? offset.top : offset.bottom
10156    });
10157  }
10158
10159  this._setRectSize( elem, rect );
10160  // save its space in the packer
10161  this.packer.placed( rect );
10162  this._setMaxXY( rect );
10163};
10164
10165// -------------------------- methods -------------------------- //
10166
10167function verticalSorter( a, b ) {
10168  return a.position.y - b.position.y || a.position.x - b.position.x;
10169}
10170
10171function horizontalSorter( a, b ) {
10172  return a.position.x - b.position.x || a.position.y - b.position.y;
10173}
10174
10175proto.sortItemsByPosition = function() {
10176  var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;
10177  this.items.sort( sorter );
10178};
10179
10180/**
10181 * Fit item element in its current position
10182 * Packery will position elements around it
10183 * useful for expanding elements
10184 *
10185 * @param {Element} elem
10186 * @param {Number} x - horizontal destination position, optional
10187 * @param {Number} y - vertical destination position, optional
10188 */
10189proto.fit = function( elem, x, y ) {
10190  var item = this.getItem( elem );
10191  if ( !item ) {
10192    return;
10193  }
10194
10195  // stamp item to get it out of layout
10196  this.stamp( item.element );
10197  // set placing flag
10198  item.enablePlacing();
10199  this.updateShiftTargets( item );
10200  // fall back to current position for fitting
10201  x = x === undefined ? item.rect.x: x;
10202  y = y === undefined ? item.rect.y: y;
10203  // position it best at its destination
10204  this.shift( item, x, y );
10205  this._bindFitEvents( item );
10206  item.moveTo( item.rect.x, item.rect.y );
10207  // layout everything else
10208  this.shiftLayout();
10209  // return back to regularly scheduled programming
10210  this.unstamp( item.element );
10211  this.sortItemsByPosition();
10212  item.disablePlacing();
10213};
10214
10215/**
10216 * emit event when item is fit and other items are laid out
10217 * @param {Packery.Item} item
10218 * @private
10219 */
10220proto._bindFitEvents = function( item ) {
10221  var _this = this;
10222  var ticks = 0;
10223  function onLayout() {
10224    ticks++;
10225    if ( ticks != 2 ) {
10226      return;
10227    }
10228    _this.dispatchEvent( 'fitComplete', null, [ item ] );
10229  }
10230  // when item is laid out
10231  item.once( 'layout', onLayout );
10232  // when all items are laid out
10233  this.once( 'layoutComplete', onLayout );
10234};
10235
10236// -------------------------- resize -------------------------- //
10237
10238// debounced, layout on resize
10239proto.resize = function() {
10240  // don't trigger if size did not change
10241  // or if resize was unbound. See #285, outlayer#9
10242  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
10243    return;
10244  }
10245
10246  if ( this.options.shiftPercentResize ) {
10247    this.resizeShiftPercentLayout();
10248  } else {
10249    this.layout();
10250  }
10251};
10252
10253/**
10254 * check if layout is needed post layout
10255 * @returns Boolean
10256 */
10257proto.needsResizeLayout = function() {
10258  var size = getSize( this.element );
10259  var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';
10260  return size[ innerSize ] != this.size[ innerSize ];
10261};
10262
10263proto.resizeShiftPercentLayout = function() {
10264  var items = this._getItemsForLayout( this.items );
10265
10266  var isHorizontal = this._getOption('horizontal');
10267  var coord = isHorizontal ? 'y' : 'x';
10268  var measure = isHorizontal ? 'height' : 'width';
10269  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
10270  var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';
10271
10272  // proportional re-align items
10273  var previousSegment = this[ segmentName ];
10274  previousSegment = previousSegment && previousSegment + this.gutter;
10275
10276  if ( previousSegment ) {
10277    this._getMeasurements();
10278    var currentSegment = this[ segmentName ] + this.gutter;
10279    items.forEach( function( item ) {
10280      var seg = Math.round( item.rect[ coord ] / previousSegment );
10281      item.rect[ coord ] = seg * currentSegment;
10282    });
10283  } else {
10284    var currentSize = getSize( this.element )[ innerSize ] + this.gutter;
10285    var previousSize = this.packer[ measure ];
10286    items.forEach( function( item ) {
10287      item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;
10288    });
10289  }
10290
10291  this.shiftLayout();
10292};
10293
10294// -------------------------- drag -------------------------- //
10295
10296/**
10297 * handle an item drag start event
10298 * @param {Element} elem
10299 */
10300proto.itemDragStart = function( elem ) {
10301  if ( !this.isEnabled ) {
10302    return;
10303  }
10304  this.stamp( elem );
10305  // this.ignore( elem );
10306  var item = this.getItem( elem );
10307  if ( !item ) {
10308    return;
10309  }
10310
10311  item.enablePlacing();
10312  item.showDropPlaceholder();
10313  this.dragItemCount++;
10314  this.updateShiftTargets( item );
10315};
10316
10317proto.updateShiftTargets = function( dropItem ) {
10318  this.shiftPacker.reset();
10319
10320  // pack stamps
10321  this._getBoundingRect();
10322  var isOriginLeft = this._getOption('originLeft');
10323  var isOriginTop = this._getOption('originTop');
10324  this.stamps.forEach( function( stamp ) {
10325    // ignore dragged item
10326    var item = this.getItem( stamp );
10327    if ( item && item.isPlacing ) {
10328      return;
10329    }
10330    var offset = this._getElementOffset( stamp );
10331    var rect = new Rect({
10332      x: isOriginLeft ? offset.left : offset.right,
10333      y: isOriginTop ? offset.top : offset.bottom
10334    });
10335    this._setRectSize( stamp, rect );
10336    // save its space in the packer
10337    this.shiftPacker.placed( rect );
10338  }, this );
10339
10340  // reset shiftTargets
10341  var isHorizontal = this._getOption('horizontal');
10342  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
10343  var measure = isHorizontal ? 'height' : 'width';
10344
10345  this.shiftTargetKeys = [];
10346  this.shiftTargets = [];
10347  var boundsSize;
10348  var segment = this[ segmentName ];
10349  segment = segment && segment + this.gutter;
10350
10351  if ( segment ) {
10352    var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );
10353    var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );
10354    boundsSize = ( segs - segmentSpan ) * segment;
10355    // add targets on top
10356    for ( var i=0; i < segs; i++ ) {
10357      this._addShiftTarget( i * segment, 0, boundsSize );
10358    }
10359  } else {
10360    boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];
10361    this._addShiftTarget( 0, 0, boundsSize );
10362  }
10363
10364  // pack each item to measure where shiftTargets are
10365  var items = this._getItemsForLayout( this.items );
10366  var packMethod = this._getPackMethod();
10367  items.forEach( function( item ) {
10368    var rect = item.rect;
10369    this._setRectSize( item.element, rect );
10370    this.shiftPacker[ packMethod ]( rect );
10371
10372    // add top left corner
10373    this._addShiftTarget( rect.x, rect.y, boundsSize );
10374    // add bottom left / top right corner
10375    var cornerX = isHorizontal ? rect.x + rect.width : rect.x;
10376    var cornerY = isHorizontal ? rect.y : rect.y + rect.height;
10377    this._addShiftTarget( cornerX, cornerY, boundsSize );
10378
10379    if ( segment ) {
10380      // add targets for each column on bottom / row on right
10381      var segSpan = Math.round( rect[ measure ] / segment );
10382      for ( var i=1; i < segSpan; i++ ) {
10383        var segX = isHorizontal ? cornerX : rect.x + segment * i;
10384        var segY = isHorizontal ? rect.y + segment * i : cornerY;
10385        this._addShiftTarget( segX, segY, boundsSize );
10386      }
10387    }
10388  }, this );
10389
10390};
10391
10392proto._addShiftTarget = function( x, y, boundsSize ) {
10393  var checkCoord = this._getOption('horizontal') ? y : x;
10394  if ( checkCoord !== 0 && checkCoord > boundsSize ) {
10395    return;
10396  }
10397  // create string for a key, easier to keep track of what targets
10398  var key = x + ',' + y;
10399  var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;
10400  if ( hasKey ) {
10401    return;
10402  }
10403  this.shiftTargetKeys.push( key );
10404  this.shiftTargets.push({ x: x, y: y });
10405};
10406
10407// -------------------------- drop -------------------------- //
10408
10409proto.shift = function( item, x, y ) {
10410  var shiftPosition;
10411  var minDistance = Infinity;
10412  var position = { x: x, y: y };
10413  this.shiftTargets.forEach( function( target ) {
10414    var distance = getDistance( target, position );
10415    if ( distance < minDistance ) {
10416      shiftPosition = target;
10417      minDistance = distance;
10418    }
10419  });
10420  item.rect.x = shiftPosition.x;
10421  item.rect.y = shiftPosition.y;
10422};
10423
10424function getDistance( a, b ) {
10425  var dx = b.x - a.x;
10426  var dy = b.y - a.y;
10427  return Math.sqrt( dx * dx + dy * dy );
10428}
10429
10430// -------------------------- drag move -------------------------- //
10431
10432var DRAG_THROTTLE_TIME = 120;
10433
10434/**
10435 * handle an item drag move event
10436 * @param {Element} elem
10437 * @param {Number} x - horizontal change in position
10438 * @param {Number} y - vertical change in position
10439 */
10440proto.itemDragMove = function( elem, x, y ) {
10441  var item = this.isEnabled && this.getItem( elem );
10442  if ( !item ) {
10443    return;
10444  }
10445
10446  x -= this.size.paddingLeft;
10447  y -= this.size.paddingTop;
10448
10449  var _this = this;
10450  function onDrag() {
10451    _this.shift( item, x, y );
10452    item.positionDropPlaceholder();
10453    _this.layout();
10454  }
10455
10456  // throttle
10457  var now = new Date();
10458  if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {
10459    clearTimeout( this.dragTimeout );
10460    this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );
10461  } else {
10462    onDrag();
10463    this._itemDragTime = now;
10464  }
10465};
10466
10467// -------------------------- drag end -------------------------- //
10468
10469/**
10470 * handle an item drag end event
10471 * @param {Element} elem
10472 */
10473proto.itemDragEnd = function( elem ) {
10474  var item = this.isEnabled && this.getItem( elem );
10475  if ( !item ) {
10476    return;
10477  }
10478
10479  clearTimeout( this.dragTimeout );
10480  item.element.classList.add('is-positioning-post-drag');
10481
10482  var completeCount = 0;
10483  var _this = this;
10484  function onDragEndLayoutComplete() {
10485    completeCount++;
10486    if ( completeCount != 2 ) {
10487      return;
10488    }
10489    // reset drag item
10490    item.element.classList.remove('is-positioning-post-drag');
10491    item.hideDropPlaceholder();
10492    _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
10493  }
10494
10495  item.once( 'layout', onDragEndLayoutComplete );
10496  this.once( 'layoutComplete', onDragEndLayoutComplete );
10497  item.moveTo( item.rect.x, item.rect.y );
10498  this.layout();
10499  this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );
10500  this.sortItemsByPosition();
10501  item.disablePlacing();
10502  this.unstamp( item.element );
10503};
10504
10505/**
10506 * binds Draggabilly events
10507 * @param {Draggabilly} draggie
10508 */
10509proto.bindDraggabillyEvents = function( draggie ) {
10510  this._bindDraggabillyEvents( draggie, 'on' );
10511};
10512
10513proto.unbindDraggabillyEvents = function( draggie ) {
10514  this._bindDraggabillyEvents( draggie, 'off' );
10515};
10516
10517proto._bindDraggabillyEvents = function( draggie, method ) {
10518  var handlers = this.handleDraggabilly;
10519  draggie[ method ]( 'dragStart', handlers.dragStart );
10520  draggie[ method ]( 'dragMove', handlers.dragMove );
10521  draggie[ method ]( 'dragEnd', handlers.dragEnd );
10522};
10523
10524/**
10525 * binds jQuery UI Draggable events
10526 * @param {jQuery} $elems
10527 */
10528proto.bindUIDraggableEvents = function( $elems ) {
10529  this._bindUIDraggableEvents( $elems, 'on' );
10530};
10531
10532proto.unbindUIDraggableEvents = function( $elems ) {
10533  this._bindUIDraggableEvents( $elems, 'off' );
10534};
10535
10536proto._bindUIDraggableEvents = function( $elems, method ) {
10537  var handlers = this.handleUIDraggable;
10538  $elems
10539    [ method ]( 'dragstart', handlers.start )
10540    [ method ]( 'drag', handlers.drag )
10541    [ method ]( 'dragstop', handlers.stop );
10542};
10543
10544// ----- destroy ----- //
10545
10546var _destroy = proto.destroy;
10547proto.destroy = function() {
10548  _destroy.apply( this, arguments );
10549  // disable flag; prevent drag events from triggering. #72
10550  this.isEnabled = false;
10551};
10552
10553// -----  ----- //
10554
10555Packery.Rect = Rect;
10556Packery.Packer = Packer;
10557
10558return Packery;
10559
10560}));
10561
10562/*!
10563 * Packery layout mode v2.0.1
10564 * sub-classes Packery
10565 */
10566
10567/*jshint browser: true, strict: true, undef: true, unused: true */
10568
10569( function( window, factory ) {
10570
10571  // universal module definition
10572  if ( typeof define == 'function' && define.amd ) {
10573    // AMD
10574    define( [
10575        'isotope-layout/js/layout-mode',
10576        'packery/js/packery'
10577      ],
10578      factory );
10579  } else if ( typeof module == 'object' && module.exports ) {
10580    // CommonJS
10581    module.exports = factory(
10582      require('isotope-layout/js/layout-mode'),
10583      require('packery')
10584    );
10585  } else {
10586    // browser global
10587    factory(
10588      window.Isotope.LayoutMode,
10589      window.Packery
10590    );
10591  }
10592
10593}( window, function factor( LayoutMode, Packery ) {
10594
10595
10596  // create an Outlayer layout class
10597  var PackeryMode = LayoutMode.create('packery');
10598  var proto = PackeryMode.prototype;
10599
10600  var keepModeMethods = {
10601    _getElementOffset: true,
10602    _getMeasurement: true
10603  };
10604
10605  // inherit Packery prototype
10606  for ( var method in Packery.prototype ) {
10607    // do not inherit mode methods
10608    if ( !keepModeMethods[ method ] ) {
10609      proto[ method ] = Packery.prototype[ method ];
10610    }
10611  }
10612
10613  // set packer in _resetLayout
10614  var _resetLayout = proto._resetLayout;
10615  proto._resetLayout = function() {
10616    this.packer = this.packer || new Packery.Packer();
10617    this.shiftPacker = this.shiftPacker || new Packery.Packer();
10618    _resetLayout.apply( this, arguments );
10619  };
10620
10621  var _getItemLayoutPosition = proto._getItemLayoutPosition;
10622  proto._getItemLayoutPosition = function( item ) {
10623    // set packery rect
10624    item.rect = item.rect || new Packery.Rect();
10625    return _getItemLayoutPosition.call( this, item );
10626  };
10627
10628  // needsResizeLayout for vertical or horizontal
10629  var _needsResizeLayout = proto.needsResizeLayout;
10630  proto.needsResizeLayout = function() {
10631    if ( this._getOption('horizontal') ) {
10632      return this.needsVerticalResizeLayout();
10633    } else {
10634      return _needsResizeLayout.call( this );
10635    }
10636  };
10637
10638  // point to mode options for horizontal
10639  var _getOption = proto._getOption;
10640  proto._getOption = function( option ) {
10641    if ( option == 'horizontal' ) {
10642      return this.options.isHorizontal !== undefined ?
10643        this.options.isHorizontal : this.options.horizontal;
10644    }
10645    return _getOption.apply( this.isotope, arguments );
10646  };
10647
10648  return PackeryMode;
10649
10650}));
10651
10652/*!
10653 * cellsByRows layout mode for Isotope
10654 * v1.1.3
10655 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
10656 */
10657
10658/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
10659
10660( function( window, factory ) {
10661  // universal module definition
10662  /* jshint strict: false */ /*globals define, module, require */
10663  if ( typeof define === 'function' && define.amd ) {
10664    // AMD
10665    define( [
10666        'isotope/js/layout-mode'
10667      ],
10668      factory );
10669  } else if ( typeof exports === 'object' ) {
10670    // CommonJS
10671    module.exports = factory(
10672      require('isotope-layout/js/layout-mode')
10673    );
10674  } else {
10675    // browser global
10676    factory(
10677      window.Isotope.LayoutMode
10678    );
10679  }
10680
10681}( window, function factory( LayoutMode ) {
10682  'use strict';
10683
10684  var CellsByRow = LayoutMode.create( 'cellsByRow' );
10685  var proto = CellsByRow.prototype;
10686
10687  proto._resetLayout = function() {
10688    // reset properties
10689    this.itemIndex = 0;
10690    // measurements
10691    this.getColumnWidth();
10692    this.getRowHeight();
10693    // set cols
10694    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
10695    this.cols = Math.max( this.cols, 1 );
10696  };
10697
10698  proto._getItemLayoutPosition = function( item ) {
10699    item.getSize();
10700    var col = this.itemIndex % this.cols;
10701    var row = Math.floor( this.itemIndex / this.cols );
10702    // center item within cell
10703    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
10704    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
10705    this.itemIndex++;
10706    return { x: x, y: y };
10707  };
10708
10709  proto._getContainerSize = function() {
10710    return {
10711      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
10712    };
10713  };
10714
10715  return CellsByRow;
10716
10717}));
10718/*global jQuery: true */
10719
10720/*!
10721   --------------------------------
10722   Infinite Scroll
10723   --------------------------------
10724   + https://github.com/paulirish/infinite-scroll
10725   + version 2.1.0
10726   + Copyright 2011/12 Paul Irish & Luke Shumard
10727   + Licensed under the MIT license
10728
10729   + Documentation: http://infinite-scroll.com/
10730*/
10731
10732// Uses AMD or browser globals to create a jQuery plugin.
10733(function (factory) {
10734    if (typeof define === 'function' && define.amd) {
10735        // AMD. Register as an anonymous module.
10736        define(['jquery'], factory);
10737    } else {
10738        // Browser globals
10739        factory(jQuery);
10740    }
10741}(function ($, undefined) {
10742    'use strict';
10743
10744    $.infinitescroll = function infscr(options, callback, element) {
10745        this.element = $(element);
10746
10747        // Flag the object in the event of a failed creation
10748        if (!this._create(options, callback)) {
10749            this.failed = true;
10750        }
10751    };
10752
10753    $.infinitescroll.defaults = {
10754        loading: {
10755            finished: undefined,
10756            finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
10757            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
10757MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
10757iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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',
10758            msg: null,
10759            msgText: '<em>Loading the next set of posts...</em>',
10760            selector: null,
10761            speed: 'fast',
10762            start: undefined
10763        },
10764        state: {
10765            isDuringAjax: false,
10766            isInvalidPage: false,
10767            isDestroyed: false,
10768            isDone: false, // For when it goes all the way through the archive.
10769            isPaused: false,
10770            isBeyondMaxPage: false,
10771            currPage: 1
10772        },
10773        debug: false,
10774        behavior: undefined,
10775        binder: $(window), // used to cache the selector
10776        nextSelector: 'div.navigation a:first',
10777        navSelector: 'div.navigation',
10778        contentSelector: null, // rename to pageFragment
10779        extraScrollPx: 150,
10780        itemSelector: 'div.post',
10781        animate: false,
10782        pathParse: undefined,
10783        dataType: 'html',
10784        appendCallback: true,
10785        bufferPx: 40,
10786        errorCallback: function () { },
10787        infid: 0, //Instance ID
10788        pixelsFromNavToBottom: undefined,
10789        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
10790        prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
10791        maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
10792    };
10793
10794    $.infinitescroll.prototype = {
10795
10796        /*
10797            ----------------------------
10798            Private methods
10799            ----------------------------
10800            */
10801
10802        // Bind or unbind from scroll
10803        _binding: function infscr_binding(binding) {
10804
10805            var instance = this,
10806            opts = instance.options;
10807
10808            opts.v = '2.0b2.120520';
10809
10810            // if behavior is defined and this function is extended, call that instead of default
10811            if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) {
10812                this['_binding_'+opts.behavior].call(this);
10813                return;
10814            }
10815
10816            if (binding !== 'bind' && binding !== 'unbind') {
10817                this._debug('Binding value  ' + binding + ' not valid');
10818                return false;
10819            }
10820
10821            if (binding === 'unbind') {
10822                (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
10823            } else {
10824                (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
10825                    instance.scroll();
10826                });
10827            }
10828
10829            this._debug('Binding', binding);
10830        },
10831
10832        // Fundamental aspects of the plugin are initialized
10833        _create: function infscr_create(options, callback) {
10834
10835            // Add custom options to defaults
10836            var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
10837            this.options = opts;
10838            var $window = $(window);
10839            var instance = this;
10840
10841            // Validate selectors
10842            if (!instance._validate(options)) {
10843                return false;
10844            }
10845
10846            // Validate page fragment path
10847            var path = $(opts.nextSelector).attr('href');
10848            if (!path) {
10849                this._debug('Navigation selector not found');
10850                return false;
10851            }
10852
10853            // Set the path to be a relative URL from root.
10854            opts.path = opts.path || this._determinepath(path);
10855
10856            // contentSelector is 'page fragment' option for .load() / .ajax() calls
10857            opts.contentSelector = opts.contentSelector || this.element;
10858
10859            // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
10860            opts.loading.selector = opts.loading.selector || opts.contentSelector;
10861
10862            // Define loading.msg
10863            opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
10864
10865            // Preload loading.img
10866            (new Image()).src = opts.loading.img;
10867
10868            // distance from nav links to bottom
10869            // computed as: height of the document + top offset of container - top offset of nav link
10870            if(opts.pixelsFromNavToBottom === undefined) {
10871                opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
10872                this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
10873            }
10874
10875            var self = this;
10876
10877            // determine loading.start actions
10878            opts.loading.start = opts.loading.start || function() {
10879                $(opts.navSelector).hide();
10880                opts.loading.msg
10881                .appendTo(opts.loading.selector)
10882                .show(opts.loading.speed, $.proxy(function() {
10883                    this.beginAjax(opts);
10884                }, self));
10885            };
10886
10887            // determine loading.finished actions
10888            opts.loading.finished = opts.loading.finished || function() {
10889                if (!opts.state.isBeyondMaxPage)
10890                    opts.loading.msg.fadeOut(opts.loading.speed);
10891            };
10892
10893            // callback loading
10894            opts.callback = function(instance, data, url) {
10895                if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) {
10896                    instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url);
10897                }
10898
10899                if (callback) {
10900                    callback.call($(opts.contentSelector)[0], data, opts, url);
10901                }
10902
10903                if (opts.prefill) {
10904                    $window.bind('resize.infinite-scroll', instance._prefill);
10905                }
10906            };
10907
10908            if (options.debug) {
10909                // Tell IE9 to use its built-in console
10910                if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
10911                    ['log','info','warn','error','assert','dir','clear','profile','profileEnd']
10912                        .forEach(function (method) {
10913                            console[method] = this.call(console[method], console);
10914                        }, Function.prototype.bind);
10915                }
10916            }
10917
10918            this._setup();
10919
10920            // Setups the prefill method for use
10921            if (opts.prefill) {
10922                this._prefill();
10923            }
10924
10925            // Return true to indicate successful creation
10926            return true;
10927        },
10928
10929        _prefill: function infscr_prefill() {
10930            var instance = this;
10931            var $window = $(window);
10932
10933            function needsPrefill() {
10934                return ( $(instance.options.contentSelector).height() <= $window.height() );
10935            }
10936
10937            this._prefill = function() {
10938                if (needsPrefill()) {
10939                    instance.scroll();
10940                }
10941
10942                $window.bind('resize.infinite-scroll', function() {
10943                    if (needsPrefill()) {
10944                        $window.unbind('resize.infinite-scroll');
10945                        instance.scroll();
10946                    }
10947                });
10948            };
10949
10950            // Call self after setting up the new function
10951            this._prefill();
10952        },
10953
10954        // Console log wrapper
10955        _debug: function infscr_debug() {
10956            if (true !== this.options.debug) {
10957                return;
10958            }
10959
10960            if (typeof console !== 'undefined' && typeof console.log === 'function') {
10961                // Modern browsers
10962                // Single argument, which is a string
10963                if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
10964                    console.log( (Array.prototype.slice.call(arguments)).toString() );
10965                } else {
10966                    console.log( Array.prototype.slice.call(arguments) );
10967                }
10968            } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
10969                // IE8
10970                Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
10971            }
10972        },
10973
10974        // find the number to increment in the path.
10975        _determinepath: function infscr_determinepath(path) {
10976
10977            var opts = this.options;
10978
10979            // if behavior is defined and this function is extended, call that instead of default
10980            if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) {
10981                return this['_determinepath_'+opts.behavior].call(this,path);
10982            }
10983
10984            if (!!opts.pathParse) {
10985
10986                this._debug('pathParse manual');
10987                return opts.pathParse(path, this.options.state.currPage+1);
10988
10989            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
10990                path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
10991
10992                // if there is any 2 in the url at all.
10993            } else if (path.match(/^(.*?)2(.*?$)/)) {
10994
10995                // page= is used in django:
10996                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
10997                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
10998                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
10999                    return path;
11000                }
11001
11002                path = path.match(/^(.*?)2(.*?$)/).slice(1);
11003
11004            } else {
11005
11006                // page= is used in drupal too but second page is page=1 not page=2:
11007                // thx Jerod Fritz, vladikoff
11008                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
11009                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
11010                    return path;
11011                } else {
11012                    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.");
11013                    // Get rid of isInvalidPage to allow permalink to state
11014                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
11015                }
11016            }
11017            this._debug('determinePath', path);
11018            return path;
11019
11020        },
11021
11022        // Custom error
11023        _error: function infscr_error(xhr) {
11024
11025            var opts = this.options;
11026
11027            // if behavior is defined and this function is extended, call that instead of default
11028            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
11029                this['_error_'+opts.behavior].call(this,xhr);
11030                return;
11031            }
11032
11033            if (xhr !== 'destroy' && xhr !== 'end') {
11034                xhr = 'unknown';
11035            }
11036
11037            this._debug('Error', xhr);
11038
11039            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
11040                this._showdonemsg();
11041            }
11042
11043            opts.state.isDone = true;
11044            opts.state.currPage = 1; // if you need to go back to this instance
11045            opts.state.isPaused = false;
11046            opts.state.isBeyondMaxPage = false;
11047            this._binding('unbind');
11048
11049        },
11050
11051        // Load Callback
11052        _loadcallback: function infscr_loadcallback(box, data, url) {
11053            var opts = this.options,
11054            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
11055            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
11056            frag;
11057
11058            // if behavior is defined and this function is extended, call that instead of default
11059            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
11060                this['_loadcallback_'+opts.behavior].call(this,box,data);
11061                return;
11062            }
11063
11064            switch (result) {
11065                case 'done':
11066                    this._showdonemsg();
11067                    return false;
11068
11069                case 'no-append':
11070                    if (opts.dataType === 'html') {
11071                        data = '<div>' + data + '</div>';
11072                        data = $(data).find(opts.itemSelector);
11073                    }
11074
11075                    // if it didn't return anything
11076                    if (data.length === 0) {
11077                        return this._error('end');
11078                    }
11079
11080                    break;
11081
11082                case 'append':
11083                    var children = box.children();
11084                    // if it didn't return anything
11085                    if (children.length === 0) {
11086                        return this._error('end');
11087                    }
11088
11089                    // use a documentFragment because it works when content is going into a table or UL
11090                    frag = document.createDocumentFragment();
11091                    while (box[0].firstChild) {
11092                        frag.appendChild(box[0].firstChild);
11093                    }
11094
11095                    this._debug('contentSelector', $(opts.contentSelector)[0]);
11096                    $(opts.contentSelector)[0].appendChild(frag);
11097                    // previously, we would pass in the new DOM element as context for the callback
11098                    // however we're now using a documentfragment, which doesn't have parents or children,
11099                    // so the context is the contentContainer guy, and we pass in an array
11100                    // of the elements collected as the first argument.
11101
11102                    data = children.get();
11103                    break;
11104            }
11105
11106            // loadingEnd function
11107            opts.loading.finished.call($(opts.contentSelector)[0],opts);
11108
11109            // smooth scroll to ease in the new content
11110            if (opts.animate) {
11111                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
11112                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
11113            }
11114
11115            if (!opts.animate) {
11116                // once the call is done, we can allow it again.
11117                opts.state.isDuringAjax = false;
11118            }
11119
11120            callback(this, data, url);
11121
11122            if (opts.prefill) {
11123                this._prefill();
11124            }
11125        },
11126
11127        _nearbottom: function infscr_nearbottom() {
11128
11129            var opts = this.options,
11130            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
11131
11132            // if behavior is defined and this function is extended, call that instead of default
11133            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
11134                return this['_nearbottom_'+opts.behavior].call(this);
11135            }
11136
11137            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
11138
11139            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
11140            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
11141
11142        },
11143
11144        // Pause / temporarily disable plugin from firing
11145        _pausing: function infscr_pausing(pause) {
11146
11147            var opts = this.options;
11148
11149            // if behavior is defined and this function is extended, call that instead of default
11150            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
11151                this['_pausing_'+opts.behavior].call(this,pause);
11152                return;
11153            }
11154
11155            // If pause is not 'pause' or 'resume', toggle it's value
11156            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
11157                this._debug('Invalid argument. Toggling pause value instead');
11158            }
11159
11160            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
11161
11162            switch (pause) {
11163                case 'pause':
11164                    opts.state.isPaused = true;
11165                break;
11166
11167                case 'resume':
11168                    opts.state.isPaused = false;
11169                break;
11170
11171                case 'toggle':
11172                    opts.state.isPaused = !opts.state.isPaused;
11173                break;
11174            }
11175
11176            this._debug('Paused', opts.state.isPaused);
11177            return false;
11178
11179        },
11180
11181        // Behavior is determined
11182        // If the behavior option is undefined, it will set to default and bind to scroll
11183        _setup: function infscr_setup() {
11184
11185            var opts = this.options;
11186
11187            // if behavior is defined and this function is extended, call that instead of default
11188            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
11189                this['_setup_'+opts.behavior].call(this);
11190                return;
11191            }
11192
11193            this._binding('bind');
11194
11195            return false;
11196
11197        },
11198
11199        // Show done message
11200        _showdonemsg: function infscr_showdonemsg() {
11201
11202            var opts = this.options;
11203
11204            // if behavior is defined and this function is extended, call that instead of default
11205            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
11206                this['_showdonemsg_'+opts.behavior].call(this);
11207                return;
11208            }
11209
11210            opts.loading.msg
11211            .find('img')
11212            .hide()
11213            .parent()
11214            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
11215                $(this).parent().fadeOut(opts.loading.speed);
11216            });
11217
11218            // user provided callback when done
11219            opts.errorCallback.call($(opts.contentSelector)[0],'done');
11220        },
11221
11222        // grab each selector option and see if any fail
11223        _validate: function infscr_validate(opts) {
11224            for (var key in opts) {
11225                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
11226                    this._debug('Your ' + key + ' found no elements.');
11227                    return false;
11228                }
11229            }
11230
11231            return true;
11232        },
11233
11234        /*
11235            ----------------------------
11236            Public methods
11237            ----------------------------
11238            */
11239
11240        // Bind to scroll
11241        bind: function infscr_bind() {
11242            this._binding('bind');
11243        },
11244
11245        // Destroy current instance of plugin
11246        destroy: function infscr_destroy() {
11247            this.options.state.isDestroyed = true;
11248            this.options.loading.finished();
11249            return this._error('destroy');
11250        },
11251
11252        // Set pause value to false
11253        pause: function infscr_pause() {
11254            this._pausing('pause');
11255        },
11256
11257        // Set pause value to false
11258        resume: function infscr_resume() {
11259            this._pausing('resume');
11260        },
11261
11262        beginAjax: function infscr_ajax(opts) {
11263            var instance = this,
11264                path = opts.path,
11265                box, desturl, method, condition;
11266
11267            // increment the URL bit. e.g. /page/3/
11268            opts.state.currPage++;
11269
11270            // Manually control maximum page
11271            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
11272                opts.state.isBeyondMaxPage = true;
11273                this.destroy();
11274                return;
11275            }
11276
11277            // if we're dealing with a table we can't use DIVs
11278            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
11279
11280            desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
11281            instance._debug('heading into ajax', desturl);
11282
11283            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
11284            if (opts.appendCallback && opts.dataType === 'html') {
11285                method += '+callback';
11286            }
11287
11288            switch (method) {
11289                case 'html+callback':
11290                    instance._debug('Using HTML via .load() method');
11291                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
11292                        instance._loadcallback(box, responseText, desturl);
11293                    });
11294
11295                    break;
11296
11297                case 'html':
11298                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
11299                    $.ajax({
11300                        // params
11301                        url: desturl,
11302                        dataType: opts.dataType,
11303                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
11304                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
11305                            if (condition) {
11306                                instance._loadcallback(box, jqXHR.responseText, desturl);
11307                            } else {
11308                                instance._error('end');
11309                            }
11310                        }
11311                    });
11312
11313                    break;
11314                case 'json':
11315                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
11316                    $.ajax({
11317                        dataType: 'json',
11318                        type: 'GET',
11319                        url: desturl,
11320                        success: function (data, textStatus, jqXHR) {
11321                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
11322                            if (opts.appendCallback) {
11323                                // if appendCallback is true, you must defined template in options.
11324                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
11325                                if (opts.template !== undefined) {
11326                                    var theData = opts.template(data);
11327                                    box.append(theData);
11328                                    if (condition) {
11329                                        instance._loadcallback(box, theData);
11330                                    } else {
11331                                        instance._error('end');
11332                                    }
11333                                } else {
11334                                    instance._debug('template must be defined.');
11335                                    instance._error('end');
11336                                }
11337                            } else {
11338                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
11339                                if (condition) {
11340                                    instance._loadcallback(box, data, desturl);
11341                                } else {
11342                                    instance._error('end');
11343                                }
11344                            }
11345                        },
11346                        error: function() {
11347                            instance._debug('JSON ajax request failed.');
11348                            instance._error('end');
11349                        }
11350                    });
11351
11352                    break;
11353            }
11354        },
11355
11356        // Retrieve next set of content items
11357        retrieve: function infscr_retrieve(pageNum) {
11358            pageNum = pageNum || null;
11359
11360            var instance = this,
11361            opts = instance.options;
11362
11363            // if behavior is defined and this function is extended, call that instead of default
11364            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
11365                this['retrieve_'+opts.behavior].call(this,pageNum);
11366                return;
11367            }
11368
11369            // for manual triggers, if destroyed, get out of here
11370            if (opts.state.isDestroyed) {
11371                this._debug('Instance is destroyed');
11372                return false;
11373            }
11374
11375            // we dont want to fire the ajax multiple times
11376            opts.state.isDuringAjax = true;
11377
11378            opts.loading.start.call($(opts.contentSelector)[0],opts);
11379        },
11380
11381        // Check to see next page is needed
11382        scroll: function infscr_scroll() {
11383
11384            var opts = this.options,
11385            state = opts.state;
11386
11387            // if behavior is defined and this function is extended, call that instead of default
11388            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
11389                this['scroll_'+opts.behavior].call(this);
11390                return;
11391            }
11392
11393            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
11394                return;
11395            }
11396
11397            if (!this._nearbottom()) {
11398                return;
11399            }
11400
11401            this.retrieve();
11402
11403        },
11404
11405        // Toggle pause value
11406        toggle: function infscr_toggle() {
11407            this._pausing();
11408        },
11409
11410        // Unbind from scroll
11411        unbind: function infscr_unbind() {
11412            this._binding('unbind');
11413        },
11414
11415        // update options
11416        update: function infscr_options(key) {
11417            if ($.isPlainObject(key)) {
11418                this.options = $.extend(true,this.options,key);
11419            }
11420        }
11421    };
11422
11423
11424    /*
11425        ----------------------------
11426        Infinite Scroll function
11427        ----------------------------
11428
11429        Borrowed logic from the following...
11430
11431        jQuery UI
11432        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
11433
11434        jCarousel
11435        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
11436
11437        Masonry
11438        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
11439
11440*/
11441
11442    $.fn.infinitescroll = function infscr_init(options, callback) {
11443
11444
11445        var thisCall = typeof options;
11446
11447        switch (thisCall) {
11448
11449            // method
11450            case 'string':
11451                var args = Array.prototype.slice.call(arguments, 1);
11452
11453                this.each(function () {
11454                    var instance = $.data(this, 'infinitescroll');
11455
11456                    if (!instance) {
11457                        // not setup yet
11458                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
11459                        return false;
11460                    }
11461
11462                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
11463                        // return $.error('No such method ' + options + ' for Infinite Scroll');
11464                        return false;
11465                    }
11466
11467                    // no errors!
11468                    instance[options].apply(instance, args);
11469                });
11470
11471            break;
11472
11473            // creation
11474            case 'object':
11475
11476                this.each(function () {
11477
11478                var instance = $.data(this, 'infinitescroll');
11479
11480                if (instance) {
11481
11482                    // update options of current instance
11483                    instance.update(options);
11484
11485                } else {
11486
11487                    // initialize new instance
11488                    instance = new $.infinitescroll(options, callback, this);
11489
11490                    // don't attach if instantiation failed
11491                    if (!instance.failed) {
11492                        $.data(this, 'infinitescroll', instance);
11493                    }
11494
11495                }
11496
11497            });
11498
11499            break;
11500
11501        }
11502
11503        return this;
11504    };
11505
11506
11507
11508    /*
11509     * smartscroll: debounced scroll event for jQuery *
11510     * https://github.com/lukeshumard/smartscroll
11511     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
11512     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
11513     */
11514
11515    var event = $.event,
11516    scrollTimeout;
11517
11518    event.special.smartscroll = {
11519        setup: function () {
11520            $(this).bind('scroll', event.special.smartscroll.handler);
11521        },
11522        teardown: function () {
11523            $(this).unbind('scroll', event.special.smartscroll.handler);
11524        },
11525        handler: function (event, execAsap) {
11526            // Save the context
11527            var context = this,
11528            args = arguments;
11529
11530            // set correct event type
11531            event.type = 'smartscroll';
11532
11533            if (scrollTimeout) { clearTimeout(scrollTimeout); }
11534            scrollTimeout = setTimeout(function () {
11535                $(context).trigger('smartscroll', args);
11536            }, execAsap === 'execAsap' ? 0 : 100);
11537        }
11538    };
11539
11540    $.fn.smartscroll = function (fn) {
11541        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
11542    };
11543
11544}));
11545
11546/*!
11547Waypoints - 4.0.1
11548Copyright © 2011-2016 Caleb Troughton
11549Licensed under the MIT license.
11550https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
11551*/
11552(function() {
11553  'use strict'
11554
11555  var keyCounter = 0
11556  var allWaypoints = {}
11557
11558  /* http://imakewebthings.com/waypoints/api/waypoint */
11559  function Waypoint(options) {
11560    if (!options) {
11561      throw new Error('No options passed to Waypoint constructor')
11562    }
11563    if (!options.element) {
11564      throw new Error('No element option passed to Waypoint constructor')
11565    }
11566    if (!options.handler) {
11567      throw new Error('No handler option passed to Waypoint constructor')
11568    }
11569
11570    this.key = 'waypoint-' + keyCounter
11571    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
11572    this.element = this.options.element
11573    this.adapter = new Waypoint.Adapter(this.element)
11574    this.callback = options.handler
11575    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
11576    this.enabled = this.options.enabled
11577    this.triggerPoint = null
11578    this.group = Waypoint.Group.findOrCreate({
11579      name: this.options.group,
11580      axis: this.axis
11581    })
11582    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
11583
11584    if (Waypoint.offsetAliases[this.options.offset]) {
11585      this.options.offset = Waypoint.offsetAliases[this.options.offset]
11586    }
11587    this.group.add(this)
11588    this.context.add(this)
11589    allWaypoints[this.key] = this
11590    keyCounter += 1
11591  }
11592
11593  /* Private */
11594  Waypoint.prototype.queueTrigger = function(direction) {
11595    this.group.queueTrigger(this, direction)
11596  }
11597
11598  /* Private */
11599  Waypoint.prototype.trigger = function(args) {
11600    if (!this.enabled) {
11601      return
11602    }
11603    if (this.callback) {
11604      this.callback.apply(this, args)
11605    }
11606  }
11607
11608  /* Public */
11609  /* http://imakewebthings.com/waypoints/api/destroy */
11610  Waypoint.prototype.destroy = function() {
11611    this.context.remove(this)
11612    this.group.remove(this)
11613    delete allWaypoints[this.key]
11614  }
11615
11616  /* Public */
11617  /* http://imakewebthings.com/waypoints/api/disable */
11618  Waypoint.prototype.disable = function() {
11619    this.enabled = false
11620    return this
11621  }
11622
11623  /* Public */
11624  /* http://imakewebthings.com/waypoints/api/enable */
11625  Waypoint.prototype.enable = function() {
11626    this.context.refresh()
11627    this.enabled = true
11628    return this
11629  }
11630
11631  /* Public */
11632  /* http://imakewebthings.com/waypoints/api/next */
11633  Waypoint.prototype.next = function() {
11634    return this.group.next(this)
11635  }
11636
11637  /* Public */
11638  /* http://imakewebthings.com/waypoints/api/previous */
11639  Waypoint.prototype.previous = function() {
11640    return this.group.previous(this)
11641  }
11642
11643  /* Private */
11644  Waypoint.invokeAll = function(method) {
11645    var allWaypointsArray = []
11646    for (var waypointKey in allWaypoints) {
11647      allWaypointsArray.push(allWaypoints[waypointKey])
11648    }
11649    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
11650      allWaypointsArray[i][method]()
11651    }
11652  }
11653
11654  /* Public */
11655  /* http://imakewebthings.com/waypoints/api/destroy-all */
11656  Waypoint.destroyAll = function() {
11657    Waypoint.invokeAll('destroy')
11658  }
11659
11660  /* Public */
11661  /* http://imakewebthings.com/waypoints/api/disable-all */
11662  Waypoint.disableAll = function() {
11663    Waypoint.invokeAll('disable')
11664  }
11665
11666  /* Public */
11667  /* http://imakewebthings.com/waypoints/api/enable-all */
11668  Waypoint.enableAll = function() {
11669    Waypoint.Context.refreshAll()
11670    for (var waypointKey in allWaypoints) {
11671      allWaypoints[waypointKey].enabled = true
11672    }
11673    return this
11674  }
11675
11676  /* Public */
11677  /* http://imakewebthings.com/waypoints/api/refresh-all */
11678  Waypoint.refreshAll = function() {
11679    Waypoint.Context.refreshAll()
11680  }
11681
11682  /* Public */
11683  /* http://imakewebthings.com/waypoints/api/viewport-height */
11684  Waypoint.viewportHeight = function() {
11685    return window.innerHeight || document.documentElement.clientHeight
11686  }
11687
11688  /* Public */
11689  /* http://imakewebthings.com/waypoints/api/viewport-width */
11690  Waypoint.viewportWidth = function() {
11691    return document.documentElement.clientWidth
11692  }
11693
11694  Waypoint.adapters = []
11695
11696  Waypoint.defaults = {
11697    context: window,
11698    continuous: true,
11699    enabled: true,
11700    group: 'default',
11701    horizontal: false,
11702    offset: 0
11703  }
11704
11705  Waypoint.offsetAliases = {
11706    'bottom-in-view': function() {
11707      return this.context.innerHeight() - this.adapter.outerHeight()
11708    },
11709    'right-in-view': function() {
11710      return this.context.innerWidth() - this.adapter.outerWidth()
11711    }
11712  }
11713
11714  window.Waypoint = Waypoint
11715}())
11716;(function() {
11717  'use strict'
11718
11719  function requestAnimationFrameShim(callback) {
11720    window.setTimeout(callback, 1000 / 60)
11721  }
11722
11723  var keyCounter = 0
11724  var contexts = {}
11725  var Waypoint = window.Waypoint
11726  var oldWindowLoad = window.onload
11727
11728  /* http://imakewebthings.com/waypoints/api/context */
11729  function Context(element) {
11730    this.element = element
11731    this.Adapter = Waypoint.Adapter
11732    this.adapter = new this.Adapter(element)
11733    this.key = 'waypoint-context-' + keyCounter
11734    this.didScroll = false
11735    this.didResize = false
11736    this.oldScroll = {
11737      x: this.adapter.scrollLeft(),
11738      y: this.adapter.scrollTop()
11739    }
11740    this.waypoints = {
11741      vertical: {},
11742      horizontal: {}
11743    }
11744
11745    element.waypointContextKey = this.key
11746    contexts[element.waypointContextKey] = this
11747    keyCounter += 1
11748    if (!Waypoint.windowContext) {
11749      Waypoint.windowContext = true
11750      Waypoint.windowContext = new Context(window)
11751    }
11752
11753    this.createThrottledScrollHandler()
11754    this.createThrottledResizeHandler()
11755  }
11756
11757  /* Private */
11758  Context.prototype.add = function(waypoint) {
11759    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
11760    this.waypoints[axis][waypoint.key] = waypoint
11761    this.refresh()
11762  }
11763
11764  /* Private */
11765  Context.prototype.checkEmpty = function() {
11766    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
11767    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
11768    var isWindow = this.element == this.element.window
11769    if (horizontalEmpty && verticalEmpty && !isWindow) {
11770      this.adapter.off('.waypoints')
11771      delete contexts[this.key]
11772    }
11773  }
11774
11775  /* Private */
11776  Context.prototype.createThrottledResizeHandler = function() {
11777    var self = this
11778
11779    function resizeHandler() {
11780      self.handleResize()
11781      self.didResize = false
11782    }
11783
11784    this.adapter.on('resize.waypoints', function() {
11785      if (!self.didResize) {
11786        self.didResize = true
11787        Waypoint.requestAnimationFrame(resizeHandler)
11788      }
11789    })
11790  }
11791
11792  /* Private */
11793  Context.prototype.createThrottledScrollHandler = function() {
11794    var self = this
11795    function scrollHandler() {
11796      self.handleScroll()
11797      self.didScroll = false
11798    }
11799
11800    this.adapter.on('scroll.waypoints', function() {
11801      if (!self.didScroll || Waypoint.isTouch) {
11802        self.didScroll = true
11803        Waypoint.requestAnimationFrame(scrollHandler)
11804      }
11805    })
11806  }
11807
11808  /* Private */
11809  Context.prototype.handleResize = function() {
11810    Waypoint.Context.refreshAll()
11811  }
11812
11813  /* Private */
11814  Context.prototype.handleScroll = function() {
11815    var triggeredGroups = {}
11816    var axes = {
11817      horizontal: {
11818        newScroll: this.adapter.scrollLeft(),
11819        oldScroll: this.oldScroll.x,
11820        forward: 'right',
11821        backward: 'left'
11822      },
11823      vertical: {
11824        newScroll: this.adapter.scrollTop(),
11825        oldScroll: this.oldScroll.y,
11826        forward: 'down',
11827        backward: 'up'
11828      }
11829    }
11830
11831    for (var axisKey in axes) {
11832      var axis = axes[axisKey]
11833      var isForward = axis.newScroll > axis.oldScroll
11834      var direction = isForward ? axis.forward : axis.backward
11835
11836      for (var waypointKey in this.waypoints[axisKey]) {
11837        var waypoint = this.waypoints[axisKey][waypointKey]
11838        if (waypoint.triggerPoint === null) {
11839          continue
11840        }
11841        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
11842        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
11843        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
11844        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
11845        if (crossedForward || crossedBackward) {
11846          waypoint.queueTrigger(direction)
11847          triggeredGroups[waypoint.group.id] = waypoint.group
11848        }
11849      }
11850    }
11851
11852    for (var groupKey in triggeredGroups) {
11853      triggeredGroups[groupKey].flushTriggers()
11854    }
11855
11856    this.oldScroll = {
11857      x: axes.horizontal.newScroll,
11858      y: axes.vertical.newScroll
11859    }
11860  }
11861
11862  /* Private */
11863  Context.prototype.innerHeight = function() {
11864    /*eslint-disable eqeqeq */
11865    if (this.element == this.element.window) {
11866      return Waypoint.viewportHeight()
11867    }
11868    /*eslint-enable eqeqeq */
11869    return this.adapter.innerHeight()
11870  }
11871
11872  /* Private */
11873  Context.prototype.remove = function(waypoint) {
11874    delete this.waypoints[waypoint.axis][waypoint.key]
11875    this.checkEmpty()
11876  }
11877
11878  /* Private */
11879  Context.prototype.innerWidth = function() {
11880    /*eslint-disable eqeqeq */
11881    if (this.element == this.element.window) {
11882      return Waypoint.viewportWidth()
11883    }
11884    /*eslint-enable eqeqeq */
11885    return this.adapter.innerWidth()
11886  }
11887
11888  /* Public */
11889  /* http://imakewebthings.com/waypoints/api/context-destroy */
11890  Context.prototype.destroy = function() {
11891    var allWaypoints = []
11892    for (var axis in this.waypoints) {
11893      for (var waypointKey in this.waypoints[axis]) {
11894        allWaypoints.push(this.waypoints[axis][waypointKey])
11895      }
11896    }
11897    for (var i = 0, end = allWaypoints.length; i < end; i++) {
11898      allWaypoints[i].destroy()
11899    }
11900  }
11901
11902  /* Public */
11903  /* http://imakewebthings.com/waypoints/api/context-refresh */
11904  Context.prototype.refresh = function() {
11905    /*eslint-disable eqeqeq */
11906    var isWindow = this.element == this.element.window
11907    /*eslint-enable eqeqeq */
11908    var contextOffset = isWindow ? undefined : this.adapter.offset()
11909    var triggeredGroups = {}
11910    var axes
11911
11912    this.handleScroll()
11913    axes = {
11914      horizontal: {
11915        contextOffset: isWindow ? 0 : contextOffset.left,
11916        contextScroll: isWindow ? 0 : this.oldScroll.x,
11917        contextDimension: this.innerWidth(),
11918        oldScroll: this.oldScroll.x,
11919        forward: 'right',
11920        backward: 'left',
11921        offsetProp: 'left'
11922      },
11923      vertical: {
11924        contextOffset: isWindow ? 0 : contextOffset.top,
11925        contextScroll: isWindow ? 0 : this.oldScroll.y,
11926        contextDimension: this.innerHeight(),
11927        oldScroll: this.oldScroll.y,
11928        forward: 'down',
11929        backward: 'up',
11930        offsetProp: 'top'
11931      }
11932    }
11933
11934    for (var axisKey in axes) {
11935      var axis = axes[axisKey]
11936      for (var waypointKey in this.waypoints[axisKey]) {
11937        var waypoint = this.waypoints[axisKey][waypointKey]
11938        var adjustment = waypoint.options.offset
11939        var oldTriggerPoint = waypoint.triggerPoint
11940        var elementOffset = 0
11941        var freshWaypoint = oldTriggerPoint == null
11942        var contextModifier, wasBeforeScroll, nowAfterScroll
11943        var triggeredBackward, triggeredForward
11944
11945        if (waypoint.element !== waypoint.element.window) {
11946          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
11947        }
11948
11949        if (typeof adjustment === 'function') {
11950          adjustment = adjustment.apply(waypoint)
11951        }
11952        else if (typeof adjustment === 'string') {
11953          adjustment = parseFloat(adjustment)
11954          if (waypoint.options.offset.indexOf('%') > - 1) {
11955            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
11956          }
11957        }
11958
11959        contextModifier = axis.contextScroll - axis.contextOffset
11960        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
11961        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
11962        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
11963        triggeredBackward = wasBeforeScroll && nowAfterScroll
11964        triggeredForward = !wasBeforeScroll && !nowAfterScroll
11965
11966        if (!freshWaypoint && triggeredBackward) {
11967          waypoint.queueTrigger(axis.backward)
11968          triggeredGroups[waypoint.group.id] = waypoint.group
11969        }
11970        else if (!freshWaypoint && triggeredForward) {
11971          waypoint.queueTrigger(axis.forward)
11972          triggeredGroups[waypoint.group.id] = waypoint.group
11973        }
11974        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
11975          waypoint.queueTrigger(axis.forward)
11976          triggeredGroups[waypoint.group.id] = waypoint.group
11977        }
11978      }
11979    }
11980
11981    Waypoint.requestAnimationFrame(function() {
11982      for (var groupKey in triggeredGroups) {
11983        triggeredGroups[groupKey].flushTriggers()
11984      }
11985    })
11986
11987    return this
11988  }
11989
11990  /* Private */
11991  Context.findOrCreateByElement = function(element) {
11992    return Context.findByElement(element) || new Context(element)
11993  }
11994
11995  /* Private */
11996  Context.refreshAll = function() {
11997    for (var contextId in contexts) {
11998      contexts[contextId].refresh()
11999    }
12000  }
12001
12002  /* Public */
12003  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
12004  Context.findByElement = function(element) {
12005    return contexts[element.waypointContextKey]
12006  }
12007
12008  window.onload = function() {
12009    if (oldWindowLoad) {
12010      oldWindowLoad()
12011    }
12012    Context.refreshAll()
12013  }
12014
12015
12016  Waypoint.requestAnimationFrame = function(callback) {
12017    var requestFn = window.requestAnimationFrame ||
12018      window.mozRequestAnimationFrame ||
12019      window.webkitRequestAnimationFrame ||
12020      requestAnimationFrameShim
12021    requestFn.call(window, callback)
12022  }
12023  Waypoint.Context = Context
12024}())
12025;(function() {
12026  'use strict'
12027
12028  function byTriggerPoint(a, b) {
12029    return a.triggerPoint - b.triggerPoint
12030  }
12031
12032  function byReverseTriggerPoint(a, b) {
12033    return b.triggerPoint - a.triggerPoint
12034  }
12035
12036  var groups = {
12037    vertical: {},
12038    horizontal: {}
12039  }
12040  var Waypoint = window.Waypoint
12041
12042  /* http://imakewebthings.com/waypoints/api/group */
12043  function Group(options) {
12044    this.name = options.name
12045    this.axis = options.axis
12046    this.id = this.name + '-' + this.axis
12047    this.waypoints = []
12048    this.clearTriggerQueues()
12049    groups[this.axis][this.name] = this
12050  }
12051
12052  /* Private */
12053  Group.prototype.add = function(waypoint) {
12054    this.waypoints.push(waypoint)
12055  }
12056
12057  /* Private */
12058  Group.prototype.clearTriggerQueues = function() {
12059    this.triggerQueues = {
12060      up: [],
12061      down: [],
12062      left: [],
12063      right: []
12064    }
12065  }
12066
12067  /* Private */
12068  Group.prototype.flushTriggers = function() {
12069    for (var direction in this.triggerQueues) {
12070      var waypoints = this.triggerQueues[direction]
12071      var reverse = direction === 'up' || direction === 'left'
12072      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
12073      for (var i = 0, end = waypoints.length; i < end; i += 1) {
12074        var waypoint = waypoints[i]
12075        if (waypoint.options.continuous || i === waypoints.length - 1) {
12076          waypoint.trigger([direction])
12077        }
12078      }
12079    }
12080    this.clearTriggerQueues()
12081  }
12082
12083  /* Private */
12084  Group.prototype.next = function(waypoint) {
12085    this.waypoints.sort(byTriggerPoint)
12086    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12087    var isLast = index === this.waypoints.length - 1
12088    return isLast ? null : this.waypoints[index + 1]
12089  }
12090
12091  /* Private */
12092  Group.prototype.previous = function(waypoint) {
12093    this.waypoints.sort(byTriggerPoint)
12094    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12095    return index ? this.waypoints[index - 1] : null
12096  }
12097
12098  /* Private */
12099  Group.prototype.queueTrigger = function(waypoint, direction) {
12100    this.triggerQueues[direction].push(waypoint)
12101  }
12102
12103  /* Private */
12104  Group.prototype.remove = function(waypoint) {
12105    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12106    if (index > -1) {
12107      this.waypoints.splice(index, 1)
12108    }
12109  }
12110
12111  /* Public */
12112  /* http://imakewebthings.com/waypoints/api/first */
12113  Group.prototype.first = function() {
12114    return this.waypoints[0]
12115  }
12116
12117  /* Public */
12118  /* http://imakewebthings.com/waypoints/api/last */
12119  Group.prototype.last = function() {
12120    return this.waypoints[this.waypoints.length - 1]
12121  }
12122
12123  /* Private */
12124  Group.findOrCreate = function(options) {
12125    return groups[options.axis][options.name] || new Group(options)
12126  }
12127
12128  Waypoint.Group = Group
12129}())
12130;(function() {
12131  'use strict'
12132
12133  var $ = window.jQuery
12134  var Waypoint = window.Waypoint
12135
12136  function JQueryAdapter(element) {
12137    this.$element = $(element)
12138  }
12139
12140  $.each([
12141    'innerHeight',
12142    'innerWidth',
12143    'off',
12144    'offset',
12145    'on',
12146    'outerHeight',
12147    'outerWidth',
12148    'scrollLeft',
12149    'scrollTop'
12150  ], function(i, method) {
12151    JQueryAdapter.prototype[method] = function() {
12152      var args = Array.prototype.slice.call(arguments)
12153      return this.$element[method].apply(this.$element, args)
12154    }
12155  })
12156
12157  $.each([
12158    'extend',
12159    'inArray',
12160    'isEmptyObject'
12161  ], function(i, method) {
12162    JQueryAdapter[method] = $[method]
12163  })
12164
12165  Waypoint.adapters.push({
12166    name: 'jquery',
12167    Adapter: JQueryAdapter
12168  })
12169  Waypoint.Adapter = JQueryAdapter
12170}())
12171;(function() {
12172  'use strict'
12173
12174  var Waypoint = window.Waypoint
12175
12176  function createExtension(framework) {
12177    return function() {
12178      var waypoints = []
12179      var overrides = arguments[0]
12180
12181      if (framework.isFunction(arguments[0])) {
12182        overrides = framework.extend({}, arguments[1])
12183        overrides.handler = arguments[0]
12184      }
12185
12186      this.each(function() {
12187        var options = framework.extend({}, overrides, {
12188          element: this
12189        })
12190        if (typeof options.context === 'string') {
12191          options.context = framework(this).closest(options.context)[0]
12192        }
12193        waypoints.push(new Waypoint(options))
12194      })
12195
12196      return waypoints
12197    }
12198  }
12199
12200  if (window.jQuery) {
12201    window.jQuery.fn.waypoint = createExtension(window.jQuery)
12202  }
12203  if (window.Zepto) {
12204    window.Zepto.fn.waypoint = createExtension(window.Zepto)
12205  }
12206}())
12207;
12208/*!
12209Waypoints Inview Shortcut - 4.0.1
12210Copyright © 2011-2016 Caleb Troughton
12211Licensed under the MIT license.
12212https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
12213*/
12214(function() {
12215  'use strict'
12216
12217  function noop() {}
12218
12219  var Waypoint = window.Waypoint
12220
12221  /* http://imakewebthings.com/waypoints/shortcuts/inview */
12222  function Inview(options) {
12223    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
12224    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
12225    this.waypoints = []
12226    this.element = this.options.element
12227    this.createWaypoints()
12228  }
12229
12230  /* Private */
12231  Inview.prototype.createWaypoints = function() {
12232    var configs = {
12233      vertical: [{
12234        down: 'enter',
12235        up: 'exited',
12236        offset: '100%'
12237      }, {
12238        down: 'entered',
12239        up: 'exit',
12240        offset: 'bottom-in-view'
12241      }, {
12242        down: 'exit',
12243        up: 'entered',
12244        offset: 0
12245      }, {
12246        down: 'exited',
12247        up: 'enter',
12248        offset: function() {
12249          return -this.adapter.outerHeight()
12250        }
12251      }],
12252      horizontal: [{
12253        right: 'enter',
12254        left: 'exited',
12255        offset: '100%'
12256      }, {
12257        right: 'entered',
12258        left: 'exit',
12259        offset: 'right-in-view'
12260      }, {
12261        right: 'exit',
12262        left: 'entered',
12263        offset: 0
12264      }, {
12265        right: 'exited',
12266        left: 'enter',
12267        offset: function() {
12268          return -this.adapter.outerWidth()
12269        }
12270      }]
12271    }
12272
12273    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
12274      var config = configs[this.axis][i]
12275      this.createWaypoint(config)
12276    }
12277  }
12278
12279  /* Private */
12280  Inview.prototype.createWaypoint = function(config) {
12281    var self = this
12282    this.waypoints.push(new Waypoint({
12283      context: this.options.context,
12284      element: this.options.element,
12285      enabled: this.options.enabled,
12286      handler: (function(config) {
12287        return function(direction) {
12288          self.options[config[direction]].call(self, direction)
12289        }
12290      }(config)),
12291      offset: config.offset,
12292      horizontal: this.options.horizontal
12293    }))
12294  }
12295
12296  /* Public */
12297  Inview.prototype.destroy = function() {
12298    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12299      this.waypoints[i].destroy()
12300    }
12301    this.waypoints = []
12302  }
12303
12304  Inview.prototype.disable = function() {
12305    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12306      this.waypoints[i].disable()
12307    }
12308  }
12309
12310  Inview.prototype.enable = function() {
12311    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12312      this.waypoints[i].enable()
12313    }
12314  }
12315
12316  Inview.defaults = {
12317    context: window,
12318    enabled: true,
12319    enter: noop,
12320    entered: noop,
12321    exit: noop,
12322    exited: noop
12323  }
12324
12325  Waypoint.Inview = Inview
12326}())
12327;
12328
12329/*
12330 * SmartMenus jQuery v0.9.6
12331 * http://www.smartmenus.org/
12332 *
12333 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
12334 * http://vadikom.com/
12335 *
12336 * Released under the MIT license:
12337 * http://www.opensource.org/licenses/MIT
12338 */
12339
12340(function($) {
12341
12342	var menuTrees = [],
12343		IE = !!window.createPopup, // we need to detect it, unfortunately
12344		IElt9 = IE && !document.defaultView,
12345		IElt8 = IE && !document.querySelector,
12346		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
12347		mouse = false, // optimize for touch by default - we will detect for mouse input
12348		mouseDetectionEnabled = false;
12349
12350	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
12351	function initMouseDetection(disable) {
12352		if (!mouseDetectionEnabled && !disable) {
12353			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
12354			// 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)
12355			var firstTime = true,
12356				lastMove = null;
12357			$(document).bind({
12358				'mousemove.smartmenus_mouse': function(e) {
12359					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
12360					if (lastMove) {
12361						var deltaX = Math.abs(lastMove.x - thisMove.x),
12362							deltaY = Math.abs(lastMove.y - thisMove.y);
12363	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
12364							mouse = true;
12365							// 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
12366							if (firstTime) {
12367								var $a = $(e.target).closest('a');
12368								if ($a.is('a')) {
12369									$.each(menuTrees, function() {
12370										if ($.contains(this.$root[0], $a[0])) {
12371											this.itemEnter({ currentTarget: $a[0] });
12372											return false;
12373										}
12374									});
12375								}
12376								firstTime = false;
12377							}
12378						}
12379					}
12380					lastMove = thisMove;
12381				},
12382				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
12383					if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) {
12384						mouse = false;
12385					}
12386				}
12387			});
12388			mouseDetectionEnabled = true;
12389		} else if (mouseDetectionEnabled && disable) {
12390			$(document).unbind('.smartmenus_mouse');
12391			mouseDetectionEnabled = false;
12392		}
12393	};
12394
12395	$.SmartMenus = function(elm, options) {
12396		this.$root = $(elm);
12397		this.opts = options;
12398		this.rootId = ''; // internal
12399		this.$subArrow = null;
12400		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)
12401		this.activatedItems = []; // stores last activated A's for each level
12402		this.visibleSubMenus = []; // stores visible sub menus UL's
12403		this.showTimeout = 0;
12404		this.hideTimeout = 0;
12405		this.scrollTimeout = 0;
12406		this.clickActivated = false;
12407		this.zIndexInc = 0;
12408		this.$firstLink = null; // we'll use these for some tests
12409		this.$firstSub = null; // at runtime so we'll cache them
12410		this.disabled = false;
12411		this.$disableOverlay = null;
12412		this.init();
12413	};
12414
12415	$.extend($.SmartMenus, {
12416		hideAll: function() {
12417			$.each(menuTrees, function() {
12418				this.menuHideAll();
12419			});
12420		},
12421		destroy: function() {
12422			while (menuTrees.length) {
12423				menuTrees[0].destroy();
12424			}
12425			initMouseDetection(true);
12426		},
12427		prototype: {
12428			init: function(refresh) {
12429				var self = this;
12430
12431				if (!refresh) {
12432					menuTrees.push(this);
12433
12434					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
12435
12436					if (this.$root.hasClass('sm-rtl')) {
12437						this.opts.rightToLeftSubMenus = true;
12438					}
12439
12440					// init root (main menu)
12441					this.$root
12442						.data('smartmenus', this)
12443						.attr('data-smartmenus-id', this.rootId)
12444						.dataSM('level', 1)
12445						.bind({
12446							'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
12447							'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
12448						})
12449						.delegate('a, div.logo-container', {
12450							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
12451							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
12452							'mousedown.smartmenus': $.proxy(this.itemDown, this),
12453							'focus.smartmenus': $.proxy(this.itemFocus, this),
12454							'blur.smartmenus': $.proxy(this.itemBlur, this),
12455							'click.smartmenus': $.proxy(this.itemClick, this),
12456							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
12457						});
12458
12459					var eNamespace = '.smartmenus' + this.rootId;
12460					// hide menus on tap or click outside the root UL
12461					if (this.opts.hideOnClick) {
12462							$(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
12463								.on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
12464								.on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
12465								// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
12466								.on('click' + eNamespace, $.proxy(this.docClick, this));
12467					}
12468					// hide sub menus on resize
12469					$(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12470					//$(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12471
12472					if (this.opts.subIndicators) {
12473						this.$subArrow = $('<span/>').addClass('sub-arrow');
12474						if (this.opts.subIndicatorsText) {
12475							this.$subArrow.html(this.opts.subIndicatorsText);
12476						}
12477					}
12478
12479					// make sure mouse detection is enabled
12480					initMouseDetection();
12481				}
12482
12483				// init sub menus
12484				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
12485
12486				this.$firstLink = this.$root.find('a').eq(0);
12487
12488				// find current item
12489				if (this.opts.markCurrentItem) {
12490					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
12491						reHash = /#.*/,
12492						locHref = window.location.href.replace(reDefaultDoc, ''),
12493						locHrefNoHash = locHref.replace(reHash, '');
12494					this.$root.find('a').each(function() {
12495						var href = this.href.replace(reDefaultDoc, ''),
12496							$this = $(this);
12497						if (href == locHref || href == locHrefNoHash) {
12498							$this.addClass('current');
12499							if (self.opts.markCurrentTree) {
12500								$this.parents('li').each(function() {
12501									var $this = $(this);
12502									if ($this.dataSM('sub')) {
12503										$this.children('a').addClass('current');
12504									}
12505								});
12506							}
12507						}
12508					});
12509				}
12510			},
12511			destroy: function() {
12512				this.menuHideAll();
12513				this.$root
12514					.removeData('smartmenus')
12515					.removeAttr('data-smartmenus-id')
12516					.removeDataSM('level')
12517					.unbind('.smartmenus')
12518					.undelegate('.smartmenus');
12519				var eNamespace = '.smartmenus' + this.rootId;
12520				$(document).unbind(eNamespace);
12521				$(window).unbind(eNamespace);
12522				if (this.opts.subIndicators) {
12523					this.$subArrow = null;
12524				}
12525				var self = this;
12526				$.each(this.subMenus, function() {
12527					if (this.hasClass('mega-menu')) {
12528						this.find('ul').removeDataSM('in-mega');
12529					}
12530					if (this.dataSM('shown-before')) {
12531						if (IElt8) {
12532							this.children().css({ styleFloat: '', width: '' });
12533						}
12534						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
12535							if (!IE6) {
12536								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
12537							} else {
12538								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
12539							}
12540						}
12541						if (this.dataSM('scroll-arrows')) {
12542							this.dataSM('scroll-arrows').remove();
12543						}
12544						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
12545					}
12546					if (self.opts.subIndicators) {
12547						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
12548					}
12549					this.removeDataSM('shown-before')
12550						.removeDataSM('ie-shim')
12551						.removeDataSM('scroll-arrows')
12552						.removeDataSM('parent-a')
12553						.removeDataSM('level')
12554						.removeDataSM('beforefirstshowfired')
12555						.parent().removeDataSM('sub');
12556				});
12557				if (this.opts.markCurrentItem) {
12558					this.$root.find('a.current').removeClass('current');
12559				}
12560				this.$root = null;
12561				this.$firstLink = null;
12562				this.$firstSub = null;
12563				if (this.$disableOverlay) {
12564					this.$disableOverlay.remove();
12565					this.$disableOverlay = null;
12566				}
12567				menuTrees.splice($.inArray(this, menuTrees), 1);
12568			},
12569			disable: function(noOverlay) {
12570				if (!this.disabled) {
12571					this.menuHideAll();
12572					// display overlay over the menu to prevent interaction
12573					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
12574						var pos = this.$root.offset();
12575						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
12576							position: 'absolute',
12577							top: pos.top,
12578							left: pos.left,
12579							width: this.$root.outerWidth(),
12580							height: this.$root.outerHeight(),
12581							zIndex: this.getStartZIndex() + 1,
12582							opacity: 0
12583						}).appendTo(document.body);
12584					}
12585					this.disabled = true;
12586				}
12587			},
12588			docClick: function(e) {
12589				// hide on any click outside the menu or on a menu link
12590				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
12591					this.menuHideAll($(e.target));
12592				}
12593			},
12594			docTouchEnd: function(e) {
12595				if (!this.lastTouch) {
12596					return;
12597				}
12598				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))) {
12599					if (this.hideTimeout) {
12600						clearTimeout(this.hideTimeout);
12601						this.hideTimeout = 0;
12602					}
12603					// hide with a delay to prevent triggering accidental unwanted click on some page element
12604					var self = this;
12605					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
12606				}
12607				this.lastTouch = null;
12608			},
12609			docTouchMove: function(e) {
12610				if (!this.lastTouch) {
12611					return;
12612				}
12613				var touchPoint = e.originalEvent.touches[0];
12614				this.lastTouch.x2 = touchPoint.pageX;
12615				this.lastTouch.y2 = touchPoint.pageY;
12616			},
12617			docTouchStart: function(e) {
12618				var touchPoint = e.originalEvent.touches[0];
12619				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
12620			},
12621			enable: function() {
12622				if (this.disabled) {
12623					if (this.$disableOverlay) {
12624						this.$disableOverlay.remove();
12625						this.$disableOverlay = null;
12626					}
12627					this.disabled = false;
12628				}
12629			},
12630			getHeight: function($elm) {
12631				return this.getOffset($elm, true);
12632			},
12633			// returns precise width/height float values in IE9+, FF4+, recent WebKit
12634			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
12635			getOffset: function($elm, height) {
12636				var old,
12637					$win = $(window),
12638					winW = $win.width();
12639				if ($elm.css('display') == 'none') {
12640					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
12641					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
12642					if ( 
12643						($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length)
12644						||
12645						($('body').hasClass('vmenu-offcanvas-overlay') && winW >= 960 && $elm.closest('.main-menu-container').length)
12646					) {
12647						$elm.closest('li').addClass('smartmenu-open-item');
12648					}
12649				}
12650				var defaultView = $elm[0].ownerDocument.defaultView,
12651					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
12652					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
12653				if (val) {
12654					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
12655	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
12656	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
12657	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
12658				} else {
12659					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
12660				}
12661				if (old) {
12662					$elm.hide().css(old);
12663				}
12664				return val;
12665			},
12666			getWidth: function($elm) {
12667				return this.getOffset($elm);
12668			},
12669			getStartZIndex: function() {
12670				var zIndex = parseInt(this.$root.css('z-index'));
12671				return !isNaN(zIndex) ? zIndex : 1;
12672			},
12673			handleEvents: function() {
12674				return !this.disabled && this.isCSSOn();
12675			},
12676			handleItemEvents: function($a) {
12677				return this.handleEvents() && !this.isLinkInMegaMenu($a);
12678			},
12679			isCollapsible: function() {
12680				return this.$firstSub.css('position') == 'static';
12681			},
12682			isCSSOn: function() {
12683				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';
12684			},
12685			isFixed: function() {
12686				return this.$root.css('position') == 'fixed';
12687			},
12688			isLinkInMegaMenu: function($a) {
12689				return !$a.parent().parent().dataSM('level');
12690			},
12691			isTouchMode: function() {
12692				return !mouse || this.isCollapsible();
12693			},
12694			itemActivate: function($a) {
12695				var $li = $a.parent(),
12696					$ul = $li.parent(),
12697					level = $ul.dataSM('level');
12698				// 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
12699				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
12700					var self = this;
12701					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
12702						self.itemActivate($(this).dataSM('parent-a'));
12703					});
12704				}
12705				// hide any visible deeper level sub menus
12706				if (this.visibleSubMenus.length > level) {
12707					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--) {
12708						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12709							this.menuHide(this.visibleSubMenus[i]);
12710						//}
12711					}
12712				}
12713				// save new active item and sub menu for this level
12714				this.activatedItems[level - 1] = $a;
12715				this.visibleSubMenus[level - 1] = $ul;
12716				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
12717					return;
12718				}
12719				// show the sub menu if this item has one
12720				var $sub = $li.dataSM('sub');
12721				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
12722					this.menuShow($sub);
12723				}
12724			},
12725			itemBlur: function(e) {
12726				var $a = $(e.currentTarget);
12727				if (!this.handleItemEvents($a)) {
12728					return;
12729				}
12730				this.$root.triggerHandler('blur.smapi', $a[0]);
12731			},
12732			itemClick: function(e) {
12733				var $a = $(e.currentTarget);
12734
12735				if (!this.handleItemEvents($a)) {
12736					return;
12737				}
12738				$a.removeDataSM('mousedown');
12739				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
12740					return false;
12741				}
12742				var $sub = $a.parent().dataSM('sub');
12743				if (this.isTouchMode()) {
12744					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
12745					if ($a.dataSM('href')) {
12746						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
12747					}
12748					// if the sub is not visible
12749					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12750						// try to activate the item and show the sub
12751						this.itemActivate($a);
12752						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
12753						// 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
12754						if ($sub.is(':visible')) {
12755							return false;
12756						}
12757					}
12758				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
12759					this.clickActivated = true;
12760					this.menuShow($sub);
12761					return false;
12762				}
12763				if ($a.hasClass('disabled')) {
12764					return false;
12765				}
12766				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
12767					return false;
12768				}
12769			},
12770			itemDown: function(e) {
12771				var $a = $(e.currentTarget);
12772				if (!this.handleItemEvents($a)) {
12773					return;
12774				}
12775				$a.dataSM('mousedown', true);
12776			},
12777			itemEnter: function(e) {
12778				var $a = $(e.currentTarget);
12779				if (!this.handleItemEvents($a)) {
12780					return;
12781				}
12782				if (!this.isTouchMode()) {
12783					if (this.showTimeout) {
12784						clearTimeout(this.showTimeout);
12785						this.showTimeout = 0;
12786					}
12787					var self = this;
12788					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
12789				}
12790				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
12791			},
12792			itemFocus: function(e) {
12793				var $a = $(e.currentTarget);
12794				if (!this.handleItemEvents($a)) {
12795					return;
12796				}
12797				// 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
12798				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
12799					this.itemActivate($a);
12800				}
12801				this.$root.triggerHandler('focus.smapi', $a[0]);
12802			},
12803			itemLeave: function(e) {
12804				var $a = $(e.currentTarget);
12805				if (!this.handleItemEvents($a)) {
12806					return;
12807				}
12808				if (!this.isTouchMode()) {
12809					if ($a[0].blur) {
12810						$a[0].blur();
12811					}
12812					if (this.showTimeout) {
12813						clearTimeout(this.showTimeout);
12814						this.showTimeout = 0;
12815					}
12816				}
12817				$a.removeDataSM('mousedown');
12818				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
12819			},
12820			itemTouchEnd: function(e) {
12821				var $a = $(e.currentTarget);
12822				if (!this.handleItemEvents($a)) {
12823					return;
12824				}
12825				// prevent the address bar on iPhone from sliding down when expanding a sub menu
12826				var $sub = $a.parent().dataSM('sub');
12827				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12828					$a.dataSM('href', $a.attr('href'));
12829					$a.attr('href', '#');
12830				}
12831			},
12832			menuFixLayout: function($ul) {
12833				// fixes a menu that is being shown for the first time
12834				if (!$ul.dataSM('shown-before')) {
12835					$ul.hide().dataSM('shown-before', true);
12836					// fix the layout of the items in IE<8
12837					if (IElt8) {
12838						$ul.children().css({ styleFloat: 'left', width: '100%' });
12839					}
12840				}
12841			},
12842			menuHide: function($sub) {
12843				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
12844					return;
12845				}
12846				$sub.stop(true, true);
12847				if ($sub.is(':visible')) {
12848					var complete = function() {
12849						// unset z-index
12850						if (IElt9) {
12851							$sub.parent().css('z-index', '');
12852						} else {
12853							$sub.css('z-index', '');
12854						}
12855					};
12856					// if sub is collapsible (mobile view)
12857					if (this.isCollapsible()) {
12858						if (this.opts.collapsibleHideFunction) {
12859							this.opts.collapsibleHideFunction.call(this, $sub, complete);
12860						} else {
12861							$sub.hide(this.opts.collapsibleHideDuration, complete);
12862						}
12863					} else {
12864						if (this.opts.hideFunction) {
12865							this.opts.hideFunction.call(this, $sub, complete);
12866						} else {
12867							$sub.hide(this.opts.hideDuration, complete);
12868						}
12869					}
12870					// remove IE iframe shim
12871					if ($sub.dataSM('ie-shim')) {
12872						$sub.dataSM('ie-shim').remove();
12873					}
12874					// deactivate scrolling if it is activated for this sub
12875					if ($sub.dataSM('scroll')) {
12876						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
12877					}
12878					// unhighlight parent item
12879					$sub.dataSM('parent-a').removeClass('highlighted');
12880					var level = $sub.dataSM('level');
12881					this.activatedItems.splice(level - 1, 1);
12882					this.visibleSubMenus.splice(level - 1, 1);
12883					this.$root.triggerHandler('hide.smapi', $sub[0]);
12884				}
12885			},
12886			menuHideAll: function($item) {
12887				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
12888				var $win = $(window),
12889					winW = $win.width();
12890				if (this.showTimeout) {
12891					clearTimeout(this.showTimeout);
12892					this.showTimeout = 0;
12893				}
12894				// hide all subs
12895				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
12896					if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) {
12897						if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) {
12898							this.menuHide(this.visibleSubMenus[i]);
12899							$(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item');
12900						} else {
12901							return;
12902						}
12903					} else {
12904						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12905							this.menuHide(this.visibleSubMenus[i]);
12906						//}
12907					}
12908				}
12909				// hide root if it's popup
12910				if (this.opts.isPopup) {
12911					this.$root.stop(true, true);
12912					if (this.$root.is(':visible')) {
12913						if (this.opts.hideFunction) {
12914							this.opts.hideFunction.call(this, this.$root);
12915						} else {
12916							this.$root.hide(this.opts.hideDuration);
12917						}
12918						// remove IE iframe shim
12919						if (this.$root.dataSM('ie-shim')) {
12920							this.$root.dataSM('ie-shim').remove();
12921						}
12922					}
12923				}
12924				this.activatedItems = [];
12925				this.visibleSubMenus = [];
12926				this.clickActivated = false;
12927				// reset z-index increment
12928				this.zIndexInc = 0;
12929			},
12930			menuIframeShim: function($ul) {
12931				// create iframe shim for the menu
12932				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
12933					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
12934						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
12935					);
12936				}
12937			},
12938			menuInit: function($ul) {
12939				if (!$ul.dataSM('in-mega')) {
12940					this.subMenus.push($ul);
12941					// mark UL's in mega drop downs (if any) so we can neglect them
12942					if ($ul.hasClass('mega-menu')) {
12943						$ul.find('ul').dataSM('in-mega', true);
12944					}
12945					// get level (much faster than, for example, using parentsUntil)
12946					var level = 2,
12947						par = $ul[0];
12948					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
12949						level++;
12950					}
12951					// cache stuff
12952					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
12953						.dataSM('level', level)
12954						.parent().dataSM('sub', $ul);
12955					// add sub indicator to parent item
12956					if (this.opts.subIndicators) {
12957						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
12958					}
12959				}
12960			},
12961			menuPosition: function($sub) {
12962				var fixIE = $('html.ie').length;
12963				// if (fixIE) {
12964				// 	var $rowParent = $($sub).closest('.main-menu-container');
12965				// 	$rowParent.height($rowParent.height());
12966				// }
12967				var $a = $sub.dataSM('parent-a'),
12968					$li = $sub.parent(),
12969					$ul = $sub.parent().parent(),
12970					// $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'),
12971					$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'),
12972					level = $sub.dataSM('level'),
12973					subW = this.getWidth($sub),
12974					subH = this.getHeight($sub),
12975					itemOffset = $a.offset(),
12976					itemX = itemOffset.left,
12977					itemY = itemOffset.top,
12978					itemW = this.getWidth($a),
12979					itemH = this.getHeight($a),
12980					$win = $(window),
12981					winX = $win.scrollLeft(),
12982					winY = $win.scrollTop(),
12983					winW = $win.width(),
12984					winH = $win.height(),
12985					containerW = $container.width(),
12986					containerOffsetX = containerW + ((winW - containerW) / 2),
12987					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
12988					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
12989					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
12990					x, y, leftPos;
12991
12992				if (horizontalParent) {
12993					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
12994					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
12995				} else {
12996					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
12997					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
12998				}
12999				if (this.opts.keepInViewport && !this.isCollapsible()) {
13000					if (this.isFixed()) {
13001						itemX -= winX;
13002						itemY -= winY;
13003						winX = winY = 0;
13004					}
13005					var absX = itemX + x,
13006						absY = itemY + y;
13007					if (this.opts.rightToLeftSubMenus && absX < winX) {
13008						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
13009					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
13010						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
13011					}
13012					if (!horizontalParent) {
13013						if (subH < winH && absY + subH > winY + winH) {
13014							y += winY + winH - subH - absY;
13015						} else if (subH >= winH || absY < winY) {
13016							y += winY - absY;
13017						}
13018					}
13019					// do we need scrolling?
13020					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
13021					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
13022						var self = this;
13023						if (!$sub.dataSM('scroll-arrows')) {
13024							$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]])
13025								.bind({
13026									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
13027									mouseleave: function(e) {
13028										self.menuScrollStop($sub);
13029										self.menuScrollOut($sub, e);
13030									},
13031									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
13032								})
13033								.insertAfter($sub)
13034							);
13035						}
13036						// bind events to show/hide arrows on hover and save scrolling data for this sub
13037						var vportY = winY - (itemY + itemH);
13038						$sub.dataSM('scroll', {
13039								vportY: vportY,
13040								subH: subH,
13041								winH: winH,
13042								step: 1
13043							})
13044							.bind({
13045								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
13046								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
13047								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
13048							})
13049							.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
13049StartZIndex() + this.zIndexInc })
13050							.eq(0).css('margin-top', vportY).end()
13051							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
13052							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
13053					}
13054				}
13055				if ( !$sub.closest('.menu-accordion').length ) {
13056					var rightPos = 'auto';
13057					if ( $sub.closest('.grid-filters').length ) {
13058						if ( $sub.closest('.text-right').length ) {
13059							leftPos = '0px';
13060							rightPos = 'auto';
13061						} else {
13062							leftPos = 'auto';
13063							rightPos = '0px';
13064						}
13065						x = 0;
13066					} else {
13067						if ( $sub.hasClass('mega-menu-inner') ) {
13068							$sub.css({ width: containerW});
13069							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
13070							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
13071								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
13072							}
13073							x = 0;
13074						} else {
13075							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
13076							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
13077						}
13078					}
13079				}
13080
13081				// $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) });
13082				$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) });
13083				// IE iframe shim
13084				this.menuIframeShim($sub);
13085				if ($sub.dataSM('ie-shim')) {
13086					$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) });
13087				}
13088			},
13089			menuScroll: function($sub, up, wheel) {
13090				var y = parseFloat($sub.css('margin-top')),
13091					scroll = $sub.dataSM('scroll'),
13092					end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH),
13093					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
13094				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
13095				y = parseFloat($sub.css('margin-top'));
13096				// show opposite arrow if appropriate
13097				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
13098					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
13099				}
13100				// accelerate when not using mousewheel to scroll
13101				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
13102					$sub.dataSM('scroll').step += 0.5;
13103				}
13104				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
13105				if (Math.abs(y - end) < 1) {
13106					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
13107					$sub.dataSM('scroll').step = 1;
13108				} else if (!wheel) {
13109					var self = this;
13110					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
13111				}
13112			},
13113			menuScrollMousewheel: function($sub, e) {
13114				var $closestSub = $(e.target).closest('ul');
13115				while ($closestSub.dataSM('in-mega')) {
13116					$closestSub = $closestSub.parent().closest('ul');
13117				}
13118				if ($closestSub[0] == $sub[0]) {
13119					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
13120					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
13121						this.menuScroll($sub, up, true);
13122					}
13123				}
13124				e.preventDefault();
13125			},
13126			menuScrollOut: function($sub, e) {
13127				var reClass = /^scroll-(up|down)/,
13128					$closestSub = $(e.relatedTarget).closest('ul');
13129				while ($closestSub.dataSM('in-mega')) {
13130					$closestSub = $closestSub.parent().closest('ul');
13131				}
13132				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
13133					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
13134				}
13135			},
13136			menuScrollOver: function($sub, e) {
13137				var reClass = /^scroll-(up|down)/,
13138					$closestSub = $(e.target).closest('ul');
13139				while ($closestSub.dataSM('in-mega')) {
13140					$closestSub = $closestSub.parent().closest('ul');
13141				}
13142				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
13143					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
13144				}
13145			},
13146			menuScrollStop: function($sub) {
13147				if (this.scrollTimeout) {
13148					clearTimeout(this.scrollTimeout);
13149					this.scrollTimeout = 0;
13150					$sub.dataSM('scroll').step = 1;
13151				}
13152			},
13153			menuShow: function($sub) {
13154				if (!$sub.dataSM('beforefirstshowfired')) {
13155					$sub.dataSM('beforefirstshowfired', true);
13156					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
13157						return;
13158					}
13159				}
13160				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
13161					return;
13162				}
13163				this.menuFixLayout($sub);
13164				$sub.stop(true, true);
13165				if (!$sub.is(':visible')) {
13166					$sub.css({
13167						'visibility': 'visible',
13168						'pointer-events': 'auto',
13169					});
13170					// set z-index - for IE < 9 set it to the parent LI
13171					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
13172					if (IElt9) {
13173						$sub.parent().css('z-index', zIndex);
13174					} else {
13175						$sub.css('z-index', zIndex);
13176					}
13177					// highlight parent item
13178					if (this.opts.keepHighlighted || this.isCollapsible()) {
13179						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
13180							$sub.dataSM('parent-a').addClass('highlighted');
13181					}
13182					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
13183					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
13184						if (!IElt8) {
13185							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13186							if (this.opts.subMenusMinWidth) {
13187							 	$sub.css('min-width', this.opts.subMenusMinWidth);
13188							}
13189							if (this.opts.subMenusMaxWidth) {
13190							 	var noMaxWidth = this.getWidth($sub);
13191							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13192								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13193							 	}
13194								if (noMaxWidth > this.getWidth($sub)) {
13195									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13196								}
13197							}
13198						// IE6,7
13199 						} else {
13200							$sub.children().css('styleFloat', 'none');
13201							if (IE6) {
13202								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
13203									.children().children('a').css('white-space', 'nowrap');
13204							} else { // IE7
13205								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13206								if (this.opts.subMenusMinWidth) {
13207									$sub.css('min-width', this.opts.subMenusMinWidth);
13208								}
13209							}
13210							if (this.opts.subMenusMaxWidth) {
13211								var noMaxWidth = $sub.width();
13212								if (IE6) {
13213							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
13214									if (noMaxWidth > maxWidth) {
13215										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
13216									} else {
13217										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
13218									}
13219								} else { // IE7
13220								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13221									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13222								 	}
13223									if (noMaxWidth > $sub.width()) {
13224										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13225									} else {
13226										$sub.width(noMaxWidth);
13227									}
13228								}
13229							} else {
13230							 	$sub.width($sub.width());
13231							}
13232							$sub.children().css('styleFloat', 'left');
13233						}
13234					}
13235					this.menuPosition($sub);
13236					// insert IE iframe shim
13237					if ($sub.dataSM('ie-shim')) {
13238						$sub.dataSM('ie-shim').insertBefore($sub);
13239					}
13240					var complete = function() {
13241						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
13242						$sub.css('overflow', '');
13243					};
13244					// if sub is collapsible (mobile view)
13245					if (this.isCollapsible()) {
13246						if (this.opts.collapsibleShowFunction) {
13247							this.opts.collapsibleShowFunction.call(this, $sub, complete);
13248						} else {
13249							$sub.show(this.opts.collapsibleShowDuration, complete);
13250						}
13251					} else {
13252						if (this.opts.showFunction) {
13253							this.opts.showFunction.call(this, $sub, complete);
13254						} else {
13255							$sub.show(this.opts.showDuration, complete);
13256						}
13257					}
13258					// save new sub menu for this level
13259					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
13260					this.$root.triggerHandler('show.smapi', $sub[0]);
13261				}
13262			},
13263			popupHide: function(noHideTimeout) {
13264				if (this.hideTimeout) {
13265					clearTimeout(this.hideTimeout);
13266					this.hideTimeout = 0;
13267				}
13268				var self = this;
13269				this.hideTimeout = setTimeout(function() {
13270					self.menuHideAll();
13271				}, noHideTimeout ? 1 : this.opts.hideTimeout);
13272			},
13273			popupShow: function(left, top) {
13274				if (!this.opts.isPopup) {
13275					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
13276					return;
13277				}
13278				if (this.hideTimeout) {
13279					clearTimeout(this.hideTimeout);
13280					this.hideTimeout = 0;
13281				}
13282				this.menuFixLayout(this.$root);
13283				this.$root.stop(true, true);
13284				if (!this.$root.is(':visible')) {
13285					this.$root.css({ left: left, top: top });
13286					// IE iframe shim
13287					this.menuIframeShim(this.$root);
13288					if (this.$root.dataSM('ie-shim')) {
13289						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
13289: left, top: top }).insertBefore(this.$root);
13290					}
13291					// show menu
13292					if (this.opts.showFunction) {
13293						this.opts.showFunction.call(this, this.$root);
13294					} else {
13295						this.$root.show(this.opts.showDuration);
13296					}
13297					this.visibleSubMenus[0] = this.$root;
13298				}
13299			},
13300			refresh: function() {
13301				this.menuHideAll();
13302				this.$root.find('ul').each(function() {
13303						var $this = $(this);
13304						if ($this.dataSM('scroll-arrows')) {
13305							$this.dataSM('scroll-arrows').remove();
13306						}
13307					})
13308					.removeDataSM('in-mega')
13309					.removeDataSM('shown-before')
13310					.removeDataSM('ie-shim')
13311					.removeDataSM('scroll-arrows')
13312					.removeDataSM('parent-a')
13313					.removeDataSM('level')
13314					.removeDataSM('beforefirstshowfired');
13315				this.$root.find('a.has-submenu').removeClass('has-submenu')
13316					.parent().removeDataSM('sub');
13317				if (this.opts.subIndicators) {
13318					this.$root.find('span.sub-arrow').remove();
13319				}
13320				if (this.opts.markCurrentItem) {
13321					this.$root.find('a.current').removeClass('current');
13322				}
13323				this.subMenus = [];
13324				this.init(true);
13325			},
13326			rootOut: function(e) {
13327				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13328					return;
13329				}
13330				if (this.hideTimeout) {
13331					clearTimeout(this.hideTimeout);
13332					this.hideTimeout = 0;
13333				}
13334				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
13335					var self = this;
13336					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
13337				}
13338			},
13339			rootOver: function(e) {
13340				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13341					return;
13342				}
13343				if (this.hideTimeout) {
13344					clearTimeout(this.hideTimeout);
13345					this.hideTimeout = 0;
13346				}
13347			},
13348			winResize: function(e) {
13349				if (!this.handleEvents()) {
13350					// we still need to resize the disable overlay if it's visible
13351					if (this.$disableOverlay) {
13352						var pos = this.$root.offset();
13353	 					this.$disableOverlay.css({
13354							top: pos.top,
13355							left: pos.left,
13356							width: this.$root.outerWidth(),
13357							height: this.$root.outerHeight()
13358						});
13359					}
13360					return;
13361				}
13362				// hide sub menus on resize - on mobile do it only on orientation change
13363				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
13364					if (this.activatedItems.length) {
13365						this.activatedItems[this.activatedItems.length - 1][0].blur();
13366					}
13367					this.menuHideAll();
13368				}
13369			}
13370		}
13371	});
13372
13373	$.fn.dataSM = function(key, val) {
13374		if (val) {
13375			return this.data(key + '_smartmenus', val);
13376		}
13377		return this.data(key + '_smartmenus');
13378	}
13379
13380	$.fn.removeDataSM = function(key) {
13381		return this.removeData(key + '_smartmenus');
13382	}
13383
13384	$.fn.smartmenus = function(options) {
13385		if (typeof options == 'string') {
13386			var args = arguments,
13387				method = options;
13388			Array.prototype.shift.call(args);
13389			return this.each(function() {
13390				var smartmenus = $(this).data('smartmenus');
13391				if (smartmenus && smartmenus[method]) {
13392					smartmenus[method].apply(smartmenus, args);
13393				}
13394			});
13395		}
13396		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
13397		return this.each(function() {
13398			new $.SmartMenus(this, opts);
13399		});
13400	}
13401
13402	// default settings
13403	$.fn.smartmenus.defaults = {
13404		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
13405		mainMenuSubOffsetX:	0,		// pixels offset from default position
13406		mainMenuSubOffsetY:	0,		// pixels offset from default position
13407		subMenusSubOffsetX:	0,		// pixels offset from default position
13408		subMenusSubOffsetY:	0,		// pixels offset from default position
13409		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13410		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13411		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
13412		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
13413		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
13414		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
13415		scrollInterval:		30,		// interval between each scrolling step
13416		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
13417		showTimeout:		250,		// timeout before showing the sub menus
13418		hideTimeout:		500,		// timeout before hiding the sub menus
13419		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
13420		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
13421							// don't forget to call complete() at the end of whatever you do
13422							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
13423		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
13424		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
13425							// don't forget to call complete() at the end of whatever you do
13426							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
13427		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
13428		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
13429							// (i.e. when mobile styles are used to make the sub menus collapsible)
13430		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
13431		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
13432							// (i.e. when mobile styles are used to make the sub menus collapsible)
13433		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
13434		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
13435		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
13436		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
13437		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
13438		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
13439		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
13440		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
13441		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
13442	};
13443
13444})(jQuery);
13445/*
13446 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
13447 * Open source under the BSD License.
13448 * Copyright © 2008 George McGinley Smith
13449 * All rights reserved.
13450 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
13451*/
13452
13453/* globals jQuery, define, module, require */
13454(function (factory) {
13455	if (typeof define === "function" && define.amd) {
13456		define(['jquery'], function ($) {
13457			return factory($);
13458		});
13459	} else if (typeof module === "object" && typeof module.exports === "object") {
13460		module.exports = factory(require('jquery'));
13461	} else {
13462		factory(jQuery);
13463	}
13464})(function($){
13465
13466	// Preserve the original jQuery "swing" easing as "jswing"
13467	if (typeof $.easing !== 'undefined') {
13468		$.easing['jswing'] = $.easing['swing'];
13469	}
13470
13471	var pow = Math.pow,
13472		sqrt = Math.sqrt,
13473		sin = Math.sin,
13474		cos = Math.cos,
13475		PI = Math.PI,
13476		c1 = 1.70158,
13477		c2 = c1 * 1.525,
13478		c3 = c1 + 1,
13479		c4 = ( 2 * PI ) / 3,
13480		c5 = ( 2 * PI ) / 4.5;
13481
13482	// x is the fraction of animation progress, in the range 0..1
13483	function bounceOut(x) {
13484		var n1 = 7.5625,
13485			d1 = 2.75;
13486		if ( x < 1/d1 ) {
13487			return n1*x*x;
13488		} else if ( x < 2/d1 ) {
13489			return n1*(x-=(1.5/d1))*x + .75;
13490		} else if ( x < 2.5/d1 ) {
13491			return n1*(x-=(2.25/d1))*x + .9375;
13492		} else {
13493			return n1*(x-=(2.625/d1))*x + .984375;
13494		}
13495	}
13496
13497	$.extend( $.easing, {
13498		def: 'easeOutQuad',
13499		swing: function (x) {
13500			return $.easing[$.easing.def](x);
13501		},
13502		easeInQuad: function (x) {
13503			return x * x;
13504		},
13505		easeOutQuad: function (x) {
13506			return 1 - ( 1 - x ) * ( 1 - x );
13507		},
13508		easeInOutQuad: function (x) {
13509			return x < 0.5 ?
13510				2 * x * x :
13511				1 - pow( -2 * x + 2, 2 ) / 2;
13512		},
13513		easeInCubic: function (x) {
13514			return x * x * x;
13515		},
13516		easeOutCubic: function (x) {
13517			return 1 - pow( 1 - x, 3 );
13518		},
13519		easeInOutCubic: function (x) {
13520			return x < 0.5 ?
13521				4 * x * x * x :
13522				1 - pow( -2 * x + 2, 3 ) / 2;
13523		},
13524		easeInQuart: function (x) {
13525			return x * x * x * x;
13526		},
13527		easeOutQuart: function (x) {
13528			return 1 - pow( 1 - x, 4 );
13529		},
13530		easeInOutQuart: function (x) {
13531			return x < 0.5 ?
13532				8 * x * x * x * x :
13533				1 - pow( -2 * x + 2, 4 ) / 2;
13534		},
13535		easeInQuint: function (x) {
13536			return x * x * x * x * x;
13537		},
13538		easeOutQuint: function (x) {
13539			return 1 - pow( 1 - x, 5 );
13540		},
13541		easeInOutQuint: function (x) {
13542			return x < 0.5 ?
13543				16 * x * x * x * x * x :
13544				1 - pow( -2 * x + 2, 5 ) / 2;
13545		},
13546		easeInSine: function (x) {
13547			return 1 - cos( x * PI/2 );
13548		},
13549		easeOutSine: function (x) {
13550			return sin( x * PI/2 );
13551		},
13552		easeInOutSine: function (x) {
13553			return -( cos( PI * x ) - 1 ) / 2;
13554		},
13555		easeInExpo: function (x) {
13556			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
13557		},
13558		easeOutExpo: function (x) {
13559			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
13560		},
13561		easeInOutExpo: function (x) {
13562			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13563				pow( 2, 20 * x - 10 ) / 2 :
13564				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
13565		},
13566		easeInCirc: function (x) {
13567			return 1 - sqrt( 1 - pow( x, 2 ) );
13568		},
13569		easeOutCirc: function (x) {
13570			return sqrt( 1 - pow( x - 1, 2 ) );
13571		},
13572		easeInOutCirc: function (x) {
13573			return x < 0.5 ?
13574				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
13575				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
13576		},
13577		easeInElastic: function (x) {
13578			return x === 0 ? 0 : x === 1 ? 1 :
13579				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
13580		},
13581		easeOutElastic: function (x) {
13582			return x === 0 ? 0 : x === 1 ? 1 :
13583				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
13584		},
13585		easeInOutElastic: function (x) {
13586			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13587				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
13588				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
13589		},
13590		easeInBack: function (x) {
13591			return c3 * x * x * x - c1 * x * x;
13592		},
13593		easeOutBack: function (x) {
13594			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
13595		},
13596		easeInOutBack: function (x) {
13597			return x < 0.5 ?
13598				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
13599				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
13600		},
13601		easeInBounce: function (x) {
13602			return 1 - bounceOut( 1 - x );
13603		},
13604		easeOutBounce: bounceOut,
13605		easeInOutBounce: function (x) {
13606			return x < 0.5 ?
13607				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
13608				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
13609		}
13610	});
13611	return $;
13612});
13613
13614/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
13615 * Licensed under the MIT License (LICENSE.txt).
13616 *
13617 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
13618 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
13619 * Thanks to: Seamus Leahy for adding deltaX and deltaY
13620 *
13621 * Version: 3.0.6
13622 *
13623 * Requires: 1.2.2+
13624 */
13625(function($) {
13626    var types = ['DOMMouseScroll', 'mousewheel'];
13627    if ($.event.fixHooks) {
13628        for (var i = types.length; i;) {
13629            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
13630        }
13631    }
13632    $.event.special.mousewheel = {
13633        setup: function() {
13634            if (this.addEventListener) {
13635                for (var i = types.length; i;) {
13636                    this.addEventListener(types[--i], handler, false);
13637                }
13638            } else {
13639                this.onmousewheel = handler;
13640            }
13641        },
13642        teardown: function() {
13643            if (this.removeEventListener) {
13644                for (var i = types.length; i;) {
13645                    this.removeEventListener(types[--i], handler, false);
13646                }
13647            } else {
13648                this.onmousewheel = null;
13649            }
13650        }
13651    };
13652    $.fn.extend({
13653        mousewheel: function(fn) {
13654            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
13655        },
13656        unmousewheel: function(fn) {
13657            return this.unbind("mousewheel", fn);
13658        }
13659    });
13660
13661    function handler(event) {
13662        var orgEvent = event || window.event,
13663            args = [].slice.call(arguments, 1),
13664            delta = 0,
13665            returnValue = true,
13666            deltaX = 0,
13667            deltaY = 0;
13668        event = $.event.fix(orgEvent);
13669        event.type = "mousewheel";
13670        // Old school scrollwheel delta
13671        if (orgEvent.wheelDelta) {
13672            delta = orgEvent.wheelDelta / 120;
13673        }
13674        if (orgEvent.detail) {
13675            delta = -orgEvent.detail / 3;
13676        }
13677        // New school multidimensional scroll (touchpads) deltas
13678        deltaY = delta;
13679        // Gecko
13680        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
13681            deltaY = 0;
13682            deltaX = -1 * delta;
13683        }
13684        // Webkit
13685        if (orgEvent.wheelDeltaY !== undefined) {
13686            deltaY = orgEvent.wheelDeltaY / 120;
13687        }
13688        if (orgEvent.wheelDeltaX !== undefined) {
13689            deltaX = -1 * orgEvent.wheelDeltaX / 120;
13690        }
13691        // Add event and delta to the front of the arguments
13692        args.unshift(event, delta, deltaX, deltaY);
13693        return ($.event.dispatch || $.event.handle).apply(this, args);
13694    }
13695})(jQuery);
13696/**
13697 * jQuery iLightBox - Revolutionary Lightbox Plugin
13698 * http://www.ilightbox.net/
13699 *
13700 * @version: 2.2.4 - October 14, 2017
13701 *
13702 * @author: iProDev (Hemn Chawroka)
13703 *          http://www.iprodev.com/
13704 *
13705 */
13706(function($, window, undefined) {
13707
13708	var extensions = {
13709			flash: ['swf'],
13710			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
13711			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
13712			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
13713		},
13714
13715		// Global DOM elements
13716		$win = $(window),
13717		$doc = $(document),
13718
13719		// Support indicators
13720		browser,
13721		transform,
13722		gpuAcceleration,
13723		fullScreenApi = '',
13724		userAgent = navigator.userAgent || navigator.vendor || window.opera,
13725        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
13726        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
13727        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)),
13728
13729		// Events
13730		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
13731		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
13732		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
13733		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
13734
13735		// Math shorthands
13736		abs = Math.abs,
13737		sqrt = Math.sqrt,
13738		round = Math.round,
13739		max = Math.max,
13740		min = Math.min,
13741		floor = Math.floor,
13742		random = Math.random,
13743
13744		pluginspages = {
13745			quicktime: 'http://www.apple.com/quicktime/download',
13746			flash: 'http://www.adobe.com/go/getflash'
13747		},
13748
13749		iLightBox = function(el, options, items, instant) {
13750			var iL = this;
13751
13752			iL.options = options,
13753				iL.selector = options.selector || el,
13754				iL.context = document,
13755				iL.instant = instant;
13756
13757			if (items.length < 1) iL.attachItems();
13758			else iL.items = items;
13759
13760			iL.vars = {
13761				total: iL.items.length,
13762				start: 0,
13763				current: null,
13764				next: null,
13765				prev: null,
13766				BODY: $('body'),
13767				loadRequests: 0,
13768				overlay: $('<div class="ilightbox-overlay"></div>'),
13769				loader: $('<div class="ilightbox-loader"><div></div></div>'),
13770				toolbar: $('<div class="ilightbox-toolbar"></div>'),
13771				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
13772				title: $('<div class="ilightbox-title"></div>'),
13773				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
13774				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
13775				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
13776				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
13777				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
13778				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13779				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13780				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13781				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
13782				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13783				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>'),
13784				thumbs: false,
13785				nextLock: false,
13786				prevLock: false,
13787				hashLock: false,
13788				isMobile: false,
13789				mobileMaxWidth: 980,
13790				isInFullScreen: false,
13791				isSwipe: false,
13792				mouseID: 0,
13793				cycleID: 0,
13794				isPaused: 0,
13795				captionHeight: 39,
13796			};
13797
13798			// Hideable elements with mousemove event
13799			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
13800
13801			iL.normalizeItems();
13802
13803			//Check necessary plugins
13804			iL.availPlugins();
13805
13806			//Set startFrom
13807			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
13808
13809			//If randomStart
13810			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
13811			iL.vars.start = iL.options.startFrom;
13812
13813			if (instant) iL.instantCall();
13814			else iL.patchItemsEvents();
13815
13816			if (iL.options.linkId) {
13817				iL.hashChangeHandler();
13818				$win.iLightBoxHashChange(function() {
13819					iL.hashChangeHandler();
13820				});
13821			}
13822
13823			if (supportTouch) {
13824				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
13825					replace = "itap";
13826				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
13827					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
13828					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
13829					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
13830			}
13831
13832			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
13833				$.extend(iL.options.styles, {
13834					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13835					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13836					nextOpacity: 0,
13837					prevOpacity: 0
13838				});
13839			}
13840		};
13841
13842	//iLightBox helpers
13843	iLightBox.prototype = {
13844		showLoader: function() {
13845			var iL = this;
13846			iL.vars.loadRequests += 1;
13847			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
13848				//top: '-30px'
13849				opacity: '1'
13850			}, iL.options.show.speed, 'easeOutCirc');
13851			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
13852				//left: '-30px'
13853				opacity: '1'
13854			}, iL.options.show.speed, 'easeOutCirc');
13855		},
13856
13857		hideLoader: function() {
13858			var iL = this;
13859			iL.vars.loadRequests -= 1;
13860			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
13861			if (iL.options.path.toLowerCase() == "horizontal") {
13862				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13863					//top: '-192px'
13864					opacity: '0'
13865				}, iL.options.show.speed, 'easeInCirc');
13866			} else {
13867				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13868					//left: '-192px'
13869					opacity: '0'
13870				}, iL.options.show.speed, 'easeInCirc');
13871			}
13872		},
13873
13874		createUI: function() {
13875			var iL = this;
13876
13877			iL.ui = {
13878				currentElement: iL.vars.holder,
13879				nextElement: iL.vars.nextPhoto,
13880				prevElement: iL.vars.prevPhoto,
13881				currentItem: iL.vars.current,
13882				nextItem: iL.vars.next,
13883				prevItem: iL.vars.prev,
13884				hide: function() {
13885					iL.closeAction();
13886				},
13887				refresh: function() {
13888					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13889				},
13890				fullscreen: function() {
13891					iL.fullScreenAction();
13892				}
13893			};
13894		},
13895
13896		attachItems: function() {
13897			var iL = this,
13898				itemsObject = new Array(),
13899				items = new Array();
13900
13901			$(iL.selector, iL.context).each(function() {
13902				var t = $(this),
13903					URL = t.attr(iL.options.attr) || null,
13904					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
13905					caption = t.data('caption'),
13906					title = t.data('title'),
13907					type = t.data('type') || getTypeByExtension(URL),
13908					clone = t.data('lbox-clone') || false;
13909
13910				//Uncode addition ##START##
13911				if (type === false) {
13912					return;
13913				}
13914				//Uncode addition ##END##
13915
13916				if (t.data('lbox-clone') != undefined) return;
13917
13918				//Uncode addition ##START##
13919				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
13920					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
13921						URL_i,
13922						URLS_LENGHT = ALBUM_URLS.length;
13923
13924					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
13925						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
13926							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
13927							item_opts = item_opts && eval("({" + item_opts + "})") || {},
13928							items.push({
13929								URL: ALBUM_URLS[URL_i].url,
13930								caption: ALBUM_URLS[URL_i].caption,
13931								title: ALBUM_URLS[URL_i].title,
13932								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
13933								options: item_opts,
13934								clone: clone
13935							});
13936							var newT = t;
13937							newT.attr('href',ALBUM_URLS[URL_i].url);
13938							if (!iL.instant) itemsObject.push(newT);
13939						}
13940					}
13941				} else {
13942				//Uncode addition ##END##
13943					items.push({
13944						URL: URL,
13945						caption: caption,
13946						title: title,
13947						type: type,
13948						options: options,
13949						clone: clone
13950					});
13951				}
13952
13953
13954				if (iL.vars != undefined) iL.vars.total = items.length;
13955
13956				if (!iL.instant) itemsObject.push(t);
13957			});
13958
13959			iL.items = items,
13960				iL.itemsObject = itemsObject;
13961
13962		},
13963
13964		normalizeItems: function() {
13965			var iL = this,
13966				newItems = new Array();
13967
13968			$.each(iL.items, function(key, val) {
13969
13970				if (typeof val == "string") val = {
13971					url: val
13972				};
13973
13974				var URL = val.url || val.URL || null,
13975					options = val.options || {},
13976					caption = val.caption || null,
13977					title = val.title || null,
13978					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
13979					ext = (typeof URL != 'object') ? getExtension(URL) : '';
13980
13981				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
13982				options.videoType = options.videoType || null,
13983				options.skin = options.skin || iL.options.skin,
13984				options.width = options.width || null,
13985				options.height = options.height || null,
13986				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
13987				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
13988				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
13989
13990				if (type == "video") {
13991					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
13992
13993					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
13994					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
13995					options.html5video.preload = options.html5video.preload || "metadata";
13996					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
13997					//UNCODE addition
13998					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
13999				}
14000
14001				if (!options.width || !options.height) {
14002					if (type == "video") options.width = 1280, options.height = 720;
14003					else if (type == "iframe") options.width = '100%', options.height = '90%';
14004					else if (type == "flash") options.width = 1280, options.height = 720;
14005				}
14006
14007				delete val.url;
14008				val.index = key;
14009				val.URL = URL;
14010				val.caption = caption;
14011				val.title = title;
14012				val.type = type;
14013				val.options = options;
14014				val.ext = ext;
14015
14016				newItems.push(val);
14017			});
14018
14019			iL.items = newItems;
14020		},
14021
14022		instantCall: function() {
14023			var iL = this,
14024				key = iL.vars.start;
14025
14026			iL.vars.current = key;
14027			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
14028			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
14029
14030			iL.addContents();
14031			iL.patchEvents();
14032		},
14033
14034		addContents: function() {
14035			var iL = this,
14036				vars = iL.vars,
14037				opts = iL.options,
14038				viewport = getViewport(),
14039				path = opts.path.toLowerCase(),
14040				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
14041					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
14042				}),
14043				needRecognition = recognizingItems.length > 0;
14044
14045			if (opts.mobileOptimizer && !opts.innerToolbar)
14046				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14047
14048			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
14049
14050			if (opts.linkId)
14051				vars.overlay[0].setAttribute('linkid', opts.linkId);
14052
14053			//Add Toolbar Buttons
14054			if (opts.controls.toolbar) {
14055				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
14056				if (opts.controls.fullscreen)
14057					vars.toolbar.append(vars.fullScreenButton);
14058				if (opts.controls.slideshow)
14059					vars.toolbar.append(vars.innerPlayButton);
14060				if (vars.total > 1)
14061					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
14062			}
14063
14064			//Append elements to body
14065			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
14066
14067			if (!opts.innerToolbar)
14068				vars.BODY.append(vars.toolbar);
14069			if (opts.controls.arrows)
14070				vars.BODY.append(vars.nextButton).append(vars.prevButton);
14071
14072			if (opts.controls.thumbnail && vars.total > 1) {
14073				vars.BODY.append(vars.thumbnails);
14074				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
14075				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
14076				vars.thumbs = true;
14077			}
14078
14079			//Configure loader and arrows
14080			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
14081				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
14082			} : {
14083				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
14084			};
14085			vars.loader.addClass(opts.skin).css(loaderCss);
14086			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
14087			if (path == "horizontal")
14088				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
14089
14090			// Configure arrow buttons
14091			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14092
14093			if (!opts.infinite) {
14094				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14095
14096				if (vars.current == 0)
14097					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14098				if (vars.current >= vars.total - 1)
14099					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14100			}
14101
14102			if (opts.show.effect) {
14103				vars.overlay.stop().fadeIn(opts.show.speed);
14104				vars.toolbar.stop().fadeIn(opts.show.speed);
14105			} else {
14106				vars.overlay.show();
14107				vars.toolbar.show();
14108			}
14109
14110			var length = recognizingItems.length;
14111			if (needRecognition) {
14112				iL.showLoader();
14113
14114				$.each(recognizingItems, function(key, val) {
14115					var resultFnc = function(result) {
14116							var key = -1,
14117								filter = iL.items.filter(function(e, i, arr) {
14118									if (e.URL == result.url)
14119										key = i;
14120
14121									return e.URL == result.url;
14122								}),
14123								self = iL.items[key];
14124
14125							if (result)
14126								$.extend(true, self, {
14127									URL: result.source,
14128									type: result.type,
14129									recognized: true,
14130									options: {
14131										html5video: result.html5video,
14132										width: (result.type == "image") ? 0 : (result.width || self.width),
14133										height: (result.type == "image") ? 0 : (result.height || self.height),
14134										thumbnail: self.options.thumbnail || result.thumbnail
14135									}
14136								});
14137
14138							length--;
14139
14140							if (length == 0) {
14141								iL.hideLoader();
14142
14143								vars.dontGenerateThumbs = false;
14144								iL.generateThumbnails();
14145
14146								if (opts.show.effect)
14147									setTimeout(function() {
14148										iL.generateBoxes();
14149									}, opts.show.speed);
14150								else
14151									iL.generateBoxes();
14152							}
14153						};
14154
14155					iL.ogpRecognition(this, resultFnc);
14156				});
14157			}
14158			else {
14159				if (opts.show.effect)
14160					setTimeout(function() {
14161						iL.generateBoxes();
14162					}, opts.show.speed);
14163				else
14164					iL.generateBoxes();
14165			}
14166
14167			iL.createUI();
14168
14169			window.iLightBox = {
14170				close: function() {
14171					iL.closeAction();
14172				},
14173				fullscreen: function() {
14174					iL.fullScreenAction();
14175				},
14176				moveNext: function() {
14177					iL.moveTo('next');
14178				},
14179				movePrev: function() {
14180					iL.moveTo('prev');
14181				},
14182				goTo: function(index) {
14183					iL.goTo(index);
14184				},
14185				refresh: function() {
14186					iL.refresh();
14187				},
14188				reposition: function() {
14189					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
14190				},
14191				setOption: function(options) {
14192					iL.setOption(options);
14193				},
14194				destroy: function() {
14195					iL.closeAction();
14196					iL.dispatchItemsEvents();
14197				}
14198			};
14199
14200			if (opts.linkId) {
14201				vars.hashLock = true;
14202				window.location.hash = opts.linkId + '/' + vars.current;
14203				setTimeout(function() {
14204					vars.hashLock = false;
14205				}, 55);
14206			}
14207
14208			if (!opts.slideshow.startPaused) {
14209				iL.resume();
14210				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
14211			}
14212
14213			//Trigger the onOpen callback
14214			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
14215		},
14216
14217		loadContent: function(obj, opt, speed) {
14218			var iL = this,
14219				holder, item;
14220
14221			iL.createUI();
14222
14223			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
14224
14225			if (opt == 'current') {
14226				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
14227				else iL.vars.lockWheel = false;
14228
14229				if (!obj.options.swipe) iL.vars.lockSwipe = true;
14230				else iL.vars.lockSwipe = false;
14231			}
14232
14233			switch (opt) {
14234				case 'current':
14235					holder = iL.vars.holder, item = iL.vars.current;
14236					break;
14237				case 'next':
14238					holder = iL.vars.nextPhoto, item = iL.vars.next;
14239					break;
14240				case 'prev':
14241					holder = iL.vars.prevPhoto, item = iL.vars.prev;
14242					break;
14243			}
14244
14245			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
14246			$('div.ilightbox-inner-toolbar', holder).remove();
14247
14248			if (obj.title || iL.options.innerToolbar) {
14249				var innerToolbar = iL.vars.innerToolbar.clone();
14250				if (obj.title && iL.options.show.title) {
14251					var title = iL.vars.title.clone();
14252					title.empty().html(obj.title);
14253					innerToolbar.append(title);
14254				}
14255				if (iL.options.innerToolbar) {
14256					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
14257				}
14258				holder.prepend(innerToolbar);
14259			}
14260
14261			//console.warn('loadContent', arguments);
14262
14263			iL.loadSwitcher(obj, holder, item, opt);
14264		},
14265
14266		loadSwitcher: function(obj, holder, item, opt) {
14267			var iL = this,
14268				opts = iL.options,
14269				api = {
14270					element: holder,
14271					position: item
14272				};
14273
14274			switch (obj.type) {
14275				case 'image':
14276					//Trigger the onBeforeLoad callback
14277					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14278					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14279
14280					iL.loadImage(obj.URL, function(img) {
14281						//Trigger the onAfterLoad callback
14282						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14283						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14284
14285						var width = (img) ? img.width : 400,
14286							height = (img) ? img.height : 200;
14287
14288						holder.data({
14289							naturalWidth: width,
14290							naturalHeight: height
14291						});
14292
14293						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
14294
14295						//Trigger the onRender callback
14296						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14297						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14298
14299						iL.configureHolder(obj, opt, holder);
14300					});
14301
14302					break;
14303
14304				case 'video':
14305					holder.data({
14306						naturalWidth: obj.options.width,
14307						naturalHeight: obj.options.height
14308					});
14309
14310					if (opt === 'current') {
14311						iL.addContent(holder, obj);
14312
14313						//Trigger the onRender callback
14314						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14315						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14316					} else {
14317						$('div.ilightbox-container', holder).empty();
14318					}
14319
14320					iL.configureHolder(obj, opt, holder);
14321
14322					break;
14323
14324				case 'iframe':
14325					//iL.showLoader();
14326					holder.data({
14327						naturalWidth: obj.options.width,
14328						naturalHeight: obj.options.height
14329					});
14330
14331					iL.configureHolder(obj, opt, holder);
14332
14333					if (opt === 'current') {
14334						var el = iL.addContent(holder, obj);
14335
14336						//Trigger the onRender callback
14337						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14338						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14339
14340						//Trigger the onBeforeLoad callback
14341						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14342						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14343
14344						el.bind('load', function() {
14345							//Trigger the onAfterLoad callback
14346							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14347							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14348
14349							//iL.hideLoader();
14350							el.unbind('load');
14351						});
14352					} else {
14353						$('div.ilightbox-container', holder).empty();
14354					}
14355
14356					break;
14357
14358				case 'inline':
14359					var el = $(obj.URL),
14360						content = iL.addContent(holder, obj),
14361						images = findImageInElement(holder);
14362
14363					holder.data({
14364						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14365						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14366					});
14367					content.children().eq(0).show();
14368
14369					//Trigger the onRender callback
14370					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14371					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14372
14373					//Trigger the onBeforeLoad callback
14374					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14375					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14376
14377					iL.loadImage(images, function() {
14378						//Trigger the onAfterLoad callback
14379						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14380						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14381
14382						iL.configureHolder(obj, opt, holder);
14383					});
14384
14385					break;
14386
14387				case 'flash':
14388					var el = iL.addContent(holder, obj);
14389
14390					holder.data({
14391						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14392						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14393					});
14394
14395					//Trigger the onRender callback
14396					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14397					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14398
14399					iL.configureHolder(obj, opt, holder);
14400
14401					break;
14402
14403				case 'ajax':
14404					var ajax = obj.options.ajax || {};
14405					//Trigger the onBeforeLoad callback
14406					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14407					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14408
14409					iL.showLoader();
14410					$.ajax({
14411						url: obj.URL || opts.ajaxSetup.url,
14412						data: ajax.data || null,
14413						dataType: ajax.dataType || "html",
14414						type: ajax.type || opts.ajaxSetup.type,
14415						cache: ajax.cache || opts.ajaxSetup.cache,
14416						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
14417						global: ajax.global || opts.ajaxSetup.global,
14418						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
14419						username: ajax.username || opts.ajaxSetup.username,
14420						password: ajax.password || opts.ajaxSetup.password,
14421						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
14422						complete: ajax.complete || opts.ajaxSetup.complete,
14423						success: function(data, textStatus, jqXHR) {
14424							iL.hideLoader();
14425
14426							var el = $(data),
14427								container = $('div.ilightbox-container', holder),
14428								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
14429								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
14430								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
14431									'overflow': 'hidden'
14432								} : {};
14433
14434							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
14435							holder.show().data({
14436								naturalWidth: (elWidth || container.outerWidth()),
14437								naturalHeight: (elHeight || container.outerHeight())
14438							}).hide();
14439
14440							//Trigger the onRender callback
14441							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14442							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14443
14444							var images = findImageInElement(holder);
14445							iL.loadImage(images, function() {
14446								//Trigger the onAfterLoad callback
14447								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14448								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14449
14450								iL.configureHolder(obj, opt, holder);
14451							});
14452
14453							opts.ajaxSetup.success(data, textStatus, jqXHR);
14454							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
14455						},
14456						error: function(jqXHR, textStatus, errorThrown) {
14457							//Trigger the onAfterLoad callback
14458							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14459							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14460
14461							iL.hideLoader();
14462							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
14463							iL.configureHolder(obj, opt, holder);
14464
14465							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
14466							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
14467						}
14468					});
14469
14470					break;
14471
14472				case 'html':
14473					var object = obj.URL,
14474						el
14475					container = $('div.ilightbox-container', holder);
14476
14477					if (object[0].nodeName) el = object.clone();
14478					else {
14479						var dom = $(object);
14480						if (dom.selector) el = $('<div>' + dom + '</div>');
14481						else el = dom;
14482					}
14483
14484					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
14485						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
14486
14487					iL.addContent(holder, obj);
14488
14489					el.appendTo(document.documentElement).hide();
14490
14491					//Trigger the onRender callback
14492					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14493					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14494
14495					var images = findImageInElement(holder);
14496
14497					//Trigger the onBeforeLoad callback
14498					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14499					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14500
14501					iL.loadImage(images, function() {
14502						//Trigger the onAfterLoad callback
14503						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14504						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14505
14506						holder.show().data({
14507							naturalWidth: (elWidth || container.outerWidth()),
14508							naturalHeight: (elHeight || container.outerHeight())
14509						}).hide();
14510						el.remove();
14511
14512						iL.configureHolder(obj, opt, holder);
14513					});
14514
14515					break;
14516			}
14517		},
14518
14519		configureHolder: function(obj, opt, holder) {
14520			var iL = this,
14521				vars = iL.vars,
14522				opts = iL.options;
14523
14524			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
14525
14526			if (opt == "current")
14527				var item = vars.current;
14528			else if (opt == "next")
14529				var opacity = opts.styles.nextOpacity,
14530					item = vars.next;
14531			else
14532				var opacity = opts.styles.prevOpacity,
14533					item = vars.prev;
14534
14535			var api = {
14536				element: holder,
14537				position: item
14538			};
14539
14540			iL.items[item].options.width = iL.items[item].options.width || 0,
14541			iL.items[item].options.height = iL.items[item].options.height || 0;
14542
14543			if (opt == "current") {
14544				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
14545					holder.css(transform, '');
14546					if (obj.caption) {
14547						iL.setCaption(obj, holder);
14548						var caption = $('div.ilightbox-caption', holder),
14549							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
14550						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
14550Speed);
14551					}
14552
14553					var social = obj.options.social;
14554					if (social) {
14555						iL.setSocial(social, obj.URL, holder);
14556						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
14557					}
14558
14559					//Generate thumbnails
14560					iL.generateThumbnails();
14561
14562					//Trigger the onShow callback
14563					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14564					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14565				});
14566				else {
14567					holder.show();
14568
14569					//Generate thumbnails
14570					iL.generateThumbnails();
14571
14572					//Trigger the onShow callback
14573					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14574					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14575				}
14576			} else {
14577				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
14578					if (opt == "next") vars.nextLock = false;
14579					else vars.prevLock = false;
14580
14581					//Generate thumbnails
14582					iL.generateThumbnails();
14583
14584					//Trigger the onShow callback
14585					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14586					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14587				});
14588				else {
14589					holder.css({
14590						opacity: opacity
14591					}).show();
14592					if (opt == "next") vars.nextLock = false;
14593					else vars.prevLock = false;
14594
14595					//Generate thumbnails
14596					iL.generateThumbnails();
14597
14598					//Trigger the onShow callback
14599					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14600					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14601				}
14602			}
14603
14604			setTimeout(function() {
14605				iL.repositionPhoto();
14606			}, 0);
14607		},
14608
14609		generateBoxes: function() {
14610			var iL = this,
14611				vars = iL.vars,
14612				opts = iL.options;
14613
14614			if (opts.infinite && vars.total >= 3) {
14615				if (vars.current == vars.total - 1) vars.next = 0;
14616				if (vars.current == 0) vars.prev = vars.total - 1;
14617			} else opts.infinite = false;
14618
14619			//UNCODE addition
14620			if ( typeof iL.items[vars.current] == 'undefined' )
14621				vars.current = 0;
14622
14623			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
14624
14625			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
14626			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
14627		},
14628
14629		generateThumbnails: function() {
14630			var iL = this,
14631				vars = iL.vars,
14632				opts = iL.options,
14633				timeOut = null;
14634
14635			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
14636				var thumbnails = vars.thumbnails,
14637					container = $('div.ilightbox-thumbnails-container', thumbnails),
14638					grid = $('div.ilightbox-thumbnails-grid', container),
14639					i = 0;
14640
14641				grid.removeAttr('style').empty();
14642
14643				$.each(iL.items, function(key, val) {
14644					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
14645						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
14646						thumb = val.options.thumbnail,
14647						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
14648						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
14649
14650					thumbnail.css({
14651						opacity: 0
14652					}).addClass(isActive);
14653
14654					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
14655						icon.addClass('ilightbox-thumbnail-video');
14656						thumbnail.append(icon);
14657					} else if (val.options.icon) {
14658						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
14659						thumbnail.append(icon);
14660					}
14661
14662					if (thumb) iL.loadImage(thumb, function(img) {
14663						i++;
14664						if (img) thumbnail.data({
14665							naturalWidth: img.width,
14666							naturalHeight: img.height
14667						}).append('<img src="' + thumb + '" border="0" />');
14668						else thumbnail.data({
14669							naturalWidth: opts.thumbnails.maxWidth,
14670							naturalHeight: opts.thumbnails.maxHeight
14671						});
14672
14673						clearTimeout(timeOut);
14674						timeOut = setTimeout(function() {
14675							iL.positionThumbnails(thumbnails, container, grid);
14676						}, 20);
14677						setTimeout(function() {
14678							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
14679						}, i * 20);
14680					});
14681
14682					grid.append(thumbnail);
14683				});
14684				iL.vars.dontGenerateThumbs = true;
14685			}
14686		},
14687
14688		positionThumbnails: function(thumbnails, container, grid) {
14689			var iL = this,
14690				vars = iL.vars,
14691				opts = iL.options,
14692				viewport = getViewport(),
14693				path = opts.path.toLowerCase();
14694
14695			if (!thumbnails) thumbnails = vars.thumbnails;
14696			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
14697			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
14698
14699			var thumbs = $('.ilightbox-thumbnail', grid),
14700				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
14701				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
14702				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
14703				gridHeight = (path == 'horizontal') ? heightAvail : 0,
14704				active = $('.ilightbox-active', grid),
14705				gridCss = {},
14706				css = {};
14707
14708			if (arguments.length < 3) {
14709				thumbs.css({
14710					opacity: opts.thumbnails.normalOpacity
14711				});
14712				active.css({
14713					opacity: opts.thumbnails.activeOpacity
14714				});
14715			}
14716
14717			thumbs.each(function(i) {
14718				var t = $(this),
14719					data = t.data(),
14720					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
14721				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
14722				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
14723
14724				t.css({
14725					width: dims.width,
14726					height: dims.height
14727				});
14728				if (path == 'horizontal') t.css({
14729					'float': 'left'
14730				});
14731
14732				(path == 'horizontal') ? (
14733					gridWidth += t.outerWidth()
14734				) : (
14735					gridHeight += t.outerHeight()
14736				);
14737			});
14738
14739			gridCss = {
14740				width: gridWidth,
14741				height: gridHeight
14742			};
14743
14744			grid.css(gridCss);
14745
14746			gridCss = {};
14747
14748			var gridOffset = grid.offset(),
14749				activeOffset = (active.length) ? active.offset() : {
14750					top: parseInt(heightAvail / 2),
14751					left: parseInt(widthAvail / 2)
14752				};
14753
14754			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
14755				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
14756				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
14757				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
14758
14759			(path == 'horizontal') ? (
14760				gridCss.top = 0,
14761				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
14762			) : (
14763				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
14764				gridCss.left = 0
14765			);
14766
14767			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
14768			else grid.css(gridCss);
14769		},
14770
14771		loadImage: function(image, callback) {
14772			if (!$.isArray(image)) image = [image];
14773
14774			var iL = this,
14775				length = image.length;
14776
14777			if (length > 0) {
14778				iL.showLoader();
14779				$.each(image, function(index, value) {
14780					var img = new Image();
14781					img.onload = function() {
14782						length -= 1;
14783						if (length == 0) {
14784							iL.hideLoader();
14785							callback(img);
14786						}
14787					};
14788					img.onerror = img.onabort = function() {
14789						length -= 1;
14790						if (length == 0) {
14791							iL.hideLoader();
14792							callback(false);
14793						}
14794					};
14795					img.src = image[index];
14796				});
14797			} else callback(false);
14798		},
14799
14800		patchItemsEvents: function() {
14801			var iL = this,
14802				vars = iL.vars,
14803				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
14804				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
14805
14806			if (iL.context && iL.selector) {
14807				var $items = $(iL.selector, iL.context);
14808
14809				$(iL.context).on(clickEvent, iL.selector, function() {
14810					var $this = $(this),
14811						//UNCODE addition
14812						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
14813					if (UNCODE.isMobile) {
14814						var isCarousel = $this.closest('.owl-carousel');
14815						if (isCarousel.length) {
14816							if (isCarousel.hasClass('owl-translating')) return false;
14817						}
14818					}
14819
14820					vars.current = key;
14821					vars.next = iL.items[key + 1] ? key + 1 : null;
14822					vars.prev = iL.items[key - 1] ? key - 1 : null;
14823
14824					//UNCODE addition
14825					if ( vars.BODY.hasClass('fp-slide-scrolling') )
14826						return false;
14827
14828					iL.addContents();
14829					iL.patchEvents();
14830
14831					return false;
14832				}).on(vEvent, iL.selector, function() {
14833					return false;
14834				});
14835			} else
14836				$.each(iL.itemsObject, function(key, val) {
14837					val.on(clickEvent, function() {
14838						vars.current = key;
14839						vars.next = iL.items[key + 1] ? key + 1 : null;
14840						vars.prev = iL.items[key - 1] ? key - 1 : null;
14841
14842						iL.addContents();
14843						iL.patchEvents();
14844
14845						return false;
14846					}).on(vEvent, function() {
14847						return false;
14848					});
14849				});
14850		},
14851
14852		dispatchItemsEvents: function() {
14853			var iL = this,
14854				vars = iL.vars,
14855				opts = iL.options;
14856
14857			if (iL.context && iL.selector)
14858				$(iL.context).off('.iL', iL.selector);
14859			else
14860				$.each(iL.itemsObject, function(key, val) {
14861					val.off('.iL');
14862				});
14863		},
14864
14865		refresh: function() {
14866			var iL = this;
14867
14868			iL.dispatchItemsEvents();
14869			iL.attachItems();
14870			iL.normalizeItems();
14871			iL.patchItemsEvents();
14872		},
14873
14874		patchEvents: function() {
14875			var iL = this,
14876				vars = iL.vars,
14877				opts = iL.options,
14878				path = opts.path.toLowerCase(),
14879				holders = $('.ilightbox-holder'),
14880				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
14881				durationThreshold = 1000,
14882				horizontalDistanceThreshold =
14883				verticalDistanceThreshold = 100,
14884				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
14885
14886			$win.bind('resize.iLightBox', function() {
14887				var viewport = getViewport();
14888
14889				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14890				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14891
14892				iL.repositionPhoto(null);
14893				if (supportTouch) {
14894					clearTimeout(vars.setTime);
14895					vars.setTime = setTimeout(function() {
14896						var scrollTop = getScrollXY().y;
14897						window.scrollTo(0, scrollTop - 30);
14898						window.scrollTo(0, scrollTop + 30);
14899						window.scrollTo(0, scrollTop);
14900					}, 2000);
14901				}
14902				if (vars.thumbs) iL.positionThumbnails();
14903			}).bind('keydown.iLightBox', function(event) {
14904				if (opts.controls.keyboard) {
14905					switch (event.keyCode) {
14906						case 13:
14907							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
14908							break;
14909						case 27:
14910							if (opts.keyboard.esc) iL.closeAction();
14911							break;
14912						case 37:
14913							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
14914							break;
14915						case 38:
14916							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
14917							break;
14918						case 39:
14919							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
14920							break;
14921						case 40:
14922							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
14923							break;
14924					}
14925				}
14926			});
14927
14928			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
14929				iL.doFullscreen();
14930			});
14931
14932			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
14933					return arr.lastIndexOf(e) === i;
14934				}),
14935				holderEvents = "";
14936
14937			$.each(holderEventsArr, function(key, val) {
14938				if (key != 0) holderEvents += ' ';
14939				holderEvents += val;
14940			});
14941
14942			$doc.on(clickEvent, '.ilightbox-overlay', function() {
14943				if (opts.overlay.blur) iL.closeAction();
14944			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
14945				iL.moveTo('next');
14946			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
14947				iL.moveTo('prev');
14948			}).on(clickEvent, '.ilightbox-thumbnail', function() {
14949				var t = $(this),
14950					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
14951					index = thumbs.index(t);
14952
14953				if (index != vars.current) iL.goTo(index);
14954			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14955				var caption = $('div.ilightbox-caption', vars.holder),
14956					social = $('div.ilightbox-social', vars.holder),
14957					fadeSpeed = opts.effects.fadeSpeed;
14958
14959				if (vars.nextLock || vars.prevLock) {
14960					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
14961					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
14962
14963					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
14964					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
14965				} else {
14966					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
14967					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
14968
14969					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
14970					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
14971				}
14972			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
14973				if (e.type == 'mouseenter') vars.lockWheel = true;
14974				else vars.lockWheel = false;
14975			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
14976				var t = $(this);
14977
14978				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
14979				else if (t.hasClass('ilightbox-play')) {
14980					iL.resume();
14981					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
14982				} else if (t.hasClass('ilightbox-pause')) {
14983					iL.pause();
14984					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
14985				} else iL.closeAction();
14986			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
14987				// prevent scrolling
14988				e.preventDefault();
14989			});
14990
14991			function mouseMoveHandler(e) {
14992				if (!vars.isMobile) {
14993					if (!vars.mouseID) {
14994						vars.hideableElements.show();
14995					}
14996
14997					vars.mouseID = clearTimeout(vars.mouseID);
14998
14999					if (buttonsArray.indexOf(e.target) === -1)
15000						vars.mouseID = setTimeout(function() {
15001							vars.hideableElements.hide();
15002							vars.mouseID = clearTimeout(vars.mouseID);
15003						}, 3000);
15004				}
15005			}
15006
15007			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
15008
15009			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15010				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
15011				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
15012			});
15013
15014			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
15015				delay = false;
15016
15017			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
15018				event.preventDefault();
15019				if (delay) return;
15020				delay = true;
15021				if (!vars.lockWheel) {
15022					event.preventDefault();
15023					if (delta < 0) {
15024						iL.moveTo('next');
15025					} else if (delta > 0) {
15026						iL.moveTo('prev');
15027					}
15028				}
15029				setTimeout(function(){
15030					delay = false;
15031				}, 2000);
15032			});
15033
15034			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
15035				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
15036
15037				vars.BODY.addClass('ilightbox-closedhand');
15038
15039				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
15040					scrollTop = $doc.scrollTop(),
15041					scrollLeft = $doc.scrollLeft(),
15042					offsets = [
15043						holders.eq(0).offset(),
15044						holders.eq(1).offset(),
15045						holders.eq(2).offset()
15046					],
15047					offSet = [{
15048						top: offsets[0].top - scrollTop,
15049						left: offsets[0].left - scrollLeft
15050					}, {
15051						top: offsets[1].top - scrollTop,
15052						left: offsets[1].left - scrollLeft
15053					}, {
15054						top: offsets[2].top - scrollTop,
15055						left: offsets[2].left - scrollLeft
15056					}],
15057					start = {
15058						time: (new Date()).getTime(),
15059						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15060					},
15061					stop;
15062
15063				function moveEachHandler(i) {
15064					var t = $(this),
15065						offset = offSet[i],
15066						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
15067
15068					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
15069				}
15070
15071				function moveHandler(event) {
15072
15073					if (!start) return;
15074
15075					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
15076
15077					stop = {
15078						time: (new Date()).getTime(),
15079						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15080					};
15081
15082					holders.each(moveEachHandler);
15083
15084					// prevent scrolling
15085					event.preventDefault();
15086				}
15087
15088				function repositionHolders() {
15089					holders.each(function() {
15090						var t = $(this),
15091							offset = t.data('offset') || {
15092								top: t.offset().top - scrollTop,
15093								left: t.offset().left - scrollLeft
15094							},
15095							top = offset.top,
15096							left = offset.left;
15097
15098						t.css(transform, gpuAcceleration).stop().animate({
15099							top: top,
15100							left: left
15101						}, 500, 'easeOutCirc', function() {
15102							t.css(transform, '');
15103						});
15104					});
15105				}
15106
15107				holders.bind(touchMoveEvent, moveHandler);
15108				$doc.one(touchStopEvent, function(event) {
15109					holders.unbind(touchMoveEvent, moveHandler);
15110
15111					vars.BODY.removeClass('ilightbox-closedhand');
15112
15113					if (start && stop) {
15114						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
15115							if (start.coords[0] > stop.coords[0]) {
15116								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15117								else {
15118									vars.isSwipe = true;
15119									iL.moveTo('next');
15120								}
15121							} else {
15122								if (vars.current == 0 && !opts.infinite) repositionHolders();
15123								else {
15124									vars.isSwipe = true;
15125									iL.moveTo('prev');
15126								}
15127							}
15128						} 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) {
15129							if (start.coords[1] > stop.coords[1]) {
15130								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15131								else {
15132									vars.isSwipe = true;
15133									iL.moveTo('next');
15134								}
15135							} else {
15136								if (vars.current == 0 && !opts.infinite) repositionHolders();
15137								else {
15138									vars.isSwipe = true;
15139									iL.moveTo('prev');
15140								}
15141							}
15142						} else repositionHolders();
15143					}
15144					start = stop = undefined;
15145				});
15146			});
15147
15148		},
15149
15150		goTo: function(index) {
15151			var iL = this,
15152				vars = iL.vars,
15153				opts = iL.options,
15154				diff = (index - vars.current);
15155
15156			if (opts.infinite) {
15157				if (index == vars.total - 1 && vars.current == 0) diff = -1;
15158				if (vars.current == vars.total - 1 && index == 0) diff = 1;
15159			}
15160
15161			if (diff == 1) iL.moveTo('next');
15162			else if (diff == -1) iL.moveTo('prev');
15163			else {
15164
15165				if (vars.nextLock || vars.prevLock) return false;
15166
15167				//Trigger the onBeforeChange callback
15168				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
15169
15170				if (opts.linkId) {
15171					vars.hashLock = true;
15172					window.location.hash = opts.linkId + '/' + index;
15173				}
15174
15175				if (iL.items[index]) {
15176					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
15177					else iL.vars.lockWheel = false;
15178
15179					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
15180					else vars.lockSwipe = false;
15181				}
15182
15183				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
15184					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
15185				});
15186
15187				vars.current = index;
15188				vars.next = index + 1;
15189				vars.prev = index - 1;
15190
15191				iL.createUI();
15192
15193				setTimeout(function() {
15194					iL.generateBoxes();
15195				}, opts.effects.loadedFadeSpeed + 50);
15196
15197				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
15198				iL.positionThumbnails();
15199
15200				if (opts.linkId) setTimeout(function() {
15201					vars.hashLock = false;
15202				}, 55);
15203
15204				// Configure arrow buttons
15205				if (!opts.infinite) {
15206					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15207
15208					if (vars.current == 0) {
15209						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15210					}
15211					if (vars.current >= vars.total - 1) {
15212						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15213					}
15214				}
15215
15216				// Reset next cycle timeout
15217				iL.resetCycle();
15218
15219				//Trigger the onAfterChange callback
15220				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
15221			}
15222		},
15223
15224		moveTo: function(side) {
15225			var iL = this,
15226				vars = iL.vars,
15227				opts = iL.options,
15228				path = opts.path.toLowerCase(),
15229				viewport = getViewport(),
15230				switchSpeed = opts.effects.switchSpeed;
15231
15232			if (vars.nextLock || vars.prevLock) return false;
15233			else {
15234
15235				var item = (side == "next") ? vars.next : vars.prev;
15236
15237				if (opts.linkId) {
15238					vars.hashLock = true;
15239					window.location.hash = opts.linkId + '/' + item;
15240				}
15241
15242				if (side == "next") {
15243					if (!iL.items[item]) return false;
15244					var firstHolder = vars.nextPhoto,
15245						secondHolder = vars.holder,
15246						lastHolder = vars.prevPhoto,
15247						firstClass = 'ilightbox-prev',
15248						secondClass = 'ilightbox-next';
15249				} else if (side == "prev") {
15250					if (!iL.items[item]) return false;
15251					var firstHolder = vars.prevPhoto,
15252						secondHolder = vars.holder,
15253						lastHolder = vars.nextPhoto,
15254						firstClass = 'ilightbox-next',
15255						secondClass = 'ilightbox-prev';
15256				}
15257
15258				//Trigger the onBeforeChange callback
15259				if (typeof opts.callback.onBeforeChange == 'function')
15260					opts.callback.onBeforeChange.call(iL, iL.ui);
15261
15262				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
15263
15264				var captionFirst = $('div.ilightbox-caption', secondHolder),
15265					socialFirst = $('div.ilightbox-social', secondHolder);
15266
15267				if (captionFirst.length)
15268					captionFirst.stop().fadeOut(switchSpeed, function() {
15269						$(this).remove();
15270					});
15271				if (socialFirst.length)
15272					socialFirst.stop().fadeOut(switchSpeed, function() {
15273						$(this).remove();
15274					});
15275
15276				if (iL.items[item].caption) {
15277					iL.setCaption(iL.items[item], firstHolder);
15278					var caption = $('div.ilightbox-caption', firstHolder),
15279						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
15280					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
15281				}
15282
15283				var social = iL.items[item].options.social;
15284				if (social) {
15285					iL.setSocial(social, iL.items[item].URL, firstHolder);
15286					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
15287				}
15288
15289				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
15290					val.removeClass('ilightbox-next ilightbox-prev');
15291				});
15292
15293				var firstOffset = firstHolder.data('offset'),
15294					winW = (viewport.width - (opts.styles.pageOffsetX)),
15295					winH = (viewport.height - (opts.styles.pageOffsetY)),
15296					width = firstOffset.newDims.width,
15297					height = firstOffset.newDims.height,
15298					thumbsOffset = firstOffset.thumbsOffset,
15299					diff = firstOffset.diff,
15300					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
15301					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15302
15303				var secondOffset = secondHolder.data('offset'),
15304					object = secondOffset.object;
15305
15306				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15307					var objRatio = width / height;
15308					height = height - vars.captionHeight;
15309					width = height * objRatio;
15310					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
15311					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15312				}*/
15313
15314				firstHolder.show().css(transform, gpuAcceleration).animate({
15315					top: top,
15316					left: left,
15317					opacity: 1
15318				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15319					firstHolder.css(transform, '');
15320				});
15321
15322				$('div.ilightbox-container', firstHolder).animate({
15323					width: width,
15324					height: height
15325				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15326
15327				diff = secondOffset.diff;
15328
15329				width = secondOffset.newDims.width,
15330					height = secondOffset.newDims.height;
15331
15332				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15333					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15334					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
15335
15336				if (side == 'prev')
15337					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
15338				else {
15339					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
15340					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
15341				}
15342
15343				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15344					var objRatio = width / height;
15345					height = height - vars.captionHeight;
15346					width = height * objRatio;
15347					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
15348				}*/
15349
15350				$('div.ilightbox-container', secondHolder).animate({
15351					width: width,
15352					height: height
15353				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15354
15355				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
15356					top: top,
15357					left: left,
15358					opacity: opts.styles.prevOpacity,
15359				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15360					secondHolder.css(transform, '');
15361
15362					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
15363					iL.positionThumbnails();
15364
15365					if (iL.items[item]) {
15366						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
15367						else vars.lockWheel = false;
15368
15369						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
15370						else vars.lockSwipe = false;
15371					}
15372
15373					vars.isSwipe = false;
15374
15375					// Remove iframe & video from previous slide
15376					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15377						$('div.ilightbox-container', secondHolder).empty();
15378					}
15379
15380					if (side == "next") {
15381						vars.nextPhoto = lastHolder,
15382							vars.prevPhoto = secondHolder,
15383							vars.holder = firstHolder;
15384
15385						vars.nextPhoto.hide();
15386
15387						vars.next = vars.next + 1,
15388							vars.prev = vars.current,
15389							vars.current = vars.current + 1;
15390
15391						if (opts.infinite) {
15392							if (vars.current > vars.total - 1) vars.current = 0;
15393							if (vars.current == vars.total - 1) vars.next = 0;
15394							if (vars.current == 0) vars.prev = vars.total - 1;
15395						}
15396
15397						iL.createUI();
15398
15399						if (!iL.items[vars.next])
15400							vars.nextLock = false;
15401						else
15402							iL.loadContent(iL.items[vars.next], 'next');
15403					} else {
15404						vars.prevPhoto = lastHolder;
15405						vars.nextPhoto = secondHolder;
15406						vars.holder = firstHolder;
15407
15408						vars.prevPhoto.hide();
15409
15410						vars.next = vars.current;
15411						vars.current = vars.prev;
15412						vars.prev = vars.current - 1;
15413
15414						if (opts.infinite) {
15415							if (vars.current == vars.total - 1) vars.next = 0;
15416							if (vars.current == 0) vars.prev = vars.total - 1;
15417						}
15418
15419						iL.createUI();
15420
15421						if (!iL.items[vars.prev])
15422							vars.prevLock = false;
15423						else
15424							iL.loadContent(iL.items[vars.prev], 'prev');
15425					}
15426
15427					// Add iframe & video content for current slide
15428					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15429						iL.loadContent(iL.items[vars.current], 'current');
15430					}
15431
15432					if (opts.linkId) setTimeout(function() {
15433						vars.hashLock = false;
15434					}, 55);
15435
15436					// Configure arrow buttons
15437					if (!opts.infinite) {
15438						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15439
15440						if (vars.current == 0)
15441							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15442						if (vars.current >= vars.total - 1)
15443							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15444					}
15445
15446					iL.repositionPhoto();
15447
15448					// Reset next cycle timeout
15449					iL.resetCycle();
15450
15451					//Trigger the onAfterChange callback
15452					if (typeof opts.callback.onAfterChange == 'function')
15453						opts.callback.onAfterChange.call(iL, iL.ui);
15454				});
15455
15456				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
15457					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
15458
15459				lastHolder.css(transform, gpuAcceleration).animate({
15460					top: top,
15461					left: left,
15462					opacity: opts.styles.nextOpacity
15463				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15464					lastHolder.css(transform, '');
15465				}).addClass(secondClass);
15466			}
15467		},
15468
15469		setCaption: function(obj, target) {
15470			var iL = this,
15471				caption = $('<div class="ilightbox-caption"></div>');
15472
15473			if (obj.caption) {
15474				caption.html(obj.caption);
15475				$('div.ilightbox-container', target).append(caption);
15476			}
15477		},
15478
15479		normalizeSocial: function(obj, url) {
15480			var iL = this,
15481				vars = iL.vars,
15482				opts = iL.options,
15483				baseURL = window.location.href;
15484
15485			$.each(obj, function(key, value) {
15486				if (!value)
15487					return true;
15488
15489				var item = key.toLowerCase(),
15490					source, text;
15491
15492				switch (item) {
15493					case 'facebook':
15494						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
15495							text = "Share on Facebook";
15496						break;
15497					case 'twitter':
15498						source = "http://twitter.com/home?status={URL}",
15499							text = "Share on Twitter";
15500						break;
15501					case 'digg':
15502						source = "http://digg.com/submit?phase=2&url={URL}",
15503							text = "Share on Digg";
15504						break;
15505					case 'reddit':
15506						source = "http://reddit.com/submit?url={URL}",
15507							text = "Share on reddit";
15508						break;
15509				}
15510
15511				obj[key] = {
15512					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
15513					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
15514					text: value.text || text || "Share on " + key,
15515					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
15516					height: value.height || 360
15517				};
15518
15519			});
15520
15521			return obj;
15522		},
15523
15524		setSocial: function(obj, url, target) {
15525			var iL = this,
15526				socialBar = $('<div class="ilightbox-social"></div>'),
15527				buttons = '<ul>';
15528
15529			obj = iL.normalizeSocial(obj, url);
15530
15531			$.each(obj, function(key, value) {
15532				var item = key.toLowerCase(),
15533					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, '+'));
15534				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>';
15535			});
15536
15537			buttons += '</ul>';
15538
15539			socialBar.html(buttons);
15540			$('div.ilightbox-container', target).append(socialBar);
15541		},
15542
15543		fullScreenAction: function() {
15544			var iL = this,
15545				vars = iL.vars;
15546
15547			if (fullScreenApi.supportsFullScreen) {
15548				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
15549				else fullScreenApi.requestFullScreen(document.documentElement);
15550			} else {
15551				iL.doFullscreen();
15552			}
15553		},
15554
15555		doFullscreen: function() {
15556			var iL = this,
15557				vars = iL.vars,
15558				viewport = getViewport(),
15559				opts = iL.options;
15560
15561			if (opts.fullAlone) {
15562				var currentHolder = vars.holder,
15563					current = iL.items[vars.current],
15564					windowWidth = viewport.width,
15565					windowHeight = viewport.height,
15566					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
15567					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15568
15569				if (!vars.isInFullScreen) {
15570					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
15571					vars.overlay.css({
15572						opacity: 1
15573					});
15574
15575					$.each(hideElements, function(i, element) {
15576						element.hide();
15577					});
15578
15579					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
15580
15581					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
15582						naturalWidthOld: currentHolder.data('naturalWidth'),
15583						naturalHeightOld: currentHolder.data('naturalHeight'),
15584						naturalWidth: windowWidth,
15585						naturalHeight: windowHeight
15586					});
15587					else {
15588						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
15589							newWidth = windowWidth,
15590							newHeight = windowHeight,
15591							width = currentHolder.data('naturalWidth'),
15592							height = currentHolder.data('naturalHeight');
15593
15594						if (viewport.toLowerCase() == 'fill') {
15595							newHeight = (newWidth / width) * height;
15596
15597							if (newHeight < windowHeight) {
15598								newWidth = (windowHeight / height) * width,
15599									newHeight = windowHeight;
15600							}
15601						} else if (viewport.toLowerCase() == 'fit') {
15602							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
15603
15604							newWidth = dims.width,
15605								newHeight = dims.height;
15606						} else if (viewport.toLowerCase() == 'stretch') {
15607							newWidth = newWidth,
15608								newHeight = newHeight;
15609						} else {
15610							var scale = (width > newWidth || height > newHeight) ? true : false,
15611								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
15612							newWidth = dims.width,
15613								newHeight = dims.height;
15614						}
15615
15616						currentHolder.data({
15617							naturalWidthOld: currentHolder.data('naturalWidth'),
15618							naturalHeightOld: currentHolder.data('naturalHeight'),
15619							naturalWidth: newWidth,
15620							naturalHeight: newHeight
15621						});
15622					}
15623
15624					$.each(elements, function(key, val) {
15625						val.addClass('ilightbox-fullscreen');
15626					});
15627
15628					//Trigger the onEnterFullScreen callback
15629					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
15630				} else {
15631					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
15632					vars.overlay.css({
15633						opacity: iL.options.overlay.opacity
15634					});
15635
15636					$.each(hideElements, function(i, element) {
15637						element.show();
15638					});
15639
15640					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
15641
15642					currentHolder.data({
15643						naturalWidth: currentHolder.data('naturalWidthOld'),
15644						naturalHeight: currentHolder.data('naturalHeightOld'),
15645						naturalWidthOld: null,
15646						naturalHeightOld: null
15647					});
15648
15649					$.each(elements, function(key, val) {
15650						val.removeClass('ilightbox-fullscreen');
15651					});
15652
15653					//Trigger the onExitFullScreen callback
15654					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
15655				}
15656			} else {
15657				if (!vars.isInFullScreen) vars.isInFullScreen = true;
15658				else vars.isInFullScreen = false;
15659			}
15660			iL.repositionPhoto(true);
15661		},
15662
15663		closeAction: function() {
15664			var iL = this,
15665				vars = iL.vars,
15666				opts = iL.options;
15667
15668			$win.unbind('.iLightBox');
15669			$doc.off('.iLightBox');
15670
15671			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
15672
15673			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
15674
15675			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
15676				vars.overlay.remove();
15677				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15678			});
15679			else {
15680				vars.overlay.remove();
15681				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15682			}
15683
15684			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15685
15686			$.each(fadeOuts, function(i, element) {
15687				element.removeAttr('style').remove();
15688			});
15689
15690			vars.dontGenerateThumbs = vars.isInFullScreen = false;
15691
15692			window.iLightBox = null;
15693
15694			if (opts.linkId) {
15695				vars.hashLock = true;
15696				removeHash();
15697				setTimeout(function() {
15698					vars.hashLock = false;
15699				}, 55);
15700			}
15701
15702			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15703
15704			//Trigger the onHide callback
15705			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
15706		},
15707
15708		repositionPhoto: function() {
15709			var iL = this,
15710				vars = iL.vars,
15711				opts = iL.options,
15712				path = opts.path.toLowerCase(),
15713				viewport = getViewport(),
15714				winWidth = viewport.width,
15715				winHeight = viewport.height;
15716
15717			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
15718
15719			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
15720				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
15721				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
15722				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
15723				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,
15724				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)));
15725
15726			var elObject = {
15727				type: 'current',
15728				width: width,
15729				height: height,
15730				item: iL.items[vars.current],
15731				offsetW: offsetW,
15732				offsetH: offsetH,
15733				thumbsOffsetW: thumbsOffsetW,
15734				thumbsOffsetH: thumbsOffsetH,
15735				animate: arguments.length,
15736				holder: vars.holder
15737			};
15738
15739			iL.repositionEl(elObject);
15740
15741			if (iL.items[vars.next]) {
15742				elObject = $.extend(elObject, {
15743					type: 'next',
15744					item: iL.items[vars.next],
15745					offsetX: opts.styles.nextOffsetX,
15746					offsetY: opts.styles.nextOffsetY,
15747					holder: vars.nextPhoto
15748				});
15749
15750				iL.repositionEl(elObject);
15751			}
15752
15753			if (iL.items[vars.prev]) {
15754				elObject = $.extend(elObject, {
15755					type: 'prev',
15756					item: iL.items[vars.prev],
15757					offsetX: opts.styles.nextOffsetX,
15758					offsetY: opts.styles.prevOffsetY,
15759					holder: vars.prevPhoto
15760				});
15761
15762				iL.repositionEl(elObject);
15763			}
15764
15765			var loaderCss = (path == "horizontal") ? {
15766				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
15767			} : {
15768				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
15769			};
15770			vars.loader.css(loaderCss);
15771		},
15772
15773		repositionEl: function(obj) {
15774			var iL = this,
15775				vars = iL.vars,
15776				opts = iL.options,
15777				path = opts.path.toLowerCase(),
15778				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
15779				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
15780				itemParent = obj.item,
15781				item = obj.item.options,
15782				holder = obj.holder,
15783				offsetX = obj.offsetX || 0,
15784				offsetY = obj.offsetY || 0,
15785				//Uncode change ##START##
15786				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
15787				//Uncode change ##END##
15788				thumbsOffsetW = obj.thumbsOffsetW,
15789				thumbsOffsetH = obj.thumbsOffsetH;
15790
15791			if (obj.type == 'current') {
15792				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);
15793				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);
15794			} else {
15795				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
15796				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
15797			}
15798
15799
15800			//Uncode change ##START##
15801			heightAvail = parseInt(heightAvail - toolbarHeight);
15802			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
15803			//Uncode change ##END##
15804
15805			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
15806				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
15807
15808			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
15809					width: width,
15810					height: height
15811				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
15812				newDims = $.extend({}, dims, {});
15813
15814			if (obj.type == 'prev' || obj.type == 'next')
15815				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
15816				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
15817			else
15818				width = dims.width,
15819				height = dims.height;
15820
15821			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
15822				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);
15823
15824			switch (obj.type) {
15825				case 'current':
15826					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
15827						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15828					break;
15829
15830				case 'next':
15831					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
15832						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
15833					break;
15834
15835				case 'prev':
15836					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
15837						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15838					break;
15839			}
15840
15841			holder.data('offset', {
15842				top: top,
15843				left: left,
15844				newDims: newDims,
15845				diff: {
15846					W: widthDiff,
15847					H: heightDiff
15848				},
15849				thumbsOffset: {
15850					W: thumbsOffsetW,
15851					H: thumbsOffsetH
15852				},
15853				object: obj
15854			});
15855
15856			var opacityMobile;
15857			if ( isMobile ) {
15858				opacityMobile = {
15859					opacity: 1,
15860					top: top,
15861					left: left
15862				};
15863			} else {
15864				opacityMobile = {
15865					top: top,
15866					left: left
15867				};
15868			}
15869
15870			if (obj.animate > 0 && opts.effects.reposition) {
15871				holder.css(transform, gpuAcceleration).stop().animate(
15872					opacityMobile,
15873					opts.effects.repositionSpeed, 'easeOutCirc', function() {
15874					holder.css(transform, '');
15875				});
15876				$('div.ilightbox-container', holder).stop().animate({
15877					width: width,
15878					height: height
15879				}, opts.effects.repositionSpeed, 'easeOutCirc');
15880				$('div.ilightbox-inner-toolbar', holder).stop().animate({
15881					width: width
15882				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
15883					$(this).css('overflow', 'visible');
15884				});
15885			} else {
15886				holder.css(opacityMobile);
15887				$('div.ilightbox-container', holder).css({
15888					width: width,
15889					height: height
15890				});
15891				$('div.ilightbox-inner-toolbar', holder).css({
15892					width: width
15893				});
15894			}
15895		},
15896
15897
15898		resume: function(priority) {
15899			var iL = this,
15900				vars = iL.vars,
15901				opts = iL.options;
15902
15903			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
15904				return;
15905			}
15906
15907			vars.isPaused = 0;
15908
15909			if (vars.cycleID) {
15910				vars.cycleID = clearTimeout(vars.cycleID);
15911			}
15912
15913			vars.cycleID = setTimeout(function() {
15914				if (vars.current == vars.total - 1) iL.goTo(0);
15915				else iL.moveTo('next');
15916			}, opts.slideshow.pauseTime);
15917		},
15918
15919		pause: function(priority) {
15920			var iL = this,
15921				vars = iL.vars,
15922				opts = iL.options;
15923
15924			if (priority < vars.isPaused) {
15925				return;
15926			}
15927
15928			vars.isPaused = priority || 100;
15929
15930			if (vars.cycleID) {
15931				vars.cycleID = clearTimeout(vars.cycleID);
15932			}
15933		},
15934
15935		resetCycle: function() {
15936			var iL = this,
15937				vars = iL.vars,
15938				opts = iL.options;
15939
15940			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
15941				iL.resume();
15942			}
15943		},
15944
15945		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
15946			var iL = this;
15947
15948			if (!width) factor = height / height_old;
15949			else if (!height) factor = width / width_old;
15950			else factor = min(width / width_old, height / height_old);
15951
15952			if (!thumb) {
15953				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
15954				else if (factor < iL.options.minScale) factor = iL.options.minScale;
15955			}
15956
15957			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
15958				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
15959
15960			return {
15961				width: final_width,
15962				height: final_height,
15963				ratio: factor
15964			};
15965		},
15966
15967		setOption: function(options) {
15968			var iL = this;
15969
15970			iL.options = $.extend(true, iL.options, options || {});
15971			iL.refresh();
15972		},
15973
15974		availPlugins: function() {
15975			var iL = this,
15976				testEl = document.createElement("video");
15977
15978			iL.plugins = {
15979				flash: !isMobile,
15980				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
15981				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
15982				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
15983				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
15984				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
15985			};
15986		},
15987
15988		addContent: function(element, obj) {
15989			var iL = this,
15990				el;
15991
15992			switch (obj.type) {
15993				case 'video':
15994					var HTML5 = false,
15995						videoType = obj.videoType,
15996						html5video = obj.options.html5video;
15997
15998					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
15999						obj.ext = 'mp4',
16000						obj.URL = html5video.h264 || obj.URL;
16001					else if (html5video.webm && iL.plugins.html5WebM)
16002						obj.ext = 'webm',
16003						obj.URL = html5video.webm || obj.URL;
16004					else if (html5video.ogg && iL.plugins.html5Vorbis)
16005						obj.ext = 'ogv',
16006						obj.URL = html5video.ogg || obj.URL;
16007
16008					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
16009					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
16010					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
16011					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
16012
16013					if (HTML5) {
16014						el = $('<video />
16014', {
16015							"width": "100%",
16016							"height": "100%",
16017							"preload": html5video.preload,
16018							"autoplay": html5video.autoplay,
16019							"loop": html5video.loop,
16020							"poster": html5video.poster,
16021							"controls": html5video.controls,
16022							"controlslist": "nodownload"
16023						}).append($('<source />', {
16024							"src": obj.URL,
16025							"type": videoType
16026						}));
16027					} else {
16028						if (!iL.plugins.quicktime) el = $('<span />', {
16029							"class": "ilightbox-alert",
16030							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
16031						});
16032						else {
16033
16034							el = $('<object />', {
16035								"type": "video/quicktime",
16036								"pluginspage": pluginspages.quicktime
16037							}).attr({
16038								"data": obj.URL,
16039								"width": "100%",
16040								"height": "100%"
16041							}).append($('<param />', {
16042								"name": "src",
16043								"value": obj.URL
16044							})).append($('<param />', {
16045								"name": "autoplay",
16046								"value": "false"
16047							})).append($('<param />', {
16048								"name": "loop",
16049								"value": "false"
16050							})).append($('<param />', {
16051								"name": "scale",
16052								"value": "tofit"
16053							}));
16054
16055							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
16056						}
16057					}
16058
16059					break;
16060
16061				case 'flash':
16062					if (!iL.plugins.flash) el = $('<span />', {
16063						"class": "ilightbox-alert",
16064						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
16065					});
16066					else {
16067						var flashvars = "",
16068							i = 0;
16069
16070						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
16071							if (i != 0) flashvars += "&";
16072							flashvars += k + "=" + encodeURIComponent(v);
16073							i++;
16074						});
16075						else flashvars = null;
16076
16077						el = $('<embed />').attr({
16078							"type": "application/x-shockwave-flash",
16079							"src": obj.URL,
16080							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16081							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16082							"quality": "high",
16083							"bgcolor": "#000000",
16084							"play": "true",
16085							"loop": "true",
16086							"menu": "true",
16087							"wmode": "transparent",
16088							"scale": "showall",
16089							"allowScriptAccess": "always",
16090							"allowFullScreen": "true",
16091							"flashvars": flashvars,
16092							"fullscreen": "yes"
16093						});
16094					}
16095
16096					break;
16097
16098				case 'iframe':
16099					el = $('<iframe />').attr({
16100						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16101						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16102						src: obj.URL,
16103						frameborder: 0,
16104						'hspace': 0,
16105						'vspace': 0,
16106						'scrolling': supportTouch ? 'auto' : 'scroll',
16107						'webkitAllowFullScreen': '',
16108						'mozallowfullscreen': '',
16109						'allowFullScreen': ''
16110					});
16111
16112					break;
16113
16114				case 'inline':
16115					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
16116
16117					break;
16118
16119				case 'html':
16120					var object = obj.URL,
16121						el;
16122
16123					if (object[0].nodeName) {
16124						el = $('<div class="ilightbox-wrapper"></div>').html(object);
16125					} else {
16126						var dom = $(obj.URL),
16127							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
16128						el = $('<div class="ilightbox-wrapper"></div>').html(html);
16129					}
16130
16131					break;
16132			}
16133
16134			$('div.ilightbox-container', element).empty().html(el);
16135
16136			// For fixing Chrome about just playing the video for first time
16137			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
16138				var src = el[0].currentSrc + '?' + floor(random() * 30000);
16139				el[0].currentSrc = src;
16140				el[0].src = src;
16141			});
16142
16143			return el;
16144		},
16145
16146		ogpRecognition: function(obj, callback) {
16147			var iL = this,
16148				url = obj.URL;
16149
16150			iL.showLoader();
16151			doAjax(url, function(data) {
16152				iL.hideLoader();
16153				if (data) {
16154					var object = new Object();
16155
16156					object.length = false,
16157					object.url = data.url;
16158
16159					if (data.status == 200) {
16160						var result = data.results,
16161							type = result.type,
16162							source = result.source;
16163
16164						object.source = source.src,
16165						object.width = source.width && parseInt(source.width) || 0,
16166						object.height = source.height && parseInt(source.height) || 0,
16167						object.type = type,
16168						object.thumbnail = source.thumbnail || result.images && result.images[0],
16169						object.html5video = result.html5video || {},
16170						object.length = true;
16171
16172						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
16173						else if (source.type.indexOf("video/") != -1) object.type = "video";
16174						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
16175						else if (source.type.indexOf("image/") != -1) object.type = "image";
16176
16177					} else if (typeof data.response != 'undefined')
16178						throw data.response;
16179
16180					callback.call(this, object.length ? object : false);
16181				}
16182			});
16183		},
16184
16185		hashChangeHandler: function(url) {
16186			var iL = this,
16187				vars = iL.vars,
16188				opts = iL.options,
16189				URL = url || window.location.href,
16190				hash = parseURI(URL).hash,
16191				split = hash.split('/'),
16192				index = split[1];
16193
16194			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
16195
16196			if (index) {
16197				var target = split[1] || 0;
16198				if (iL.items[target]) {
16199					var overlay = $('.ilightbox-overlay');
16200					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
16201						iL.goTo(target);
16202					} else {
16203						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
16204						//iL.goTo(target);
16205					}
16206				} else {
16207					var overlay = $('.ilightbox-overlay');
16208					if (overlay.length) iL.closeAction();
16209				}
16210			} else {
16211				var overlay = $('.ilightbox-overlay');
16212				if (overlay.length) iL.closeAction();
16213			}
16214		}
16215	};
16216
16217	/**
16218	 * Parse style to pixels.
16219	 *
16220	 * @param {Object}   $element   jQuery object with element.
16221	 * @param {Property} property   CSS property to get the pixels from.
16222	 *
16223	 * @return {Int}
16224	 */
16225	function getPixel($element, property) {
16226		return parseInt($element.css(property), 10) || 0;
16227	}
16228
16229	/**
16230	 * Make sure that number is within the limits.
16231	 *
16232	 * @param {Number} number
16233	 * @param {Number} min
16234	 * @param {Number} max
16235	 *
16236	 * @return {Number}
16237	 */
16238	function within(number, min, max) {
16239		return number < min ? min : number > max ? max : number;
16240	}
16241
16242	/**
16243	 * Get viewport/window size (width and height).
16244	 *
16245	 * @return {Object}
16246	 */
16247	function getViewport() {
16248		var e = window,
16249			a = 'inner';
16250		if (!('innerWidth' in window)) {
16251			a = 'client';
16252			e = document.documentElement || document.body;
16253		}
16254		return {
16255			width: e[a + 'Width'],
16256			height: e[a + 'Height']
16257		}
16258	}
16259
16260	/**
16261	 * Remove hash tag from the URL
16262	 *
16263	 * @return {Void}
16264	 */
16265	function removeHash() {
16266		var scroll = getScrollXY();
16267
16268		//UNCODE change
16269		// window.location.hash = "";
16270		// history.pushState("", document.title, window.location.pathname + window.location.search);
16271		history.replaceState({}, document.title, window.location.pathname + window.location.search);
16272
16273		// Restore the scroll offset, should be flicker free
16274		window.scrollTo(scroll.x, scroll.y);
16275	}
16276
16277	/**
16278	 * Do the ajax requests with callback.
16279	 *
16280	 * @param {String}   url
16281	 * @param {Function} callback
16282	 *
16283	 * @return {Void}
16284	 */
16285	function doAjax(url, callback) {
16286		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');
16287		$.ajax({
16288			url: url,
16289			dataType: 'jsonp'
16290		});
16291
16292		iLCallback = function(data) {
16293			callback.call(this, data);
16294		};
16295	}
16296
16297	/**
16298	 * Find image from DOM elements
16299	 *
16300	 * @param {Element} element
16301	 *
16302	 * @return {Void}
16303	 */
16304	function findImageInElement(element) {
16305		var elements = $('*', element),
16306			imagesArr = new Array();
16307
16308		elements.each(function() {
16309			var url = "",
16310				element = this;
16311
16312			if ($(element).css("background-image") != "none") {
16313				url = $(element).css("background-image");
16314			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
16315				url = $(element).attr("src");
16316			}
16317
16318			if (url.indexOf("gradient") == -1) {
16319				url = url.replace(/url\(\"/g, "");
16320				url = url.replace(/url\(/g, "");
16321				url = url.replace(/\"\)/g, "");
16322				url = url.replace(/\)/g, "");
16323
16324				var urls = url.split(",");
16325
16326				for (var i = 0; i < urls.length; i++) {
16327					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
16328						var extra = "";
16329						if (browser.msie && browser.version < 9) {
16330							extra = "?" + floor(random() * 3000);
16331						}
16332						imagesArr.push(urls[i] + extra);
16333					}
16334				}
16335			}
16336		});
16337
16338		return imagesArr;
16339	}
16340
16341	/**
16342	 * Get file extension.
16343	 *
16344	 * @param {String} URL
16345	 *
16346	 * @return {String}
16347	 */
16348	function getExtension(URL) {
16349		if (URL !== null) {
16350			//UNCODE: fix issue to detect media type with query strings
16351			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
16352			ext = ext.split('.').pop().toLowerCase();
16353
16354			return ext;
16355		}
16356	}
16357
16358	/**
16359	 * Get type via extension.
16360	 *
16361	 * @param {String} URL
16362	 *
16363	 * @return {String}
16364	 */
16365	function getTypeByExtension(URL) {
16366		var type,
16367			ext = getExtension(URL);
16368
16369		//Uncode addition ##START##
16370		if (URL == undefined) {
16371			return false;
16372		}
16373		//Uncode addition ##END##
16374
16375		if (extensions.image.indexOf(ext) !== -1) type = 'image';
16376		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
16377		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
16378		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
16379		else type = 'iframe';
16380
16381		return type;
16382	}
16383
16384	/**
16385	 * Return value from percent of a number.
16386	 *
16387	 * @param {Number} percent
16388	 * @param {Number} total
16389	 *
16390	 * @return {Number}
16391	 */
16392	function percentToValue(percent, total) {
16393		return parseInt((total / 100) * percent);
16394	}
16395
16396	/**
16397	 * A JavaScript equivalent of PHP’s parse_url.
16398	 *
16399	 * @param {String} url           The URL to parse.
16400	 *
16401	 * @return {Mixed}
16402	 */
16403	function parseURI(url) {
16404		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
16405		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
16406		return (m ? {
16407			href: m[0] || '',
16408			protocol: m[1] || '',
16409			authority: m[2] || '',
16410			host: m[3] || '',
16411			hostname: m[4] || '',
16412			port: m[5] || '',
16413			pathname: m[6] || '',
16414			search: m[7] || '',
16415			hash: m[8] || ''
16416		} : null);
16417	}
16418
16419	/**
16420	 * Gets the absolute URI.
16421	 *
16422	 * @param {String} href     The relative URL.
16423	 * @param {String} base     The base URL.
16424	 *
16425	 * @return {String}         The absolute URL.
16426	 */
16427	function absolutizeURI(base, href) { // RFC 3986
16428		var iL = this;
16429
16430		function removeDotSegments(input) {
16431			var output = [];
16432			input.replace(/^(\.\.?(\/|$))+/, '')
16433				.replace(/\/(\.(\/|$))+/g, '/')
16434				.replace(/\/\.\.$/, '/../')
16435				.replace(/\/?[^\/]*/g, function(p) {
16436					if (p === '/..') {
16437						output.pop();
16438					} else {
16439						output.push(p);
16440					}
16441				});
16442			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
16443		}
16444
16445		href = parseURI(href || '');
16446		base = parseURI(base || '');
16447
16448		return !href || !base ? null : (href.protocol || base.protocol) +
16449			(href.protocol || href.authority ? href.authority : base.authority) +
16450			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)) +
16451			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
16452			href.hash;
16453	}
16454
16455	/**
16456	 * A JavaScript equivalent of PHP’s version_compare.
16457	 *
16458	 * @param {String} v1
16459	 * @param {String} v2
16460	 * @param {String} operator
16461	 *
16462	 * @return {Boolean}
16463	 */
16464	function version_compare(v1, v2, operator) {
16465		this.php_js = this.php_js || {};
16466		this.php_js.ENV = this.php_js.ENV || {};
16467		var i = 0,
16468			x = 0,
16469			compare = 0,
16470			vm = {
16471				'dev': -6,
16472				'alpha': -5,
16473				'a': -5,
16474				'beta': -4,
16475				'b': -4,
16476				'RC': -3,
16477				'rc': -3,
16478				'#': -2,
16479				'p': 1,
16480				'pl': 1
16481			},
16482			prepVersion = function(v) {
16483				v = ('' + v).replace(/[_\-+]/g, '.');
16484				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
16485				return (!v.length ? [-8] : v.split('.'));
16486			},
16487			numVersion = function(v) {
16488				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
16489			};
16490		v1 = prepVersion(v1);
16491		v2 = prepVersion(v2);
16492		x = max(v1.length, v2.length);
16493		for (i = 0; i < x; i++) {
16494			if (v1[i] == v2[i]) {
16495				continue;
16496			}
16497			v1[i] = numVersion(v1[i]);
16498			v2[i] = numVersion(v2[i]);
16499			if (v1[i] < v2[i]) {
16500				compare = -1;
16501				break;
16502			} else if (v1[i] > v2[i]) {
16503				compare = 1;
16504				break;
16505			}
16506		}
16507		if (!operator) {
16508			return compare;
16509		}
16510
16511		switch (operator) {
16512			case '>':
16513			case 'gt':
16514				return (compare > 0);
16515			case '>=':
16516			case 'ge':
16517				return (compare >= 0);
16518			case '<=':
16519			case 'le':
16520				return (compare <= 0);
16521			case '==':
16522			case '=':
16523			case 'eq':
16524				return (compare === 0);
16525			case '<>':
16526			case '!=':
16527			case 'ne':
16528				return (compare !== 0);
16529			case '':
16530			case '<':
16531			case 'lt':
16532				return (compare < 0);
16533			default:
16534				return null;
16535		}
16536	}
16537
16538
16539	// Begin the iLightBox plugin
16540	$.fn.iLightBox = function() {
16541
16542		var args = arguments,
16543			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
16544			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
16545
16546		if (!opt) opt = {};
16547
16548		// Default options. Play carefully.
16549		var options = $.extend(true, {
16550			attr: 'href',
16551			path: 'vertical',
16552			skin: 'dark',
16553			linkId: false,
16554			infinite: false,
16555			startFrom: 0,
16556			randomStart: false,
16557			keepAspectRatio: true,
16558			maxScale: 1,
16559			minScale: .2,
16560			innerToolbar: false,
16561			smartRecognition: false,
16562			mobileOptimizer: true,
16563			fullAlone: true,
16564			fullViewPort: null,
16565			fullStretchTypes: 'flash, video',
16566			overlay: {
16567				blur: true,
16568				opacity: .85
16569			},
16570			controls: {
16571				arrows: false,
16572				slideshow: false,
16573				toolbar: true,
16574				fullscreen: true,
16575				thumbnail: true,
16576				keyboard: true,
16577				mousewheel: true,
16578				swipe: true
16579			},
16580			keyboard: {
16581				left: true, // previous
16582				right: true, // next
16583				up: true, // previous
16584				down: true, // next
16585				esc: true, // close
16586				shift_enter: true // fullscreen
16587			},
16588			show: {
16589				effect: true,
16590				speed: 300,
16591				title: true
16592			},
16593			hide: {
16594				effect: true,
16595				speed: 300
16596			},
16597			caption: {
16598				start: true,
16599				show: 'mouseenter',
16600				hide: 'mouseleave'
16601			},
16602			social: {
16603				start: true,
16604				show: 'mouseenter',
16605				hide: 'mouseleave',
16606				buttons: false
16607			},
16608			styles: {
16609				pageOffsetX: 0,
16610				pageOffsetY: 0,
16611				nextOffsetX: 45,
16612				nextOffsetY: 0,
16613				nextOpacity: 1,
16614				nextScale: 1,
16615				prevOffsetX: 45,
16616				prevOffsetY: 0,
16617				prevOpacity: 1,
16618				prevScale: 1
16619			},
16620			thumbnails: {
16621				maxWidth: 120,
16622				maxHeight: 80,
16623				normalOpacity: 1,
16624				activeOpacity: .6
16625			},
16626			effects: {
16627				reposition: true,
16628				repositionSpeed: 200,
16629				switchSpeed: 500,
16630				loadedFadeSpeed: 180,
16631				fadeSpeed: 200
16632			},
16633			slideshow: {
16634				pauseTime: 5000,
16635				pauseOnHover: false,
16636				startPaused: true
16637			},
16638			text: {
16639				close: "Press Esc to close",
16640				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
16641				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
16642				slideShow: "Slideshow",
16643				next: "Next",
16644				previous: "Previous"
16645			},
16646			errors: {
16647				loadImage: "An error occurred when trying to load photo.",
16648				loadContents: "An error occurred when trying to load contents.",
16649				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
16650			},
16651			ajaxSetup: {
16652				url: '',
16653				beforeSend: function(jqXHR, settings) {},
16654				cache: false,
16655				complete: function(jqXHR, textStatus) {},
16656				crossDomain: false,
16657				error: function(jqXHR, textStatus, errorThrown) {},
16658				success: function(data, textStatus, jqXHR) {},
16659				global: true,
16660				ifModified: false,
16661				username: null,
16662				password: null,
16663				type: 'GET'
16664			},
16665			callback: {}
16666		}, opt);
16667
16668		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
16669
16670		items = $.isArray(items) ? items : new Array();
16671
16672		if (typeof args[0] == 'string') items[0] = args[0];
16673
16674		if (version_compare($.fn.jquery, '1.8', '>=')) {
16675			var iLB = new iLightBox($(this), options, items, instant);
16676			return {
16677				close: function() {
16678					iLB.closeAction();
16679				},
16680				fullscreen: function() {
16681					iLB.fullScreenAction();
16682				},
16683				moveNext: function() {
16684					iLB.moveTo('next');
16685				},
16686				movePrev: function() {
16687					iLB.moveTo('prev');
16688				},
16689				goTo: function(index) {
16690					iLB.goTo(index);
16691				},
16692				refresh: function() {
16693					iLB.refresh();
16694				},
16695				reposition: function() {
16696					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
16697				},
16698				setOption: function(options) {
16699					iLB.setOption(options);
16700				},
16701				destroy: function() {
16702					iLB.closeAction();
16703					iLB.dispatchItemsEvents();
16704				}
16705			};
16706		} else {
16707			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
16708		}
16709
16710	};
16711
16712
16713	$.iLightBox = function() {
16714		return $.fn.iLightBox(arguments[0], arguments[1]);
16715	};
16716
16717	function getScrollXY() {
16718		var scrOfX = 0,
16719			scrOfY = 0;
16720		if (typeof(window.pageYOffset) == 'number') {
16721			//Netscape compliant
16722			scrOfY = window.pageYOffset;
16723			scrOfX = window.pageXOffset;
16724		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
16725			//DOM compliant
16726			scrOfY = document.body.scrollTop;
16727			scrOfX = document.body.scrollLeft;
16728		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
16729			//IE6 standards compliant mode
16730			scrOfY = document.documentElement.scrollTop;
16731			scrOfX = document.documentElement.scrollLeft;
16732		}
16733		return {
16734			x: scrOfX,
16735			y: scrOfY
16736		};
16737	}
16738
16739	(function() {
16740		// add new event shortcuts
16741		$.each(("touchstart touchmove touchend " +
16742			"tap taphold " +
16743			"swipe swipeleft swiperight " +
16744			"scrollstart scrollstop").split(" "), function(i, name) {
16745
16746			$.fn[name] = function(fn) {
16747				return fn ? this.bind(name, fn) : this.trigger(name);
16748			};
16749
16750			// jQuery < 1.8
16751			// if ($.attrFn) {
16752			// 	$.attrFn[name] = true;
16753			// }
16754		});
16755
16756		var tapSettings = {
16757			startEvent: 'touchstart.iTap',
16758			endEvent: 'touchend.iTap'
16759		};
16760
16761		// tap Event:
16762		$.event.special.itap = {
16763			setup: function() {
16764
16765				var self = this,
16766					$self = $(this),
16767					start, stop;
16768
16769				$self.bind(tapSettings.startEvent, function(event) {
16770					start = getScrollXY();
16771
16772					$self.one(tapSettings.endEvent, function(event) {
16773						stop = getScrollXY();
16774
16775						var orgEvent = event || window.event;
16776						event = $.event.fix(orgEvent);
16777						event.type = "itap";
16778
16779						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
16780
16781						start = stop = undefined;
16782					});
16783				});
16784			},
16785
16786			teardown: function() {
16787				$(this).unbind(tapSettings.startEvent);
16788			}
16789		};
16790	}());
16791
16792
16793	//Fullscreen API
16794	(function() {
16795		fullScreenApi = {
16796				supportsFullScreen: false,
16797				isFullScreen: function() {
16798					return false;
16799				},
16800				requestFullScreen: function() {},
16801				cancelFullScreen: function() {},
16802				fullScreenEventName: '',
16803				prefix: ''
16804			},
16805			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
16806
16807		// check for native support
16808		if (typeof document.cancelFullScreen != 'undefined') {
16809			fullScreenApi.supportsFullScreen = true;
16810		} else {
16811			// check for fullscreen support by vendor prefix
16812			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
16813				fullScreenApi.prefix = browserPrefixes[i];
16814
16815				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
16816					fullScreenApi.supportsFullScreen = true;
16817
16818					break;
16819				}
16820			}
16821		}
16822
16823		// update methods to do something useful
16824		if (fullScreenApi.supportsFullScreen) {
16825			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
16826
16827			fullScreenApi.isFullScreen = function() {
16828				switch (this.prefix) {
16829					case '':
16830						return document.fullScreen;
16831					case 'webkit':
16832						return document.webkitIsFullScreen;
16833					default:
16834						return document[this.prefix + 'FullScreen'];
16835				}
16836			}
16837			fullScreenApi.requestFullScreen = function(el) {
16838				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
16839			}
16840			fullScreenApi.cancelFullScreen = function(el) {
16841				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
16842			}
16843		}
16844	}());
16845
16846	// Browser detect
16847	(function() {
16848		function uaMatch(ua) {
16849			ua = ua.toLowerCase();
16850
16851			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
16852				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
16853				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
16854				/(msie) ([\w.]+)/.exec(ua) ||
16855				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
16856
16857			return {
16858				browser: match[1] || "",
16859				version: match[2] || "0"
16860			};
16861		}
16862
16863		var matched = uaMatch(navigator.userAgent);
16864		browser = {};
16865
16866		if (matched.browser) {
16867			browser[matched.browser] = true;
16868			browser.version = matched.version;
16869		}
16870
16871		// Chrome is Webkit, but Webkit is also Safari.
16872		if (browser.chrome) {
16873			browser.webkit = true;
16874		} else if (browser.webkit) {
16875			browser.safari = true;
16876		}
16877	}());
16878
16879	// Feature detects
16880	(function() {
16881		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
16882		var el = document.createElement('div');
16883
16884		function testProp(prop) {
16885			for (var p = 0, pl = prefixes.length; p < pl; p++) {
16886				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
16887				if (el.style[prefixedProp] !== undefined) {
16888					return prefixedProp;
16889				}
16890			}
16891		}
16892
16893		// Global support indicators
16894		transform = testProp('transform') || '';
16895		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
16896	}());
16897
16898
16899	/*
16900		PluginDetect v0.7.9
16901		www.pinlady.net/PluginDetect/license/
16902		[ getVersion onWindowLoaded BetterIE ]
16903		[ Flash QuickTime Shockwave ]
16904	*/
16905	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;
16905d++){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);
16905d.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)}
16905c.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;
16905if(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();
16906
16907	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)};
16908
16909
16910	/*
16911		jQuery hashchange event v1.3
16912		https://github.com/cowboy/jquery-hashchange
16913		Copyright (c) 2010 "Cowboy" Ben Alman
16914		Dual licensed under the MIT and GPL licenses.
16915	*/
16916	(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=
16917	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||
16918	"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;
16918a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
16919
16920	if (!Array.prototype.filter) {
16921		Array.prototype.filter = function(fun /*, thisp */ ) {
16922			"use strict";
16923
16924			if (this == null)
16925				throw new TypeError();
16926
16927			var t = Object(this);
16928			var len = t.length >>> 0;
16929			if (typeof fun != "function")
16930				throw new TypeError();
16931
16932			var res = [];
16933			var thisp = arguments[1];
16934			for (var i = 0; i < len; i++) {
16935				if (i in t) {
16936					var val = t[i]; // in case fun mutates this
16937					if (fun.call(thisp, val, i, t))
16938						res.push(val);
16939				}
16940			}
16941
16942			return res;
16943		};
16944	}
16945
16946	if (!Array.prototype.indexOf) {
16947		Array.prototype.indexOf = function(searchElement, fromIndex) {
16948			var k;
16949
16950			if (this == null) {
16951				throw new TypeError('"this" is null or not defined');
16952			}
16953
16954			var O = Object(this);
16955
16956			var len = O.length >>> 0;
16957
16958			if (len === 0) {
16959				return -1;
16960			}
16961
16962			var n = +fromIndex || 0;
16963
16964			if (abs(n) === Infinity) {
16965				n = 0;
16966			}
16967
16968			if (n >= len) {
16969				return -1;
16970			}
16971
16972			k = max(n >= 0 ? n : len - abs(n), 0);
16973
16974			while (k < len) {
16975				var kValue;
16976				if (k in O && O[k] === searchElement) {
16977					return k;
16978				}
16979				k++;
16980			}
16981			return -1;
16982		};
16983	}
16984
16985	if (!Array.prototype.lastIndexOf) {
16986		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
16987			"use strict";
16988
16989			if (this == null)
16990				throw new TypeError();
16991
16992			var t = Object(this);
16993			var len = t.length >>> 0;
16994			if (len === 0)
16995				return -1;
16996
16997			var n = len;
16998			if (arguments.length > 1) {
16999				n = Number(arguments[1]);
17000				if (n != n)
17001					n = 0;
17002				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
17003					n = (n > 0 || -1) * floor(abs(n));
17004			}
17005
17006			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
17007
17008			for (; k >= 0; k--) {
17009				if (k in t && t[k] === searchElement)
17010					return k;
17011			}
17012			return -1;
17013		};
17014	}
17015})(jQuery, this);
17016
17017/*!
17018 * lightgallery | 2.5.0 | June 13th 2022
17019 * http://www.lightgalleryjs.com/
17020 * Copyright (c) 2020 Sachin Neravath;
17021 * @license GPLv3
17022 */
17023
17024(function (global, factory) {
17025	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
17026	typeof define === 'function' && define.amd ? define(factory) :
17027	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
17028}(this, (function () { 'use strict';
17029
17030	/*! *****************************************************************************
17031	Copyright (c) Microsoft Corporation.
17032
17033	Permission to use, copy, modify, and/or distribute this software for any
17034	purpose with or without fee is hereby granted.
17035
17036	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17037	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17038	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17039	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17040	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17041	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17042	PERFORMANCE OF THIS SOFTWARE.
17043	***************************************************************************** */
17044
17045	var __assign = function() {
17046		__assign = Object.assign || function __assign(t) {
17047			for (var s, i = 1, n = arguments.length; i < n; i++) {
17048				s = arguments[i];
17049				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
17050			}
17051			return t;
17052		};
17053		return __assign.apply(this, arguments);
17054	};
17055
17056	function __spreadArrays() {
17057		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
17058		for (var r = Array(s), k = 0, i = 0; i < il; i++)
17059			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
17060				r[k] = a[j];
17061		return r;
17062	}
17063
17064	/**
17065	 * List of lightGallery events
17066	 * All events should be documented here
17067	 * Below interfaces are used to build the website documentations
17068	 * */
17069	var lGEvents = {
17070		afterAppendSlide: 'lgAfterAppendSlide',
17071		init: 'lgInit',
17072		hasVideo: 'lgHasVideo',
17073		containerResize: 'lgContainerResize',
17074		updateSlides: 'lgUpdateSlides',
17075		afterAppendSubHtml: 'lgAfterAppendSubHtml',
17076		beforeOpen: 'lgBeforeOpen',
17077		afterOpen: 'lgAfterOpen',
17078		slideItemLoad: 'lgSlideItemLoad',
17079		beforeSlide: 'lgBeforeSlide',
17080		afterSlide: 'lgAfterSlide',
17081		posterClick: 'lgPosterClick',
17082		dragStart: 'lgDragStart',
17083		dragMove: 'lgDragMove',
17084		dragEnd: 'lgDragEnd',
17085		beforeNextSlide: 'lgBeforeNextSlide',
17086		beforePrevSlide: 'lgBeforePrevSlide',
17087		beforeClose: 'lgBeforeClose',
17088		afterClose: 'lgAfterClose',
17089		rotateLeft: 'lgRotateLeft',
17090		rotateRight: 'lgRotateRight',
17091		flipHorizontal: 'lgFlipHorizontal',
17092		flipVertical: 'lgFlipVertical',
17093		autoplay: 'lgAutoplay',
17094		autoplayStart: 'lgAutoplayStart',
17095		autoplayStop: 'lgAutoplayStop',
17096	};
17097
17098	var lightGalleryCoreSettings = {
17099		mode: 'lg-slide',
17100		easing: 'ease',
17101		speed: 400,
17102		licenseKey: '0000-0000-000-0000',
17103		height: '100%',
17104		width: '100%',
17105		addClass: '',
17106		startClass: 'lg-start-zoom',
17107		backdropDuration: 300,
17108		container: '',
17109		startAnimationDuration: 400,
17110		zoomFromOrigin: true,
17111		hideBarsDelay: 0,
17112		showBarsAfter: 10000,
17113		slideDelay: 0,
17114		supportLegacyBrowser: true,
17115		allowMediaOverlap: false,
17116		videoMaxSize: '1280-720',
17117		loadYouTubePoster: true,
17118		defaultCaptionHeight: 0,
17119		ariaLabelledby: '',
17120		ariaDescribedby: '',
17121		resetScrollPosition: true,
17122		hideScrollbar: false,
17123		closable: true,
17124		swipeToClose: true,
17125		closeOnTap: true,
17126		showCloseIcon: true,
17127		showMaximizeIcon: false,
17128		loop: true,
17129		escKey: true,
17130		keyPress: true,
17131		trapFocus: true,
17132		controls: true,
17133		slideEndAnimation: true,
17134		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 17135-17682
17135		mousewheel: false,
17136		getCaptionFromTitleOrAlt: true,
17137		appendSubHtmlTo: '.lg-sub-html',
17138		subHtmlSelectorRelative: false,
17139		preload: 2,
17140		numberOfSlideItemsInDom: 10,
17141		selector: '',
17142		selectWithin: '',
17143		nextHtml: '',
17144		prevHtml: '',
17145		index: 0,
17146		iframeWidth: '100%',
17147		iframeHeight: '100%',
17148		iframeMaxWidth: '100%',
17149		iframeMaxHeight: '100%',
17150		download: true,
17151		counter: true,
17152		appendCounterTo: '.lg-toolbar',
17153		swipeThreshold: 50,
17154		enableSwipe: true,
17155		enableDrag: true,
17156		dynamic: false,
17157		dynamicEl: [],
17158		extraProps: [],
17159		exThumbImage: '',
17160		isMobile: undefined,
17161		mobileSettings: {
17162			controls: false,
17163			showCloseIcon: false,
17164			download: false,
17165		},
17166		plugins: [],
17167		strings: {
17168			closeGallery: 'Close gallery',
17169			toggleMaximize: 'Toggle maximize',
17170			previousSlide: 'Previous slide',
17171			nextSlide: 'Next slide',
17172			download: 'Download',
17173			playVideo: 'Play video',
17174		},
17175	};
17176
17177	function initLgPolyfills() {
17178		(function () {
17179			if (typeof window.CustomEvent === 'function')
17180				return false;
17181			function CustomEvent(event, params) {
17182				params = params || {
17183					bubbles: false,
17184					cancelable: false,
17185					detail: null,
17186				};
17187				var evt = document.createEvent('CustomEvent');
17188				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
17189				return evt;
17190			}
17191			window.CustomEvent = CustomEvent;
17192		})();
17193		(function () {
17194			if (!Element.prototype.matches) {
17195				Element.prototype.matches =
17196					Element.prototype.msMatchesSelector ||
17197						Element.prototype.webkitMatchesSelector;
17198			}
17199		})();
17200	}
17201	var lgQuery = /** @class */ (function () {
17202		function lgQuery(selector) {
17203			this.cssVenderPrefixes = [
17204				'TransitionDuration',
17205				'TransitionTimingFunction',
17206				'Transform',
17207				'Transition',
17208			];
17209			this.selector = this._getSelector(selector);
17210			this.firstElement = this._getFirstEl();
17211			return this;
17212		}
17213		lgQuery.generateUUID = function () {
17214			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
17215				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
17216				return v.toString(16);
17217			});
17218		};
17219		lgQuery.prototype._getSelector = function (selector, context) {
17220			if (context === void 0) { context = document; }
17221			if (typeof selector !== 'string') {
17222				return selector;
17223			}
17224			context = context || document;
17225			var fl = selector.substring(0, 1);
17226			if (fl === '#') {
17227				return context.querySelector(selector);
17228			}
17229			else {
17230				return context.querySelectorAll(selector);
17231			}
17232		};
17233		lgQuery.prototype._each = function (func) {
17234			if (!this.selector) {
17235				return this;
17236			}
17237			if (this.selector.length !== undefined) {
17238				[].forEach.call(this.selector, func);
17239			}
17240			else {
17241				func(this.selector, 0);
17242			}
17243			return this;
17244		};
17245		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
17246			// prettier-ignore
17247			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
17248				return group1.toUpperCase();
17249			});
17250			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
17251				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
17252				el.style['webkit' + property] = value;
17253				el.style['moz' + property] = value;
17254				el.style['ms' + property] = value;
17255				el.style['o' + property] = value;
17256			}
17257			else {
17258				el.style[property] = value;
17259			}
17260		};
17261		lgQuery.prototype._getFirstEl = function () {
17262			if (this.selector && this.selector.length !== undefined) {
17263				return this.selector[0];
17264			}
17265			else {
17266				return this.selector;
17267			}
17268		};
17269		lgQuery.prototype.isEventMatched = function (event, eventName) {
17270			var eventNamespace = eventName.split('.');
17271			return event
17272				.split('.')
17273				.filter(function (e) { return e; })
17274				.every(function (e) {
17275				return eventNamespace.indexOf(e) !== -1;
17276			});
17277		};
17278		lgQuery.prototype.attr = function (attr, value) {
17279			if (value === undefined) {
17280				if (!this.firstElement) {
17281					return '';
17282				}
17283				return this.firstElement.getAttribute(attr);
17284			}
17285			this._each(function (el) {
17286				el.setAttribute(attr, value);
17287			});
17288			return this;
17289		};
17290		lgQuery.prototype.find = function (selector) {
17291			return $LG(this._getSelector(selector, this.selector));
17292		};
17293		lgQuery.prototype.first = function () {
17294			if (this.selector && this.selector.length !== undefined) {
17295				return $LG(this.selector[0]);
17296			}
17297			else {
17298				return $LG(this.selector);
17299			}
17300		};
17301		lgQuery.prototype.eq = function (index) {
17302			return $LG(this.selector[index]);
17303		};
17304		lgQuery.prototype.parent = function () {
17305			return $LG(this.selector.parentElement);
17306		};
17307		lgQuery.prototype.get = function () {
17308			return this._getFirstEl();
17309		};
17310		lgQuery.prototype.removeAttr = function (attributes) {
17311			var attrs = attributes.split(' ');
17312			this._each(function (el) {
17313				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
17314			});
17315			return this;
17316		};
17317		lgQuery.prototype.wrap = function (className) {
17318			if (!this.firstElement) {
17319				return this;
17320			}
17321			var wrapper = document.createElement('div');
17322			wrapper.className = className;
17323			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
17324			this.firstElement.parentNode.removeChild(this.firstElement);
17325			wrapper.appendChild(this.firstElement);
17326			return this;
17327		};
17328		lgQuery.prototype.addClass = function (classNames) {
17329			if (classNames === void 0) { classNames = ''; }
17330			this._each(function (el) {
17331				// IE doesn't support multiple arguments
17332				classNames.split(' ').forEach(function (className) {
17333					if (className) {
17334						el.classList.add(className);
17335					}
17336				});
17337			});
17338			return this;
17339		};
17340		lgQuery.prototype.removeClass = function (classNames) {
17341			this._each(function (el) {
17342				// IE doesn't support multiple arguments
17343				classNames.split(' ').forEach(function (className) {
17344					if (className) {
17345						el.classList.remove(className);
17346					}
17347				});
17348			});
17349			return this;
17350		};
17351		lgQuery.prototype.hasClass = function (className) {
17352			if (!this.firstElement) {
17353				return false;
17354			}
17355			return this.firstElement.classList.contains(className);
17356		};
17357		lgQuery.prototype.hasAttribute = function (attribute) {
17358			if (!this.firstElement) {
17359				return false;
17360			}
17361			return this.firstElement.hasAttribute(attribute);
17362		};
17363		lgQuery.prototype.toggleClass = function (className) {
17364			if (!this.firstElement) {
17365				return this;
17366			}
17367			if (this.hasClass(className)) {
17368				this.removeClass(className);
17369			}
17370			else {
17371				this.addClass(className);
17372			}
17373			return this;
17374		};
17375		lgQuery.prototype.css = function (property, value) {
17376			var _this = this;
17377			this._each(function (el) {
17378				_this._setCssVendorPrefix(el, property, value);
17379			});
17380			return this;
17381		};
17382		// Need to pass separate namespaces for separate elements
17383		lgQuery.prototype.on = function (events, listener) {
17384			var _this = this;
17385			if (!this.selector) {
17386				return this;
17387			}
17388			events.split(' ').forEach(function (event) {
17389				if (!Array.isArray(lgQuery.eventListeners[event])) {
17390					lgQuery.eventListeners[event] = [];
17391				}
17392				lgQuery.eventListeners[event].push(listener);
17393				_this.selector.addEventListener(event.split('.')[0], listener);
17394			});
17395			return this;
17396		};
17397		// @todo - test this
17398		lgQuery.prototype.once = function (event, listener) {
17399			var _this = this;
17400			this.on(event, function () {
17401				_this.off(event);
17402				listener(event);
17403			});
17404			return this;
17405		};
17406		lgQuery.prototype.off = function (event) {
17407			var _this = this;
17408			if (!this.selector) {
17409				return this;
17410			}
17411			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
17412				if (_this.isEventMatched(event, eventName)) {
17413					lgQuery.eventListeners[eventName].forEach(function (listener) {
17414						_this.selector.removeEventListener(eventName.split('.')[0], listener);
17415					});
17416					lgQuery.eventListeners[eventName] = [];
17417				}
17418			});
17419			return this;
17420		};
17421		lgQuery.prototype.trigger = function (event, detail) {
17422			if (!this.firstElement) {
17423				return this;
17424			}
17425			var customEvent = new CustomEvent(event.split('.')[0], {
17426				detail: detail || null,
17427			});
17428			this.firstElement.dispatchEvent(customEvent);
17429			return this;
17430		};
17431		// Does not support IE
17432		lgQuery.prototype.load = function (url) {
17433			var _this = this;
17434			fetch(url)
17435				.then(function (res) { return res.text(); })
17436				.then(function (html) {
17437				_this.selector.innerHTML = html;
17438			});
17439			return this;
17440		};
17441		lgQuery.prototype.html = function (html) {
17442			if (html === undefined) {
17443				if (!this.firstElement) {
17444					return '';
17445				}
17446				return this.firstElement.innerHTML;
17447			}
17448			this._each(function (el) {
17449				el.innerHTML = html;
17450			});
17451			return this;
17452		};
17453		lgQuery.prototype.append = function (html) {
17454			this._each(function (el) {
17455				if (typeof html === 'string') {
17456					el.insertAdjacentHTML('beforeend', html);
17457				}
17458				else {
17459					el.appendChild(html);
17460				}
17461			});
17462			return this;
17463		};
17464		lgQuery.prototype.prepend = function (html) {
17465			this._each(function (el) {
17466				el.insertAdjacentHTML('afterbegin', html);
17467			});
17468			return this;
17469		};
17470		lgQuery.prototype.remove = function () {
17471			this._each(function (el) {
17472				el.parentNode.removeChild(el);
17473			});
17474			return this;
17475		};
17476		lgQuery.prototype.empty = function () {
17477			this._each(function (el) {
17478				el.innerHTML = '';
17479			});
17480			return this;
17481		};
17482		lgQuery.prototype.scrollTop = function (scrollTop) {
17483			if (scrollTop !== undefined) {
17484				document.body.scrollTop = scrollTop;
17485				document.documentElement.scrollTop = scrollTop;
17486				return this;
17487			}
17488			else {
17489				return (window.pageYOffset ||
17490					document.documentElement.scrollTop ||
17491					document.body.scrollTop ||
17492					0);
17493			}
17494		};
17495		lgQuery.prototype.scrollLeft = function (scrollLeft) {
17496			if (scrollLeft !== undefined) {
17497				document.body.scrollLeft = scrollLeft;
17498				document.documentElement.scrollLeft = scrollLeft;
17499				return this;
17500			}
17501			else {
17502				return (window.pageXOffset ||
17503					document.documentElement.scrollLeft ||
17504					document.body.scrollLeft ||
17505					0);
17506			}
17507		};
17508		lgQuery.prototype.offset = function () {
17509			if (!this.firstElement) {
17510				return {
17511					left: 0,
17512					top: 0,
17513				};
17514			}
17515			var rect = this.firstElement.getBoundingClientRect();
17516			var bodyMarginLeft = $LG('body').style().marginLeft;
17517			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
17518			return {
17519				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
17520				top: rect.top + this.scrollTop(),
17521			};
17522		};
17523		lgQuery.prototype.style = function () {
17524			if (!this.firstElement) {
17525				return {};
17526			}
17527			return (this.firstElement.currentStyle ||
17528				window.getComputedStyle(this.firstElement));
17529		};
17530		// Width without padding and border even if box-sizing is used.
17531		lgQuery.prototype.width = function () {
17532			var style = this.style();
17533			return (this.firstElement.clientWidth -
17534				parseFloat(style.paddingLeft) -
17535				parseFloat(style.paddingRight));
17536		};
17537		// Height without padding and border even if box-sizing is used.
17538		lgQuery.prototype.height = function () {
17539			var style = this.style();
17540			return (this.firstElement.clientHeight -
17541				parseFloat(style.paddingTop) -
17542				parseFloat(style.paddingBottom));
17543		};
17544		lgQuery.eventListeners = {};
17545		return lgQuery;
17546	}());
17547	function $LG(selector) {
17548		initLgPolyfills();
17549		return new lgQuery(selector);
17550	}
17551
17552	var defaultDynamicOptions = [
17553		'src',
17554		'sources',
17555		'subHtml',
17556		'subHtmlUrl',
17557		'html',
17558		'video',
17559		'poster',
17560		'slideName',
17561		'responsive',
17562		'srcset',
17563		'sizes',
17564		'iframe',
17565		'downloadUrl',
17566		'download',
17567		'width',
17568		'facebookShareUrl',
17569		'tweetText',
17570		'iframeTitle',
17571		'twitterShareUrl',
17572		'pinterestShareUrl',
17573		'pinterestText',
17574		'fbHtml',
17575		'disqusIdentifier',
17576		'disqusUrl',
17577	];
17578	// Convert html data-attribute to camalcase
17579	function convertToData(attr) {
17580		// FInd a way for lgsize
17581		if (attr === 'href') {
17582			return 'src';
17583		}
17584		attr = attr.replace('data-', '');
17585		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
17586		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
17587		return attr;
17588	}
17589	var utils = {
17590		/**
17591		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
17592		 */
17593		//Uncode edit ##START##
17594		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
17595		// getSize: function (el, container, spacing, defaultLgSize) {
17596		//Uncode edit ##END##
17597			if (spacing === void 0) { spacing = 0; }
17598			var LGel = $LG(el);
17599			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
17600			//Uncode edit ##START##
17601			if ( typeof galleryItem.size && galleryItem.size != null ) {
17602				lgSize = galleryItem.size;
17603			}
17604			//Uncode edit ##END##
17605			if (!lgSize) {
17606				return;
17607			}
17608			var isResponsiveSizes = lgSize.split(',');
17609			// if at-least two viewport sizes are available
17610			if (isResponsiveSizes[1]) {
17611				var wWidth = window.innerWidth;
17612				for (var i = 0; i < isResponsiveSizes.length; i++) {
17613					var size_1 = isResponsiveSizes[i];
17614					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
17615					if (responsiveWidth > wWidth) {
17616						lgSize = size_1;
17617						break;
17618					}
17619					// take last item as last option
17620					if (i === isResponsiveSizes.length - 1) {
17621						lgSize = size_1;
17622					}
17623				}
17624			}
17625			var size = lgSize.split('-');
17626			var width = parseInt(size[0], 10);
17627			var height = parseInt(size[1], 10);
17628			var cWidth = container.width();
17629			var cHeight = container.height() - spacing;
17630			var maxWidth = Math.min(cWidth, width);
17631			var maxHeight = Math.min(cHeight, height);
17632			var ratio = Math.min(maxWidth / width, maxHeight / height);
17633			return { width: width * ratio, height: height * ratio };
17634		},
17635		/**
17636		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
17637		 * @param {jQuery Element}
17638		 * @returns {String} Transform CSS string
17639		 */
17640		getTransform: function (el, container, top, bottom, imageSize) {
17641			if (!imageSize) {
17642				return;
17643			}
17644			var LGel = $LG(el).find('img').first();
17645			if (!LGel.get()) {
17646				return;
17647			}
17648			var containerRect = container.get().getBoundingClientRect();
17649			var wWidth = containerRect.width;
17650			// using innerWidth to include mobile safari bottom bar
17651			var wHeight = container.height() - (top + bottom);
17652			var elWidth = LGel.width();
17653			var elHeight = LGel.height();
17654			var elStyle = LGel.style();
17655			var x = (wWidth - elWidth) / 2 -
17656				LGel.offset().left +
17657				(parseFloat(elStyle.paddingLeft) || 0) +
17658				(parseFloat(elStyle.borderLeft) || 0) +
17659				$LG(window).scrollLeft() +
17660				containerRect.left;
17661			var y = (wHeight - elHeight) / 2 -
17662				LGel.offset().top +
17663				(parseFloat(elStyle.paddingTop) || 0) +
17664				(parseFloat(elStyle.borderTop) || 0) +
17665				$LG(window).scrollTop() +
17666				top;
17667			var scX = elWidth / imageSize.width;
17668			var scY = elHeight / imageSize.height;
17669			var transform = 'translate3d(' +
17670				(x *= -1) +
17671				'px, ' +
17672				(y *= -1) +
17673				'px, 0) scale3d(' +
17674				scX +
17675				', ' +
17676				scY +
17677				', 1)';
17678			return transform;
17679		},
17680		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
17681			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
17682			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 17682-17754
17682+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
17683		},
17684		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
17685			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
17686			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17687			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17688			var sourceTag = '';
17689			if (sources) {
17690				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17691				sourceTag = sourceObj.map(function (source) {
17692					var attrs = '';
17693					Object.keys(source).forEach(function (key) {
17694						// Do not remove the first space as it is required to separate the attributes
17695						attrs += " " + key + "=\"" + source[key] + "\"";
17696					});
17697					return "<source " + attrs + "></source>";
17698				});
17699			}
17700			return "" + sourceTag + imgMarkup;
17701		},
17702		// Get src from responsive src
17703		getResponsiveSrc: function (srcItms) {
17704			var rsWidth = [];
17705			var rsSrc = [];
17706			var src = '';
17707			for (var i = 0; i < srcItms.length; i++) {
17708				var _src = srcItms[i].split(' ');
17709				// Manage empty space
17710				if (_src[0] === '') {
17711					_src.splice(0, 1);
17712				}
17713				rsSrc.push(_src[0]);
17714				rsWidth.push(_src[1]);
17715			}
17716			var wWidth = window.innerWidth;
17717			for (var j = 0; j < rsWidth.length; j++) {
17718				if (parseInt(rsWidth[j], 10) > wWidth) {
17719					src = rsSrc[j];
17720					break;
17721				}
17722			}
17723			return src;
17724		},
17725		isImageLoaded: function (img) {
17726			if (!img)
17727				return false;
17728			// During the onload event, IE correctly identifies any images that
17729			// weren’t downloaded as not complete. Others should too. Gecko-based
17730			// browsers act like NS4 in that they report this incorrectly.
17731			if (!img.complete) {
17732				return false;
17733			}
17734			// However, they do have two very useful properties: naturalWidth and
17735			// naturalHeight. These give the true size of the image. If it failed
17736			// to load, either of these should be zero.
17737			if (img.naturalWidth === 0) {
17738				return false;
17739			}
17740			// No other way of checking: assume it’s ok.
17741			return true;
17742		},
17743		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17744			var videoClass = '';
17745			if (_isVideo && _isVideo.youtube) {
17746				videoClass = 'lg-has-youtube';
17747			}
17748			else if (_isVideo && _isVideo.vimeo) {
17749				videoClass = 'lg-has-vimeo';
17750			}
17751			else {
17752				videoClass = 'lg-has-html5';
17753			}
17754			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
vendor: 5,030 bytes, lines 17754-17865
17754\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>";
17755		},
17756		getFocusableElements: function (container) {
17757			var elements = container.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])');
17758			var visibleElements = [].filter.call(elements, function (element) {
17759				var style = window.getComputedStyle(element);
17760				return style.display !== 'none' && style.visibility !== 'hidden';
17761			});
17762			return visibleElements;
17763		},
17764		/**
17765		 * @desc Create dynamic elements array from gallery items when dynamic option is false
17766		 * It helps to avoid frequent DOM interaction
17767		 * and avoid multiple checks for dynamic elments
17768		 *
17769		 * @returns {Array} dynamicEl
17770		 */
17771		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17772			var dynamicElements = [];
17773			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17774			[].forEach.call(items, function (item) {
17775				var dynamicEl = {};
17776				for (var i = 0; i < item.attributes.length; i++) {
17777					var attr = item.attributes[i];
17778					if (attr.specified) {
17779						var dynamicAttr = convertToData(attr.name);
17780						var label = '';
17781						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17782							label = dynamicAttr;
17783						}
17784						if (label) {
17785							dynamicEl[label] = attr.value;
17786						}
17787					}
17788				}
17789				var currentItem = $LG(item);
17790				var alt = currentItem.find('img').first().attr('alt');
17791				var title = currentItem.attr('title');
17792				//Uncode edit ##START##
17793				// var thumb = exThumbImage
17794				var thumb = exThumbImage && currentItem.attr(exThumbImage)
17795				//Uncode edit ##END##
17796					? currentItem.attr(exThumbImage)
17797					: currentItem.find('img').first().attr('src');
17798				dynamicEl.thumb = thumb;
17799				//Uncode edit ##START##
17800				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17801					// dynamicEl.subHtml = title || alt || '';
17802					dynamicEl.subHtml = title || '';
17803				}
17804				// dynamicEl.alt = alt || title || '';
17805				dynamicEl.alt = title || '';
17806				var inlineType = currentItem.attr('data-type');
17807				dynamicEl.type = inlineType;
17808				//Uncode edit ##END##
17809				dynamicElements.push(dynamicEl);
17810			});
17811			return dynamicElements;
17812		},
17813		isMobile: function () {
17814			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17815		},
17816		/**
17817		 * @desc Check the given src is video
17818		 * @param {String} src
17819		 * @return {Object} video type
17820		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17821		 *
17822		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
17823		 */
17824		isVideo: function (src, isHTML5VIdeo, index) {
17825			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
17826				if (isHTML5VIdeo) {
17827					return {
17828						html5: true,
17829					};
17830				}
17831				else {
17832					console.warn('lightGallery :- data-src is not provided on slide item ' +
17833						(index + 1) +
17834						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17835					return;
17836				}
17837			}
17838			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17839			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17840			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17841			if (youtube) {
17842				return {
17843					youtube: youtube,
17844				};
17845			}
17846			else if (vimeo) {
17847				return {
17848					vimeo: vimeo,
17849				};
17850			}
17851			else if (wistia) {
17852				return {
17853					wistia: wistia,
17854				};
17855			}
17856		},
17857	};
17858
17859	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17860	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17861	// Unique id for each gallery
17862	var lgId = 0;
17863	var LightGallery = /** @class */ (function () {
17864		function LightGallery(element, options) {
17865			this.lgOpened = false;
vendor: 4,563 bytes, lines 17866-18000
17866			this.index = 0;
17867			// lightGallery modules
17868			this.plugins = [];
17869			// false when lightGallery load first slide content;
17870			this.lGalleryOn = false;
17871			// True when a slide animation is in progress
17872			this.lgBusy = false;
17873			this.currentItemsInDom = [];
17874			// Scroll top value before lightGallery is opened
17875			this.prevScrollTop = 0;
17876			this.bodyPaddingRight = 0;
17877			this.isDummyImageRemoved = false;
17878			this.dragOrSwipeEnabled = false;
17879			this.mediaContainerPosition = {
17880				top: 0,
17881				bottom: 0,
17882			};
17883			if (!element) {
17884				return this;
17885			}
17886			lgId++;
17887			this.lgId = lgId;
17888			this.el = element;
17889			this.LGel = $LG(element);
17890			this.generateSettings(options);
17891			this.buildModules();
17892			// When using dynamic mode, ensure dynamicEl is an array
17893			if (this.settings.dynamic &&
17894				this.settings.dynamicEl !== undefined &&
17895				!Array.isArray(this.settings.dynamicEl)) {
17896				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17897			}
17898			this.galleryItems = this.getItems();
17899			this.normalizeSettings();
17900			// Gallery items
17901			this.init();
17902			//Uncode edit ##START##
17903			// this.validateLicense();
17904			//Uncode edit ##END##
17905			return this;
17906		}
17907		LightGallery.prototype.generateSettings = function (options) {
17908			// lightGallery settings
17909			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17910			if (this.settings.isMobile &&
17911				typeof this.settings.isMobile === 'function'
17912				? this.settings.isMobile()
17913				: utils.isMobile()) {
17914				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17915				this.settings = __assign(__assign({}, this.settings), mobileSettings);
17916			}
17917		};
17918		LightGallery.prototype.normalizeSettings = function () {
17919			if (this.settings.slideEndAnimation) {
17920				this.settings.hideControlOnEnd = false;
17921			}
17922			if (!this.settings.closable) {
17923				this.settings.swipeToClose = false;
17924			}
17925			// And reset it on close to get the correct value next time
17926			this.zoomFromOrigin = this.settings.zoomFromOrigin;
17927			// At the moment, Zoom from image doesn't support dynamic options
17928			// @todo add zoomFromOrigin support for dynamic images
17929			if (this.settings.dynamic) {
17930				this.zoomFromOrigin = false;
17931			}
17932			if (!this.settings.container) {
17933				this.settings.container = document.body;
17934			}
17935			// settings.preload should not be grater than $item.length
17936			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17937		};
17938		LightGallery.prototype.init = function () {
17939			var _this = this;
17940			this.addSlideVideoInfo(this.galleryItems);
17941			this.buildStructure();
17942			this.LGel.trigger(lGEvents.init, {
17943				instance: this,
17944			});
17945			if (this.settings.keyPress) {
17946				this.keyPress();
17947			}
17948			setTimeout(function () {
17949				_this.enableDrag();
17950				_this.enableSwipe();
17951				_this.triggerPosterClick();
17952			}, 50);
17953			this.arrow();
17954			if (this.settings.mousewheel) {
17955				this.mousewheel();
17956			}
17957			if (!this.settings.dynamic) {
17958				this.openGalleryOnItemClick();
17959			}
17960		};
17961		LightGallery.prototype.openGalleryOnItemClick = function () {
17962			var _this = this;
17963			var _loop_1 = function (index) {
17964				var element = this_1.items[index];
17965				var $element = $LG(element);
17966				// Using different namespace for click because click event should not unbind if selector is same object('this')
17967				// @todo manage all event listners - should have namespace that represent element
17968				var uuid = lgQuery.generateUUID();
17969				$element
17970					.attr('data-lg-id', uuid)
17971					.on("click.lgcustom-item-" + uuid, function (e) {
17972					e.preventDefault();
17973					var currentItemIndex = _this.settings.index || index;
17974					_this.openGallery(currentItemIndex, element);
17975				});
17976			};
17977			var this_1 = this;
17978			// Using for loop instead of using bubbling as the items can be any html element.
17979			for (var index = 0; index < this.items.length; index++) {
17980				_loop_1(index);
17981			}
17982		};
17983		/**
17984		 * Module constructor
17985		 * Modules are build incrementally.
17986		 * Gallery should be opened only once all the modules are initialized.
17987		 * use moduleBuildTimeout to make sure this
17988		 */
17989		LightGallery.prototype.buildModules = function () {
17990			var _this = this;
17991			this.settings.plugins.forEach(function (plugin) {
17992				_this.plugins.push(new plugin(_this, $LG));
17993			});
17994		};
17995		LightGallery.prototype.validateLicense = function () {
17996			if (!this.settings.licenseKey) {
17997				console.warn('Please provide a valid license key');
17998			}
17999			else if (this.settings.licenseKey === '0000-0000-000-0000') {
18000				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 18000-18414
18000id for production use");
18001			}
18002		};
18003		LightGallery.prototype.getSlideItem = function (index) {
18004			return $LG(this.getSlideItemId(index));
18005		};
18006		LightGallery.prototype.getSlideItemId = function (index) {
18007			return "#lg-item-" + this.lgId + "-" + index;
18008		};
18009		LightGallery.prototype.getIdName = function (id) {
18010			return id + "-" + this.lgId;
18011		};
18012		LightGallery.prototype.getElementById = function (id) {
18013			return $LG("#" + this.getIdName(id));
18014		};
18015		LightGallery.prototype.manageSingleSlideClassName = function () {
18016			if (this.galleryItems.length < 2) {
18017				this.outer.addClass('lg-single-item');
18018			}
18019			else {
18020				this.outer.removeClass('lg-single-item');
18021			}
18022		};
18023		LightGallery.prototype.buildStructure = function () {
18024			var _this = this;
18025			var container = this.$container && this.$container.get();
18026			if (container) {
18027				return;
18028			}
18029			var controls = '';
18030			var subHtmlCont = '';
18031			// Create controls
18032			if (this.settings.controls) {
18033				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>";
18034			}
18035			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18036				subHtmlCont =
18037					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
18038			}
18039			var addClasses = '';
18040			if (this.settings.allowMediaOverlap) {
18041				// Do not remove space before last single quote
18042				addClasses += 'lg-media-overlap ';
18043			}
18044			var ariaLabelledby = this.settings.ariaLabelledby
18045				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
18046				: '';
18047			var ariaDescribedby = this.settings.ariaDescribedby
18048				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
18049				: '';
18050			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
18051			var closeIcon = this.settings.closable && this.settings.showCloseIcon
18052				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
18053				: '';
18054			var maximizeIcon = this.settings.showMaximizeIcon
18055				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
18056				: '';
18057			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'
18058				? subHtmlCont
18059				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
18060				? subHtmlCont
18061				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
18062			$LG(this.settings.container).append(template);
18063			if (document.body !== this.settings.container) {
18064				$LG(this.settings.container).css('position', 'relative');
18065			}
18066			this.outer = this.getElementById('lg-outer');
18067			this.$lgComponents = this.getElementById('lg-components');
18068			this.$backdrop = this.getElementById('lg-backdrop');
18069			this.$container = this.getElementById('lg-container');
18070			this.$inner = this.getElementById('lg-inner');
18071			this.$content = this.getElementById('lg-content');
18072			this.$toolbar = this.getElementById('lg-toolbar');
18073			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
18074			var outerClassNames = this.settings.mode + " ";
18075			this.manageSingleSlideClassName();
18076			if (this.settings.enableDrag) {
18077				outerClassNames += 'lg-grab ';
18078			}
18079			this.outer.addClass(outerClassNames);
18080			this.$inner.css('transition-timing-function', this.settings.easing);
18081			this.$inner.css('transition-duration', this.settings.speed + 'ms');
18082			if (this.settings.download) {
18083				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>");
18084			}
18085			this.counter();
18086			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
18087				_this.refreshOnResize();
18088			});
18089			this.hideBars();
18090			this.manageCloseGallery();
18091			this.toggleMaximize();
18092			this.initModules();
18093		};
18094		LightGallery.prototype.refreshOnResize = function () {
18095			if (this.lgOpened) {
18096				var currentGalleryItem = this.galleryItems[this.index];
18097				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
18098				this.mediaContainerPosition = this.getMediaContainerPosition();
18099				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
18100				//Uncode edit ##START##
18101				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18102				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18103				//Uncode edit ##END##
18104				if (__slideVideoInfo) {
18105					this.resizeVideoSlide(this.index, this.currentImageSize);
18106				}
18107				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
18108					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18109					this.outer
18110						.find('.lg-current .lg-dummy-img')
18111						.first()
18112						.attr('style', imgStyle);
18113				}
18114				this.LGel.trigger(lGEvents.containerResize);
18115			}
18116		};
18117		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
18118			var lgVideoStyle = this.getVideoContStyle(imageSize);
18119			var currentSlide = this.getSlideItem(index);
18120			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
18121		};
18122		/**
18123		 * Update slides dynamically.
18124		 * Add, edit or delete slides dynamically when lightGallery is opened.
18125		 * Modify the current gallery items and pass it via updateSlides method
18126		 * @note
18127		 * - Do not mutate existing lightGallery items directly.
18128		 * - Always pass new list of gallery items
18129		 * - You need to take care of thumbnails outside the gallery if any
18130		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
18131		 * @param items Gallery items
18132		 * @param index After the update operation, which slide gallery should navigate to
18133		 * @category lGPublicMethods
18134		 * @example
18135		 * const plugin = lightGallery();
18136		 *
18137		 * // Adding slides dynamically
18138		 * let galleryItems = [
18139		 * // Access existing lightGallery items
18140		 * // galleryItems are automatically generated internally from the gallery HTML markup
18141		 * // or directly from galleryItems when dynamic gallery is used
18142		 *   ...plugin.galleryItems,
18143		 *     ...[
18144		 *       {
18145		 *         src: 'img/img-1.png',
18146		 *           thumb: 'img/thumb1.png',
18147		 *         },
18148		 *     ],
18149		 *   ];
18150		 *   plugin.updateSlides(
18151		 *     galleryItems,
18152		 *     plugin.index,
18153		 *   );
18154		 *
18155		 *
18156		 * // Remove slides dynamically
18157		 * galleryItems = JSON.parse(
18158		 *   JSON.stringify(updateSlideInstance.galleryItems),
18159		 * );
18160		 * galleryItems.shift();
18161		 * updateSlideInstance.updateSlides(galleryItems, 1);
18162		 * @see <a href="/demos/update-slides/">Demo</a>
18163		 */
18164		LightGallery.prototype.updateSlides = function (items, index) {
18165			if (this.index > items.length - 1) {
18166				this.index = items.length - 1;
18167			}
18168			if (items.length === 1) {
18169				this.index = 0;
18170			}
18171			if (!items.length) {
18172				this.closeGallery();
18173				return;
18174			}
18175			var currentSrc = this.galleryItems[index].src;
18176			this.galleryItems = items;
18177			this.updateControls();
18178			this.$inner.empty();
18179			this.currentItemsInDom = [];
18180			var _index = 0;
18181			// Find the current index based on source value of the slide
18182			this.galleryItems.some(function (galleryItem, itemIndex) {
18183				if (galleryItem.src === currentSrc) {
18184					_index = itemIndex;
18185					return true;
18186				}
18187				return false;
18188			});
18189			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
18190			this.loadContent(_index, true);
18191			this.getSlideItem(_index).addClass('lg-current');
18192			this.index = _index;
18193			this.updateCurrentCounter(_index);
18194			this.LGel.trigger(lGEvents.updateSlides);
18195		};
18196		// Get gallery items based on multiple conditions
18197		LightGallery.prototype.getItems = function () {
18198			// Gallery items
18199			this.items = [];
18200			if (!this.settings.dynamic) {
18201				if (this.settings.selector === 'this') {
18202					this.items.push(this.el);
18203				}
18204				else if (this.settings.selector) {
18205					if (typeof this.settings.selector === 'string') {
18206						if (this.settings.selectWithin) {
18207							var selectWithin = $LG(this.settings.selectWithin);
18208							this.items = selectWithin
18209								.find(this.settings.selector)
18210								.get();
18211						}
18212						else {
18213							this.items = this.el.querySelectorAll(this.settings.selector);
18214						}
18215					}
18216					else {
18217						this.items = this.settings.selector;
18218					}
18219				}
18220				else {
18221					this.items = this.el.children;
18222				}
18223				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
18224			}
18225			else {
18226				return this.settings.dynamicEl || [];
18227			}
18228		};
18229		LightGallery.prototype.shouldHideScrollbar = function () {
18230			return (this.settings.hideScrollbar &&
18231				document.body === this.settings.container);
18232		};
18233		LightGallery.prototype.hideScrollbar = function () {
18234			if (!this.shouldHideScrollbar()) {
18235				return;
18236			}
18237			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
18238			var bodyRect = document.documentElement.getBoundingClientRect();
18239			var scrollbarWidth = window.innerWidth - bodyRect.width;
18240			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
18241			$LG(document.body).addClass('lg-overlay-open');
18242		};
18243		LightGallery.prototype.resetScrollBar = function () {
18244			if (!this.shouldHideScrollbar()) {
18245				return;
18246			}
18247			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
18248			$LG(document.body).removeClass('lg-overlay-open');
18249		};
18250		/**
18251		 * Open lightGallery.
18252		 * Open gallery with specific slide by passing index of the slide as parameter.
18253		 * @category lGPublicMethods
18254		 * @param {Number} index  - index of the slide
18255		 * @param {HTMLElement} element - Which image lightGallery should zoom from
18256		 *
18257		 * @example
18258		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
18259		 * const dynamicGallery = lightGallery($dynamicGallery, {
18260		 *     dynamic: true,
18261		 *     dynamicEl: [
18262		 *         {
18263		 *              src: 'img/1.jpg',
18264		 *              thumb: 'img/thumb-1.jpg',
18265		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
18266		 *         },
18267		 *         ...
18268		 *     ],
18269		 * });
18270		 * $dynamicGallery.addEventListener('click', function () {
18271		 *     // Starts with third item.(Optional).
18272		 *     // This is useful if you want use dynamic mode with
18273		 *     // custom thumbnails (thumbnails outside gallery),
18274		 *     dynamicGallery.openGallery(2);
18275		 * });
18276		 *
18277		 */
18278		LightGallery.prototype.openGallery = function (index, element) {
18279			var _this = this;
18280			if (index === void 0) { index = this.settings.index; }
18281			// prevent accidental double execution
18282			if (this.lgOpened)
18283				return;
18284			this.lgOpened = true;
18285			this.outer.removeClass('lg-hide-items');
18286			this.hideScrollbar();
18287			// Add display block, but still has opacity 0
18288			this.$container.addClass('lg-show');
18289			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
18290			this.currentItemsInDom = itemsToBeInsertedToDom;
18291			var items = '';
18292			itemsToBeInsertedToDom.forEach(function (item) {
18293				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18294			});
18295			this.$inner.append(items);
18296			this.addHtml(index);
18297			var transform = '';
18298			this.mediaContainerPosition = this.getMediaContainerPosition();
18299			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
18300			if (!this.settings.allowMediaOverlap) {
18301				this.setMediaContainerPosition(top, bottom);
18302			}
18303			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
18304			if (this.zoomFromOrigin && element) {
18305				//Uncode edit ##START##
18306				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18307				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18308				//Uncode edit ##END##
18309				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
18310			}
18311			if (!this.zoomFromOrigin || !transform) {
18312				this.outer.addClass(this.settings.startClass);
18313				this.getSlideItem(index).removeClass('lg-complete');
18314			}
18315			var timeout = this.settings.zoomFromOrigin
18316				? 100
18317				: this.settings.backdropDuration;
18318			setTimeout(function () {
18319				_this.outer.addClass('lg-components-open');
18320			}, timeout);
18321			this.index = index;
18322			//Uncode edit ##START##
18323			// this.LGel.trigger(lGEvents.beforeOpen);
18324			this.LGel.trigger(lGEvents.beforeOpen, {
18325				galleryItems: this.galleryItems,
18326				items: this.items,
18327				outer: this.outer,
18328			});
18329			//Uncode edit ##END##
18330			// add class lg-current to remove initial transition
18331			this.getSlideItem(index).addClass('lg-current');
18332			this.lGalleryOn = false;
18333			// Store the current scroll top value to scroll back after closing the gallery..
18334			this.prevScrollTop = $LG(window).scrollTop();
18335			setTimeout(function () {
18336				// Need to check both zoomFromOrigin and transform values as we need to set set the
18337				// default opening animation if user missed to add the lg-size attribute
18338				if (_this.zoomFromOrigin && transform) {
18339					var currentSlide_1 = _this.getSlideItem(index);
18340					currentSlide_1.css('transform', transform);
18341					setTimeout(function () {
18342						currentSlide_1
18343							.addClass('lg-start-progress lg-start-end-progress')
18344							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
18345						_this.outer.addClass('lg-zoom-from-image');
18346					});
18347					setTimeout(function () {
18348						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
18349					}, 100);
18350				}
18351				setTimeout(function () {
18352					_this.$backdrop.addClass('in');
18353					_this.$container.addClass('lg-show-in');
18354				}, 10);
18355				setTimeout(function () {
18356					if (_this.settings.trapFocus &&
18357						document.body === _this.settings.container) {
18358						_this.trapFocus();
18359					}
18360				}, _this.settings.backdropDuration + 50);
18361				// lg-visible class resets gallery opacity to 1
18362				if (!_this.zoomFromOrigin || !transform) {
18363					setTimeout(function () {
18364						_this.outer.addClass('lg-visible');
18365					}, _this.settings.backdropDuration);
18366				}
18367				// initiate slide function
18368				_this.slide(index, false, false, false);
18369				_this.LGel.trigger(lGEvents.afterOpen);
18370			});
18371			if (document.body === this.settings.container) {
18372				$LG('html').addClass('lg-on');
18373			}
18374		};
18375		/**
18376		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
18377		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
18378		 * if you have dynamic captions for each media,
18379		 * you can provide an appropriate height for the captions via allowMediaOverlap option
18380		 */
18381		LightGallery.prototype.getMediaContainerPosition = function () {
18382			if (this.settings.allowMediaOverlap) {
18383				return {
18384					top: 0,
18385					bottom: 0,
18386				};
18387			}
18388			var top = this.$toolbar.get().clientHeight || 0;
18389			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
18390			var captionHeight = this.settings.defaultCaptionHeight ||
18391				(subHtml && subHtml.clientHeight) ||
18392				0;
18393			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
18394			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
18395			var bottom = thumbHeight + captionHeight;
18396			//Uncode edit ##START##
18397			bottom = bottom < 55 ? 55 : bottom;
18398			//Uncode edit ##END##
18399			return {
18400				top: top,
18401				bottom: bottom,
18402			};
18403		};
18404		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
18405			if (top === void 0) { top = 0; }
18406			if (bottom === void 0) { bottom = 0; }
18407			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
18408		};
18409		LightGallery.prototype.hideBars = function () {
18410			var _this = this;
18411			// Hide controllers if mouse doesn't move for some period
18412			setTimeout(function () {
18413				_this.outer.removeClass('lg-hide-items');
18414				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 18415-18545
18415					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
18416						_this.outer.removeClass('lg-hide-items');
18417						clearTimeout(_this.hideBarTimeout);
18418						// Timeout will be cleared on each slide movement also
18419						_this.hideBarTimeout = setTimeout(function () {
18420							_this.outer.addClass('lg-hide-items');
18421						}, _this.settings.hideBarsDelay);
18422					});
18423					_this.outer.trigger('mousemove.lg');
18424				}
18425			}, this.settings.showBarsAfter);
18426		};
18427		LightGallery.prototype.initPictureFill = function ($img) {
18428			if (this.settings.supportLegacyBrowser) {
18429				try {
18430					picturefill({
18431						elements: [$img.get()],
18432					});
18433				}
18434				catch (e) {
18435					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
18436				}
18437			}
18438		};
18439		/**
18440		 *  @desc Create image counter
18441		 *  Ex: 1/10
18442		 */
18443		LightGallery.prototype.counter = function () {
18444			if (this.settings.counter) {
18445				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>";
18446				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
18447			}
18448		};
18449		/**
18450		 *  @desc add sub-html into the slide
18451		 *  @param {Number} index - index of the slide
18452		 */
18453		LightGallery.prototype.addHtml = function (index) {
18454			var subHtml;
18455			var subHtmlUrl;
18456			if (this.galleryItems[index].subHtmlUrl) {
18457				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
18458			}
18459			else {
18460				subHtml = this.galleryItems[index].subHtml;
18461			}
18462			if (!subHtmlUrl) {
18463				if (subHtml) {
18464					// get first letter of sub-html
18465					// if first letter starts with . or # get the html form the jQuery object
18466					var fL = subHtml.substring(0, 1);
18467					if (fL === '.' || fL === '#') {
18468						if (this.settings.subHtmlSelectorRelative &&
18469							!this.settings.dynamic) {
18470							subHtml = $LG(this.items)
18471								.eq(index)
18472								.find(subHtml)
18473								.first()
18474								.html();
18475						}
18476						else {
18477							subHtml = $LG(subHtml).first().html();
18478						}
18479					}
18480				}
18481				else {
18482					subHtml = '';
18483				}
18484			}
18485			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18486				if (subHtmlUrl) {
18487					this.outer.find('.lg-sub-html').load(subHtmlUrl);
18488				}
18489				else {
18490					this.outer.find('.lg-sub-html').html(subHtml);
18491				}
18492			}
18493			else {
18494				var currentSlide = $LG(this.getSlideItemId(index));
18495				if (subHtmlUrl) {
18496					currentSlide.load(subHtmlUrl);
18497				}
18498				else {
18499					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
18500				}
18501			}
18502			// Add lg-empty-html class if title doesn't exist
18503			if (typeof subHtml !== 'undefined' && subHtml !== null) {
18504				if (subHtml === '') {
18505					this.outer
18506						.find(this.settings.appendSubHtmlTo)
18507						.addClass('lg-empty-html');
18508				}
18509				else {
18510					this.outer
18511						.find(this.settings.appendSubHtmlTo)
18512						.removeClass('lg-empty-html');
18513				}
18514			}
18515			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
18516				index: index,
18517			});
18518		};
18519		/**
18520		 *  @desc Preload slides
18521		 *  @param {Number} index - index of the slide
18522		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
18523		 */
18524		LightGallery.prototype.preload = function (index) {
18525			for (var i = 1; i <= this.settings.preload; i++) {
18526				if (i >= this.galleryItems.length - index) {
18527					break;
18528				}
18529				this.loadContent(index + i, false);
18530			}
18531			for (var j = 1; j <= this.settings.preload; j++) {
18532				if (index - j < 0) {
18533					break;
18534				}
18535				this.loadContent(index - j, false);
18536			}
18537		};
18538		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
18539			if (!imageSize)
18540				return '';
18541			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
18542		};
18543		LightGallery.prototype.getVideoContStyle = function (imageSize) {
18544			if (!imageSize)
18545				return '';
18546			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
18547		};
18548		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
18549			var $currentItem;
18550			if (!this.settings.dynamic) {
18551				$currentItem = $LG(this.items).eq(index);
18552			}
18553			if ($currentItem) {
18554				var _dummyImgSrc = void 0;
18555				if (!this.settings.exThumbImage) {
18556					_dummyImgSrc = $currentItem.find('img').first().attr('src');
18557				}
18558				else {
18559					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
18560				}
18561				if (!_dummyImgSrc)
18562					return '';
18563				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18564				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
18565				$currentSlide.addClass('lg-first-slide');
18566				this.outer.addClass('lg-first-slide-loading');
18567				return dummyImgContent;
18568			}
18569			return '';
18570		};
18571		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
18572			var currentGalleryItem = this.galleryItems[index];
18573			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18574			// Use the thumbnail as dummy image which will be resized to actual image size and
18575			// displayed on top of actual image
18576			var imgContent = '';
18577			var altAttr = alt ? 'alt="' + alt + '"' : '';
18578			if (this.isFirstSlideWithZoomAnimation()) {
18579				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
18580			}
18581			else {
18582				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
18583			}
18584			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
18585			$currentSlide.prepend(imgMarkup);
18586		};
18587		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
18588			var mediaObject = $slide.find('.lg-object').first();
18589			if (utils.isImageLoaded(mediaObject.get()) ||
18590				isHTML5VideoWithoutPoster) {
18591				onLoad();
18592			}
18593			else {
18594				mediaObject.on('load.lg error.lg', function () {
18595					onLoad && onLoad();
18596				});
18597				mediaObject.on('error.lg', function () {
18598					onError && onError();
18599				});
18600			}
18601		};
18602		/**
18603		 *
18604		 * @param $el Current slide item
18605		 * @param index
18606		 * @param delay Delay is 0 except first time
18607		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
18608		 * @param isFirstSlide
18609		 */
18610		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
18611			var _this = this;
18612			//Uncode edit ##START##
18613			var $item = _this.galleryItems[index],
18614				type = $item.type;
18615
18616			if ( typeof $item.src !== 'undefined' ) {
18617				var inline_id = $item.src.replace('#', ''),
18618					$inline = document.getElementById(inline_id),
18619					inline_html;
18620
18621				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18622					inline_html = $inline.innerHTML;
18623				} else {
18624					inline_html = '';
18625				}
18626			}
18627			//Uncode edit ##END##
18628			this.onSlideObjectLoad(currentSlide, true, function () {
18629				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
18630			}, function () {
18631				currentSlide.addClass('lg-complete lg-complete_');
18632				//Uncode edit ##START##
18633				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18634				if ( inline_html !== '' ) {
18635					currentSlide.html(inline_html);
18636				} else {
18637					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18638				}
18639				//Uncode edit ##END##
18640			});
18641		};
18642		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
18643			var _this = this;
18644			var currentGalleryItem = this.galleryItems[index];
18645			// Adding delay for video slides without poster for better performance and user experience
18646			// Videos should start playing once once the gallery is completely loaded
18647			var _speed = isFirstSlide &&
vendor: 37,932 bytes, lines 18648-19737
18648				this.getSlideType(currentGalleryItem) === 'video' &&
18649				!currentGalleryItem.poster
18650				? speed
18651				: 0;
18652			setTimeout(function () {
18653				$currentSlide.addClass('lg-complete lg-complete_');
18654				_this.LGel.trigger(lGEvents.slideItemLoad, {
18655					index: index,
18656					delay: delay || 0,
18657					isFirstSlide: isFirstSlide,
18658				});
18659			}, _speed);
18660		};
18661		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
18662			return !!(!this.lGalleryOn &&
18663				this.zoomFromOrigin &&
18664				this.currentImageSize);
18665		};
18666		// Add video slideInfo
18667		LightGallery.prototype.addSlideVideoInfo = function (items) {
18668			var _this = this;
18669			items.forEach(function (element, index) {
18670				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
18671				if (element.__slideVideoInfo &&
18672					_this.settings.loadYouTubePoster &&
18673					!element.poster &&
18674					element.__slideVideoInfo.youtube) {
18675					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
18676				}
18677			});
18678		};
18679		/**
18680		 *  Load slide content into slide.
18681		 *  This is used to load content into slides that is not visible too
18682		 *  @param {Number} index - index of the slide.
18683		 *  @param {Boolean} rec - if true call loadcontent() function again.
18684		 */
18685		LightGallery.prototype.loadContent = function (index, rec) {
18686			var _this = this;
18687			var currentGalleryItem = this.galleryItems[index];
18688			var $currentSlide = $LG(this.getSlideItemId(index));
18689			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18690			var src = currentGalleryItem.src;
18691			var video = currentGalleryItem.video;
18692			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
18693			if (currentGalleryItem.responsive) {
18694				var srcDyItms = currentGalleryItem.responsive.split(',');
18695				src = utils.getResponsiveSrc(srcDyItms) || src;
18696			}
18697			var videoInfo = currentGalleryItem.__slideVideoInfo;
18698			var lgVideoStyle = '';
18699			var iframe = !!currentGalleryItem.iframe;
18700			var isFirstSlide = !this.lGalleryOn;
18701			// delay for adding complete class. it is 0 except first time.
18702			var delay = 0;
18703			if (isFirstSlide) {
18704				if (this.zoomFromOrigin && this.currentImageSize) {
18705					delay = this.settings.startAnimationDuration + 10;
18706				}
18707				else {
18708					delay = this.settings.backdropDuration + 10;
18709				}
18710			}
18711			if (!$currentSlide.hasClass('lg-loaded')) {
18712				if (videoInfo) {
18713					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
18714					//Uncode edit ##START##
18715					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18716					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
18717					//Uncode edit ##END##
18718					lgVideoStyle = this.getVideoContStyle(videoSize);
18719				}
18720				if (iframe) {
18721					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18722					$currentSlide.prepend(markup);
18723				}
18724				else if (poster) {
18725					var dummyImg = '';
18726					var hasStartAnimation = isFirstSlide &&
18727						this.zoomFromOrigin &&
18728						this.currentImageSize;
18729					if (hasStartAnimation) {
18730						dummyImg = this.getDummyImageContent($currentSlide, index, '');
18731					}
18732					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18733					$currentSlide.prepend(markup);
18734				}
18735				//Uncode edit ##START##
18736				// else if (videoInfo) {
18737				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18738					if (! _html5Video) {
18739						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18740					}
18741					//Uncode edit ##END##
18742					$currentSlide.prepend(markup);
18743				}
18744				else {
18745					this.setImgMarkup(src, $currentSlide, index);
18746					if (srcset || sources) {
18747						var $img = $currentSlide.find('.lg-object');
18748						this.initPictureFill($img);
18749					}
18750				}
18751				if (poster || videoInfo) {
18752					this.LGel.trigger(lGEvents.hasVideo, {
18753						index: index,
18754						src: src,
18755						html5Video: _html5Video,
18756						hasPoster: !!poster,
18757					});
18758				}
18759				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18760				if (this.lGalleryOn &&
18761					this.settings.appendSubHtmlTo === '.lg-item') {
18762					this.addHtml(index);
18763				}
18764			}
18765			// For first time add some delay for displaying the start animation.
18766			var _speed = 0;
18767			// Do not change the delay value because it is required for zoom plugin.
18768			// If gallery opened from direct url (hash) speed value should be 0
18769			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18770				_speed = delay;
18771			}
18772			// Only for first slide and zoomFromOrigin is enabled
18773			if (this.isFirstSlideWithZoomAnimation()) {
18774				setTimeout(function () {
18775					$currentSlide
18776						.removeClass('lg-start-end-progress lg-start-progress')
18777						.removeAttr('style');
18778				}, this.settings.startAnimationDuration + 100);
18779				if (!$currentSlide.hasClass('lg-loaded')) {
18780					setTimeout(function () {
18781						if (_this.getSlideType(currentGalleryItem) === 'image') {
18782							var alt = currentGalleryItem.alt;
18783							var altAttr = alt ? 'alt="' + alt + '"' : '';
18784							$currentSlide
18785								.find('.lg-img-wrap')
18786								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
18787							if (srcset || sources) {
18788								var $img = $currentSlide.find('.lg-object');
18789								_this.initPictureFill($img);
18790							}
18791						}
18792						if (_this.getSlideType(currentGalleryItem) === 'image' ||
18793							(_this.getSlideType(currentGalleryItem) === 'video' &&
18794								poster)) {
18795							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18796							// load remaining slides once the slide is completely loaded
18797							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18798								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18799							}, function () {
18800								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18801							});
18802						}
18803					}, this.settings.startAnimationDuration + 100);
18804				}
18805			}
18806			// SLide content has been added to dom
18807			$currentSlide.addClass('lg-loaded');
18808			if (!this.isFirstSlideWithZoomAnimation() ||
18809				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18810				//Uncode edit ##START##
18811				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18812				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.getSlideType(currentGalleryItem) === 'audio'));
18813				//Uncode edit ##END##
18814			}
18815			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18816			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18817				$currentSlide.hasClass('lg-complete_') &&
18818				!this.lGalleryOn) {
18819				setTimeout(function () {
18820					$currentSlide.addClass('lg-complete');
18821				}, this.settings.backdropDuration);
18822			}
18823			// Content loaded
18824			// Need to set lGalleryOn before calling preload function
18825			this.lGalleryOn = true;
18826			if (rec === true) {
18827				if (!$currentSlide.hasClass('lg-complete_')) {
18828					$currentSlide
18829						.find('.lg-object')
18830						.first()
18831						.on('load.lg error.lg', function () {
18832						_this.preload(index);
18833					});
18834				}
18835				else {
18836					this.preload(index);
18837				}
18838			}
18839		};
18840		/**
18841		 * @desc Remove dummy image content and load next slides
18842		 * Called only for the first time if zoomFromOrigin animation is enabled
18843		 * @param index
18844		 * @param $currentSlide
18845		 * @param speed
18846		 */
18847		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18848			var _this = this;
18849			setTimeout(function () {
18850				$currentSlide.find('.lg-dummy-img').remove();
18851				$currentSlide.removeClass('lg-first-slide');
18852				_this.outer.removeClass('lg-first-slide-loading');
18853				_this.isDummyImageRemoved = true;
18854				_this.preload(index);
18855			}, speed + 300);
18856		};
18857		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18858			var _this = this;
18859			if (numberOfItems === void 0) { numberOfItems = 0; }
18860			var itemsToBeInsertedToDom = [];
18861			// Minimum 2 items should be there
18862			var possibleNumberOfItems = Math.max(numberOfItems, 3);
18863			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18864			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18865			if (this.galleryItems.length <= 3) {
18866				this.galleryItems.forEach(function (_element, index) {
18867					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18868				});
18869				return itemsToBeInsertedToDom;
18870			}
18871			if (index < (this.galleryItems.length - 1) / 2) {
18872				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18873					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18874				}
18875				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18876				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18877					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18878				}
18879			}
18880			else {
18881				for (var idx = index; idx <= this.galleryItems.length - 1 &&
18882					idx < index + possibleNumberOfItems / 2; idx++) {
18883					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18884				}
18885				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18886				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18887					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18888				}
18889			}
18890			if (this.settings.loop) {
18891				if (index === this.galleryItems.length - 1) {
18892					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18893				}
18894				else if (index === 0) {
18895					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18896				}
18897			}
18898			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18899				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18900			}
18901			return itemsToBeInsertedToDom;
18902		};
18903		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18904			var _this = this;
18905			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18906			itemsToBeInsertedToDom.forEach(function (item) {
18907				if (_this.currentItemsInDom.indexOf(item) === -1) {
18908					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18909				}
18910			});
18911			this.currentItemsInDom.forEach(function (item) {
18912				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18913					$LG("#" + item).remove();
18914				}
18915			});
18916			return itemsToBeInsertedToDom;
18917		};
18918		/**
18919		 * Get previous index of the slide
18920		 */
18921		LightGallery.prototype.getPreviousSlideIndex = function () {
18922			var prevIndex = 0;
18923			try {
18924				var currentItemId = this.outer
18925					.find('.lg-current')
18926					.first()
18927					.attr('id');
18928				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18929			}
18930			catch (error) {
18931				prevIndex = 0;
18932			}
18933			return prevIndex;
18934		};
18935		LightGallery.prototype.setDownloadValue = function (index) {
18936			if (this.settings.download) {
18937				var currentGalleryItem = this.galleryItems[index];
18938				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18939					currentGalleryItem.downloadUrl === 'false';
18940				if (hideDownloadBtn) {
18941					this.outer.addClass('lg-hide-download');
18942				}
18943				else {
18944					var $download = this.getElementById('lg-download');
18945					this.outer.removeClass('lg-hide-download');
18946					$download.attr('href', currentGalleryItem.downloadUrl ||
18947						currentGalleryItem.src);
18948					if (currentGalleryItem.download) {
18949						//Uncode edit ##START##
18950						var currentVideo, download_url, download_name;
18951						if ( currentGalleryItem.video ) {
18952							currentVideo = JSON.parse( currentGalleryItem.video );
18953							download_name = currentVideo.source[0].src;
18954							$download.attr('href', download_name).removeAttr('download');
18955						} else {
18956							download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src;
18957							download_name = download_url.substring(download_url.lastIndexOf('/')+1);
18958							$download.attr('download', download_name).removeAttr('href');
18959						}
18960						// $download.attr('download', currentGalleryItem.download);
18961						//Uncode edit ##END##
18962					}
18963				}
18964			}
18965		};
18966		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
18967			var _this = this;
18968			if (this.lGalleryOn) {
18969				previousSlideItem.addClass('lg-slide-progress');
18970			}
18971			setTimeout(function () {
18972				// remove all transitions
18973				_this.outer.addClass('lg-no-trans');
18974				_this.outer
18975					.find('.lg-item')
18976					.removeClass('lg-prev-slide lg-next-slide');
18977				if (direction === 'prev') {
18978					//prevslide
18979					currentSlideItem.addClass('lg-prev-slide');
18980					previousSlideItem.addClass('lg-next-slide');
18981				}
18982				else {
18983					// next slide
18984					currentSlideItem.addClass('lg-next-slide');
18985					previousSlideItem.addClass('lg-prev-slide');
18986				}
18987				// give 50 ms for browser to add/remove class
18988				setTimeout(function () {
18989					_this.outer.find('.lg-item').removeClass('lg-current');
18990					currentSlideItem.addClass('lg-current');
18991					// reset all transitions
18992					_this.outer.removeClass('lg-no-trans');
18993				}, 50);
18994			}, this.lGalleryOn ? this.settings.slideDelay : 0);
18995		};
18996		/**
18997		 * Goto a specific slide.
18998		 * @param {Number} index - index of the slide
18999		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
19000		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
19001		 * @param {String} direction - Direction of the slide(next/prev)
19002		 * @category lGPublicMethods
19003		 * @example
19004		 *  const plugin = lightGallery();
19005		 *  // to go to 3rd slide
19006		 *  plugin.slide(2);
19007		 *
19008		 */
19009		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
19010			var _this = this;
19011			var prevIndex = this.getPreviousSlideIndex();
19012			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
19013			// Prevent multiple call, Required for hsh plugin
19014			if (this.lGalleryOn && prevIndex === index) {
19015				return;
19016			}
19017			var numberOfGalleryItems = this.galleryItems.length;
19018			if (!this.lgBusy) {
19019				if (this.settings.counter) {
19020					this.updateCurrentCounter(index);
19021				}
19022				var currentSlideItem = this.getSlideItem(index);
19023				var previousSlideItem_1 = this.getSlideItem(prevIndex);
19024				var currentGalleryItem = this.galleryItems[index];
19025				var videoInfo = currentGalleryItem.__slideVideoInfo;
19026				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
19027				this.setDownloadValue(index);
19028				if (videoInfo) {
19029					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
19030					//Uncode edit ##START##
19031					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19032					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
19033					//Uncode edit ##END##
19034					this.resizeVideoSlide(index, videoSize);
19035				}
19036				this.LGel.trigger(lGEvents.beforeSlide, {
19037					prevIndex: prevIndex,
19038					index: index,
19039					fromTouch: !!fromTouch,
19040					fromThumb: !!fromThumb,
19041					//Uncode edit ##START##
19042					currentSlide: currentSlideItem,
19043					previousSlide: previousSlideItem_1,
19044					info: currentGalleryItem,
19045					item: this.items[index]
19046					//Uncode edit ##END##
19047				});
19048				this.lgBusy = true;
19049				clearTimeout(this.hideBarTimeout);
19050				this.arrowDisable(index);
19051				if (!direction) {
19052					if (index < prevIndex) {
19053						direction = 'prev';
19054					}
19055					else if (index > prevIndex) {
19056						direction = 'next';
19057					}
19058				}
19059				if (!fromTouch) {
19060					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
19061				}
19062				else {
19063					this.outer
19064						.find('.lg-item')
19065						.removeClass('lg-prev-slide lg-current lg-next-slide');
19066					var touchPrev = void 0;
19067					var touchNext = void 0;
19068					if (numberOfGalleryItems > 2) {
19069						touchPrev = index - 1;
19070						touchNext = index + 1;
19071						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
19072							// next slide
19073							touchNext = 0;
19074							touchPrev = numberOfGalleryItems - 1;
19075						}
19076						else if (index === numberOfGalleryItems - 1 &&
19077							prevIndex === 0) {
19078							// prev slide
19079							touchNext = 0;
19080							touchPrev = numberOfGalleryItems - 1;
19081						}
19082					}
19083					else {
19084						touchPrev = 0;
19085						touchNext = 1;
19086					}
19087					if (direction === 'prev') {
19088						this.getSlideItem(touchNext).addClass('lg-next-slide');
19089					}
19090					else {
19091						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
19092					}
19093					currentSlideItem.addClass('lg-current');
19094				}
19095				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
19096				if (!this.lGalleryOn) {
19097					this.loadContent(index, true);
19098				}
19099				else {
19100					setTimeout(function () {
19101						_this.loadContent(index, true);
19102						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
19103						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
19104							_this.addHtml(index);
19105						}
19106					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
19107				}
19108				setTimeout(function () {
19109					_this.lgBusy = false;
19110					previousSlideItem_1.removeClass('lg-slide-progress');
19111					_this.LGel.trigger(lGEvents.afterSlide, {
19112						prevIndex: prevIndex,
19113						index: index,
19114						fromTouch: fromTouch,
19115						fromThumb: fromThumb,
19116					});
19117				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
19118			}
19119			this.index = index;
19120		};
19121		LightGallery.prototype.updateCurrentCounter = function (index) {
19122			this.getElementById('lg-counter-current').html(index + 1 + '');
19123		};
19124		LightGallery.prototype.updateCounterTotal = function () {
19125			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
19126		};
19127		LightGallery.prototype.getSlideType = function (item) {
19128			if (item.__slideVideoInfo) {
19129				return 'video';
19130			}
19131			else if (item.iframe) {
19132				return 'iframe';
19133			}
19134			//Uncode edit ##START##
19135			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
19136				return 'audio';
19137			}
19138			//Uncode edit ##END##
19139			else {
19140				return 'image';
19141			}
19142		};
19143		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
19144			var distanceX = endCoords.pageX - startCoords.pageX;
19145			var distanceY = endCoords.pageY - startCoords.pageY;
19146			var allowSwipe = false;
19147			if (this.swipeDirection) {
19148				allowSwipe = true;
19149			}
19150			else {
19151				if (Math.abs(distanceX) > 15) {
19152					this.swipeDirection = 'horizontal';
19153					allowSwipe = true;
19154				}
19155				else if (Math.abs(distanceY) > 15) {
19156					this.swipeDirection = 'vertical';
19157					allowSwipe = true;
19158				}
19159			}
19160			if (!allowSwipe) {
19161				return;
19162			}
19163			var $currentSlide = this.getSlideItem(this.index);
19164			if (this.swipeDirection === 'horizontal') {
19165				e === null || e === void 0 ? void 0 : e.preventDefault();
19166				// reset opacity and transition duration
19167				this.outer.addClass('lg-dragging');
19168				// move current slide
19169				this.setTranslate($currentSlide, distanceX, 0);
19170				// move next and prev slide with current slide
19171				var width = $currentSlide.get().offsetWidth;
19172				var slideWidthAmount = (width * 15) / 100;
19173				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
19174				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
19175				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
19176			}
19177			else if (this.swipeDirection === 'vertical') {
19178				if (this.settings.swipeToClose) {
19179					e === null || e === void 0 ? void 0 : e.preventDefault();
19180					this.$container.addClass('lg-dragging-vertical');
19181					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
19182					this.$backdrop.css('opacity', opacity);
19183					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
19184					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
19185					if (Math.abs(distanceY) > 100) {
19186						this.outer
19187							.addClass('lg-hide-items')
19188							.removeClass('lg-components-open');
19189					}
19190				}
19191			}
19192		};
19193		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
19194			var _this = this;
19195			var distance;
19196			// keep slide animation for any mode while dragg/swipe
19197			if (this.settings.mode !== 'lg-slide') {
19198				this.outer.addClass('lg-slide');
19199			}
19200			// set transition duration
19201			setTimeout(function () {
19202				_this.$container.removeClass('lg-dragging-vertical');
19203				_this.outer
19204					.removeClass('lg-dragging lg-hide-items')
19205					.addClass('lg-components-open');
19206				var triggerClick = true;
19207				if (_this.swipeDirection === 'horizontal') {
19208					distance = endCoords.pageX - startCoords.pageX;
19209					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
19210					if (distance < 0 &&
19211						distanceAbs > _this.settings.swipeThreshold) {
19212						_this.goToNextSlide(true);
19213						triggerClick = false;
19214					}
19215					else if (distance > 0 &&
19216						distanceAbs > _this.settings.swipeThreshold) {
19217						_this.goToPrevSlide(true);
19218						triggerClick = false;
19219					}
19220				}
19221				else if (_this.swipeDirection === 'vertical') {
19222					distance = Math.abs(endCoords.pageY - startCoords.pageY);
19223					if (_this.settings.closable &&
19224						_this.settings.swipeToClose &&
19225						distance > 100) {
19226						_this.closeGallery();
19227						return;
19228					}
19229					else {
19230						_this.$backdrop.css('opacity', 1);
19231					}
19232				}
19233				_this.outer.find('.lg-item').removeAttr('style');
19234				if (triggerClick &&
19235					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
19236					// Trigger click if distance is less than 5 pix
19237					var target = $LG(event.target);
19238					if (_this.isPosterElement(target)) {
19239						_this.LGel.trigger(lGEvents.posterClick);
19240					}
19241				}
19242				_this.swipeDirection = undefined;
19243			});
19244			// remove slide class once drag/swipe is completed if mode is not slide
19245			setTimeout(function () {
19246				if (!_this.outer.hasClass('lg-dragging') &&
19247					_this.settings.mode !== 'lg-slide') {
19248					_this.outer.removeClass('lg-slide');
19249				}
19250			}, this.settings.speed + 100);
19251		};
19252		LightGallery.prototype.enableSwipe = function () {
19253			var _this = this;
19254			var startCoords = {};
19255			var endCoords = {};
19256			var isMoved = false;
19257			var isSwiping = false;
19258			if (this.settings.enableSwipe) {
19259				this.$inner.on('touchstart.lg', function (e) {
19260					_this.dragOrSwipeEnabled = true;
19261					var $item = _this.getSlideItem(_this.index);
19262					if (($LG(e.target).hasClass('lg-item') ||
19263						$item.get().contains(e.target)) &&
19264						!_this.outer.hasClass('lg-zoomed') &&
19265						!_this.lgBusy &&
19266						e.targetTouches.length === 1) {
19267						isSwiping = true;
19268						_this.touchAction = 'swipe';
19269						_this.manageSwipeClass();
19270						startCoords = {
19271							pageX: e.targetTouches[0].pageX,
19272							pageY: e.targetTouches[0].pageY,
19273						};
19274					}
19275				});
19276				this.$inner.on('touchmove.lg', function (e) {
19277					if (isSwiping &&
19278						_this.touchAction === 'swipe' &&
19279						e.targetTouches.length === 1) {
19280						endCoords = {
19281							pageX: e.targetTouches[0].pageX,
19282							pageY: e.targetTouches[0].pageY,
19283						};
19284						_this.touchMove(startCoords, endCoords, e);
19285						isMoved = true;
19286					}
19287				});
19288				this.$inner.on('touchend.lg', function (event) {
19289					if (_this.touchAction === 'swipe') {
19290						if (isMoved) {
19291							isMoved = false;
19292							_this.touchEnd(endCoords, startCoords, event);
19293						}
19294						else if (isSwiping) {
19295							var target = $LG(event.target);
19296							if (_this.isPosterElement(target)) {
19297								_this.LGel.trigger(lGEvents.posterClick);
19298							}
19299						}
19300						_this.touchAction = undefined;
19301						isSwiping = false;
19302					}
19303				});
19304			}
19305		};
19306		LightGallery.prototype.enableDrag = function () {
19307			var _this = this;
19308			var startCoords = {};
19309			var endCoords = {};
19310			var isDraging = false;
19311			var isMoved = false;
19312			if (this.settings.enableDrag) {
19313				this.outer.on('mousedown.lg', function (e) {
19314					_this.dragOrSwipeEnabled = true;
19315					var $item = _this.getSlideItem(_this.index);
19316					if ($LG(e.target).hasClass('lg-item') ||
19317						$item.get().contains(e.target)) {
19318						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
19319							e.preventDefault();
19320							if (!_this.lgBusy) {
19321								_this.manageSwipeClass();
19322								startCoords = {
19323									pageX: e.pageX,
19324									pageY: e.pageY,
19325								};
19326								isDraging = true;
19327								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
19328								_this.outer.get().scrollLeft += 1;
19329								_this.outer.get().scrollLeft -= 1;
19330								// *
19331								_this.outer
19332									.removeClass('lg-grab')
19333									.addClass('lg-grabbing');
19334								_this.LGel.trigger(lGEvents.dragStart);
19335							}
19336						}
19337					}
19338				});
19339				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
19340					if (isDraging && _this.lgOpened) {
19341						isMoved = true;
19342						endCoords = {
19343							pageX: e.pageX,
19344							pageY: e.pageY,
19345						};
19346						_this.touchMove(startCoords, endCoords);
19347						_this.LGel.trigger(lGEvents.dragMove);
19348					}
19349				});
19350				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
19351					if (!_this.lgOpened) {
19352						return;
19353					}
19354					var target = $LG(event.target);
19355					if (isMoved) {
19356						isMoved = false;
19357						_this.touchEnd(endCoords, startCoords, event);
19358						_this.LGel.trigger(lGEvents.dragEnd);
19359					}
19360					else if (_this.isPosterElement(target)) {
19361						_this.LGel.trigger(lGEvents.posterClick);
19362					}
19363					// Prevent execution on click
19364					if (isDraging) {
19365						isDraging = false;
19366						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
19367					}
19368				});
19369			}
19370		};
19371		LightGallery.prototype.triggerPosterClick = function () {
19372			var _this = this;
19373			this.$inner.on('click.lg', function (event) {
19374				if (!_this.dragOrSwipeEnabled &&
19375					_this.isPosterElement($LG(event.target))) {
19376					_this.LGel.trigger(lGEvents.posterClick);
19377				}
19378			});
19379		};
19380		LightGallery.prototype.manageSwipeClass = function () {
19381			var _touchNext = this.index + 1;
19382			var _touchPrev = this.index - 1;
19383			if (this.settings.loop && this.galleryItems.length > 2) {
19384				if (this.index === 0) {
19385					_touchPrev = this.galleryItems.length - 1;
19386				}
19387				else if (this.index === this.galleryItems.length - 1) {
19388					_touchNext = 0;
19389				}
19390			}
19391			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
19392			if (_touchPrev > -1) {
19393				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
19394			}
19395			this.getSlideItem(_touchNext).addClass('lg-next-slide');
19396		};
19397		/**
19398		 * Go to next slide
19399		 * @param {Boolean} fromTouch - true if slide function called via touch event
19400		 * @category lGPublicMethods
19401		 * @example
19402		 *  const plugin = lightGallery();
19403		 *  plugin.goToNextSlide();
19404		 * @see <a href="/demos/methods/">Demo</a>
19405		 */
19406		LightGallery.prototype.goToNextSlide = function (fromTouch) {
19407			var _this = this;
19408			var _loop = this.settings.loop;
19409			if (fromTouch && this.galleryItems.length < 3) {
19410				_loop = false;
19411			}
19412			if (!this.lgBusy) {
19413				if (this.index + 1 < this.galleryItems.length) {
19414					this.index++;
19415					this.LGel.trigger(lGEvents.beforeNextSlide, {
19416						index: this.index,
19417					});
19418					this.slide(this.index, !!fromTouch, false, 'next');
19419				}
19420				else {
19421					if (_loop) {
19422						this.index = 0;
19423						this.LGel.trigger(lGEvents.beforeNextSlide, {
19424							index: this.index,
19425						});
19426						this.slide(this.index, !!fromTouch, false, 'next');
19427					}
19428					else if (this.settings.slideEndAnimation && !fromTouch) {
19429						this.outer.addClass('lg-right-end');
19430						setTimeout(function () {
19431							_this.outer.removeClass('lg-right-end');
19432						}, 400);
19433					}
19434				}
19435			}
19436		};
19437		/**
19438		 * Go to previous slides
19439		 * @param {Boolean} fromTouch - true if slide function called via touch event
19440		 * @category lGPublicMethods
19441		 * @example
19442		 *  const plugin = lightGallery({});
19443		 *  plugin.goToPrevSlide();
19444		 * @see <a href="/demos/methods/">Demo</a>
19445		 *
19446		 */
19447		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
19448			var _this = this;
19449			var _loop = this.settings.loop;
19450			if (fromTouch && this.galleryItems.length < 3) {
19451				_loop = false;
19452			}
19453			if (!this.lgBusy) {
19454				if (this.index > 0) {
19455					this.index--;
19456					this.LGel.trigger(lGEvents.beforePrevSlide, {
19457						index: this.index,
19458						fromTouch: fromTouch,
19459					});
19460					this.slide(this.index, !!fromTouch, false, 'prev');
19461				}
19462				else {
19463					if (_loop) {
19464						this.index = this.galleryItems.length - 1;
19465						this.LGel.trigger(lGEvents.beforePrevSlide, {
19466							index: this.index,
19467							fromTouch: fromTouch,
19468						});
19469						this.slide(this.index, !!fromTouch, false, 'prev');
19470					}
19471					else if (this.settings.slideEndAnimation && !fromTouch) {
19472						this.outer.addClass('lg-left-end');
19473						setTimeout(function () {
19474							_this.outer.removeClass('lg-left-end');
19475						}, 400);
19476					}
19477				}
19478			}
19479		};
19480		LightGallery.prototype.keyPress = function () {
19481			var _this = this;
19482			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19483				if (_this.lgOpened &&
19484					_this.settings.escKey === true &&
19485					e.keyCode === 27) {
19486					e.preventDefault();
19487					if (_this.settings.allowMediaOverlap &&
19488						_this.outer.hasClass('lg-can-toggle') &&
19489						_this.outer.hasClass('lg-components-open')) {
19490						_this.outer.removeClass('lg-components-open');
19491					}
19492					else {
19493						_this.closeGallery();
19494					}
19495				}
19496				if (_this.lgOpened && _this.galleryItems.length > 1) {
19497					if (e.keyCode === 37) {
19498						e.preventDefault();
19499						_this.goToPrevSlide();
19500					}
19501					if (e.keyCode === 39) {
19502						e.preventDefault();
19503						_this.goToNextSlide();
19504					}
19505				}
19506			});
19507		};
19508		LightGallery.prototype.arrow = function () {
19509			var _this = this;
19510			this.getElementById('lg-prev').on('click.lg', function () {
19511				_this.goToPrevSlide();
19512			});
19513			this.getElementById('lg-next').on('click.lg', function () {
19514				_this.goToNextSlide();
19515			});
19516		};
19517		LightGallery.prototype.arrowDisable = function (index) {
19518			// Disable arrows if settings.hideControlOnEnd is true
19519			if (!this.settings.loop && this.settings.hideControlOnEnd) {
19520				var $prev = this.getElementById('lg-prev');
19521				var $next = this.getElementById('lg-next');
19522				if (index + 1 === this.galleryItems.length) {
19523					$next.attr('disabled', 'disabled').addClass('disabled');
19524				}
19525				else {
19526					$next.removeAttr('disabled').removeClass('disabled');
19527				}
19528				if (index === 0) {
19529					$prev.attr('disabled', 'disabled').addClass('disabled');
19530				}
19531				else {
19532					$prev.removeAttr('disabled').removeClass('disabled');
19533				}
19534			}
19535		};
19536		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
19537			if (scaleX === void 0) { scaleX = 1; }
19538			if (scaleY === void 0) { scaleY = 1; }
19539			$el.css('transform', 'translate3d(' +
19540				xValue +
19541				'px, ' +
19542				yValue +
19543				'px, 0px) scale3d(' +
19544				scaleX +
19545				', ' +
19546				scaleY +
19547				', 1)');
19548		};
19549		LightGallery.prototype.mousewheel = function () {
19550			var _this = this;
19551			var lastCall = 0;
19552			this.outer.on('wheel.lg', function (e) {
19553				if (!e.deltaY || _this.galleryItems.length < 2) {
19554					return;
19555				}
19556				e.preventDefault();
19557				var now = new Date().getTime();
19558				if (now - lastCall < 1000) {
19559					return;
19560				}
19561				lastCall = now;
19562				if (e.deltaY > 0) {
19563					_this.goToNextSlide();
19564				}
19565				else if (e.deltaY < 0) {
19566					_this.goToPrevSlide();
19567				}
19568			});
19569		};
19570		LightGallery.prototype.isSlideElement = function (target) {
19571			return (target.hasClass('lg-outer') ||
19572				target.hasClass('lg-item') ||
19573				target.hasClass('lg-img-wrap'));
19574		};
19575		LightGallery.prototype.isPosterElement = function (target) {
19576			var playButton = this.getSlideItem(this.index)
19577				.find('.lg-video-play-button')
19578				.get();
19579			return (target.hasClass('lg-video-poster') ||
19580				target.hasClass('lg-video-play-button') ||
19581				(playButton && playButton.contains(target.get())));
19582		};
19583		/**
19584		 * Maximize minimize inline gallery.
19585		 * @category lGPublicMethods
19586		 */
19587		LightGallery.prototype.toggleMaximize = function () {
19588			var _this = this;
19589			this.getElementById('lg-maximize').on('click.lg', function () {
19590				_this.$container.toggleClass('lg-inline');
19591				_this.refreshOnResize();
19592			});
19593		};
19594		LightGallery.prototype.invalidateItems = function () {
19595			for (var index = 0; index < this.items.length; index++) {
19596				var element = this.items[index];
19597				var $element = $LG(element);
19598				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
19599			}
19600		};
19601		LightGallery.prototype.trapFocus = function () {
19602			var _this = this;
19603			this.$container.get().focus({
19604				preventScroll: true,
19605			});
19606			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19607				if (!_this.lgOpened) {
19608					return;
19609				}
19610				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
19611				if (!isTabPressed) {
19612					return;
19613				}
19614				var focusableEls = utils.getFocusableElements(_this.$container.get());
19615				var firstFocusableEl = focusableEls[0];
19616				var lastFocusableEl = focusableEls[focusableEls.length - 1];
19617				if (e.shiftKey) {
19618					if (document.activeElement === firstFocusableEl) {
19619						lastFocusableEl.focus();
19620						e.preventDefault();
19621					}
19622				}
19623				else {
19624					if (document.activeElement === lastFocusableEl) {
19625						firstFocusableEl.focus();
19626						e.preventDefault();
19627					}
19628				}
19629			});
19630		};
19631		LightGallery.prototype.manageCloseGallery = function () {
19632			var _this = this;
19633			if (!this.settings.closable)
19634				return;
19635			var mousedown = false;
19636			this.getElementById('lg-close').on('click.lg', function () {
19637				_this.closeGallery();
19638			});
19639			if (this.settings.closeOnTap) {
19640				// If you drag the slide and release outside gallery gets close on chrome
19641				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
19642				this.outer.on('mousedown.lg', function (e) {
19643					var target = $LG(e.target);
19644					if (_this.isSlideElement(target)) {
19645						mousedown = true;
19646					}
19647					else {
19648						mousedown = false;
19649					}
19650				});
19651				this.outer.on('mousemove.lg', function () {
19652					mousedown = false;
19653				});
19654				this.outer.on('mouseup.lg', function (e) {
19655					var target = $LG(e.target);
19656					if (_this.isSlideElement(target) && mousedown) {
19657						if (!_this.outer.hasClass('lg-dragging')) {
19658							_this.closeGallery();
19659						}
19660					}
19661				});
19662			}
19663		};
19664		/**
19665		 * Close lightGallery if it is opened.
19666		 *
19667		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
19668		 * @return returns the estimated time to close gallery completely including the close animation duration
19669		 * @category lGPublicMethods
19670		 * @example
19671		 *  const plugin = lightGallery();
19672		 *  plugin.closeGallery();
19673		 *
19674		 */
19675		LightGallery.prototype.closeGallery = function (force) {
19676			var _this = this;
19677			if (!this.lgOpened || (!this.settings.closable && !force)) {
19678				return 0;
19679			}
19680			this.LGel.trigger(lGEvents.beforeClose);
19681			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
19682				$LG(window).scrollTop(this.prevScrollTop);
19683			}
19684			var currentItem = this.items[this.index];
19685			var transform;
19686			if (this.zoomFromOrigin && currentItem) {
19687				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
19688				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
19689				//Uncode edit ##START##
19690				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
19691				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
19692				//Uncode edit ##END##
19693				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
19694			}
19695			if (this.zoomFromOrigin && transform) {
19696				this.outer.addClass('lg-closing lg-zoom-from-image');
19697				this.getSlideItem(this.index)
19698					.addClass('lg-start-end-progress')
19699					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
19700					.css('transform', transform);
19701			}
19702			else {
19703				this.outer.addClass('lg-hide-items');
19704				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
19705				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
19706				this.outer.removeClass('lg-zoom-from-image');
19707			}
19708			// Unbind all events added by lightGallery
19709			// @todo
19710			//this.$el.off('.lg.tm');
19711			this.destroyModules();
19712			this.lGalleryOn = false;
19713			this.isDummyImageRemoved = false;
19714			this.zoomFromOrigin = this.settings.zoomFromOrigin;
19715			clearTimeout(this.hideBarTimeout);
19716			this.hideBarTimeout = false;
19717			$LG('html').removeClass('lg-on');
19718			this.outer.removeClass('lg-visible lg-components-open');
19719			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
19720			this.$backdrop.removeClass('in').css('opacity', 0);
19721			var removeTimeout = this.zoomFromOrigin && transform
19722				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
19723				: this.settings.backdropDuration;
19724			this.$container.removeClass('lg-show-in');
19725			// Once the closign animation is completed and gallery is invisible
19726			setTimeout(function () {
19727				if (_this.zoomFromOrigin && transform) {
19728					_this.outer.removeClass('lg-zoom-from-image');
19729				}
19730				_this.$container.removeClass('lg-show');
19731				// Reset scrollbar
19732				_this.resetScrollBar();
19733				// Need to remove inline opacity as it is used in the stylesheet as well
19734				_this.$backdrop
19735					.removeAttr('style')
19736					.css('transition-duration', _this.settings.backdropDuration + 'ms');
19737				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 19738-19941
19738				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
19739				_this.$inner.empty();
19740				if (_this.lgOpened) {
19741					_this.LGel.trigger(lGEvents.afterClose, {
19742						instance: _this,
19743					});
19744				}
19745				if (_this.$container.get()) {
19746					_this.$container.get().blur();
19747				}
19748				_this.lgOpened = false;
19749			}, removeTimeout + 100);
19750			return removeTimeout + 100;
19751		};
19752		LightGallery.prototype.initModules = function () {
19753			this.plugins.forEach(function (module) {
19754				try {
19755					module.init();
19756				}
19757				catch (err) {
19758					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
19759				}
19760			});
19761		};
19762		LightGallery.prototype.destroyModules = function (destroy) {
19763			this.plugins.forEach(function (module) {
19764				try {
19765					if (destroy) {
19766						module.destroy();
19767					}
19768					else {
19769						module.closeGallery && module.closeGallery();
19770					}
19771				}
19772				catch (err) {
19773					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19774				}
19775			});
19776		};
19777		/**
19778		 * Refresh lightGallery with new set of children.
19779		 *
19780		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19781		 *
19782		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19783		 * @see <a href="/demos/dynamic-mode/">Demo</a>
19784		 * @category lGPublicMethods
19785		 * @example
19786		 *  const plugin = lightGallery();
19787		 *  // Delete or add children, then call
19788		 *  plugin.refresh();
19789		 *
19790		 */
19791		LightGallery.prototype.refresh = function (galleryItems) {
19792			if (!this.settings.dynamic) {
19793				this.invalidateItems();
19794			}
19795			if (galleryItems) {
19796				this.galleryItems = galleryItems;
19797			}
19798			else {
19799				this.galleryItems = this.getItems();
19800			}
19801			this.updateControls();
19802			this.openGalleryOnItemClick();
19803			this.LGel.trigger(lGEvents.updateSlides);
19804		};
19805		LightGallery.prototype.updateControls = function () {
19806			this.addSlideVideoInfo(this.galleryItems);
19807			this.updateCounterTotal();
19808			this.manageSingleSlideClassName();
19809		};
19810		/**
19811		 * Destroy lightGallery.
19812		 * Destroy lightGallery and its plugin instances completely
19813		 *
19814		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19815		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19816		 * You can use refresh method most of the times.
19817		 * @category lGPublicMethods
19818		 * @example
19819		 *  const plugin = lightGallery();
19820		 *  plugin.destroy();
19821		 *
19822		 */
19823		LightGallery.prototype.destroy = function () {
19824			var _this = this;
19825			var closeTimeout = this.closeGallery(true);
19826			setTimeout(function () {
19827				_this.destroyModules(true);
19828				if (!_this.settings.dynamic) {
19829					_this.invalidateItems();
19830				}
19831				$LG(window).off(".lg.global" + _this.lgId);
19832				_this.LGel.off('.lg');
19833				_this.$container.remove();
19834			}, closeTimeout);
19835			return closeTimeout;
19836		};
19837		return LightGallery;
19838	}());
19839
19840	function lightGallery(el, options) {
19841		return new LightGallery(el, options);
19842	}
19843
19844	return lightGallery;
19845
19846})));
19847
19848/*!
19849 * lightgallery | 2.5.0 | June 13th 2022
19850 * http://www.lightgalleryjs.com/
19851 * Copyright (c) 2020 Sachin Neravath;
19852 * @license GPLv3
19853 */
19854
19855(function (global, factory) {
19856	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19857	typeof define === 'function' && define.amd ? define(factory) :
19858	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19859}(this, (function () { 'use strict';
19860
19861	/*! *****************************************************************************
19862	Copyright (c) Microsoft Corporation.
19863
19864	Permission to use, copy, modify, and/or distribute this software for any
19865	purpose with or without fee is hereby granted.
19866
19867	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19868	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19869	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19870	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19871	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19872	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19873	PERFORMANCE OF THIS SOFTWARE.
19874	***************************************************************************** */
19875
19876	var __assign = function() {
19877		__assign = Object.assign || function __assign(t) {
19878			for (var s, i = 1, n = arguments.length; i < n; i++) {
19879				s = arguments[i];
19880				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19881			}
19882			return t;
19883		};
19884		return __assign.apply(this, arguments);
19885	};
19886
19887	var zoomSettings = {
19888		scale: 1,
19889		zoom: true,
19890		actualSize: true,
19891		showZoomInOutIcons: false,
19892		actualSizeIcons: {
19893			zoomIn: 'lg-zoom-in',
19894			zoomOut: 'lg-zoom-out',
19895		},
19896		enableZoomAfter: 300,
19897		zoomPluginStrings: {
19898			zoomIn: 'Zoom in',
19899			zoomOut: 'Zoom out',
19900			viewActualSize: 'View actual size',
19901		},
19902	};
19903
19904	/**
19905	 * List of lightGallery events
19906	 * All events should be documented here
19907	 * Below interfaces are used to build the website documentations
19908	 * */
19909	var lGEvents = {
19910		afterAppendSlide: 'lgAfterAppendSlide',
19911		init: 'lgInit',
19912		hasVideo: 'lgHasVideo',
19913		containerResize: 'lgContainerResize',
19914		updateSlides: 'lgUpdateSlides',
19915		afterAppendSubHtml: 'lgAfterAppendSubHtml',
19916		beforeOpen: 'lgBeforeOpen',
19917		afterOpen: 'lgAfterOpen',
19918		slideItemLoad: 'lgSlideItemLoad',
19919		beforeSlide: 'lgBeforeSlide',
19920		afterSlide: 'lgAfterSlide',
19921		posterClick: 'lgPosterClick',
19922		dragStart: 'lgDragStart',
19923		dragMove: 'lgDragMove',
19924		dragEnd: 'lgDragEnd',
19925		beforeNextSlide: 'lgBeforeNextSlide',
19926		beforePrevSlide: 'lgBeforePrevSlide',
19927		beforeClose: 'lgBeforeClose',
19928		afterClose: 'lgAfterClose',
19929		rotateLeft: 'lgRotateLeft',
19930		rotateRight: 'lgRotateRight',
19931		flipHorizontal: 'lgFlipHorizontal',
19932		flipVertical: 'lgFlipVertical',
19933		autoplay: 'lgAutoplay',
19934		autoplayStart: 'lgAutoplayStart',
19935		autoplayStop: 'lgAutoplayStop',
19936	};
19937
19938	var Zoom = /** @class */ (function () {
19939		function Zoom(instance, $LG) {
19940			// get lightGallery core plugin instance
19941			this.core = instance;
19942			this.$LG = $LG;
19943			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19944			return this;
19945		}
19946		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
19947		Zoom.prototype.buildTemplates = function () {
19948			var zoomIcons = this.settings.showZoomInOutIcons
19949				? "<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>"
19950				: '';
19951			if (this.settings.actualSize) {
19952				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>";
19953			}
19954			this.core.outer.addClass('lg-use-transition-for-zoom');
19955			this.core.$toolbar.first().append(zoomIcons);
19956		};
19957		/**
19958		 * @desc Enable zoom option only once the image is completely loaded
19959		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
19960		 *
19961		 * Zoom styles are defined under lg-zoomable CSS class.
19962		 */
19963		Zoom.prototype.enableZoom = function (event) {
19964			var _this = this;
19965			// delay will be 0 except first time
19966			var _speed = this.settings.enableZoomAfter + event.detail.delay;
19967			// set _speed value 0 if gallery opened from direct url and if it is first slide
19968			if (this.$LG('body').first().hasClass('lg-from-hash') &&
19969				event.detail.delay) {
19970				// will execute only once
19971				_speed = 0;
19972			}
19973			else {
19974				// Remove lg-from-hash to enable starting animation.
19975				this.$LG('body').first().removeClass('lg-from-hash');
19976			}
19977			this.zoomableTimeout = setTimeout(function () {
19978				if (!_this.isImageSlide()) {
19979					return;
19980				}
19981				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
19982				if (event.detail.index === _this.core.index) {
19983					_this.setZoomEssentials();
19984				}
19985			}, _speed + 30);
19986		};
19987		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
19988			// Add zoomable class
19989			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
19990		};
19991		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
19992			var originalRotate = rotateValue;
19993			rotateValue = Math.abs(rotateValue);
19994			var transformValues = this.getCurrentTransform(el);
19995			if (!transformValues) {
19996				return 1;
19997			}
19998			var modifier = 1;
19999			if (axis === 'X') {
20000				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
20001				if (rotateValue === 0 || rotateValue === 180) {
20002					modifier = 1;
20003				}
20004				else if (rotateValue === 90) {
20005					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
20006						(originalRotate === 90 && flipHorizontalValue === -1)) {
20007						modifier = -1;
20008					}
20009					else {
20010						modifier = 1;
20011					}
20012				}
20013				modifier = modifier * flipHorizontalValue;
20014			}
20015			else {
20016				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
20017				if (rotateValue === 0 || rotateValue === 180) {
20018					modifier = 1;
20019				}
20020				else if (rotateValue === 90) {
20021					var sinX = parseFloat(transformValues[1]);
20022					var sinMinusX = parseFloat(transformValues[2]);
20023					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
20024				}
20025				modifier = modifier * flipVerticalValue;
20026			}
20027			return modifier;
20028		};
20029		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
20030			var imageSizes = {
20031				y: 'offsetHeight',
20032				x: 'offsetWidth',
20033			};
20034			if (Math.abs(rotateValue) === 90) {
20035				// Swap axis
20036				if (axis === 'x') {
20037					axis = 'y';
20038				}
20039				else {
20040					axis = 'x';
20041				}
20042			}
20043			return $image[imageSizes[axis]];
20044		};
20045		Zoom.prototype.getDragCords = function (e, rotateValue) {
20046			if (rotateValue === 90) {
20047				return {
20048					x: e.pageY,
20049					y: e.pageX,
20050				};
20051			}
20052			else {
20053				return {
20054					x: e.pageX,
20055					y: e.pageY,
20056				};
20057			}
20058		};
20059		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
20060			var x = e.targetTouches[0].pageX;
20061			var y = e.targetTouches[0].pageY;
20062			if (rotateValue === 90) {
20063				return {
20064					x: y,
20065					y: x,
20066				};
20067			}
20068			else {
20069				return {
20070					x: x,
20071					y: y,
20072				};
20073			}
20074		};
20075		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
20076			scale = scale || this.scale || 1;
20077			var allowY = this.imageYSize * scale > this.containerRect.height;
20078			var allowX = this.imageXSize * scale > this.containerRect.width;
20079			if (rotateValue === 90) {
20080				return {
20081					allowX: allowY,
20082					allowY: allowX,
20083				};
20084			}
20085			else {
20086				return {
20087					allowX: allowX,
20088					allowY: allowY,
20089				};
20090			}
20091		};
20092		/**
20093		 *
20094		 * @param {Element} el
20095		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
20096		 * Get the current transform value
20097		 */
20098		Zoom.prototype.getCurrentTransform = function (el) {
20099			if (!el) {
20100				return;
20101			}
20102			var st = window.getComputedStyle(el, null);
20103			var tm = st.getPropertyValue('-webkit-transform') ||
20104				st.getPropertyValue('-moz-transform') ||
20105				st.getPropertyValue('-ms-transform') ||
20106				st.getPropertyValue('-o-transform') ||
20107				st.getPropertyValue('transform') ||
20108				'none';
20109			if (tm !== 'none') {
20110				return tm.split('(')[1].split(')')[0].split(',');
20111			}
20112			return;
20113		};
20114		Zoom.prototype.getCurrentRotation = function (el) {
20115			if (!el) {
20116				return 0;
20117			}
20118			var values = this.getCurrentTransform(el);
20119			if (values) {
20120				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
20121					(180 / Math.PI));
20122				// If you want rotate in 360
20123				//return (angle < 0 ? angle + 360 : angle);
20124			}
20125			return 0;
20126		};
20127		Zoom.prototype.setZoomEssentials = function () {
20128			var $image = this.core
20129				.getSlideItem(this.core.index)
20130				.find('.lg-image')
20131				.first();
20132			var rotateEl = this.core
20133				.getSlideItem(this.core.index)
20134				.find('.lg-img-rotate')
20135				.first()
20136				.get();
20137			this.rotateValue = this.getCurrentRotation(rotateEl);
20138			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
20139			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
20140			this.containerRect = this.core.outer.get().getBoundingClientRect();
20141			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
20142			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
20143		};
20144		/**
20145		 * @desc Image zoom
20146		 * Translate the wrap and scale the image to get better user experience
20147		 *
20148		 * @param {String} scale - Zoom decrement/increment value
20149		 */
20150		Zoom.prototype.zoomImage = function (scale) {
20151			// Find offset manually to avoid issue after zoom
20152			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
20153				this.containerRect.left;
20154			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20155			var topBottomSpacing = Math.abs(top - bottom) / 2;
20156			var offsetY = (this.containerRect.height -
20157				this.imageYSize -
20158				topBottomSpacing * this.modifierX) /
20159				2 +
20160				this.scrollTop +
20161				this.containerRect.top;
20162			var originalX;
20163			var originalY;
20164			if (scale === 1) {
20165				this.positionChanged = false;
20166			}
20167			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
20168			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
20169			if (this.positionChanged) {
20170				originalX = this.left / (this.scale - 1);
20171				originalY = this.top / (this.scale - 1);
20172				this.pageX = Math.abs(originalX) + offsetX;
20173				this.pageY = Math.abs(originalY) + offsetY;
20174				this.positionChanged = false;
20175			}
20176			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
20177			var _x = offsetX - this.pageX;
20178			var _y = offsetY - this.pageY;
20179			var x = (scale - 1) * _x;
20180			var y = (scale - 1) * _y;
20181			if (allowX) {
20182				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
20183					x = possibleSwipeCords.minX;
20184				}
20185				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
20186					x = possibleSwipeCords.maxX;
20187				}
20188			}
20189			else {
20190				if (scale > 1) {
20191					if (x < possibleSwipeCords.minX) {
20192						x = possibleSwipeCords.minX;
20193					}
20194					else if (x > possibleSwipeCords.maxX) {
20195						x = possibleSwipeCords.maxX;
20196					}
20197				}
20198			}
20199			if (allowY) {
20200				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
20201					y = possibleSwipeCords.minY;
20202				}
20203				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
20204					y = possibleSwipeCords.maxY;
20205				}
20206			}
20207			else {
20208				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
20209				if (scale > 1) {
20210					//If image goes beyond viewport top, use the minim possible translate value
20211					if (y < possibleSwipeCords.minY) {
20212						y = possibleSwipeCords.minY;
20213					}
20214					else if (y > possibleSwipeCords.maxY) {
20215						y = possibleSwipeCords.maxY;
20216					}
20217				}
20218			}
20219			this.setZoomStyles({
20220				x: x,
20221				y: y,
20222				scale: scale,
20223			});
20224		};
20225		/**
20226		 * @desc apply scale3d to image and translate to image wrap
20227		 * @param {style} X,Y and scale
20228		 */
20229		Zoom.prototype.setZoomStyles = function (style) {
20230			var $image = this.core
20231				.getSlideItem(this.core.index)
20232				.find('.lg-image')
20233				.first();
20234			var $dummyImage = this.core.outer
20235				.find('.lg-current .lg-dummy-img')
20236				.first();
20237			var $imageWrap = $image.parent();
20238			this.scale = style.scale;
20239			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20240			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20241			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
20242			$imageWrap.css('transform', transform);
20243			this.left = style.x;
20244			this.top = style.y;
20245		};
20246		/**
20247		 * @param index - Index of the current slide
20248		 * @param event - event will be available only if the function is called on clicking/taping the imags
20249		 */
20250		Zoom.prototype.setActualSize = function (index, event) {
20251			var _this = this;
20252			// Allow zoom only on image
20253			if (!this.isImageSlide() ||
20254				this.core.outer.hasClass('lg-first-slide-loading')) {
20255				return;
20256			}
20257			var scale = this.getCurrentImageActualSizeScale();
20258			if (this.core.outer.hasClass('lg-zoomed')) {
20259				this.scale = 1;
20260			}
20261			else {
20262				this.scale = this.getScale(scale);
20263			}
20264			this.setPageCords(event);
20265			this.beginZoom(this.scale);
20266			this.zoomImage(this.scale);
20267			setTimeout(function () {
20268				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20269			}, 10);
20270		};
20271		Zoom.prototype.getNaturalWidth = function (index) {
20272			var $image = this.core.getSlideItem(index).find('.lg-image').first();
20273			var naturalWidth = this.core.galleryItems[index].width;
20274			return naturalWidth
20275				? parseFloat(naturalWidth)
20276				: $image.get().naturalWidth;
20277		};
20278		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
20279			var _scale;
20280			var scale;
20281			if (naturalWidth > width) {
20282				_scale = naturalWidth / width;
20283				scale = _scale || 2;
20284			}
20285			else {
20286				scale = 1;
20287			}
20288			return scale;
20289		};
20290		Zoom.prototype.getCurrentImageActualSizeScale = function () {
20291			var $image = this.core
20292				.getSlideItem(this.core.index)
20293				.find('.lg-image')
20294				.first();
20295			var width = $image.get().offsetWidth;
20296			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
20297			return this.getActualSizeScale(naturalWidth, width);
20298		};
20299		Zoom.prototype.getPageCords = function (event) {
20300			var cords = {};
20301			if (event) {
20302				cords.x = event.pageX || event.targetTouches[0].pageX;
20303				cords.y = event.pageY || event.targetTouches[0].pageY;
20304			}
20305			else {
20306				var containerRect = this.core.outer.get().getBoundingClientRect();
20307				cords.x = containerRect.width / 2 + containerRect.left;
20308				cords.y =
20309					containerRect.height / 2 + this.scrollTop + containerRect.top;
20310			}
20311			return cords;
20312		};
20313		Zoom.prototype.setPageCords = function (event) {
20314			var pageCords = this.getPageCords(event);
20315			this.pageX = pageCords.x;
20316			this.pageY = pageCords.y;
20317		};
20318		// If true, zoomed - in else zoomed out
20319		Zoom.prototype.beginZoom = function (scale) {
20320			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20321			if (scale > 1) {
20322				this.core.outer.addClass('lg-zoomed');
20323				var $actualSize = this.core.getElementById('lg-actual-size');
20324				$actualSize
20325					.removeClass(this.settings.actualSizeIcons.zoomIn)
20326					.addClass(this.settings.actualSizeIcons.zoomOut);
20327			}
20328			else {
20329				this.resetZoom();
20330			}
20331			return scale > 1;
20332		};
20333		Zoom.prototype.getScale = function (scale) {
20334			var actualSizeScale = this.getCurrentImageActualSizeScale();
20335			if (scale < 1) {
20336				scale = 1;
20337			}
20338			else if (scale > actualSizeScale) {
20339				scale = actualSizeScale;
20340			}
20341			return scale;
20342		};
20343		Zoom.prototype.init = function () {
20344			var _this = this;
20345			if (!this.settings.zoom) {
20346				return;
20347			}
20348			this.buildTemplates();
20349			this.enableZoomOnSlideItemLoad();
20350			var tapped = null;
20351			this.core.outer.on('dblclick.lg', function (event) {
20352				if (!_this.$LG(event.target).hasClass('lg-image')) {
20353					return;
20354				}
20355				_this.setActualSize(_this.core.index, event);
20356			});
20357			this.core.outer.on('touchstart.lg', function (event) {
20358				var $target = _this.$LG(event.target);
20359				if (event.targetTouches.length === 1 &&
20360					$target.hasClass('lg-image')) {
20361					if (!tapped) {
20362						tapped = setTimeout(function () {
20363							tapped = null;
20364						}, 300);
20365					}
20366					else {
20367						clearTimeout(tapped);
20368						tapped = null;
20369						event.preventDefault();
20370						_this.setActualSize(_this.core.index, event);
20371					}
20372				}
20373			});
20374			// Update zoom on resize and orientationchange
20375			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
20376				if (!_this.core.lgOpened || !_this.isImageSlide())
20377					return;
20378				_this.setPageCords();
20379				_this.setZoomEssentials();
20380				_this.zoomImage(_this.scale);
20381			});
20382			// Update zoom on resize and orientationchange
20383			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
20384				if (!_this.core.lgOpened)
20385					return;
20386				_this.scrollTop = _this.$LG(window).scrollTop();
20387			});
20388			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
20389				if (_this.core.outer.find('.lg-current .lg-image').get()) {
20390					_this.scale -= _this.settings.scale;
20391					_this.scale = _this.getScale(_this.scale);
20392					_this.beginZoom(_this.scale);
20393					_this.zoomImage(_this.scale);
20394				}
20395			});
20396			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
20397				_this.zoomIn();
20398			});
20399			this.core.getElementById('lg-actual-size').on('click.lg', function () {
20400				_this.setActualSize(_this.core.index);
20401			});
20402			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
20403				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
20404			});
20405			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
20406				_this.scrollTop = _this.$LG(window).scrollTop();
20407				// Set the initial value center
20408				_this.pageX = _this.core.outer.width() / 2;
20409				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
20410				_this.scale = 1;
20411			});
20412			// Reset zoom on slide change
20413			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
20414				var prevIndex = event.detail.prevIndex;
20415				_this.scale = 1;
20416				_this.positionChanged = false;
20417				_this.resetZoom(prevIndex);
20418				if (_this.isImageSlide()) {
20419					_this.setZoomEssentials();
20420				}
20421			});
20422			// Drag option after zoom
20423			this.zoomDrag();
20424			this.pinchZoom();
20425			this.zoomSwipe();
20426			// Store the zoomable timeout value just to clear it while closing
20427			this.zoomableTimeout = false;
20428			this.positionChanged = false;
20429		};
20430		Zoom.prototype.zoomIn = function (scale) {
20431			// Allow zoom only on image
20432			if (!this.isImageSlide()) {
20433				return;
20434			}
20435			if (scale) {
20436				this.scale = scale;
20437			}
20438			else {
20439				this.scale += this.settings.scale;
20440			}
20441			this.scale = this.getScale(this.scale);
20442			this.beginZoom(this.scale);
20443			this.zoomImage(this.scale);
20444		};
20445		// Reset zoom effect
20446		Zoom.prototype.resetZoom = function (index) {
20447			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
20448			var $actualSize = this.core.getElementById('lg-actual-size');
20449			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
20450			$actualSize
20451				.removeClass(this.settings.actualSizeIcons.zoomOut)
20452				.addClass(this.settings.actualSizeIcons.zoomIn);
20453			$item.find('.lg-img-wrap').first().removeAttr('style');
20454			$item.find('.lg-image').first().removeAttr('style');
20455			this.scale = 1;
20456			this.left = 0;
20457			this.top = 0;
20458			// Reset pagx pagy values to center
20459			this.setPageCords();
20460		};
20461		Zoom.prototype.getTouchDistance = function (e) {
20462			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
20463				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
20464				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
20465					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
20466		};
20467		Zoom.prototype.pinchZoom = function () {
20468			var _this = this;
20469			var startDist = 0;
20470			var pinchStarted = false;
20471			var initScale = 1;
20472			var $item = this.core.getSlideItem(this.core.index);
20473			this.core.$inner.on('touchstart.lg', function (e) {
20474				$item = _this.core.getSlideItem(_this.core.index);
20475				if (!_this.isImageSlide()) {
20476					return;
20477				}
20478				if (e.targetTouches.length === 2 &&
20479					!_this.core.outer.hasClass('lg-first-slide-loading') &&
20480					(_this.$LG(e.target).hasClass('lg-item') ||
20481						$item.get().contains(e.target))) {
20482					initScale = _this.scale || 1;
20483					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20484					_this.core.touchAction = 'pinch';
20485					startDist = _this.getTouchDistance(e);
20486				}
20487			});
20488			this.core.$inner.on('touchmove.lg', function (e) {
20489				if (e.targetTouches.length === 2 &&
20490					_this.core.touchAction === 'pinch' &&
20491					(_this.$LG(e.target).hasClass('lg-item') ||
20492						$item.get().contains(e.target))) {
20493					e.preventDefault();
20494					var endDist = _this.getTouchDistance(e);
20495					var distance = startDist - endDist;
20496					if (!pinchStarted && Math.abs(distance) > 5) {
20497						pinchStarted = true;
20498					}
20499					if (pinchStarted) {
20500						_this.scale = Math.max(1, initScale + -distance * 0.008);
20501						_this.zoomImage(_this.scale);
20502					}
20503				}
20504			});
20505			this.core.$inner.on('touchend.lg', function (e) {
20506				if (_this.core.touchAction === 'pinch' &&
20507					(_this.$LG(e.target).hasClass('lg-item') ||
20508						$item.get().contains(e.target))) {
20509					pinchStarted = false;
20510					startDist = 0;
20511					if (_this.scale <= 1) {
20512						_this.resetZoom();
20513					}
20514					else {
20515						_this.scale = _this.getScale(_this.scale);
20516						_this.zoomImage(_this.scale);
20517						_this.core.outer.addClass('lg-zoomed');
20518					}
20519					_this.core.touchAction = undefined;
20520				}
20521			});
20522		};
20523		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
20524			var distanceXnew = endCoords.x - startCoords.x;
20525			var distanceYnew = endCoords.y - startCoords.y;
20526			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
20527			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
20528			if (speedX > 2) {
20529				speedX += 1;
20530			}
20531			if (speedY > 2) {
20532				speedY += 1;
20533			}
20534			distanceXnew = distanceXnew * speedX;
20535			distanceYnew = distanceYnew * speedY;
20536			var _LGel = this.core
20537				.getSlideItem(this.core.index)
20538				.find('.lg-img-wrap')
20539				.first();
20540			var distance = {};
20541			distance.x = this.left + distanceXnew * this.modifierX;
20542			distance.y = this.top + distanceYnew * this.modifierY;
20543			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
20544			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
20545				if (allowY) {
20546					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20547						distance.y = possibleSwipeCords.minY;
20548					}
20549					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20550						distance.y = possibleSwipeCords.maxY;
20551					}
20552				}
20553				if (allowX) {
20554					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20555						distance.x = possibleSwipeCords.minX;
20556					}
20557					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20558						distance.x = possibleSwipeCords.maxX;
20559					}
20560				}
20561				if (allowY) {
20562					this.top = distance.y;
20563				}
20564				else {
20565					distance.y = this.top;
20566				}
20567				if (allowX) {
20568					this.left = distance.x;
20569				}
20570				else {
20571					distance.x = this.left;
20572				}
20573				this.setZoomSwipeStyles(_LGel, distance);
20574				this.positionChanged = true;
20575			}
20576		};
20577		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
20578			var distance = {};
20579			if (allowY) {
20580				distance.y =
20581					this.top + (endCoords.y - startCoords.y) * this.modifierY;
20582				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20583					var diffMinY = possibleSwipeCords.minY - distance.y;
20584					distance.y = possibleSwipeCords.minY - diffMinY / 6;
20585				}
20586				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20587					var diffMaxY = distance.y - possibleSwipeCords.maxY;
20588					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
20589				}
20590			}
20591			else {
20592				distance.y = this.top;
20593			}
20594			if (allowX) {
20595				distance.x =
20596					this.left + (endCoords.x - startCoords.x) * this.modifierX;
20597				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20598					var diffMinX = possibleSwipeCords.minX - distance.x;
20599					distance.x = possibleSwipeCords.minX - diffMinX / 6;
20600				}
20601				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20602					var difMaxX = distance.x - possibleSwipeCords.maxX;
20603					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
20604				}
20605			}
20606			else {
20607				distance.x = this.left;
20608			}
20609			return distance;
20610		};
20611		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
20612			return x >= minX;
20613		};
20614		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
20615			return x <= maxX;
20616		};
20617		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
20618			return y >= minY;
20619		};
20620		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
20621			return y <= maxY;
20622		};
20623		Zoom.prototype.isImageSlide = function () {
20624			var currentItem = this.core.galleryItems[this.core.index];
20625			return this.core.getSlideType(currentItem) === 'image';
20626		};
20627		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
20628			var dataScale = scale || this.scale || 1;
20629			var elDataScale = Math.abs(dataScale);
20630			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20631			var topBottomSpacing = Math.abs(top - bottom) / 2;
20632			var minY = (this.imageYSize - this.containerRect.height) / 2 +
20633				topBottomSpacing * this.modifierX;
20634			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
20635			var minX = (this.imageXSize - this.containerRect.width) / 2;
20636			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
20637			var possibleSwipeCords = {
20638				minY: minY,
20639				maxY: maxY,
20640				minX: minX,
20641				maxX: maxX,
20642			};
20643			if (Math.abs(rotateValue) === 90) {
20644				possibleSwipeCords = {
20645					minY: minX,
20646					maxY: maxX,
20647					minX: minY,
20648					maxX: maxY,
20649				};
20650			}
20651			return possibleSwipeCords;
20652		};
20653		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
20654			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
20655		};
20656		Zoom.prototype.zoomSwipe = function () {
20657			var _this = this;
20658			var startCoords = {};
20659			var endCoords = {};
20660			var isMoved = false;
20661			// Allow x direction drag
20662			var allowX = false;
20663			// Allow Y direction drag
20664			var allowY = false;
20665			var startTime = new Date();
20666			var endTime = new Date();
20667			var possibleSwipeCords;
20668			var _LGel;
20669			var $item = this.core.getSlideItem(this.core.index);
20670			this.core.$inner.on('touchstart.lg', function (e) {
20671				// Allow zoom only on image
20672				if (!_this.isImageSlide()) {
20673					return;
20674				}
20675				$item = _this.core.getSlideItem(_this.core.index);
20676				if ((_this.$LG(e.target).hasClass('lg-item') ||
20677					$item.get().contains(e.target)) &&
20678					e.targetTouches.length === 1 &&
20679					_this.core.outer.hasClass('lg-zoomed')) {
20680					e.preventDefault();
20681					startTime = new Date();
20682					_this.core.touchAction = 'zoomSwipe';
20683					_LGel = _this.core
20684						.getSlideItem(_this.core.index)
20685						.find('.lg-img-wrap')
20686						.first();
20687					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20688					allowY = dragAllowedAxises.allowY;
20689					allowX = dragAllowedAxises.allowX;
20690					if (allowX || allowY) {
20691						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20692					}
20693					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20694					// reset opacity and transition duration
20695					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
20696				}
20697			});
20698			this.core.$inner.on('touchmove.lg', function (e) {
20699				if (e.targetTouches.length === 1 &&
20700					_this.core.touchAction === 'zoomSwipe' &&
20701					(_this.$LG(e.target).hasClass('lg-item') ||
20702						$item.get().contains(e.target))) {
20703					e.preventDefault();
20704					_this.core.touchAction = 'zoomSwipe';
20705					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20706					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20707					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
20708						Math.abs(endCoords.y - startCoords.y) > 15) {
20709						isMoved = true;
20710						_this.setZoomSwipeStyles(_LGel, distance);
20711					}
20712				}
20713			});
20714			this.core.$inner.on('touchend.lg', function (e) {
20715				if (_this.core.touchAction === 'zoomSwipe' &&
20716					(_this.$LG(e.target).hasClass('lg-item') ||
20717						$item.get().contains(e.target))) {
20718					_this.core.touchAction = undefined;
20719					_this.core.outer.removeClass('lg-zoom-dragging');
20720					if (!isMoved) {
20721						return;
20722					}
20723					isMoved = false;
20724					endTime = new Date();
20725					var touchDuration = endTime.valueOf() - startTime.valueOf();
20726					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20727				}
20728			});
20729		};
20730		Zoom.prototype.zoomDrag = function () {
20731			var _this = this;
20732			var startCoords = {};
20733			var endCoords = {};
20734			var isDragging = false;
20735			var isMoved = false;
20736			// Allow x direction drag
20737			var allowX = false;
20738			// Allow Y direction drag
20739			var allowY = false;
20740			var startTime;
20741			var endTime;
20742			var possibleSwipeCords;
20743			var _LGel;
20744			this.core.outer.on('mousedown.lg.zoom', function (e) {
20745				// Allow zoom only on image
20746				if (!_this.isImageSlide()) {
20747					return;
20748				}
20749				var $item = _this.core.getSlideItem(_this.core.index);
20750				if (_this.$LG(e.target).hasClass('lg-item') ||
20751					$item.get().contains(e.target)) {
20752					startTime = new Date();
20753					_LGel = _this.core
20754						.getSlideItem(_this.core.index)
20755						.find('.lg-img-wrap')
20756						.first();
20757					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20758					allowY = dragAllowedAxises.allowY;
20759					allowX = dragAllowedAxises.allowX;
20760					if (_this.core.outer.hasClass('lg-zoomed')) {
20761						if (_this.$LG(e.target).hasClass('lg-object') &&
20762							(allowX || allowY)) {
20763							e.preventDefault();
20764							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20765							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20766							isDragging = true;
20767							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20768							_this.core.outer.get().scrollLeft += 1;
20769							_this.core.outer.get().scrollLeft -= 1;
20770							_this.core.outer
20771								.removeClass('lg-grab')
20772								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20773							// reset opacity and transition duration
20774						}
20775					}
20776				}
20777			});
20778			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20779				if (isDragging) {
20780					isMoved = true;
20781					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20782					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20783					_this.setZoomSwipeStyles(_LGel, distance);
20784				}
20785			});
20786			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20787				if (isDragging) {
20788					endTime = new Date();
20789					isDragging = false;
20790					_this.core.outer.removeClass('lg-zoom-dragging');
20791					// Fix for chrome mouse move on click
20792					if (isMoved &&
20793						(startCoords.x !== endCoords.x ||
20794							startCoords.y !== endCoords.y)) {
20795						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20796						var touchDuration = endTime.valueOf() - startTime.valueOf();
20797						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20798					}
20799					isMoved = false;
20800				}
20801				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20802			});
20803		};
20804		Zoom.prototype.closeGallery = function () {
20805			this.resetZoom();
20806		};
20807		Zoom.prototype.destroy = function () {
20808			// Unbind all events added by lightGallery zoom plugin
20809			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20810			this.core.LGel.off('.lg.zoom');
20811			this.core.LGel.off('.zoom');
20812			clearTimeout(this.zoomableTimeout);
20813			this.zoomableTimeout = false;
20814		};
20815		return Zoom;
20816	}());
20817
20818	return Zoom;
20819
20820})));
20821/*!
20822 * lightgallery | 2.5.0 | June 13th 2022
20823 * http://www.lightgalleryjs.com/
20824 * Copyright (c) 2020 Sachin Neravath;
20825 * @license GPLv3
20826 */
20827
20828(function (global, factory) {
20829	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20830	typeof define === 'function' && define.amd ? define(factory) :
20831	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20832}(this, (function () { 'use strict';
20833
20834	/*! *****************************************************************************
20835	Copyright (c) Microsoft Corporation.
20836
20837	Permission to use, copy, modify, and/or distribute this software for any
20838	purpose with or without fee is hereby granted.
20839
20840	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20841	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20842	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20843	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20844	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20845	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20846	PERFORMANCE OF THIS SOFTWARE.
20847	***************************************************************************** */
20848
20849	var __assign = function() {
20850		__assign = Object.assign || function __assign(t) {
20851			for (var s, i = 1, n = arguments.length; i < n; i++) {
20852				s = arguments[i];
20853				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20854			}
20855			return t;
20856		};
20857		return __assign.apply(this, arguments);
20858	};
20859
20860	var fullscreenSettings = {
20861		fullScreen: true,
20862		fullscreenPluginStrings: {
20863			toggleFullscreen: 'Toggle Fullscreen',
20864		},
20865	};
20866
20867	var FullScreen = /** @class */ (function () {
20868		function FullScreen(instance, $LG) {
20869			// get lightGallery core plugin instance
20870			this.core = instance;
20871			this.$LG = $LG;
20872			// extend module default settings with lightGallery core settings
20873			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20874			return this;
20875		}
20876		FullScreen.prototype.init = function () {
20877			var fullScreen = '';
20878			if (this.settings.fullScreen) {
20879				// check for fullscreen browser support
20880				if (!document.fullscreenEnabled &&
20881					!document.webkitFullscreenEnabled &&
20882					!document.mozFullScreenEnabled &&
20883					!document.msFullscreenEnabled) {
20884					return;
20885				}
20886				else {
20887					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20888					this.core.$toolbar.append(fullScreen);
20889					this.fullScreen();
20890				}
20891			}
20892		};
20893		FullScreen.prototype.isFullScreen = function () {
20894			return (document.fullscreenElement ||
20895				document.mozFullScreenElement ||
20896				document.webkitFullscreenElement ||
20897				document.msFullscreenElement);
20898		};
20899		FullScreen.prototype.requestFullscreen = function () {
20900			var el = document.documentElement;
20901			if (el.requestFullscreen) {
20902				el.requestFullscreen();
20903			}
20904			else if (el.msRequestFullscreen) {
20905				el.msRequestFullscreen();
20906			}
20907			else if (el.mozRequestFullScreen) {
20908				el.mozRequestFullScreen();
20909			}
20910			else if (el.webkitRequestFullscreen) {
20911				el.webkitRequestFullscreen();
20912			}
20913		};
20914		FullScreen.prototype.exitFullscreen = function () {
20915			if (document.exitFullscreen) {
20916				document.exitFullscreen();
20917			}
20918			else if (document.msExitFullscreen) {
20919				document.msExitFullscreen();
20920			}
20921			else if (document.mozCancelFullScreen) {
20922				document.mozCancelFullScreen();
20923			}
20924			else if (document.webkitExitFullscreen) {
20925				document.webkitExitFullscreen();
20926			}
20927		};
20928		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20929		FullScreen.prototype.fullScreen = function () {
20930			var _this = this;
20931			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 () {
20932				if (!_this.core.lgOpened)
20933					return;
20934				_this.core.outer.toggleClass('lg-fullscreen-on');
20935			});
20936			this.core.outer
20937				.find('.lg-fullscreen')
20938				.first()
20939				.on('click.lg', function () {
20940				if (_this.isFullScreen()) {
20941					_this.exitFullscreen();
20942				}
20943				else {
20944					_this.requestFullscreen();
20945				}
20946			});
20947		};
20948		FullScreen.prototype.closeGallery = function () {
20949			// exit from fullscreen if activated
20950			if (this.isFullScreen()) {
20951				this.exitFullscreen();
20952			}
20953		};
20954		FullScreen.prototype.destroy = function () {
20955			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);
20956		};
20957		return FullScreen;
20958	}());
20959
20960	return FullScreen;
20961
20962})));
20963
20964/*!
20965 * lightgallery | 2.5.0 | June 13th 2022
20966 * http://www.lightgalleryjs.com/
20967 * Copyright (c) 2020 Sachin Neravath;
20968 * @license GPLv3
20969 */
20970
20971(function (global, factory) {
20972	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20973	typeof define === 'function' && define.amd ? define(factory) :
20974	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
20975}(this, (function () { 'use strict';
20976
20977	/*! *****************************************************************************
20978	Copyright (c) Microsoft Corporation.
20979
20980	Permission to use, copy, modify, and/or distribute this software for any
20981	purpose with or without fee is hereby granted.
20982
20983	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20984	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20985	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20986	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20987	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20988	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20989	PERFORMANCE OF THIS SOFTWARE.
20990	***************************************************************************** */
20991
20992	var __assign = function() {
20993		__assign = Object.assign || function __assign(t) {
20994			for (var s, i = 1, n = arguments.length; i < n; i++) {
20995				s = arguments[i];
20996				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20997			}
20998			return t;
20999		};
21000		return __assign.apply(this, arguments);
21001	};
21002
21003	/**
21004	 * List of lightGallery events
21005	 * All events should be documented here
21006	 * Below interfaces are used to build the website documentations
21007	 * */
21008	var lGEvents = {
21009		afterAppendSlide: 'lgAfterAppendSlide',
21010		init: 'lgInit',
21011		hasVideo: 'lgHasVideo',
21012		containerResize: 'lgContainerResize',
21013		updateSlides: 'lgUpdateSlides',
21014		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21015		beforeOpen: 'lgBeforeOpen',
21016		afterOpen: 'lgAfterOpen',
21017		slideItemLoad: 'lgSlideItemLoad',
21018		beforeSlide: 'lgBeforeSlide',
21019		afterSlide: 'lgAfterSlide',
21020		posterClick: 'lgPosterClick',
21021		dragStart: 'lgDragStart',
21022		dragMove: 'lgDragMove',
21023		dragEnd: 'lgDragEnd',
21024		beforeNextSlide: 'lgBeforeNextSlide',
21025		beforePrevSlide: 'lgBeforePrevSlide',
21026		beforeClose: 'lgBeforeClose',
21027		afterClose: 'lgAfterClose',
21028		rotateLeft: 'lgRotateLeft',
21029		rotateRight: 'lgRotateRight',
21030		flipHorizontal: 'lgFlipHorizontal',
21031		flipVertical: 'lgFlipVertical',
21032		autoplay: 'lgAutoplay',
21033		autoplayStart: 'lgAutoplayStart',
21034		autoplayStop: 'lgAutoplayStop',
21035	};
21036
21037	var hashSettings = {
21038		hash: true,
21039		galleryId: '1',
21040		customSlideName: false,
21041	};
21042
21043	var Hash = /** @class */ (function () {
21044		function Hash(instance, $LG) {
21045			// get lightGallery core plugin instance
21046			this.core = instance;
21047			this.$LG = $LG;
21048			// extend module default settings with lightGallery core settings
21049			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
21050			return this;
21051		}
21052		Hash.prototype.init = function () {
21053			var _this = this;
21054			if (!this.settings.hash) {
21055				return;
21056			}
21057			this.oldHash = window.location.hash;
21058			setTimeout(function () {
21059				_this.buildFromHash();
21060			}, 100);
21061			// Change hash value on after each slide transition
21062			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
21063			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
21064			// Listen hash change and change the slide according to slide value
21065			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
21066		};
21067		Hash.prototype.onAfterSlide = function (event) {
21068			var slideName = this.core.galleryItems[event.detail.index].slideName;
21069			slideName = this.settings.customSlideName
21070				? slideName || event.detail.index
21071				: event.detail.index;
21072			if (history.replaceState) {
21073				history.replaceState(null, '', window.location.pathname +
21074					window.location.search +
21075					'#lg=' +
21076					this.settings.galleryId +
21077					'&slide=' +
21078					slideName);
21079			}
21080			else {
21081				window.location.hash =
21082					'lg=' + this.settings.galleryId + '&slide=' + slideName;
21083			}
21084		};
21085		/**
21086		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
21087		 * @param {String} hash
21088		 * @returns {Number} Index of the slide.
21089		 */
21090		Hash.prototype.getIndexFromUrl = function (hash) {
21091			if (hash === void 0) { hash = window.location.hash; }
21092			var slideName = hash.split('&slide=')[1];
21093			var _idx = 0;
21094			if (this.settings.customSlideName) {
21095				for (var index = 0; index < this.core.galleryItems.length; index++) {
21096					var dynamicEl = this.core.galleryItems[index];
21097					if (dynamicEl.slideName === slideName) {
21098						_idx = index;
21099						break;
21100					}
21101				}
21102			}
21103			else {
21104				_idx = parseInt(slideName, 10);
21105			}
21106			return isNaN(_idx) ? 0 : _idx;
21107		};
21108		// Build Gallery if gallery id exist in the URL
21109		Hash.prototype.buildFromHash = function () {
21110			// if dynamic option is enabled execute immediately
21111			var _hash = window.location.hash;
21112			//Uncode edit ##START##
21113			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
21114			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
21115			//Uncode edit ##END##
21116				// This class is used to remove the initial animation if galleryId present in the URL
21117				this.$LG(document.body).addClass('lg-from-hash');
21118				var index = this.getIndexFromUrl(_hash);
21119				this.core.openGallery(index);
21120				return true;
21121			}
21122		};
21123		Hash.prototype.onCloseAfter = function () {
21124			// Reset to old hash value
21125			if (this.oldHash &&
21126				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
21127				if (history.replaceState) {
21128					history.replaceState(null, '', this.oldHash);
21129				}
21130				else {
21131					window.location.hash = this.oldHash;
21132				}
21133			}
21134			else {
21135				if (history.replaceState) {
21136					history.replaceState(null, document.title, window.location.pathname + window.location.search);
21137				}
21138				else {
21139					window.location.hash = '';
21140				}
21141			}
21142		};
21143		Hash.prototype.onHashchange = function () {
21144			if (!this.core.lgOpened)
21145				return;
21146			var _hash = window.location.hash;
21147			var index = this.getIndexFromUrl(_hash);
21148			// it galleryId doesn't exist in the url close the gallery
21149			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
21150				this.core.slide(index, false, false);
21151			}
21152			else if (this.core.lGalleryOn) {
21153				this.core.closeGallery();
21154			}
21155		};
21156		Hash.prototype.closeGallery = function () {
21157			if (this.settings.hash) {
21158				this.$LG(document.body).removeClass('lg-from-hash');
21159			}
21160		};
21161		Hash.prototype.destroy = function () {
21162			this.core.LGel.off('.lg.hash');
21163			this.core.LGel.off('.hash');
21164			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
21165		};
21166		return Hash;
21167	}());
21168
21169	return Hash;
21170
21171})));
21172/*!
21173 * lightgallery | 2.5.0 | June 13th 2022
21174 * http://www.lightgalleryjs.com/
21175 * Copyright (c) 2020 Sachin Neravath;
21176 * @license GPLv3
21177 */
21178
21179(function (global, factory) {
21180	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21181	typeof define === 'function' && define.amd ? define(factory) :
21182	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
21183}(this, (function () { 'use strict';
21184
21185	/*! *****************************************************************************
21186	Copyright (c) Microsoft Corporation.
21187
21188	Permission to use, copy, modify, and/or distribute this software for any
21189	purpose with or without fee is hereby granted.
21190
21191	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21192	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21193	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21194	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21195	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21196	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21197	PERFORMANCE OF THIS SOFTWARE.
21198	***************************************************************************** */
21199
21200	var __assign = function() {
21201		__assign = Object.assign || function __assign(t) {
21202			for (var s, i = 1, n = arguments.length; i < n; i++) {
21203				s = arguments[i];
21204				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21205			}
21206			return t;
21207		};
21208		return __assign.apply(this, arguments);
21209	};
21210
21211	function __spreadArrays() {
21212		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
21213		for (var r = Array(s), k = 0, i = 0; i < il; i++)
21214			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
21215				r[k] = a[j];
21216		return r;
21217	}
21218
21219	var shareSettings = {
21220		share: true,
21221		facebook: true,
21222		facebookDropdownText: 'Facebook',
21223		twitter: true,
21224		twitterDropdownText: 'Twitter',
21225		pinterest: true,
21226		pinterestDropdownText: 'Pinterest',
21227		additionalShareOptions: [],
21228		sharePluginStrings: { share: 'Share' },
21229	};
21230
21231	function getFacebookShareLink(galleryItem) {
21232		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
21233		return (facebookBaseUrl +
21234			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
21235	}
21236
21237	function getTwitterShareLink(galleryItem) {
21238		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
21239		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
21240		var text = galleryItem.tweetText;
21241		return twitterBaseUrl + text + '&url=' + url;
21242	}
21243
21244	function getPinterestShareLink(galleryItem) {
21245		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
21246		var description = galleryItem.pinterestText;
21247		var media = encodeURIComponent(galleryItem.src);
21248		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
21249		return (pinterestBaseUrl +
21250			url +
21251			'&media=' +
21252			media +
21253			'&description=' +
21254			description);
21255	}
21256
21257	/**
21258	 * List of lightGallery events
21259	 * All events should be documented here
21260	 * Below interfaces are used to build the website documentations
21261	 * */
21262	var lGEvents = {
21263		afterAppendSlide: 'lgAfterAppendSlide',
21264		init: 'lgInit',
21265		hasVideo: 'lgHasVideo',
21266		containerResize: 'lgContainerResize',
21267		updateSlides: 'lgUpdateSlides',
21268		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21269		beforeOpen: 'lgBeforeOpen',
21270		afterOpen: 'lgAfterOpen',
21271		slideItemLoad: 'lgSlideItemLoad',
21272		beforeSlide: 'lgBeforeSlide',
21273		afterSlide: 'lgAfterSlide',
21274		posterClick: 'lgPosterClick',
21275		dragStart: 'lgDragStart',
21276		dragMove: 'lgDragMove',
21277		dragEnd: 'lgDragEnd',
21278		beforeNextSlide: 'lgBeforeNextSlide',
21279		beforePrevSlide: 'lgBeforePrevSlide',
21280		beforeClose: 'lgBeforeClose',
21281		afterClose: 'lgAfterClose',
21282		rotateLeft: 'lgRotateLeft',
21283		rotateRight: 'lgRotateRight',
21284		flipHorizontal: 'lgFlipHorizontal',
21285		flipVertical: 'lgFlipVertical',
21286		autoplay: 'lgAutoplay',
21287		autoplayStart: 'lgAutoplayStart',
21288		autoplayStop: 'lgAutoplayStop',
21289	};
21290
21291	var Share = /** @class */ (function () {
21292		function Share(instance) {
21293			this.shareOptions = [];
21294			// get lightGallery core plugin instance
21295			this.core = instance;
21296			// extend module default settings with lightGallery core settings
21297			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
21298			return this;
21299		}
21300		Share.prototype.init = function () {
21301			if (!this.settings.share) {
21302				return;
21303			}
21304			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
21305			this.setLgShareMarkup();
21306			this.core.outer
21307				.find('.lg-share .lg-dropdown')
21308				.append(this.getShareListHtml());
21309			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
21310		};
21311		Share.prototype.getShareListHtml = function () {
21312			var shareHtml = '';
21313			this.shareOptions.forEach(function (shareOption) {
21314				shareHtml += shareOption.dropdownHTML;
21315			});
21316			return shareHtml;
21317		};
21318		Share.prototype.setLgShareMarkup = function () {
21319			var _this = this;
21320			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>");
21321			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
21322			var $shareButton = this.core.outer.find('.lg-share');
21323			$shareButton.first().on('click.lg', function () {
21324				_this.core.outer.toggleClass('lg-dropdown-active');
21325				if (_this.core.outer.hasClass('lg-dropdown-active')) {
21326					_this.core.outer.attr('aria-expanded', true);
21327				}
21328				else {
21329					_this.core.outer.attr('aria-expanded', false);
21330				}
21331			});
21332			this.core.outer
21333				.find('.lg-dropdown-overlay')
21334				.first()
21335				.on('click.lg', function () {
21336				_this.core.outer.removeClass('lg-dropdown-active');
21337				_this.core.outer.attr('aria-expanded', false);
21338			});
21339		};
21340		Share.prototype.onAfterSlide = function (event) {
21341			var _this = this;
21342			var index = event.detail.index;
21343			var currentItem = this.core.galleryItems[index];
21344			setTimeout(function () {
21345				_this.shareOptions.forEach(function (shareOption) {
21346					var selector = shareOption.selector;
21347					_this.core.outer
21348						.find(selector)
21349						.attr('href', shareOption.generateLink(currentItem));
21350				});
21351			}, 100);
21352		};
21353		Share.prototype.getShareListItemHTML = function (type, text) {
21354			return "<li><a class=\"lg-share-" + type + "\" rel=\"noopener\" target=\"_blank\"><span class=\"lg-icon\"></span><span class=\"lg-dropdown-text\">" + text + "</span></a></li>";
21355		};
21356		Share.prototype.getDefaultShareOptions = function () {
21357			return __spreadArrays((this.settings.facebook
21358				? [
21359					{
21360						type: 'facebook',
21361						generateLink: getFacebookShareLink,
21362						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
21363						selector: '.lg-share-facebook',
21364					},
21365				]
21366				: []), (this.settings.twitter
21367				? [
21368					{
21369						type: 'twitter',
21370						generateLink: getTwitterShareLink,
21371						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
21372						selector: '.lg-share-twitter',
21373					},
21374				]
21375				: []), (this.settings.pinterest
21376				? [
21377					{
21378						type: 'pinterest',
21379						generateLink: getPinterestShareLink,
21380						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
21381						selector: '.lg-share-pinterest',
21382					},
21383				]
21384				: []));
21385		};
21386		Share.prototype.destroy = function () {
21387			this.core.outer.find('.lg-dropdown-overlay').remove();
21388			this.core.outer.find('.lg-share').remove();
21389			this.core.LGel.off('.lg.share');
21390			this.core.LGel.off('.share');
21391		};
21392		return Share;
21393	}());
21394
21395	return Share;
21396
21397})));
21398/*!
21399 * lightgallery | 2.5.0 | June 13th 2022
21400 * http://www.lightgalleryjs.com/
21401 * Copyright (c) 2020 Sachin Neravath;
21402 * @license GPLv3
21403 */
21404
21405(function (global, factory) {
21406	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21407	typeof define === 'function' && define.amd ? define(factory) :
21408	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
21409}(this, (function () { 'use strict';
21410
21411	/*! *****************************************************************************
21412	Copyright (c) Microsoft Corporation.
21413
21414	Permission to use, copy, modify, and/or distribute this software for any
21415	purpose with or without fee is hereby granted.
21416
21417	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21418	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21419	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21420	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21421	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21422	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21423	PERFORMANCE OF THIS SOFTWARE.
21424	***************************************************************************** */
21425
21426	var __assign = function() {
21427		__assign = Object.assign || function __assign(t) {
21428			for (var s, i = 1, n = arguments.length; i < n; i++) {
21429				s = arguments[i];
21430				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21431			}
21432			return t;
21433		};
21434		return __assign.apply(this, arguments);
21435	};
21436
21437	var thumbnailsSettings = {
21438		thumbnail: true,
21439		animateThumb: true,
21440		currentPagerPosition: 'middle',
21441		alignThumbnails: 'middle',
21442		thumbWidth: 100,
21443		thumbHeight: '80px',
21444		thumbMargin: 5,
21445		appendThumbnailsTo: '.lg-components',
21446		toggleThumb: false,
21447		enableThumbDrag: true,
21448		enableThumbSwipe: true,
21449		thumbnailSwipeThreshold: 10,
21450		loadYouTubeThumbnail: true,
21451		youTubeThumbSize: 1,
21452		thumbnailPluginStrings: {
21453			toggleThumbnails: 'Toggle thumbnails',
21454		},
21455	};
21456
21457	/**
21458	 * List of lightGallery events
21459	 * All events should be documented here
21460	 * Below interfaces are used to build the website documentations
21461	 * */
21462	var lGEvents = {
21463		afterAppendSlide: 'lgAfterAppendSlide',
21464		init: 'lgInit',
21465		hasVideo: 'lgHasVideo',
21466		containerResize: 'lgContainerResize',
21467		updateSlides: 'lgUpdateSlides',
21468		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21469		beforeOpen: 'lgBeforeOpen',
21470		afterOpen: 'lgAfterOpen',
21471		slideItemLoad: 'lgSlideItemLoad',
21472		beforeSlide: 'lgBeforeSlide',
21473		afterSlide: 'lgAfterSlide',
21474		posterClick: 'lgPosterClick',
21475		dragStart: 'lgDragStart',
21476		dragMove: 'lgDragMove',
21477		dragEnd: 'lgDragEnd',
21478		beforeNextSlide: 'lgBeforeNextSlide',
21479		beforePrevSlide: 'lgBeforePrevSlide',
21480		beforeClose: 'lgBeforeClose',
21481		afterClose: 'lgAfterClose',
21482		rotateLeft: 'lgRotateLeft',
21483		rotateRight: 'lgRotateRight',
21484		flipHorizontal: 'lgFlipHorizontal',
21485		flipVertical: 'lgFlipVertical',
21486		autoplay: 'lgAutoplay',
21487		autoplayStart: 'lgAutoplayStart',
21488		autoplayStop: 'lgAutoplayStop',
21489	};
21490
21491	var Thumbnail = /** @class */ (function () {
21492		function Thumbnail(instance, $LG) {
21493			this.thumbOuterWidth = 0;
21494			this.thumbTotalWidth = 0;
21495			this.translateX = 0;
21496			this.thumbClickable = false;
21497			// get lightGallery core plugin instance
21498			this.core = instance;
21499			this.$LG = $LG;
21500			return this;
21501		}
21502		Thumbnail.prototype.init = function () {
21503			// extend module default settings with lightGallery core settings
21504			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
21505			this.thumbOuterWidth = 0;
21506			this.thumbTotalWidth =
21507				this.core.galleryItems.length *
21508					(this.settings.thumbWidth + this.settings.thumbMargin);
21509			// Thumbnail animation value
21510			this.translateX = 0;
21511			this.setAnimateThumbStyles();
21512			if (!this.core.settings.allowMediaOverlap) {
21513				this.settings.toggleThumb = false;
21514			}
21515			if (this.settings.thumbnail) {
21516				this.build();
21517				if (this.settings.animateThumb) {
21518					if (this.settings.enableThumbDrag) {
21519						this.enableThumbDrag();
21520					}
21521					if (this.settings.enableThumbSwipe) {
21522						this.enableThumbSwipe();
21523					}
21524					this.thumbClickable = false;
21525				}
21526				else {
21527					this.thumbClickable = true;
21528				}
21529				this.toggleThumbBar();
21530				this.thumbKeyPress();
21531			}
21532		};
21533		Thumbnail.prototype.build = function () {
21534			var _this = this;
21535			this.setThumbMarkup();
21536			this.manageActiveClassOnSlideChange();
21537			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
21538				var $target = _this.$LG(e.target);
21539				if (!$target.hasAttribute('data-lg-item-id')) {
21540					return;
21541				}
21542				setTimeout(function () {
21543					// In IE9 and bellow touch does not support
21544					// Go to slide if browser does not support css transitions
21545					if (_this.thumbClickable && !_this.core.lgBusy) {
21546						var index = parseInt($target.attr('data-lg-item-id'));
21547						_this.core.slide(index, false, true, false);
21548					}
21549				}, 50);
21550			});
21551			//Uncode edit ##START##
21552			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21553			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21554			//Uncode edit ##END##
21555				var index = event.detail.index;
21556				_this.animateThumb(index);
21557			});
21558			//Uncode edit ##START##
21559			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
21560			this.core.LGel.on(lGEvents.beforeOpen, function () {
21561			//Uncode edit ##END##
21562				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21563			});
21564			//Uncode edit ##START##
21565			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
21566			this.core.LGel.on(lGEvents.updateSlides, function () {
21567			//Uncode edit ##END##
21568				_this.rebuildThumbnails();
21569			});
21570			//Uncode edit ##START##
21571			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
21572			this.core.LGel.on(lGEvents.containerResize, function () {
21573			//Uncode edit ##END##
21574				if (!_this.core.lgOpened)
21575					return;
21576				setTimeout(function () {
21577					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21578					_this.animateThumb(_this.core.index);
21579					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21580				}, 50);
21581			});
21582		};
21583		Thumbnail.prototype.setThumbMarkup = function () {
21584			var thumbOuterClassNames = 'lg-thumb-outer ';
21585			if (this.settings.alignThumbnails) {
21586				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
21587			}
21588			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
21589			this.core.outer.addClass('lg-has-thumb');
21590			if (this.settings.appendThumbnailsTo === '.lg-components') {
21591				this.core.$lgComponents.append(html);
21592			}
21593			else {
21594				this.core.outer.append(html);
21595			}
21596			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
21597			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
21598			if (this.settings.animateThumb) {
21599				this.core.outer
21600					.find('.lg-thumb')
21601					.css('transition-duration', this.core.settings.speed + 'ms')
21602					.css('width', this.thumbTotalWidth + 'px')
21603					.css('position', 'relative');
21604			}
21605			this.setThumbItemHtml(this.core.galleryItems);
21606		};
21607		Thumbnail.prototype.enableThumbDrag = function () {
21608			var _this = this;
21609			var thumbDragUtils = {
21610				cords: {
21611					startX: 0,
21612					endX: 0,
21613				},
21614				isMoved: false,
21615				newTranslateX: 0,
21616				startTime: new Date(),
21617				endTime: new Date(),
21618				touchMoveTime: 0,
21619			};
21620			var isDragging = false;
21621			this.$thumbOuter.addClass('lg-grab');
21622			this.core.outer
21623				.find('.lg-thumb')
21624				.first()
21625				.on('mousedown.lg.thumb', function (e) {
21626				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21627					// execute only on .lg-object
21628					e.preventDefault();
21629					thumbDragUtils.cords.startX = e.pageX;
21630					thumbDragUtils.startTime = new Date();
21631					_this.thumbClickable = false;
21632					isDragging = true;
21633					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
21634					_this.core.outer.get().scrollLeft += 1;
21635					_this.core.outer.get().scrollLeft -= 1;
21636					// *
21637					_this.$thumbOuter
21638						.removeClass('lg-grab')
21639						.addClass('lg-grabbing');
21640				}
21641			});
21642			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
21643				if (!_this.core.lgOpened)
21644					return;
21645				if (isDragging) {
21646					thumbDragUtils.cords.endX = e.pageX;
21647					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21648				}
21649			});
21650			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
21651				if (!_this.core.lgOpened)
21652					return;
21653				if (thumbDragUtils.isMoved) {
21654					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21655				}
21656				else {
21657					_this.thumbClickable = true;
21658				}
21659				if (isDragging) {
21660					isDragging = false;
21661					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
21662				}
21663			});
21664		};
21665		Thumbnail.prototype.enableThumbSwipe = function () {
21666			var _this = this;
21667			var thumbDragUtils = {
21668				cords: {
21669					startX: 0,
21670					endX: 0,
21671				},
21672				isMoved: false,
21673				newTranslateX: 0,
21674				startTime: new Date(),
21675				endTime: new Date(),
21676				touchMoveTime: 0,
21677			};
21678			this.$lgThumb.on('touchstart.lg', function (e) {
21679				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21680					e.preventDefault();
21681					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
21682					_this.thumbClickable = false;
21683					thumbDragUtils.startTime = new Date();
21684				}
21685			});
21686			this.$lgThumb.on('touchmove.lg', function (e) {
21687				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21688					e.preventDefault();
21689					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
21690					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21691				}
21692			});
21693			this.$lgThumb.on('touchend.lg', function () {
21694				if (thumbDragUtils.isMoved) {
21695					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21696				}
21697				else {
21698					_this.thumbClickable = true;
21699				}
21700			});
21701		};
21702		// Rebuild thumbnails
21703		Thumbnail.prototype.rebuildThumbnails = function () {
21704			var _this = this;
21705			// Remove transitions
21706			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
21707			setTimeout(function () {
21708				_this.thumbTotalWidth =
21709					_this.core.galleryItems.length *
21710						(_this.settings.thumbWidth + _this.settings.thumbMargin);
21711				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
21712				_this.$lgThumb.empty();
21713				_this.setThumbItemHtml(_this.core.galleryItems);
21714				_this.animateThumb(_this.core.index);
21715			}, 50);
21716			setTimeout(function () {
21717				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
21718			}, 200);
21719		};
21720		// @ts-check
21721		Thumbnail.prototype.setTranslate = function (value) {
21722			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
21723		};
21724		Thumbnail.prototype.getPossibleTransformX = function (left) {
21725			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
21726				left = this.thumbTotalWidth - this.thumbOuterWidth;
21727			}
21728			if (left < 0) {
21729				left = 0;
21730			}
21731			return left;
21732		};
21733		Thumbnail.prototype.animateThumb = function (index) {
21734			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
21735			if (this.settings.animateThumb) {
21736				var position = 0;
21737				switch (this.settings.currentPagerPosition) {
21738					case 'left':
21739						position = 0;
21740						break;
21741					case 'middle':
21742						position =
21743							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
21744						break;
21745					case 'right':
21746						position = this.thumbOuterWidth - this.settings.thumbWidth;
21747				}
21748				this.translateX =
21749					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
21750						1 -
21751						position;
21752				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
21753					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
21754				}
21755				if (this.translateX < 0) {
21756					this.translateX = 0;
21757				}
21758				this.setTranslate(this.translateX);
21759			}
21760		};
21761		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21762			thumbDragUtils.newTranslateX = this.translateX;
21763			thumbDragUtils.isMoved = true;
21764			thumbDragUtils.touchMoveTime = new Date().valueOf();
21765			thumbDragUtils.newTranslateX -=
21766				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21767			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21768			// move current slide
21769			this.setTranslate(thumbDragUtils.newTranslateX);
21770			this.$thumbOuter.addClass('lg-dragging');
21771			return thumbDragUtils;
21772		};
21773		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21774			thumbDragUtils.isMoved = false;
21775			thumbDragUtils.endTime = new Date();
21776			this.$thumbOuter.removeClass('lg-dragging');
21777			var touchDuration = thumbDragUtils.endTime.valueOf() -
21778				thumbDragUtils.startTime.valueOf();
21779			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21780			var speedX = Math.abs(distanceXnew) / touchDuration;
21781			// Some magical numbers
21782			// Can be improved
21783			if (speedX > 0.15 &&
21784				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21785				speedX += 1;
21786				if (speedX > 2) {
21787					speedX += 1;
21788				}
21789				speedX =
21790					speedX +
21791						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21792				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21793				distanceXnew = distanceXnew * speedX;
21794				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21795				this.setTranslate(this.translateX);
21796			}
21797			else {
21798				this.translateX = thumbDragUtils.newTranslateX;
21799			}
21800			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21801				this.settings.thumbnailSwipeThreshold) {
21802				this.thumbClickable = true;
21803			}
21804			return thumbDragUtils;
21805		};
21806		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21807			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21808			var thumbImg;
21809			if (slideVideoInfo.youtube) {
21810				if (this.settings.loadYouTubeThumbnail) {
21811					thumbImg =
21812						'//img.youtube.com/vi/' +
21813							slideVideoInfo.youtube[1] +
21814							'/' +
21815							this.settings.youTubeThumbSize +
21816							'.jpg';
21817				}
21818				else {
21819					thumbImg = thumb;
21820				}
21821			}
21822			else {
21823				thumbImg = thumb;
21824			}
21825			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>";
21826		};
21827		Thumbnail.prototype.getThumbItemHtml = function (items) {
21828			var thumbList = '';
21829			for (var i = 0; i < items.length; i++) {
21830				thumbList += this.getThumbHtml(items[i].thumb, i);
21831			}
21832			return thumbList;
21833		};
21834		Thumbnail.prototype.setThumbItemHtml = function (items) {
21835			var thumbList = this.getThumbItemHtml(items);
21836			this.$lgThumb.html(thumbList);
21837		};
21838		Thumbnail.prototype.setAnimateThumbStyles = function () {
21839			if (this.settings.animateThumb) {
21840				this.core.outer.addClass('lg-animate-thumb');
21841			}
21842		};
21843		// Manage thumbnail active calss
21844		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21845			var _this = this;
21846			// manage active class for thumbnail
21847			//Uncode edit ##START##
21848			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21849			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21850			//Uncode edit ##END##
21851				var $thumb = _this.core.outer.find('.lg-thumb-item');
21852				var index = event.detail.index;
21853				$thumb.removeClass('active');
21854				$thumb.eq(index).addClass('active');
21855			});
21856		};
21857		// Toggle thumbnail bar
21858		Thumbnail.prototype.toggleThumbBar = function () {
21859			var _this = this;
21860			if (this.settings.toggleThumb) {
21861				this.core.outer.addClass('lg-can-toggle');
21862				this.core.$toolbar.append('<button type="button" aria-label="' +
21863					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21864					'" class="lg-toggle-thumb lg-icon"></button>');
21865				this.core.outer
21866					.find('.lg-toggle-thumb')
21867					.first()
21868					.on('click.lg', function () {
21869					_this.core.outer.toggleClass('lg-components-open');
21870				});
21871			}
21872		};
21873		Thumbnail.prototype.thumbKeyPress = function () {
21874			var _this = this;
21875			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21876				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21877					return;
21878				if (e.keyCode === 38) {
21879					e.preventDefault();
21880					_this.core.outer.addClass('lg-components-open');
21881				}
21882				else if (e.keyCode === 40) {
21883					e.preventDefault();
21884					_this.core.outer.removeClass('lg-components-open');
21885				}
21886			});
21887		};
21888		Thumbnail.prototype.destroy = function () {
21889			if (this.settings.thumbnail) {
21890				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21891				this.core.LGel.off('.lg.thumb');
21892				this.core.LGel.off('.thumb');
21893				this.$thumbOuter.remove();
21894				this.core.outer.removeClass('lg-has-thumb');
21895			}
21896		};
21897		return Thumbnail;
21898	}());
21899
21900	return Thumbnail;
21901
21902})));
21903/*!
21904 * lightgallery | 2.5.0 | June 13th 2022
21905 * http://www.lightgalleryjs.com/
21906 * Copyright (c) 2020 Sachin Neravath;
21907 * @license GPLv3
21908 */
21909
21910(function (global, factory) {
21911	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21912	typeof define === 'function' && define.amd ? define(factory) :
21913	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21914}(this, (function () { 'use strict';
21915
21916	/*! *****************************************************************************
21917	Copyright (c) Microsoft Corporation.
21918
21919	Permission to use, copy, modify, and/or distribute this software for any
21920	purpose with or without fee is hereby granted.
21921
21922	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21923	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21924	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21925	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21926	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21927	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21928	PERFORMANCE OF THIS SOFTWARE.
21929	***************************************************************************** */
21930
21931	var __assign = function() {
21932		__assign = Object.assign || function __assign(t) {
21933			for (var s, i = 1, n = arguments.length; i < n; i++) {
21934				s = arguments[i];
21935				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21936			}
21937			return t;
21938		};
21939		return __assign.apply(this, arguments);
21940	};
21941
21942	var videoSettings = {
21943		autoplayFirstVideo: true,
21944		youTubePlayerParams: false,
21945		vimeoPlayerParams: false,
21946		wistiaPlayerParams: false,
21947		gotoNextSlideOnVideoEnd: true,
21948		autoplayVideoOnSlide: false,
21949		videojs: false,
21950		videojsTheme: '',
21951		videojsOptions: {},
21952	};
21953
21954	/**
21955	 * List of lightGallery events
21956	 * All events should be documented here
21957	 * Below interfaces are used to build the website documentations
21958	 * */
21959	var lGEvents = {
21960		afterAppendSlide: 'lgAfterAppendSlide',
21961		init: 'lgInit',
21962		hasVideo: 'lgHasVideo',
21963		containerResize: 'lgContainerResize',
21964		updateSlides: 'lgUpdateSlides',
21965		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21966		beforeOpen: 'lgBeforeOpen',
21967		afterOpen: 'lgAfterOpen',
21968		slideItemLoad: 'lgSlideItemLoad',
21969		beforeSlide: 'lgBeforeSlide',
21970		afterSlide: 'lgAfterSlide',
21971		posterClick: 'lgPosterClick',
21972		dragStart: 'lgDragStart',
21973		dragMove: 'lgDragMove',
21974		dragEnd: 'lgDragEnd',
21975		beforeNextSlide: 'lgBeforeNextSlide',
21976		beforePrevSlide: 'lgBeforePrevSlide',
21977		beforeClose: 'lgBeforeClose',
21978		afterClose: 'lgAfterClose',
21979		rotateLeft: 'lgRotateLeft',
21980		rotateRight: 'lgRotateRight',
21981		flipHorizontal: 'lgFlipHorizontal',
21982		flipVertical: 'lgFlipVertical',
21983		autoplay: 'lgAutoplay',
21984		autoplayStart: 'lgAutoplayStart',
21985		autoplayStop: 'lgAutoplayStop',
21986	};
21987
21988	var param = function (obj) {
21989		return Object.keys(obj)
21990			.map(function (k) {
21991			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
21992		})
21993			.join('&');
21994	};
21995	var getVimeoURLParams = function (defaultParams, videoInfo) {
21996		if (!videoInfo || !videoInfo.vimeo)
21997			return '';
21998		var urlParams = videoInfo.vimeo[2] || '';
21999		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
22000			? '&' + param(defaultParams)
22001			: '';
22002		// Support private video
22003		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
22004		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
22005		var hash = urlWithHashWithParams.split('#')[0];
22006		var isPrivate = videoInfo.vimeo[1] !== hash;
22007		if (isPrivate) {
22008			urlParams = urlParams.replace("/" + hash, '');
22009		}
22010		urlParams =
22011			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
22012		// For vimeo last params gets priority if duplicates found
22013		// Uncode edit ##START##
22014		var vimeoPlayerParams = '?autoplay=0';
22015		if ( videoInfo.autoplay !== '' ) {
22016			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22017			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
22018		} else {
22019			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
22020				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
22021			}
22022		}
22023		if ( videoInfo.muted !== '' ) {
22024			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
22025		} else {
22026			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
22027				vimeoPlayerParams += '&muted=1';
22028			}
22029		}
22030		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22031		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22032		// Uncode edit ##END##
22033		return vimeoPlayerParams;
22034	};
22035
22036	/**
22037	 * Video module for lightGallery
22038	 * Supports HTML5, YouTube, Vimeo, wistia videos
22039	 *
22040	 *
22041	 * @ref Wistia
22042	 * https://wistia.com/support/integrations/wordpress(How to get url)
22043	 * https://wistia.com/support/developers/embed-options#using-embed-options
22044	 * https://wistia.com/support/developers/player-api
22045	 * https://wistia.com/support/developers/construct-an-embed-code
22046	 * http://jsfiddle.net/xvnm7xLm/
22047	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
22048	 * https://wistia.com/support/embed-and-share/sharing-videos
22049	 * https://private-sharing.wistia.com/medias/mwhrulrucj
22050	 *
22051	 * @ref Youtube
22052	 * https://developers.google.com/youtube/player_parameters#enablejsapi
22053	 * https://developers.google.com/youtube/iframe_api_reference
22054	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
22055	 *
22056	 * @ref Vimeo
22057	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
22058	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
22059	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
22060	 */
22061	var Video = /** @class */ (function () {
22062		function Video(instance) {
22063			// get lightGallery core plugin instance
22064			this.core = instance;
22065			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
22066			return this;
22067		}
22068		Video.prototype.init = function () {
22069			var _this = this;
22070			/**
22071			 * Event triggered when video url found without poster
22072			 * Append video HTML
22073			 * Play if autoplayFirstVideo is true
22074			 */
22075			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
22076			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
22077				var $el = _this.core.getSlideItem(_this.core.index);
22078				_this.loadVideoOnPosterClick($el);
22079			});
22080			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
22081			// @desc fired immediately before each slide transition.
22082			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
22083			// @desc fired immediately after each slide transition.
22084			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
22085		};
22086		/**
22087		 * @desc Event triggered when a slide is completely loaded
22088		 *
22089		 * @param {Event} event - lightGalley custom event
22090		 */
22091		Video.prototype.onSlideItemLoad = function (event) {
22092			var _this = this;
22093			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
22094			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
22095			if (this.settings.autoplayFirstVideo &&
22096				isFirstSlide &&
22097				index === this.core.index) {
22098				// Delay is just for the transition effect on video load
22099				setTimeout(function () {
22100					_this.loadAndPlayVideo(index);
22101				}, 200);
22102			}
22103			// Should not call on first slide. should check only if the slide is active
22104			if (!isFirstSlide &&
22105				this.settings.autoplayVideoOnSlide &&
22106				index === this.core.index) {
22107					setTimeout(function () {
22108						_this.loadAndPlayVideo(index);
22109					}, 500);
22110				}
22111		};
22112		/**
22113		 * @desc Event triggered when video url or poster found
22114		 * Append video HTML is poster is not given
22115		 * Play if autoplayFirstVideo is true
22116		 *
22117		 * @param {Event} event - Javascript Event object.
22118		 */
22119		Video.prototype.onHasVideo = function (event) {
22120			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
22121			if (!hasPoster) {
22122				// All functions are called separately if poster exist in loadVideoOnPosterClick function
22123				this.appendVideos(this.core.getSlideItem(index), {
22124					src: src,
22125					addClass: 'lg-object',
22126					index: index,
22127					html5Video: html5Video,
22128					// Uncode edit ##START##
22129					autoplay: event.target.getAttribute('data-lb-autoplay'),
22130					muted: event.target.getAttribute('data-lb-muted'),
22131					// Uncode edit ##END##
22132				});
22133				// Automatically navigate to next slide once video reaches the end.
22134				this.gotoNextSlideOnVideoEnd(src, index);
22135			}
22136		};
22137		/**
22138		 * @desc fired immediately before each slide transition.
22139		 * Pause the previous video
22140		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
22141		 *
22142		 * @param {Event} event - Javascript Event object.
22143		 * @param {number} prevIndex - Previous index of the slide.
22144		 * @param {number} index - Current index of the slide
22145		 */
22146		Video.prototype.onBeforeSlide = function (event) {
22147			if (this.core.lGalleryOn) {
22148				var prevIndex = event.detail.prevIndex;
22149				this.pauseVideo(prevIndex);
22150			}
22151			// Uncode edit ##START##
22152			var _a = event.detail, index = _a.index;
22153			var $slide = this.core.getSlideItem(index);
22154			
22155			var iframe = $slide.selector.querySelector('iframe');
22156			if ( iframe != null ) {
22157
22158				var data_play = iframe.getAttribute('data-autoplay');
22159				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
22160					this.loadAndPlayVideo(index);
22161
22162					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
22163						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
22164					if (videoInfo.vimeo) {
22165						var vimeoPlayer = new Vimeo.Player($videoElement.get());
22166						vimeoPlayer.on('play', function () {
22167							vimeoPlayer.setCurrentTime(0);
22168						});
22169					} else if ( videoInfo.youtube ) {
22170						try {
22171							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
22172						}
22173						catch (e) {
22174							console.warn(e);
22175						}
22176					}
22177				}
22178			}
22179			// Uncode edit ##END##
22180		};
22181		/**
22182		 * @desc fired immediately after each slide transition.
22183		 * Play video if autoplayVideoOnSlide option is enabled.
22184		 *
22185		 * @param {Event} event - Javascript Event object.
22186		 * @param {number} prevIndex - Previous index of the slide.
22187		 * @param {number} index - Current index of the slide
22188		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
22189		 */
22190		Video.prototype.onAfterSlide = function (event) {
22191			var _this = this;
22192			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
22193			// Do not call on first slide
22194			var $slide = this.core.getSlideItem(index);
22195			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
22196				if ($slide.hasClass('lg-complete')) {
22197					setTimeout(function () {
22198						_this.loadAndPlayVideo(index);
22199					}, 100);
22200				}
22201			}
22202		};
22203		Video.prototype.loadAndPlayVideo = function (index) {
22204			var $slide = this.core.getSlideItem(index);
22205			var currentGalleryItem = this.core.galleryItems[index];
22206			if (currentGalleryItem.poster) {
22207				this.loadVideoOnPosterClick($slide, true);
22208			}
22209			else {
22210				//Uncode edit ##START##
22211				// this.playVideo(index);
22212				var iframe = $slide.selector.querySelector('iframe');
22213				if ( iframe != null ) {
22214					var data_play = iframe.getAttribute('data-autoplay');
22215					if ( typeof data_play !== 'undefined' ) {
22216						if ( data_play === '1' && this.core.index == index ) {
22217							this.playVideo(index);
22218						} else {
22219							this.pauseVideo(index);
22220						}
22221					}
22222				}
22223				//Uncode edit ##END##
22224			}
22225		};
22226		/**
22227		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22228		 * @param {number} index - Index of the slide
22229		 */
22230		Video.prototype.playVideo = function (index) {
22231			this.controlVideo(index, 'play');
22232		};
22233		/**
22234		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22235		 * @param {number} index - Index of the slide
22236		 */
22237		Video.prototype.pauseVideo = function (index) {
22238			this.controlVideo(index, 'pause');
22239		};
22240		// Uncode edit ##START##
22241		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
22242		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
22243		// Uncode edit ##END##
22244			var video = '';
22245			var videoInfo = this.core.galleryItems[index]
22246				.__slideVideoInfo || {};
22247			var currentGalleryItem = this.core.galleryItems[index];
22248			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
22249			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
22250			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
22251			if (videoInfo.youtube) {
22252				var videoId = 'lg-youtube' + index;
22253				var slideUrlParams = videoInfo.youtube[2]
22254					? videoInfo.youtube[2] + '&'
22255					: '';
22256				// For youtube first parms gets priority if duplicates found
22257				// Uncode edit ##START##
22258				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
22259				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
22260				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
22261					youTubePlayerParams += '&autoplay=0';
22262				}
22263				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
22264					youTubePlayerParams += '&mute=1';
22265				}
22266				var data_video = '';
22267				if ( autoplay !== '' ) {
22268					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
22269					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22270					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
22271					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22272				}
22273				// if ( muted !== '' ) {
22274				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
22275				// }
22276				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
22277
22278				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
22279				// Uncode edit ##END##
22280				var playerParams = youTubePlayerParams +
22281					(this.settings.youTubePlayerParams
22282						? '&' + param(this.settings.youTubePlayerParams)
22283						: '');
22284				// Uncode edit ##START##
22285				// 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>";
22286				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube.com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
22287				var tag = document.createElement('script');
22288				tag.src = "//www.youtube.com/player_api";
22289				var firstScriptTag = document.getElementsByTagName('script')[0];
22290				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
22291
22292				// Replace the 'ytplayer' element with an <iframe> and
22293				// YouTube player after the API code downloads.
22294				var ytIframeplayer,
22295					setMute = muted === 'yes' ? 0 : 100;
22296				window.onYouTubePlayerAPIReady = function() {
22297					ytIframeplayer = new YT.Player(videoId, {
22298						videoId: videoInfo.youtube[1],
22299						events: {
22300							'onReady': function (event) {
22301								event.target.setVolume(setMute);
22302							}
22303						}
22304					});
22305				}
22306				// Uncode edit ##END##
22307			}
22308			else if (videoInfo.vimeo) {
22309				var videoId = 'lg-vimeo' + index;
22310				// Uncode edit ##START##
22311				videoInfo.autoplay = autoplay;
22312				videoInfo.muted = muted;
22313				// Uncode edit ##END##
22314				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
22315				// Uncode edit ##START##
22316				// 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>";
22317				var data_video = '';
22318				if ( autoplay !== '' ) {
22319					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22320				}
22321				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-vimeo " + addClass + "\" " + videoTitle + " src=\"//player.vimeo.com/video/" + (videoInfo.vimeo[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
22322				// Uncode edit ##END##
22323			}
22324			else if (videoInfo.wistia) {
22325				var wistiaId = 'lg-wistia' + index;
22326				var playerParams = param(this.settings.wistiaPlayerParams);
22327				playerParams = playerParams ? '?' + playerParams : '';
22328				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>";
22329			}
22330			else if (videoInfo.html5) {
22331				var html5VideoMarkup = '';
22332				for (var i = 0; i < html5Video.source.length; i++) {
22333					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
22334				}
22335				if (html5Video.tracks) {
22336					var _loop_1 = function (i) {
22337						var trackAttributes = '';
22338						var track = html5Video.tracks[i];
22339						Object.keys(track || {}
22339).forEach(function (key) {
22340							trackAttributes += key + "=\"" + track[key] + "\" ";
22341						});
22342						html5VideoMarkup += "<track " + trackAttributes + ">";
22343					};
22344					for (var i = 0; i < html5Video.tracks.length; i++) {
22345						_loop_1(i);
22346					}
22347				}
22348				var html5VideoAttrs_1 = '';
22349				var videoAttributes_1 = html5Video.attributes || {};
22350				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
22351					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
22352				});
22353				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
22354					? this.settings.videojsTheme + ' '
22355					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
22356			}
22357			return video;
22358		};
22359		/**
22360		 * @desc - Append videos to the slide
22361		 *
22362		 * @param {HTMLElement} el - slide element
22363		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
22364		 */
22365		Video.prototype.appendVideos = function (el, videoParams) {
22366			var _a;
22367			// Uncode edit ##START##
22368			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
22369			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
22370			// Uncode edit ##END##
22371			el.find('.lg-video-cont').append(videoHtml);
22372			var $videoElement = el.find('.lg-video-object').first();
22373			if (videoParams.html5Video) {
22374				$videoElement.on('mousedown.lg.video', function (e) {
22375					e.stopPropagation();
22376				});
22377			}
22378			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
22379				try {
22380					return videojs($videoElement.get(), this.settings.videojsOptions);
22381				}
22382				catch (e) {
22383					console.warn('lightGallery:- Make sure you have included videojs');
22384				}
22385			}
22386		};
22387		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
22388			var _this = this;
22389			var $videoElement = this.core
22390				.getSlideItem(index)
22391				.find('.lg-video-object')
22392				.first();
22393			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22394			if (this.settings.gotoNextSlideOnVideoEnd) {
22395				if (videoInfo.html5) {
22396					$videoElement.on('ended', function () {
22397						_this.core.goToNextSlide();
22398					});
22399				}
22400				else if (videoInfo.vimeo) {
22401					try {
22402						// https://github.com/vimeo/player.js/#ended
22403						new Vimeo.Player($videoElement.get()).on('ended', function () {
22404							_this.core.goToNextSlide();
22405						});
22406					}
22407					catch (e) {
22408						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22409					}
22410				}
22411				else if (videoInfo.wistia) {
22412					try {
22413						window._wq = window._wq || [];
22414						// @todo Event is gettign triggered multiple times
22415						window._wq.push({
22416							id: $videoElement.attr('id'),
22417							onReady: function (video) {
22418								video.bind('end', function () {
22419									_this.core.goToNextSlide();
22420								});
22421							},
22422						});
22423					}
22424					catch (e) {
22425						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22426					}
22427				}
22428			}
22429		};
22430		Video.prototype.controlVideo = function (index, action) {
22431			var $videoElement = this.core
22432				.getSlideItem(index)
22433				.find('.lg-video-object')
22434				.first();
22435			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22436			if (!$videoElement.get())
22437				return;
22438			if (videoInfo.youtube) {
22439				try {
22440					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
22441				}
22442				catch (e) {
22443					console.warn("lightGallery:- " + e);
22444				}
22445			}
22446			else if (videoInfo.vimeo) {
22447				try {
22448					new Vimeo.Player($videoElement.get())[action]();
22449				}
22450				catch (e) {
22451					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22452				}
22453			}
22454			else if (videoInfo.html5) {
22455				if (this.settings.videojs) {
22456					try {
22457						videojs($videoElement.get())[action]();
22458					}
22459					catch (e) {
22460						console.warn('lightGallery:- Make sure you have included videojs');
22461					}
22462				}
22463				else {
22464					$videoElement.get()[action]();
22465				}
22466			}
22467			else if (videoInfo.wistia) {
22468				try {
22469					window._wq = window._wq || [];
22470					// @todo Find a way to destroy wistia player instance
22471					window._wq.push({
22472						id: $videoElement.attr('id'),
22473						onReady: function (video) {
22474							video[action]();
22475						},
22476					});
22477				}
22478				catch (e) {
22479					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22480				}
22481			}
22482		};
22483		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
22484			var _this = this;
22485			// check slide has poster
22486			if (!$el.hasClass('lg-video-loaded')) {
22487				// check already video element present
22488				if (!$el.hasClass('lg-has-video')) {
22489					$el.addClass('lg-has-video');
22490					var _html = void 0;
22491					var _src = this.core.galleryItems[this.core.index].src;
22492					var video = this.core.galleryItems[this.core.index].video;
22493					if (video) {
22494						_html =
22495							typeof video === 'string' ? JSON.parse(video) : video;
22496					}
22497					var videoJsPlayer_1 = this.appendVideos($el, {
22498						src: _src,
22499						addClass: '',
22500						index: this.core.index,
22501						html5Video: _html,
22502					});
22503					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
22504					var $tempImg = $el.find('.lg-object').first().get();
22505					// @todo make sure it is working
22506					$el.find('.lg-video-cont').first().append($tempImg);
22507					$el.addClass('lg-video-loading');
22508					videoJsPlayer_1 &&
22509						videoJsPlayer_1.ready(function () {
22510							videoJsPlayer_1.on('loadedmetadata', function () {
22511								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22512							});
22513						});
22514					$el.find('.lg-video-object')
22515						.first()
22516						.on('load.lg error.lg loadedmetadata.lg', function () {
22517						setTimeout(function () {
22518							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22519						}, 50);
22520					});
22521				}
22522				else {
22523					this.playVideo(this.core.index);
22524				}
22525			}
22526			else if (forcePlay) {
22527				this.playVideo(this.core.index);
22528			}
22529		};
22530		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
22531			$el.addClass('lg-video-loaded');
22532			this.playVideo(index);
22533		};
22534		Video.prototype.destroy = function () {
22535			this.core.LGel.off('.lg.video');
22536			this.core.LGel.off('.video');
22537		};
22538		return Video;
22539	}());
22540
22541	return Video;
22542
22543})));
22544
22545
22546/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
22547!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):((e="undefined"!=typeof globalThis?globalThis:e||self).Vimeo=e.Vimeo||{},e.Vimeo.Player=t())}(this,function(){"use strict";function r(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}var e="undefined"!=typeof global&&"[object global]"==={}.toString.call(global);function i(e,t){return 0===e.indexOf(t.toLowerCase())?e:"".concat(t.toLowerCase()).concat(e.substr(0,1).toUpperCase()).concat(e.substr(1))}function c(e){return/^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(e)}function s(e){var t,n=0<arguments.length&&void 0!==e?e:{},r=n.id,o=n.url,i=r||o;if(!i)throw new Error("An id or url must be passed, either in an options object or as a data-vimeo-id or data-vimeo-url attribute.");if(t=i,!isNaN(parseFloat(t))&&isFinite(t)&&Math.floor(t)==t)return"https://vimeo.com/".concat(i);if(c(i))return i.replace("http:","https:");if(r)throw new TypeError("“".concat(r,"” is not a valid video id."));throw new TypeError("“".concat(i,"” is not a vimeo.com url."))}var t=void 0!==Array.prototype.indexOf,n="undefined"!=typeof window&&void 0!==window.postMessage;if(!(e||t&&n))throw new Error("Sorry, the Vimeo Player API is not available in this browser.");var o,a,u,l,f="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function d(){if(void 0===this)throw new TypeError("Constructor WeakMap requires 'new'");if(l(this,"_id","_WeakMap_"+v()+"."+v()),0<arguments.length)throw new TypeError("WeakMap iterable is not supported")}function h(e,t){if(!m(e)||!a.call(e,"_id"))throw new TypeError(t+" method called on incompatible receiver "+typeof e)}function v(){return Math.random().toString().substring(2)}function m(e){return Object(e)===e}(o="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:f).WeakMap||(a=Object.prototype.hasOwnProperty,u=Object.defineProperty&&function(){try{return 1===Object.defineProperty({},"x",{value:1}).x}catch(e){}}(),l=function(e,t,n){u?Object.defineProperty(e,t,{configurable:!0,writable:!0,value:n}):e[t]=n},o.WeakMap=(l(d.prototype,"delete",function(e){if(h(this,"delete"),!m(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)&&(delete e[this._id],!0)}),l(d.prototype,"get",function(e){if(h(this,"get"),m(e)){var t=e[this._id];return t&&t[0]===e?t[1]:void 0}}),l(d.prototype,"has",function(e){if(h(this,"has"),!m(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)}),l(d.prototype,"set",function(e,t){if(h(this,"set"),!m(e))throw new TypeError("Invalid value used as weak map key");var n=e[this._id];return n&&n[0]===e?n[1]=t:l(e,this._id,[e,t]),this}),l(d,"_polyfill",!0),d));var p,y=(function(e){var t,n,r;r=function(){var t,n,r,o,i,a,e=Object.prototype.toString,u="undefined"!=typeof setImmediate?function(e){return setImmediate(e)}:setTimeout;try{Object.defineProperty({},"x",{}),t=function(e,t,n,r){return Object.defineProperty(e,t,{value:n,writable:!0,configurable:!1!==r})}}catch(e){t=function(e,t,n){return e[t]=n,e}}function l(e,t){this.fn=e,this.self=t,this.next=void 0}function c(e,t){r.add(e,t),n=n||u(r.drain)}function s(e){var t,n=typeof e;return null==e||"object"!=n&&"function"!=n||(t=e.then),"function"==typeof t&&t}function f(){for(var e=0;e<this.chain.length;e++)!function(e,t,n){var r,o;try{!1===t?n.reject(e.msg):(r=!0===t?e.msg:t.call(void 0,e.msg))===n.promise?n.reject(TypeError("Promise-chain cycle")):(o=s(r))?o.call(r,n.resolve,n.reject):n.resolve(r)}catch(e){n.reject(e)}}(this,1===this.state?this.chain[e].success:this.chain[e].failure,this.chain[e]);this.chain.length=0}function d(e){var n,r=this;if(!r.triggered){r.triggered=!0,r.def&&(r=r.def);try{(n=s(e))?c(function(){var t=new m(r);try{n.call(e,function(){d.apply(t,arguments)},function(){h.apply(t,arguments)})}catch(e){h.call(t,e)}}):(r.msg=e,r.state=1,0<r.chain.length&&c(f,r))}catch(e){h.call(new m(r),e)}}}function h(e){var t=this;t.triggered||(t.triggered=!0,t.def&&(t=t.def),t.msg=e,t.state=2,0<t.chain.length&&c(f,t))}function v(e,n,r,o){for(var t=0;t<n.length;t++)!function(t){e.resolve(n[t]).then(function(e){r(t,e)},o)}(t)}function m(e){this.def=e,this.triggered=!1}function p(e){this.promise=e,this.state=0,this.triggered=!1,this.chain=[],this.msg=void 0}function y(e){if("function"!=typeof e)throw TypeError("Not a function");if(0!==this.__NPO__)throw TypeError("Not a promise");this.__NPO__=1;var r=new p(this);this.then=function(e,t){var n={success:"function"!=typeof e||e,failure:"function"==typeof t&&t};return n.promise=new this.constructor(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");n.resolve=e,n.reject=t}),r.chain.push(n),0!==r.state&&c(f,r),n.promise},this.catch=function(e){return this.then(void 0,e)};try{e.call(void 0,function(e){d.call(r,e)},function(e){h.call(r,e)})}catch(e){h.call(r,e)}}var g=t({},"constructor",y,!(r={add:function(e,t){a=new l(e,t),i?i.next=a:o=a,i=a,a=void 0},drain:function(){var e=o;for(o=i=n=void 0;e;)e.fn.call(e.self),e=e.next}}));return t(y.prototype=g,"__NPO__",0,!1),t(y,"resolve",function(n){return n&&"object"==typeof n&&1===n.__NPO__?n:new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");e(n)})}),t(y,"reject",function(n){return new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");t(n)})}),t(y,"all",function(t){var a=this;return"[object Array]"!=e.call(t)?a.reject(TypeError("Not an array")):0===t.length?a.resolve([]):new a(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");var r=t.length,o=Array(r),i=0;v(a,t,function(e,t){o[e]=t,++i===r&&n(o)},e)})}),t(y,"race",function(t){var r=this;return"[object Array]"!=e.call(t)?r.reject(TypeError("Not an array")):new r(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");v(r,t,function(e,t){n(t)},e)})}),y},(n=f)[t="Promise"]=n[t]||r(),e.exports&&(e.exports=n[t])}(p={exports:{}}
22547),p.exports),g=new WeakMap;function w(e,t,n){var r=g.get(e.element)||{};t in r||(r[t]=[]),r[t].push(n),g.set(e.element,r)}function b(e,t){return(g.get(e.element)||{})[t]||[]}function k(e,t,n){var r=g.get(e.element)||{};if(!r[t])return!0;if(!n)return r[t]=[],g.set(e.element,r),!0;var o=r[t].indexOf(n);return-1!==o&&r[t].splice(o,1),g.set(e.element,r),r[t]&&0===r[t].length}function E(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){return console.warn(e),{}}return e}function T(e,t,n){var r,o;e.element.contentWindow&&e.element.contentWindow.postMessage&&(r={method:t},void 0!==n&&(r.value=n),8<=(o=parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/,"$1")))&&o<10&&(r=JSON.stringify(r)),e.element.contentWindow.postMessage(r,e.origin))}function P(n,r){var t,e,o=[];(r=E(r)).event?("error"===r.event&&b(n,r.data.method).forEach(function(e){var t=new Error(r.data.message);t.name=r.data.name,e.reject(t),k(n,r.data.method,e)}),o=b(n,"event:".concat(r.event)),t=r.data):!r.method||(e=function(e,t){var n=b(e,t);if(n.length<1)return!1;var r=n.shift();return k(e,t,r),r}(n,r.method))&&(o.push(e),t=r.value),o.forEach(function(e){try{if("function"==typeof e)return void e.call(n,t);e.resolve(t)}catch(e){}})}var M=["autopause","autoplay","background","byline","color","controls","dnt","height","id","interactive_params","keyboard","loop","maxheight","maxwidth","muted","playsinline","portrait","responsive","speed","texttrack","title","transparent","url","width"];function _(r,e){var t=1<arguments.length&&void 0!==e?e:{};return M.reduce(function(e,t){var n=r.getAttribute("data-vimeo-".concat(t));return!n&&""!==n||(e[t]=""===n?1:n),e},t)}function N(e,t){var n=e.html;if(!t)throw new TypeError("An element must be provided");if(null!==t.getAttribute("data-vimeo-initialized"))return t.querySelector("iframe");var r=document.createElement("div");return r.innerHTML=n,t.appendChild(r.firstChild),t.setAttribute("data-vimeo-initialized","true"),t.querySelector("iframe")}function F(i,e,t){var a=1<arguments.length&&void 0!==e?e:{},u=2<arguments.length?t:void 0;return new Promise(function(t,n){if(!c(i))throw new TypeError("“".concat(i,"” is not a vimeo.com url."));var e="https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(i));for(var r in a)a.hasOwnProperty(r)&&(e+="&".concat(r,"=").concat(encodeURIComponent(a[r])));var o=new("XDomainRequest"in window?XDomainRequest:XMLHttpRequest);o.open("GET",e,!0),o.onload=function(){if(404!==o.status)if(403!==o.status)try{var e=JSON.parse(o.responseText);if(403===e.domain_status_code)return N(e,u),void n(new Error("“".concat(i,"” is not embeddable.")));t(e)}catch(e){n(e)}else n(new Error("“".concat(i,"” is not embeddable.")));else n(new Error("“".concat(i,"” was not found.")))},o.onerror=function(){var e=o.status?" (".concat(o.status,")"):"";n(new Error("There was an error fetching the embed code from Vimeo".concat(e,".")))},o.send()})}var x,C,j,A=new WeakMap,S=new WeakMap,q={},Player=function(){function Player(u){var e,t,l=this,n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if(!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,Player),window.jQuery&&u instanceof jQuery&&(1<u.length&&window.console&&console.warn&&console.warn("A jQuery object with multiple elements was passed, using the first element."),u=u[0]),"undefined"!=typeof document&&"string"==typeof u&&(u=document.getElementById(u)),e=u,!Boolean(e&&1===e.nodeType&&"nodeName"in e&&e.ownerDocument&&e.ownerDocument.defaultView))throw new TypeError("You must pass either a valid element or a valid id.");if("IFRAME"===u.nodeName||(t=u.querySelector("iframe"))&&(u=t),"IFRAME"===u.nodeName&&!c(u.getAttribute("src")||""))throw new Error("The player element passed isn’t a Vimeo embed.");if(A.has(u))return A.get(u);this._window=u.ownerDocument.defaultView,this.element=u,this.origin="*";var r,o=new y(function(i,a){var e;l._onMessage=function(e){if(c(e.origin)&&l.element.contentWindow===e.source){"*"===l.origin&&(l.origin=e.origin);var t=E(e.data);if(t&&"error"===t.event&&t.data&&"ready"===t.data.method){var n=new Error(t.data.message);return n.name=t.data.name,void a(n)}
vendor: 5,252 bytes, line 22547
22547var r=t&&"ready"===t.event,o=t&&"ping"===t.method;if(r||o)return l.element.setAttribute("data-ready","true"),void i();P(l,t)}},l._window.addEventListener("message",l._onMessage),"IFRAME"!==l.element.nodeName&&F(s(e=_(u,n)),e,u).then(function(e){var t,n,r,o=N(e,u);return l.element=o,l._originalElement=u,t=u,n=o,r=g.get(t),g.set(n,r),g.delete(t),A.set(l.element,l),e}).catch(a)});return S.set(this,o),A.set(this.element,this),"IFRAME"===this.element.nodeName&&T(this,"ping"),q.isEnabled&&(r=function(){return q.exit()},this.fullscreenchangeHandler=function(){(q.isFullscreen?w:k)(l,"event:exitFullscreen",r),l.ready().then(function(){T(l,"fullscreenchange",q.isFullscreen)})},q.on("fullscreenchange",this.fullscreenchangeHandler)),this}var e,t,n;return e=Player,(t=[{key:"callMethod",value:function(n,e){var r=this,o=1<arguments.length&&void 0!==e?e:{};return new y(function(e,t){return r.ready().then(function(){w(r,n,{resolve:e,reject:t}),T(r,n,o)}).catch(t)})}},{key:"get",value:function(n){var r=this;return new y(function(e,t){return n=i(n,"get"),r.ready().then(function(){w(r,n,{resolve:e,reject:t}),T(r,n)}).catch(t)})}},{key:"set",value:function(n,r){var o=this;return new y(function(e,t){if(n=i(n,"set"),null==r)throw new TypeError("There must be a value to set.");return o.ready().then(function(){w(o,n,{resolve:e,reject:t}),T(o,n,r)}).catch(t)})}},{key:"on",value:function(e,t){if(!e)throw new TypeError("You must pass an event name.");if(!t)throw new TypeError("You must pass a callback function.");if("function"!=typeof t)throw new TypeError("The callback must be a function.");0===b(this,"event:".concat(e)).length&&this.callMethod("addEventListener",e).catch(function(){}),w(this,"event:".concat(e),t)}},{key:"off",value:function(e,t){if(!e)throw new TypeError("You must pass an event name.");if(t&&"function"!=typeof t)throw new TypeError("The callback must be a function.");k(this,"event:".concat(e),t)&&this.callMethod("removeEventListener",e).catch(function(e){})}},{key:"loadVideo",value:function(e){return this.callMethod("loadVideo",e)}},{key:"ready",value:function(){var e=S.get(this)||new y(function(e,t){t(new Error("Unknown player. Probably unloaded."))});return y.resolve(e)}},{key:"addCuePoint",value:function(e,t){var n=1<arguments.length&&void 0!==t?t:{};return this.callMethod("addCuePoint",{time:e,data:n})}},{key:"removeCuePoint",value:function(e){return this.callMethod("removeCuePoint",e)}},{key:"enableTextTrack",value:function(e,t){if(!e)throw new TypeError("You must pass a language.");return this.callMethod("enableTextTrack",{language:e,kind:t})}},{key:"disableTextTrack",value:function(){return this.callMethod("disableTextTrack")}},{key:"pause",value:function(){return this.callMethod("pause")}},{key:"play",value:function(){return this.callMethod("play")}},{key:"requestFullscreen",value:function(){return q.isEnabled?q.request(this.element):this.callMethod("requestFullscreen")}},{key:"exitFullscreen",value:function(){return q.isEnabled?q.exit():this.callMethod("exitFullscreen")}},{key:"getFullscreen",value:function(){return q.isEnabled?y.resolve(q.isFullscreen):this.get("fullscreen")}},{key:"requestPictureInPicture",value:function(){return this.callMethod("requestPictureInPicture")}},{key:"exitPictureInPicture",value:function(){return this.callMethod("exitPictureInPicture")}},{key:"getPictureInPicture",value:function(){return this.get("pictureInPicture")}},{key:"unload",value:function(){return this.callMethod("unload")}},{key:"destroy",value:function(){var n=this;return new y(function(e){var t;S.delete(n),A.delete(n.element),n._originalElement&&(A.delete(n._originalElement),n._originalElement.removeAttribute("data-vimeo-initialized")),n.element&&"IFRAME"===n.element.nodeName&&n.element.parentNode&&(n.element.parentNode.parentNode&&n._originalElement&&n._originalElement!==n.element.parentNode?n.element.parentNode.parentNode.removeChild(n.element.parentNode):n.element.parentNode.removeChild(n.element)),n.element&&"DIV"===n.element.nodeName&&n.element.parentNode&&(n.element.removeAttribute("data-vimeo-initialized"),(t=n.element.querySelector("iframe"))&&t.parentNode&&(t.parentNode.parentNode&&n._originalElement&&n._originalElement!==t.parentNode?t.parentNode.parentNode.removeChild(t.parentNode):t.parentNode.removeChild(t))),n._window.removeEventListener("message",n._onMessage),q.isEnabled&&q.off("fullscreenchange",n.fullscreenchangeHandler),e()})}},{key:"getAutopause",value:function(){return this.get("autopause")}},{key:"setAutopause",value:function(e){return this.set("autopause",e)}},{key:"getBuffered",value:function(){return this.get("buffered")}},{key:"getCameraProps",value:function(){return this.get("cameraProps")}},{key:"setCameraProps",value:function(e){return this.set("cameraProps",e)}},{key:"getChapters",value:function(){return this.get("chapters")}},{key:"getCurrentChapter",value:function(){return this.get("currentChapter")}},{key:"getColor",value:function(){return this.get("color")}},{key:"setColor",value:function(e){return this.set("color",e)}},{key:"getCuePoints",value:function(){return this.get("cuePoints")}},{key:"getCurrentTime",value:function(){return this.get("currentTime")}},{key:"setCurrentTime",value:function(e){return this.set("currentTime",e)}
22547},{key:"getDuration",value:function(){return this.get("duration")}},{key:"getEnded",value:function(){return this.get("ended")}},{key:"getLoop",value:function(){return this.get("loop")}},{key:"setLoop",value:function(e){return this.set("loop",e)}},{key:"setMuted",value:function(e){return this.set("muted",e)}},{key:"getMuted",value:function(){return this.get("muted")}},{key:"getPaused",value:function(){return this.get("paused")}},{key:"getPlaybackRate",value:function(){return this.get("playbackRate")}},{key:"setPlaybackRate",value:function(e){return this.set("playbackRate",e)}},{key:"getPlayed",value:function(){return this.get("played")}},{key:"getQualities",value:function(){return this.get("qualities")}},{key:"getQuality",value:function(){return this.get("quality")}},{key:"setQuality",value:function(e){return this.set("quality",e)}},{key:"getSeekable",value:function(){return this.get("seekable")}},{key:"getSeeking",value:function(){return this.get("seeking")}},{key:"getTextTracks",value:function(){return this.get("textTracks")}},{key:"getVideoEmbedCode",value:function(){return this.get("videoEmbedCode")}},{key:"getVideoId",value:function(){return this.get("videoId")}},{key:"getVideoTitle",value:function(){return this.get("videoTitle")}},{key:"getVideoWidth",value:function(){return this.get("videoWidth")}},{key:"getVideoHeight",value:function(){return this.get("videoHeight")}},{key:"getVideoUrl",value:function(){return this.get("videoUrl")}},{key:"getVolume",value:function(){return this.get("volume")}},{key:"setVolume",value:function(e){return this.set("volume",e)}}])&&r(e.prototype,t),n&&r(e,n),Player}();return e||(x=function(){for(var e,t=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenChange","MSFullscreenError"]],n=0,r=t.length,o={};n<r;n++)if((e=t[n])&&e[1]in document){for(n=0;n<e.length;n++)o[t[0][n]]=e[n];return o}return!1}(),C={fullscreenchange:x.fullscreenchange,fullscreenerror:x.fullscreenerror},j={request:function(o){return new Promise(function(e,t){function n(){j.off("fullscreenchange",n),e()}j.on("fullscreenchange",n);var r=(o=o||document.documentElement)[x.requestFullscreen]();r instanceof Promise&&r.then(n).catch(t)})},exit:function(){return new Promise(function(t,e){var n,r;j.isFullscreen?(n=function e(){j.off("fullscreenchange",e),t()},j.on("fullscreenchange",n),(r=document[x.exitFullscreen]())instanceof Promise&&r.then(n).catch(e)):t()})},on:function(e,t){var n=C[e];n&&document.addEventListener(n,t)},off:function(e,t){var n=C[e];n&&document.removeEventListener(n,t)}},Object.defineProperties(j,{isFullscreen:{get:function(){return Boolean(document[x.fullscreenElement])}},element:{enumerable:!0,get:function(){return document[x.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(document[x.fullscreenEnabled])}}}),q=j,function(e){function n(e){"console"in window&&console.error&&console.error("There was an error creating an embed: ".concat(e))}var t=0<arguments.length&&void 0!==e?e:document;[].slice.call(t.querySelectorAll("[data-vimeo-id], [data-vimeo-url]")).forEach(function(t){try{if(null!==t.getAttribute("data-vimeo-defer"))return;var e=_(t);F(s(e),e,t).then(function(e){return N(e,t)}).catch(n)}catch(e){n(e)}})}(),function(e){var r=0<arguments.length&&void 0!==e?e:document;window.VimeoPlayerResizeEmbeds_||(window.VimeoPlayerResizeEmbeds_=!0,window.addEventListener("message",function(e){if(c(e.origin)&&e.data&&"spacechange"===e.data.event)for(var t=r.querySelectorAll("iframe"),n=0;n<t.length;n++)if(t[n].contentWindow===e.source){t[n].parentElement.style.paddingBottom="".concat(e.data.data[0].bottom,"px");break}}
vendor: 31,994 bytes, lines 22547-23754
22547))}(),function(e){var u=0<arguments.length&&void 0!==e?e:document;window.VimeoSeoMetadataAppended||(window.VimeoSeoMetadataAppended=!0,window.addEventListener("message",function(e){if(c(e.origin)){var t=E(e.data);if(t&&"ready"===t.event)for(var n,r=u.querySelectorAll("iframe"),o=0;o<r.length;o++){var i=r[o],a=i.contentWindow===e.source;n=i.src,/^https:\/\/player\.vimeo\.com\/video\/\d+/.test(n)&&a&&new Player(i).callMethod("appendVideoMetadata",window.location.href)}}}))}()),Player});
22548
22549/**
22550 * Owl carousel
22551 * @version 2.0.0-beta.3
22552 * @author Bartosz Wojciechowski
22553 * @license The MIT License (MIT)
22554 * @todo Lazy Load Icon
22555 * @todo prevent animationend bubling
22556 * @todo itemsScaleUp
22557 * @todo Test Zepto
22558 * @todo stagePadding calculate wrong active classes
22559 */
22560;(function($, window, document, undefined) {
22561
22562	/**
22563	 * Creates a carousel.
22564	 * @class The Owl Carousel.
22565	 * @public
22566	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
22567	 * @param {Object} [options] - The options
22568	 */
22569	function Owl(element, options) {
22570
22571		/**
22572		 * Current settings for the carousel.
22573		 * @public
22574		 */
22575		this.settings = null;
22576
22577		/**
22578		 * Current options set by the caller including defaults.
22579		 * @public
22580		 */
22581		this.options = $.extend({}, Owl.Defaults, options);
22582
22583		/**
22584		 * Plugin element.
22585		 * @public
22586		 */
22587		this.$element = $(element);
22588
22589		/**
22590		 * Proxied event handlers.
22591		 * @protected
22592		 */
22593		this._handlers = {};
22594
22595		/**
22596		 * References to the running plugins of this carousel.
22597		 * @protected
22598		 */
22599		this._plugins = {};
22600
22601		/**
22602		 * Currently suppressed events to prevent them from beeing retriggered.
22603		 * @protected
22604		 */
22605		this._supress = {};
22606
22607		/**
22608		 * Absolute current position.
22609		 * @protected
22610		 */
22611		this._current = null;
22612
22613		/**
22614		 * Animation speed in milliseconds.
22615		 * @protected
22616		 */
22617		this._speed = null;
22618
22619		/**
22620		 * Coordinates of all items in pixel.
22621		 * @todo The name of this member is missleading.
22622		 * @protected
22623		 */
22624		this._coordinates = [];
22625
22626		/**
22627		 * Current breakpoint.
22628		 * @todo Real media queries would be nice.
22629		 * @protected
22630		 */
22631		this._breakpoint = null;
22632
22633		/**
22634		 * Current width of the plugin element.
22635		 */
22636		this._width = null;
22637
22638		/**
22639		 * All real items.
22640		 * @protected
22641		 */
22642		this._items = [];
22643
22644		/**
22645		 * All cloned items.
22646		 * @protected
22647		 */
22648		this._clones = [];
22649
22650		/**
22651		 * Merge values of all items.
22652		 * @todo Maybe this could be part of a plugin.
22653		 * @protected
22654		 */
22655		this._mergers = [];
22656
22657		/**
22658		 * Widths of all items.
22659		 */
22660		this._widths = [];
22661
22662		/**
22663		 * Invalidated parts within the update process.
22664		 * @protected
22665		 */
22666		this._invalidated = {};
22667
22668		/**
22669		 * Ordered list of workers for the update process.
22670		 * @protected
22671		 */
22672		this._pipe = [];
22673
22674		/**
22675		 * Current state information for the drag operation.
22676		 * @todo #261
22677		 * @protected
22678		 */
22679		this._drag = {
22680			time: null,
22681			target: null,
22682			pointer: null,
22683			stage: {
22684				start: null,
22685				current: null
22686			},
22687			direction: null
22688		};
22689
22690		/**
22691		 * Current state information and their tags.
22692		 * @type {Object}
22693		 * @protected
22694		 */
22695		this._states = {
22696			current: {},
22697			tags: {
22698				'initializing': [ 'busy' ],
22699				'animating': [ 'busy' ],
22700				'dragging': [ 'interacting' ]
22701			}
22702		};
22703
22704		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
22705			this._handlers[handler] = $.proxy(this[handler], this);
22706		}, this));
22707
22708		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
22709			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
22710				= new plugin(this);
22711		}, this));
22712
22713		$.each(Owl.Workers, $.proxy(function(priority, worker) {
22714			this._pipe.push({
22715				'filter': worker.filter,
22716				'run': $.proxy(worker.run, this)
22717			});
22718		}, this));
22719
22720		this.setup();
22721		this.initialize();
22722	}
22723
22724	/**
22725	 * Default options for the carousel.
22726	 * @public
22727	 */
22728	Owl.Defaults = {
22729		items: 3,
22730		loop: false,
22731		center: false,
22732		rewind: false,
22733
22734		mouseDrag: true,
22735		touchDrag: true,
22736		pullDrag: true,
22737		freeDrag: false,
22738
22739		margin: 0,
22740		stagePadding: 0,
22741
22742		merge: false,
22743		mergeFit: true,
22744		autoWidth: false,
22745
22746		startPosition: 0,
22747		rtl: false,
22748
22749		smartSpeed: 250,
22750		fluidSpeed: false,
22751		dragEndSpeed: false,
22752
22753		responsive: {},
22754		responsiveRefreshRate: 200,
22755		responsiveBaseElement: window,
22756
22757		fallbackEasing: 'swing',
22758
22759		info: false,
22760
22761		nestedItemSelector: false,
22762		itemElement: 'div',
22763		stageElement: 'div',
22764
22765		refreshClass: 'owl-refresh',
22766		loadedClass: 'owl-loaded',
22767		loadingClass: 'owl-loading',
22768		rtlClass: 'owl-rtl',
22769		responsiveClass: 'owl-responsive',
22770		dragClass: 'owl-drag',
22771		itemClass: 'owl-item',
22772		stageClass: 'owl-stage',
22773		stageOuterClass: 'owl-stage-outer',
22774		grabClass: 'owl-grab'
22775	};
22776
22777	/**
22778	 * Enumeration for width.
22779	 * @public
22780	 * @readonly
22781	 * @enum {String}
22782	 */
22783	Owl.Width = {
22784		Default: 'default',
22785		Inner: 'inner',
22786		Outer: 'outer'
22787	};
22788
22789	/**
22790	 * Enumeration for types.
22791	 * @public
22792	 * @readonly
22793	 * @enum {String}
22794	 */
22795	Owl.Type = {
22796		Event: 'event',
22797		State: 'state'
22798	};
22799
22800	/**
22801	 * Contains all registered plugins.
22802	 * @public
22803	 */
22804	Owl.Plugins = {};
22805
22806	/**
22807	 * List of workers involved in the update process.
22808	 */
22809	Owl.Workers = [ {
22810		filter: [ 'width', 'settings' ],
22811		run: function() {
22812			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
22813			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
22814		}
22815	}, {
22816		filter: [ 'width', 'items', 'settings' ],
22817		run: function(cache) {
22818			cache.current = this._items && this._items[this.relative(this._current)];
22819		}
22820	}, {
22821		filter: [ 'items', 'settings' ],
22822		run: function() {
22823			this.$stage.children('.cloned').remove();
22824		}
22825	}, {
22826		filter: [ 'width', 'items', 'settings' ],
22827		run: function(cache) {
22828			var margin = this.settings.margin || '',
22829				grid = !this.settings.autoWidth,
22830				rtl = this.settings.rtl,
22831				css = {
22832					'width': 'auto',
22833					'margin-left': rtl ? margin : '',
22834					'margin-right': rtl ? '' : margin
22835				};
22836
22837			!grid && this.$stage.children().css(css);
22838
22839			cache.css = css;
22840		}
22841	}, {
22842		filter: [ 'width', 'items', 'settings' ],
22843		run: function(cache) {
22844			//UNCODE edit to fix Chrome stage padding issue
22845			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
22846				merge = null,
22847				iterator = this._items.length,
22848				grid = !this.settings.autoWidth,
22849				widths = [];
22850
22851			cache.items = {
22852				merge: false,
22853				width: width
22854			};
22855
22856			while (iterator--) {
22857				merge = this._mergers[iterator];
22858				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
22859
22860				cache.items.merge = merge > 1 || cache.items.merge;
22861
22862				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22863			}
22864
22865			this._widths = widths;
22866		}
22867	}, {
22868		filter: [ 'items', 'settings' ],
22869		run: function() {
22870			var clones = [],
22871				items = this._items,
22872				settings = this.settings,
22873				view = Math.max(settings.items * 2, 4),
22874				size = Math.ceil(items.length / 2) * 2,
22875				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22876				append = '',
22877				prepend = '';
22878
22879			repeat /= 2;
22880
22881			while (repeat--) {
22882				clones.push(this.normalize(clones.length / 2, true));
22883				append = append + items[clones[clones.length - 1]][0].outerHTML;
22884				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22885				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22886			}
22887
22888			this._clones = clones;
22889
22890			// var appendVideo = $(append).find('.uncode-video-container');
22891			// if (appendVideo.length) {
22892			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22893			// }
22894			// var prependVideo = $(prepend).find('.uncode-video-container');
22895			// if (prependVideo.length) {
22896			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22897			// }
22898			$(append).addClass('cloned').appendTo(this.$stage);
22899			$(prepend).addClass('cloned').prependTo(this.$stage);
22900		}
22901	}, {
22902		filter: [ 'width', 'items', 'settings' ],
22903		run: function() {
22904			var rtl = this.settings.rtl ? 1 : -1,
22905				size = this._clones.length + this._items.length,
22906				iterator = -1,
22907				previous = 0,
22908				current = 0,
22909				coordinates = [];
22910
22911			while (++iterator < size) {
22912				previous = coordinates[iterator - 1] || 0;
22913				current = this._widths[this.relative(iterator)] + this.settings.margin;
22914				coordinates.push(previous + current * rtl);
22915			}
22916
22917			this._coordinates = coordinates;
22918		}
22919	}, {
22920		filter: [ 'width', 'items', 'settings' ],
22921		run: function() {
22922			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22923				padding = stagePadding,
22924				coordinates = this._coordinates,
22925				css = {
22926					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22927					'padding-left': padding || '',
22928					'padding-right': padding || ''
22929				};
22930
22931			this.$stage.css(css);
22932		}
22933	}, {
22934		filter: [ 'width', 'items', 'settings' ],
22935		run: function(cache) {
22936			var iterator = this._coordinates.length,
22937				grid = !this.settings.autoWidth,
22938				items = this.$stage.children();
22939
22940			if (grid && cache.items.merge) {
22941				while (iterator--) {
22942					cache.css.width = this._widths[this.relative(iterator)];
22943					items.eq(iterator).css(cache.css);
22944				}
22945			} else if (grid) {
22946				cache.css.width = cache.items.width;
22947				items.css(cache.css);
22948			}
22949		}
22950	}, {
22951		filter: [ 'items' ],
22952		run: function() {
22953			this._coordinates.length < 1 && this.$stage.removeAttr('style');
22954		}
22955	}, {
22956		filter: [ 'width', 'items', 'settings' ],
22957		run: function(cache) {
22958			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
22959			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
22960			this.reset(cache.current);
22961		}
22962	}, {
22963		filter: [ 'position' ],
22964		run: function() {
22965			this.animate(this.coordinates(this._current));
22966		}
22967	}, {
22968		filter: [ 'width', 'position', 'items', 'settings' ],
22969		run: function() {
22970			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22971				rtl = this.settings.rtl ? 1 : -1,
22972				padding = this.settings.stagePadding * 2,
22973				begin = this.coordinates(this.current()) + padding,
22974				end = begin + this.width() * rtl,
22975				inner, outer, matches = [], i, n;
22976
22977			for (i = 0, n = this._coordinates.length; i < n; i++) {
22978				inner = this._coordinates[i - 1] || 0;
22979				outer = Math.abs(this._coordinates[i]) + padding * rtl;
22980
22981				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
22982					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
22983					matches.push(i);
22984				}
22985			}
22986
22987			this.$stage.children('.active').removeClass('active');
22988			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
22989
22990			if (this.settings.center) {
22991				this.$stage.children('.center').removeClass('center');
22992				this.$stage.children().eq(this.current()).addClass('center');
22993			}
22994		}
22995	} ];
22996
22997	/**
22998	 * Initializes the carousel.
22999	 * @protected
23000	 */
23001	Owl.prototype.initialize = function() {
23002		this.enter('initializing');
23003		this.trigger('initialize');
23004
23005		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
23006
23007		if (this.settings.autoWidth && !this.is('pre-loading')) {
23008			var imgs, nestedSelector, width;
23009			imgs = this.$element.find('img');
23010			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
23011			width = this.$element.children(nestedSelector).width();
23012
23013			if (imgs.length && width <= 0) {
23014				this.preloadAutoWidthImages(imgs);
23015			}
23016		}
23017
23018		this.$element.addClass(this.options.loadingClass);
23019
23020		// create stage
23021		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
23022			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
23023
23024		// append stage
23025		this.$element.append(this.$stage.parent());
23026
23027		// append content
23028		this.replace(this.$element.children().not(this.$stage.parent()));
23029
23030		// check visibility
23031		if (this.$element.is(':visible')) {
23032			// update view
23033			this.refresh();
23034		} else {
23035			// invalidate width
23036			this.invalidate('width');
23037		}
23038
23039		this.$element
23040			.removeClass(this.options.loadingClass)
23041			.addClass(this.options.loadedClass);
23042
23043		// register event handlers
23044		this.registerEventHandlers();
23045
23046		this.leave('initializing');
23047		this.trigger('initialized');
23048	};
23049
23050	/**
23051	 * Setups the current settings.
23052	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
23053	 * @todo Support for media queries by using `matchMedia` would be nice.
23054	 * @public
23055	 */
23056	Owl.prototype.setup = function() {
23057		var viewport = this.viewport(),
23058			overwrites = this.options.responsive,
23059			match = -1,
23060			settings = null;
23061
23062		if (!overwrites) {
23063			settings = $.extend({}, this.options);
23064		} else {
23065			$.each(overwrites, function(breakpoint) {
23066				if (breakpoint <= viewport && breakpoint > match) {
23067					match = Number(breakpoint);
23068				}
23069			});
23070
23071			settings = $.extend({}, this.options, overwrites[match]);
23072			delete settings.responsive;
23073
23074			// responsive class
23075			if (settings.responsiveClass) {
23076				this.$element.attr('class',
23077					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
23078				);
23079			}
23080		}
23081
23082		if (this.settings === null || this._breakpoint !== match) {
23083			this.trigger('change', { property: { name: 'settings', value: settings } });
23084			this._breakpoint = match;
23085			this.settings = settings;
23086			this.invalidate('settings');
23087			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
23088		}
23089	};
23090
23091	/**
23092	 * Updates option logic if necessery.
23093	 * @protected
23094	 */
23095	Owl.prototype.optionsLogic = function() {
23096		if (this.settings.autoWidth) {
23097			this.settings.stagePadding = false;
23098			this.settings.merge = false;
23099		}
23100	};
23101
23102	/**
23103	 * Prepares an item before add.
23104	 * @todo Rename event parameter `content` to `item`.
23105	 * @protected
23106	 * @returns {jQuery|HTMLElement} - The item container.
23107	 */
23108	Owl.prototype.prepare = function(item, index) {
23109		var event = this.trigger('prepare', { content: item });
23110		if (!event.data) {
23111			event.data = $('<' + this.settings.itemElement + '/>')
23112				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
23113		}
23114
23115		this.trigger('prepared', { content: event.data });
23116
23117		return event.data;
23118	};
23119
23120	/**
23121	 * Updates the view.
23122	 * @public
23123	 */
23124	Owl.prototype.update = function() {
23125		var i = 0,
23126			n = this._pipe.length,
23127			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
23128			cache = {};
23129
23130		while (i < n) {
23131			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
23132				this._pipe[i].run(cache);
23133			}
23134			i++;
23135		}
23136
23137		this._invalidated = {};
23138
23139		!this.is('valid') && this.enter('valid');
23140	};
23141
23142	/**
23143	 * Gets the width of the view.
23144	 * @public
23145	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
23146	 * @returns {Number} - The width of the view in pixel.
23147	 */
23148	Owl.prototype.width = function(dimension) {
23149		dimension = dimension || Owl.Width.Default;
23150		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
23151		switch (dimension) {
23152			case Owl.Width.Inner:
23153			case Owl.Width.Outer:
23154				return this._width;
23155			default:
23156				return this._width - stagePadding * 2 + this.settings.margin;
23157		}
23158	};
23159
23160	/**
23161	 * Refreshes the carousel primarily for adaptive purposes.
23162	 * @public
23163	 */
23164	Owl.prototype.refresh = function() {
23165		this.enter('refreshing');
23166		this.trigger('refresh');
23167
23168		this.setup();
23169
23170		this.optionsLogic();
23171
23172		this.$element.addClass(this.options.refreshClass);
23173
23174		this.update();
23175
23176		this.$element.removeClass(this.options.refreshClass);
23177
23178		this.leave('refreshing');
23179		this.trigger('refreshed');
23180	};
23181
23182	/**
23183	 * Checks window `resize` event.
23184	 * @protected
23185	 */
23186	Owl.prototype.onThrottledResize = function() {
23187		window.clearTimeout(this.resizeTimer);
23188		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
23189	};
23190
23191	/**
23192	 * Checks window `resize` event.
23193	 * @protected
23194	 */
23195	Owl.prototype.onResize = function() {
23196		if (!this._items.length) {
23197			return false;
23198		}
23199
23200		if (this._width === this.$element.width()) {
23201			return false;
23202		}
23203
23204		if (!this.$element.is(':visible')) {
23205			return false;
23206		}
23207
23208		this.enter('resizing');
23209
23210		if (this.trigger('resize').isDefaultPrevented()) {
23211			this.leave('resizing');
23212			return false;
23213		}
23214
23215		this.invalidate('width');
23216
23217		this.refresh();
23218
23219		this.leave('resizing');
23220		this.trigger('resized');
23221	};
23222
23223	/**
23224	 * Registers event handlers.
23225	 * @todo Check `msPointerEnabled`
23226	 * @todo #261
23227	 * @protected
23228	 */
23229	Owl.prototype.registerEventHandlers = function() {
23230		if ($.support.transition) {
23231			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
23232		}
23233
23234		if (this.settings.responsive !== false) {
23235			this.on(window, 'resize', this._handlers.onThrottledResize);
23236		}
23237
23238		if (this.settings.mouseDrag) {
23239			this.$element.addClass(this.options.dragClass);
23240			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
23241			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
23242		}
23243
23244		if (this.settings.touchDrag){
23245			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
23246			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
23247		}
23248	};
23249
23250	/**
23251	 * Handles `touchstart` and `mousedown` events.
23252	 * @todo Horizontal swipe threshold as option
23253	 * @todo #261
23254	 * @protected
23255	 * @param {Event} event - The event arguments.
23256	 */
23257	Owl.prototype.onDragStart = function(event) {
23258		var stage = null;
23259
23260		if (event.which === 3) {
23261			return;
23262		}
23263
23264		if ($.support.transform) {
23265			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
23266			stage = {
23267				x: stage[stage.length === 16 ? 12 : 4],
23268				y: stage[stage.length === 16 ? 13 : 5]
23269			};
23270		} else {
23271			stage = this.$stage.position();
23272			stage = {
23273				x: this.settings.rtl ?
23274					stage.left + this.$stage.width() - this.width() + this.settings.margin :
23275					stage.left,
23276				y: stage.top
23277			};
23278		}
23279
23280		if (this.is('animating')) {
23281			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
23282			this.invalidate('position');
23283		}
23284
23285		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
23286
23287		this.speed(0);
23288
23289		this._drag.time = new Date().getTime();
23290		this._drag.target = $(event.target);
23291		this._drag.stage.start = stage;
23292		this._drag.stage.current = stage;
23293		this._drag.pointer = this.pointer(event);
23294
23295		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
23296
23297		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
23298			var delta = this.difference(this._drag.pointer, this.pointer(event));
23299
23300			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
23301
23302			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
23303				return;
23304			}
23305
23306			event.preventDefault();
23307
23308			this.enter('dragging');
23309			this.trigger('drag');
23310		}, this));
23311	};
23312
23313	/**
23314	 * Handles the `touchmove` and `mousemove` events.
23315	 * @todo #261
23316	 * @protected
23317	 * @param {Event} event - The event arguments.
23318	 */
23319	Owl.prototype.onDragMove = function(event) {
23320		var minimum = null,
23321			maximum = null,
23322			pull = null,
23323			delta = this.difference(this._drag.pointer, this.pointer(event)),
23324			stage = this.difference(this._drag.stage.start, delta);
23325
23326		if (!this.is('dragging')) {
23327			return;
23328		}
23329
23330		event.preventDefault();
23331
23332		if (this.settings.loop) {
23333			minimum = this.coordinates(this.minimum());
23334			maximum = this.coordinates(this.maximum() + 1) - minimum;
23335			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
23336		} else {
23337			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
23338			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
23339			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
23340			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
23341		}
23342
23343		this._drag.stage.current = stage;
23344
23345		this.animate(stage.x);
23346	};
23347
23348	/**
23349	 * Handles the `touchend` and `mouseup` events.
23350	 * @todo #261
23351	 * @todo Threshold for click event
23352	 * @protected
23353	 * @param {Event} event - The event arguments.
23354	 */
23355	Owl.prototype.onDragEnd = function(event) {
23356		var delta = this.difference(this._drag.pointer, this.pointer(event)),
23357			stage = this._drag.stage.current,
23358			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
23359
23360		$(document).off('.owl.core');
23361
23362		this.$element.removeClass(this.options.grabClass);
23363
23364		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
23365			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
23366			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
23367			this.invalidate('position');
23368			this.update();
23369
23370			this._drag.direction = direction;
23371
23372			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
23373				this._drag.target.one('click.owl.core', function() { return false; });
23374			}
23375		}
23376
23377		if (!this.is('dragging')) {
23378			return;
23379		}
23380
23381		this.leave('dragging');
23382		this.trigger('dragged');
23383	};
23384
23385	/**
23386	 * Gets absolute position of the closest item for a coordinate.
23387	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
23388	 * @protected
23389	 * @param {Number} coordinate - The coordinate in pixel.
23390	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
23391	 * @return {Number} - The absolute position of the closest item.
23392	 */
23393	Owl.prototype.closest = function(coordinate, direction) {
23394		var position = -1,
23395			pull = 30,
23396			width = this.width(),
23397			coordinates = this.coordinates();
23398
23399		if (!this.settings.freeDrag) {
23400			// check closest item
23401			$.each(coordinates, $.proxy(function(index, value) {
23402				if (coordinate > value - pull && coordinate < value + pull) {
23403					position = index;
23404				} else if (this.op(coordinate, '<', value)
23405					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
23406					position = direction === 'left' ? index + 1 : index;
23407				}
23408				return position === -1;
23409			}, this));
23410		}
23411
23412		if (!this.settings.loop) {
23413			// non loop boundries
23414			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
23415				position = coordinate = this.minimum();
23416			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
23417				position = coordinate = this.maximum();
23418			}
23419		}
23420
23421		return position;
23422	};
23423
23424	/**
23425	 * Animates the stage.
23426	 * @todo #270
23427	 * @public
23428	 * @param {Number} coordinate - The coordinate in pixels.
23429	 */
23430	Owl.prototype.animate = function(coordinate) {
23431		var animate = this.speed() > 0;
23432
23433		this.is('animating') && this.onTransitionEnd();
23434
23435		if (animate) {
23436			this.enter('animating');
23437			this.trigger('translate');
23438		}
23439
23440		if ($.support.transform3d && $.support.transition) {
23441			this.$stage.css({
23442				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
23443				transition: (this.speed() / 1000) + 's'
23444			});
23445		} else if (animate) {
23446			this.$stage.animate({
23447				left: coordinate + 'px'
23448			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
23449		} else {
23450			this.$stage.css({
23451				left: coordinate + 'px'
23452			});
23453		}
23454	};
23455
23456	/**
23457	 * Checks whether the carousel is in a specific state or not.
23458	 * @param {String} state - The state to check.
23459	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
23460	 */
23461	Owl.prototype.is = function(state) {
23462		return this._states.current[state] && this._states.current[state] > 0;
23463	};
23464
23465	/**
23466	 * Sets the absolute position of the current item.
23467	 * @public
23468	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
23469	 * @returns {Number} - The absolute position of the current item.
23470	 */
23471	Owl.prototype.current = function(position) {
23472		if (position === undefined) {
23473			return this._current;
23474		}
23475
23476		if (this._items.length === 0) {
23477			return undefined;
23478		}
23479
23480		position = this.normalize(position);
23481
23482		if (this._current !== position) {
23483			var event = this.trigger('change', { property: { name: 'position', value: position } });
23484
23485			if (event.data !== undefined) {
23486				position = this.normalize(event.data);
23487			}
23488
23489			this._current = position;
23490
23491			this.invalidate('position');
23492
23493			this.trigger('changed', { property: { name: 'position', value: this._current } });
23494		}
23495
23496		return this._current;
23497	};
23498
23499	/**
23500	 * Invalidates the given part of the update routine.
23501	 * @param {String} [part] - The part to invalidate.
23502	 * @returns {Array.<String>} - The invalidated parts.
23503	 */
23504	Owl.prototype.invalidate = function(part) {
23505		if ($.type(part) === 'string') {
23506			this._invalidated[part] = true;
23507			this.is('valid') && this.leave('valid');
23508		}
23509		return $.map(this._invalidated, function(v, i) { return i });
23510	};
23511
23512	/**
23513	 * Resets the absolute position of the current item.
23514	 * @public
23515	 * @param {Number} position - The absolute position of the new item.
23516	 */
23517	Owl.prototype.reset = function(position) {
23518		position = this.normalize(position);
23519
23520		if (position === undefined) {
23521			return;
23522		}
23523
23524		this._speed = 0;
23525		this._current = position;
23526
23527		this.suppress([ 'translate', 'translated' ]);
23528
23529		this.animate(this.coordinates(position));
23530
23531		this.release([ 'translate', 'translated' ]);
23532	};
23533
23534	/**
23535	 * Normalizes an absolute or a relative position of an item.
23536	 * @public
23537	 * @param {Number} position - The absolute or relative position to normalize.
23538	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
23539	 * @returns {Number} - The normalized position.
23540	 */
23541	Owl.prototype.normalize = function(position, relative) {
23542		var n = this._items.length,
23543			m = relative ? 0 : this._clones.length;
23544
23545		if (!$.isNumeric(position) || n < 1) {
23546			position = undefined;
23547		} else if (position < 0 || position >= n + m) {
23548			position = ((position - m / 2) % n + n) % n + m / 2;
23549		}
23550
23551		return position;
23552	};
23553
23554	/**
23555	 * Converts an absolute position of an item into a relative one.
23556	 * @public
23557	 * @param {Number} position - The absolute position to convert.
23558	 * @returns {Number} - The converted position.
23559	 */
23560	Owl.prototype.relative = function(position) {
23561		position -= this._clones.length / 2;
23562		return this.normalize(position, true);
23563	};
23564
23565	/**
23566	 * Gets the maximum position for the current item.
23567	 * @public
23568	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23569	 * @returns {Number}
23570	 */
23571	Owl.prototype.maximum = function(relative) {
23572		var settings = this.settings,
23573			maximum = this._coordinates.length,
23574			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
23575			i = -1, j;
23576
23577		if (settings.loop) {
23578			maximum = this._clones.length / 2 + this._items.length - 1;
23579		} else if (settings.autoWidth || settings.merge) {
23580			// binary search
23581			while (maximum - i > 1) {
23582				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
23583					? i = j : maximum = j;
23584			}
23585		} else if (settings.center) {
23586			maximum = this._items.length - 1;
23587		} else {
23588			maximum = this._items.length - settings.items;
23589		}
23590
23591		if (relative) {
23592			maximum -= this._clones.length / 2;
23593		}
23594
23595		return Math.max(maximum, 0);
23596	};
23597
23598	/**
23599	 * Gets the minimum position for the current item.
23600	 * @public
23601	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23602	 * @returns {Number}
23603	 */
23604	Owl.prototype.minimum = function(relative) {
23605		return relative ? 0 : this._clones.length / 2;
23606	};
23607
23608	/**
23609	 * Gets an item at the specified relative position.
23610	 * @public
23611	 * @param {Number} [position] - The relative position of the item.
23612	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23613	 */
23614	Owl.prototype.items = function(position) {
23615		if (position === undefined) {
23616			return this._items.slice();
23617		}
23618
23619		position = this.normalize(position, true);
23620		return this._items[position];
23621	};
23622
23623	/**
23624	 * Gets an item at the specified relative position.
23625	 * @public
23626	 * @param {Number} [position] - The relative position of the item.
23627	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23628	 */
23629	Owl.prototype.mergers = function(position) {
23630		if (position === undefined) {
23631			return this._mergers.slice();
23632		}
23633
23634		position = this.normalize(position, true);
23635		return this._mergers[position];
23636	};
23637
23638	/**
23639	 * Gets the absolute positions of clones for an item.
23640	 * @public
23641	 * @param {Number} [position] - The relative position of the item.
23642	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
23643	 */
23644	Owl.prototype.clones = function(position) {
23645		var odd = this._clones.length / 2,
23646			even = odd + this._items.length,
23647			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
23648
23649		if (position === undefined) {
23650			return $.map(this._clones, function(v, i) { return map(i) });
23651		}
23652
23653		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
23654	};
23655
23656	/**
23657	 * Sets the current animation speed.
23658	 * @public
23659	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
23660	 * @returns {Number} - The current animation speed in milliseconds.
23661	 */
23662	Owl.prototype.speed = function(speed) {
23663		if (speed !== undefined) {
23664			this._speed = speed;
23665		}
23666
23667		return this._speed;
23668	};
23669
23670	/**
23671	 * Gets the coordinate of an item.
23672	 * @todo The name of this method is missleanding.
23673	 * @public
23674	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
23675	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
23676	 */
23677	Owl.prototype.coordinates = function(position) {
23678		var coordinate = null;
23679
23680		if (position === undefined) {
23681			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
23682				return this.coordinates(index);
23683			}, this));
23684		}
23685
23686		if (this.settings.center) {
23687			coordinate = this._coordinates[position];
23688			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
23689		} else {
23690			coordinate = this._coordinates[position - 1] || 0;
23691		}
23692
23693		return coordinate;
23694	};
23695
23696	/**
23697	 * Calculates the speed for a translation.
23698	 * @protected
23699	 * @param {Number} from - The absolute position of the start item.
23700	 * @param {Number} to - The absolute position of the target item.
23701	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
23702	 * @returns {Number} - The time in milliseconds for the translation.
23703	 */
23704	Owl.prototype.duration = function(from, to, factor) {
23705		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
23706	};
23707
23708	/**
23709	 * Slides to the specified item.
23710	 * @public
23711	 * @param {Number} position - The position of the item.
23712	 * @param {Number} [speed] - The time in milliseconds for the transition.
23713	 */
23714	Owl.prototype.to = function(position, speed) {
23715		var current = this.current(),
23716			revert = null,
23717			distance = position - this.relative(current),
23718			direction = (distance > 0) - (distance < 0),
23719			items = this._items.length,
23720			minimum = this.minimum(),
23721			maximum = this.maximum();
23722
23723		if (this.settings.loop) {
23724			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
23725				distance += direction * -1 * items;
23726			}
23727
23728			position = current + distance;
23729			revert = ((position - minimum) % items + items) % items + minimum;
23730
23731			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
23732				current = revert - distance;
23733				position = revert;
23734				this.reset(current);
23735			}
23736		} else if (this.settings.rewind) {
23737			maximum += 1;
23738			position = (position % maximum + maximum) % maximum;
23739		} else {
23740			position = Math.max(minimum, Math.min(maximum, position));
23741		}
23742
23743		this.speed(this.duration(current, position, speed));
23744		this.current(position);
23745
23746		if (this.$element.is(':visible')) {
23747			this.update();
23748		}
23749	};
23750
23751	/**
23752	 * Slides to the next item.
23753	 * @public
23754	 * @param {Number}
vendor: 12,284 bytes, lines 23754-24174
23754 [speed] - The time in milliseconds for the transition.
23755	 */
23756	Owl.prototype.next = function(speed) {
23757		speed = speed || false;
23758		this.to(this.relative(this.current()) + 1, speed);
23759	};
23760
23761	/**
23762	 * Slides to the previous item.
23763	 * @public
23764	 * @param {Number} [speed] - The time in milliseconds for the transition.
23765	 */
23766	Owl.prototype.prev = function(speed) {
23767		speed = speed || false;
23768		this.to(this.relative(this.current()) - 1, speed);
23769	};
23770
23771	/**
23772	 * Handles the end of an animation.
23773	 * @protected
23774	 * @param {Event} event - The event arguments.
23775	 */
23776	Owl.prototype.onTransitionEnd = function(event) {
23777
23778		// if css2 animation then event object is undefined
23779		if (event !== undefined) {
23780			event.stopPropagation();
23781
23782			// Catch only owl-stage transitionEnd event
23783			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
23784				return false;
23785			}
23786		}
23787
23788		this.leave('animating');
23789		this.trigger('translated');
23790	};
23791
23792	/**
23793	 * Gets viewport width.
23794	 * @protected
23795	 * @return {Number} - The width in pixel.
23796	 */
23797	Owl.prototype.viewport = function() {
23798		var width;
23799		if (this.options.responsiveBaseElement !== window) {
23800			width = $(this.options.responsiveBaseElement).width();
23801		} else if (window.innerWidth) {
23802			width = window.innerWidth;
23803		} else if (document.documentElement && document.documentElement.clientWidth) {
23804			width = document.documentElement.clientWidth;
23805		} else {
23806			throw 'Can not detect viewport width.';
23807		}
23808
23809		return width;
23810	};
23811
23812	/**
23813	 * Replaces the current content.
23814	 * @public
23815	 * @param {HTMLElement|jQuery|String} content - The new content.
23816	 */
23817	Owl.prototype.replace = function(content) {
23818		this.$stage.empty();
23819		this._items = [];
23820
23821		if (content) {
23822			content = (content instanceof jQuery) ? content : $(content);
23823		}
23824
23825		if (this.settings.nestedItemSelector) {
23826			content = content.find('.' + this.settings.nestedItemSelector);
23827		}
23828
23829		content.filter(function() {
23830			return this.nodeType === 1;
23831		}).each($.proxy(function(index, item) {
23832			item = this.prepare(item, index);
23833			this.$stage.append(item);
23834			this._items.push(item);
23835			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
23836		}, this));
23837
23838		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
23839
23840		this.invalidate('items');
23841	};
23842
23843	/**
23844	 * Adds an item.
23845	 * @todo Use `item` instead of `content` for the event arguments.
23846	 * @public
23847	 * @param {HTMLElement|jQuery|String} content - The item content to add.
23848	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
23849	 */
23850	Owl.prototype.add = function(content, position) {
23851		var current = this.relative(this._current);
23852
23853		position = position === undefined ? this._items.length : this.normalize(position, true);
23854		content = content instanceof jQuery ? content : $(content);
23855
23856		this.trigger('add', { content: content, position: position });
23857
23858		content = this.prepare(content, this._items[current].index());
23859
23860		if (this._items.length === 0 || position === this._items.length) {
23861			this._items.length === 0 && this.$stage.append(content);
23862			this._items.length !== 0 && this._items[position - 1].after(content);
23863			this._items.push(content);
23864			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23865		} else {
23866			this._items[position].before(content);
23867			this._items.splice(position, 0, content);
23868			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23869		}
23870
23871		this._items[current] && this.reset(this._items[current].index());
23872
23873		this.invalidate('items');
23874
23875		this.trigger('added', { content: content, position: position });
23876	};
23877
23878	/**
23879	 * Removes an item by its position.
23880	 * @todo Use `item` instead of `content` for the event arguments.
23881	 * @public
23882	 * @param {Number} position - The relative position of the item to remove.
23883	 */
23884	Owl.prototype.remove = function(position) {
23885		position = this.normalize(position, true);
23886
23887		if (position === undefined) {
23888			return;
23889		}
23890
23891		this.trigger('remove', { content: this._items[position], position: position });
23892
23893		this._items[position].remove();
23894		this._items.splice(position, 1);
23895		this._mergers.splice(position, 1);
23896
23897		this.invalidate('items');
23898
23899		this.trigger('removed', { content: null, position: position });
23900	};
23901
23902	/**
23903	 * Preloads images with auto width.
23904	 * @todo Replace by a more generic approach
23905	 * @protected
23906	 */
23907	Owl.prototype.preloadAutoWidthImages = function(images) {
23908		images.each($.proxy(function(i, element) {
23909			this.enter('pre-loading');
23910			element = $(element);
23911			$(new Image()).one('load', $.proxy(function(e) {
23912				element.attr('src', e.target.src);
23913				element.css('opacity', 1);
23914				this.leave('pre-loading');
23915				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23916			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23917		}, this));
23918	};
23919
23920	/**
23921	 * Destroys the carousel.
23922	 * @public
23923	 */
23924	Owl.prototype.destroy = function() {
23925
23926		this.$element.off('.owl.core');
23927		this.$stage.off('.owl.core');
23928		$(document).off('.owl.core');
23929
23930		if (this.settings.responsive !== false) {
23931			window.clearTimeout(this.resizeTimer);
23932			this.off(window, 'resize', this._handlers.onThrottledResize);
23933		}
23934
23935		for (var i in this._plugins) {
23936			this._plugins[i].destroy();
23937		}
23938
23939		this.$stage.children('.cloned').remove();
23940
23941		this.$stage.unwrap();
23942		this.$stage.children().contents().unwrap();
23943		this.$stage.children().unwrap();
23944
23945		this.$element
23946			.removeClass(this.options.refreshClass)
23947			.removeClass(this.options.loadingClass)
23948			.removeClass(this.options.loadedClass)
23949			.removeClass(this.options.rtlClass)
23950			.removeClass(this.options.dragClass)
23951			.removeClass(this.options.grabClass)
23952			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
23953			.removeData('owl.carousel');
23954	};
23955
23956	/**
23957	 * Operators to calculate right-to-left and left-to-right.
23958	 * @protected
23959	 * @param {Number} [a] - The left side operand.
23960	 * @param {String} [o] - The operator.
23961	 * @param {Number} [b] - The right side operand.
23962	 */
23963	Owl.prototype.op = function(a, o, b) {
23964		var rtl = this.settings.rtl;
23965		switch (o) {
23966			case '<':
23967				return rtl ? a > b : a < b;
23968			case '>':
23969				return rtl ? a < b : a > b;
23970			case '>=':
23971				return rtl ? a <= b : a >= b;
23972			case '<=':
23973				return rtl ? a >= b : a <= b;
23974			default:
23975				break;
23976		}
23977	};
23978
23979	/**
23980	 * Attaches to an internal event.
23981	 * @protected
23982	 * @param {HTMLElement} element - The event source.
23983	 * @param {String} event - The event name.
23984	 * @param {Function} listener - The event handler to attach.
23985	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
23986	 */
23987	Owl.prototype.on = function(element, event, listener, capture) {
23988		if (element.addEventListener) {
23989			element.addEventListener(event, listener, capture);
23990		} else if (element.attachEvent) {
23991			element.attachEvent('on' + event, listener);
23992		}
23993	};
23994
23995	/**
23996	 * Detaches from an internal event.
23997	 * @protected
23998	 * @param {HTMLElement} element - The event source.
23999	 * @param {String} event - The event name.
24000	 * @param {Function} listener - The attached event handler to detach.
24001	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
24002	 */
24003	Owl.prototype.off = function(element, event, listener, capture) {
24004		if (element.removeEventListener) {
24005			element.removeEventListener(event, listener, capture);
24006		} else if (element.detachEvent) {
24007			element.detachEvent('on' + event, listener);
24008		}
24009	};
24010
24011	/**
24012	 * Triggers a public event.
24013	 * @todo Remove `status`, `relatedTarget` should be used instead.
24014	 * @protected
24015	 * @param {String} name - The event name.
24016	 * @param {*} [data=null] - The event data.
24017	 * @param {String} [namespace=carousel] - The event namespace.
24018	 * @param {String} [state] - The state which is associated with the event.
24019	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
24020	 * @returns {Event} - The event arguments.
24021	 */
24022	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
24023		var status = {
24024			item: { count: this._items.length, index: this.current() }
24025		}, handler = $.camelCase(
24026			$.grep([ 'on', name, namespace ], function(v) { return v })
24027				.join('-').toLowerCase()
24028		), event = $.Event(
24029			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
24030			$.extend({ relatedTarget: this }, status, data)
24031		);
24032
24033		if (!this._supress[name]) {
24034			$.each(this._plugins, function(name, plugin) {
24035				if (plugin.onTrigger) {
24036					plugin.onTrigger(event);
24037				}
24038			});
24039
24040			this.register({ type: Owl.Type.Event, name: name });
24041			this.$element.trigger(event);
24042
24043			if (this.settings && typeof this.settings[handler] === 'function') {
24044				this.settings[handler].call(this, event);
24045			}
24046		}
24047
24048		return event;
24049	};
24050
24051	/**
24052	 * Enters a state.
24053	 * @param name - The state name.
24054	 */
24055	Owl.prototype.enter = function(name) {
24056		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24057			if (this._states.current[name] === undefined) {
24058				this._states.current[name] = 0;
24059			}
24060
24061			this._states.current[name]++;
24062		}, this));
24063	};
24064
24065	/**
24066	 * Leaves a state.
24067	 * @param name - The state name.
24068	 */
24069	Owl.prototype.leave = function(name) {
24070		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24071			this._states.current[name]--;
24072		}, this));
24073	};
24074
24075	/**
24076	 * Registers an event or state.
24077	 * @public
24078	 * @param {Object} object - The event or state to register.
24079	 */
24080	Owl.prototype.register = function(object) {
24081		if (object.type === Owl.Type.Event) {
24082			if (!$.event.special[object.name]) {
24083				$.event.special[object.name] = {};
24084			}
24085
24086			if (!$.event.special[object.name].owl) {
24087				var _default = $.event.special[object.name]._default;
24088				$.event.special[object.name]._default = function(e) {
24089					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
24090						return _default.apply(this, arguments);
24091					}
24092					return e.namespace && e.namespace.indexOf('owl') > -1;
24093				};
24094				$.event.special[object.name].owl = true;
24095			}
24096		} else if (object.type === Owl.Type.State) {
24097			if (!this._states.tags[object.name]) {
24098				this._states.tags[object.name] = object.tags;
24099			} else {
24100				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
24101			}
24102
24103			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
24104				return $.inArray(tag, this._states.tags[object.name]) === i;
24105			}, this));
24106		}
24107	};
24108
24109	/**
24110	 * Suppresses events.
24111	 * @protected
24112	 * @param {Array.<String>} events - The events to suppress.
24113	 */
24114	Owl.prototype.suppress = function(events) {
24115		$.each(events, $.proxy(function(index, event) {
24116			this._supress[event] = true;
24117		}, this));
24118	};
24119
24120	/**
24121	 * Releases suppressed events.
24122	 * @protected
24123	 * @param {Array.<String>} events - The events to release.
24124	 */
24125	Owl.prototype.release = function(events) {
24126		$.each(events, $.proxy(function(index, event) {
24127			delete this._supress[event];
24128		}, this));
24129	};
24130
24131	/**
24132	 * Gets unified pointer coordinates from event.
24133	 * @todo #261
24134	 * @protected
24135	 * @param {Event} - The `mousedown` or `touchstart` event.
24136	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
24137	 */
24138	Owl.prototype.pointer = function(event) {
24139		var result = { x: null, y: null };
24140
24141		event = event.originalEvent || event || window.event;
24142
24143		event = event.touches && event.touches.length ?
24144			event.touches[0] : event.changedTouches && event.changedTouches.length ?
24145				event.changedTouches[0] : event;
24146
24147		if (event.pageX) {
24148			result.x = event.pageX;
24149			result.y = event.pageY;
24150		} else {
24151			result.x = event.clientX;
24152			result.y = event.clientY;
24153		}
24154
24155		return result;
24156	};
24157
24158	/**
24159	 * Gets the difference of two vectors.
24160	 * @todo #261
24161	 * @protected
24162	 * @param {Object} - The first vector.
24163	 * @param {Object} - The second vector.
24164	 * @returns {Object} - The difference.
24165	 */
24166	Owl.prototype.difference = function(first, second) {
24167		return {
24168			x: first.x - second.x,
24169			y: first.y - second.y
24170		};
24171	};
24172
24173	/**
24174	 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 24175-25457
24175	 * @todo Navigation plugin `next` and `prev`
24176	 * @public
24177	 */
24178	$.fn.owlCarousel = function(option) {
24179		var args = Array.prototype.slice.call(arguments, 1);
24180
24181		return this.each(function() {
24182			var $this = $(this),
24183				data = $this.data('owl.carousel');
24184
24185			if (!data) {
24186				data = new Owl(this, typeof option == 'object' && option);
24187				$this.data('owl.carousel', data);
24188
24189				$.each([
24190					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
24191				], function(i, event) {
24192					data.register({ type: Owl.Type.Event, name: event });
24193					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
24194						if (e.namespace && e.relatedTarget !== this) {
24195							this.suppress([ event ]);
24196							data[event].apply(this, [].slice.call(arguments, 1));
24197							this.release([ event ]);
24198						}
24199					}, data));
24200				});
24201			}
24202
24203			if (typeof option == 'string' && option.charAt(0) !== '_') {
24204				data[option].apply(data, args);
24205			}
24206		});
24207	};
24208
24209	/**
24210	 * The constructor for the jQuery Plugin
24211	 * @public
24212	 */
24213	$.fn.owlCarousel.Constructor = Owl;
24214
24215})(window.Zepto || window.jQuery, window, document);
24216
24217/**
24218 * AutoRefresh Plugin
24219 * @version 2.0.0-beta.3
24220 * @author Artus Kolanowski
24221 * @license The MIT License (MIT)
24222 */
24223;(function($, window, document, undefined) {
24224
24225	/**
24226	 * Creates the auto refresh plugin.
24227	 * @class The Auto Refresh Plugin
24228	 * @param {Owl} carousel - The Owl Carousel
24229	 */
24230	var AutoRefresh = function(carousel) {
24231		/**
24232		 * Reference to the core.
24233		 * @protected
24234		 * @type {Owl}
24235		 */
24236		this._core = carousel;
24237
24238		/**
24239		 * Refresh interval.
24240		 * @protected
24241		 * @type {number}
24242		 */
24243		this._interval = null;
24244
24245		/**
24246		 * Whether the element is currently visible or not.
24247		 * @protected
24248		 * @type {Boolean}
24249		 */
24250		this._visible = null;
24251
24252		/**
24253		 * All event handlers.
24254		 * @protected
24255		 * @type {Object}
24256		 */
24257		this._handlers = {
24258			'initialized.owl.carousel': $.proxy(function(e) {
24259				if (e.namespace && this._core.settings.autoRefresh) {
24260					this.watch();
24261				}
24262			}, this)
24263		};
24264
24265		// set default options
24266		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
24267
24268		// register event handlers
24269		this._core.$element.on(this._handlers);
24270	};
24271
24272	/**
24273	 * Default options.
24274	 * @public
24275	 */
24276	AutoRefresh.Defaults = {
24277		autoRefresh: true,
24278		autoRefreshInterval: 500
24279	};
24280
24281	/**
24282	 * Watches the element.
24283	 */
24284	AutoRefresh.prototype.watch = function() {
24285		if (this._interval) {
24286			return;
24287		}
24288
24289		this._visible = this._core.$element.is(':visible');
24290		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
24291	};
24292
24293	/**
24294	 * Refreshes the element.
24295	 */
24296	AutoRefresh.prototype.refresh = function() {
24297		if (this._core.$element.is(':visible') === this._visible) {
24298			return;
24299		}
24300
24301		this._visible = !this._visible;
24302
24303		this._core.$element.toggleClass('owl-hidden', !this._visible);
24304
24305		this._visible && (this._core.invalidate('width') && this._core.refresh());
24306	};
24307
24308	/**
24309	 * Destroys the plugin.
24310	 */
24311	AutoRefresh.prototype.destroy = function() {
24312		var handler, property;
24313
24314		window.clearInterval(this._interval);
24315
24316		for (handler in this._handlers) {
24317			this._core.$element.off(handler, this._handlers[handler]);
24318		}
24319		for (property in Object.getOwnPropertyNames(this)) {
24320			typeof this[property] != 'function' && (this[property] = null);
24321		}
24322	};
24323
24324	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
24325
24326})(window.Zepto || window.jQuery, window, document);
24327
24328/**
24329 * Lazy Plugin
24330 * @version 2.0.0-beta.3
24331 * @author Bartosz Wojciechowski
24332 * @license The MIT License (MIT)
24333 */
24334;(function($, window, document, undefined) {
24335
24336	/**
24337	 * Creates the lazy plugin.
24338	 * @class The Lazy Plugin
24339	 * @param {Owl} carousel - The Owl Carousel
24340	 */
24341	var Lazy = function(carousel) {
24342
24343		/**
24344		 * Reference to the core.
24345		 * @protected
24346		 * @type {Owl}
24347		 */
24348		this._core = carousel;
24349
24350		/**
24351		 * Already loaded items.
24352		 * @protected
24353		 * @type {Array.<jQuery>}
24354		 */
24355		this._loaded = [];
24356
24357		/**
24358		 * Event handlers.
24359		 * @protected
24360		 * @type {Object}
24361		 */
24362		this._handlers = {
24363			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
24364				if (!e.namespace) {
24365					return;
24366				}
24367
24368				if (!this._core.settings || !this._core.settings.lazyLoad) {
24369					return;
24370				}
24371
24372				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
24373					var settings = this._core.settings,
24374						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
24375						i = ((settings.center && n * -1) || 0),
24376						position = ((e.property && e.property.value) || this._core.current()) + i,
24377						clones = this._core.clones().length,
24378						load = $.proxy(function(i, v) { this.load(v) }, this);
24379
24380					while (i++ < n) {
24381						this.load(clones / 2 + this._core.relative(position));
24382						clones && $.each(this._core.clones(this._core.relative(position)), load);
24383						position++;
24384					}
24385				}
24386			}, this)
24387		};
24388
24389		// set the default options
24390		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
24391
24392		// register event handler
24393		this._core.$element.on(this._handlers);
24394	}
24395
24396	/**
24397	 * Default options.
24398	 * @public
24399	 */
24400	Lazy.Defaults = {
24401		lazyLoad: false
24402	}
24403
24404	/**
24405	 * Loads all resources of an item at the specified position.
24406	 * @param {Number} position - The absolute position of the item.
24407	 * @protected
24408	 */
24409	Lazy.prototype.load = function(position) {
24410		var $item = this._core.$stage.children().eq(position),
24411			$elements = $item && $item.find('.owl-lazy');
24412
24413		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
24414			return;
24415		}
24416
24417		$elements.each($.proxy(function(index, element) {
24418			var $element = $(element), image,
24419				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
24420
24421			this._core.trigger('load', { element: $element, url: url }, 'lazy');
24422
24423			if ($element.is('img')) {
24424				$element.one('load.owl.lazy', $.proxy(function() {
24425					$element.css('opacity', 1);
24426					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24427				}, this)).attr('src', url);
24428			} else {
24429				image = new Image();
24430				image.onload = $.proxy(function() {
24431					$element.css({
24432						'background-image': 'url(' + url + ')',
24433						'opacity': '1'
24434					});
24435					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24436				}, this);
24437				image.src = url;
24438			}
24439		}, this));
24440
24441		this._loaded.push($item.get(0));
24442	}
24443
24444	/**
24445	 * Destroys the plugin.
24446	 * @public
24447	 */
24448	Lazy.prototype.destroy = function() {
24449		var handler, property;
24450
24451		for (handler in this.handlers) {
24452			this._core.$element.off(handler, this.handlers[handler]);
24453		}
24454		for (property in Object.getOwnPropertyNames(this)) {
24455			typeof this[property] != 'function' && (this[property] = null);
24456		}
24457	};
24458
24459	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
24460
24461})(window.Zepto || window.jQuery, window, document);
24462
24463/**
24464 * AutoHeight Plugin
24465 * @version 2.0.0-beta.3
24466 * @author Bartosz Wojciechowski
24467 * @license The MIT License (MIT)
24468 */
24469;(function($, window, document, undefined) {
24470
24471	/**
24472	 * Creates the auto height plugin.
24473	 * @class The Auto Height Plugin
24474	 * @param {Owl} carousel - The Owl Carousel
24475	 */
24476	var AutoHeight = function(carousel) {
24477		/**
24478		 * Reference to the core.
24479		 * @protected
24480		 * @type {Owl}
24481		 */
24482		this._core = carousel;
24483
24484		/**
24485		 * All event handlers.
24486		 * @protected
24487		 * @type {Object}
24488		 */
24489		this._handlers = {
24490			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
24491				if (e.namespace && this._core.settings.autoHeight) {
24492					this.update();
24493				}
24494			}, this),
24495			'changed.owl.carousel': $.proxy(function(e) {
24496				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
24497					this.update();
24498				}
24499			}, this),
24500			'loaded.owl.lazy': $.proxy(function(e) {
24501				if (e.namespace && this._core.settings.autoHeight
24502					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
24503					this.update();
24504				}
24505			}, this)
24506		};
24507
24508		// set default options
24509		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
24510
24511		// register event handlers
24512		this._core.$element.on(this._handlers);
24513	};
24514
24515	/**
24516	 * Default options.
24517	 * @public
24518	 */
24519	AutoHeight.Defaults = {
24520		autoHeight: false,
24521		autoHeightClass: 'owl-height'
24522	};
24523
24524	/**
24525	 * Updates the view.
24526	 */
24527	AutoHeight.prototype.update = function() {
24528		var start = this._core._current,
24529			end = start + this._core.settings.items,
24530			visible = this._core.$stage.children().toArray().slice(start, end);
24531			heights = [],
24532			maxheight = 0;
24533
24534		$.each(visible, function(index, item) {
24535			heights.push($(item).height());
24536		});
24537
24538		maxheight = Math.max.apply(null, heights);
24539
24540		this._core.$stage.parent()
24541			.height(maxheight)
24542			.addClass(this._core.settings.autoHeightClass);
24543	};
24544
24545	AutoHeight.prototype.destroy = function() {
24546		var handler, property;
24547
24548		for (handler in this._handlers) {
24549			this._core.$element.off(handler, this._handlers[handler]);
24550		}
24551		for (property in Object.getOwnPropertyNames(this)) {
24552			typeof this[property] != 'function' && (this[property] = null);
24553		}
24554	};
24555
24556	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
24557
24558})(window.Zepto || window.jQuery, window, document);
24559
24560/**
24561 * Video Plugin
24562 * @version 2.0.0-beta.3
24563 * @author Bartosz Wojciechowski
24564 * @license The MIT License (MIT)
24565 */
24566;(function($, window, document, undefined) {
24567
24568	/**
24569	 * Creates the video plugin.
24570	 * @class The Video Plugin
24571	 * @param {Owl} carousel - The Owl Carousel
24572	 */
24573	var Video = function(carousel) {
24574		/**
24575		 * Reference to the core.
24576		 * @protected
24577		 * @type {Owl}
24578		 */
24579		this._core = carousel;
24580
24581		/**
24582		 * Cache all video URLs.
24583		 * @protected
24584		 * @type {Object}
24585		 */
24586		this._videos = {};
24587
24588		/**
24589		 * Current playing item.
24590		 * @protected
24591		 * @type {jQuery}
24592		 */
24593		this._playing = null;
24594
24595		/**
24596		 * All event handlers.
24597		 * @todo The cloned content removale is too late
24598		 * @protected
24599		 * @type {Object}
24600		 */
24601		this._handlers = {
24602			'initialized.owl.carousel': $.proxy(function(e) {
24603				if (e.namespace) {
24604					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
24605				}
24606			}, this),
24607			'resize.owl.carousel': $.proxy(function(e) {
24608				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
24609					e.preventDefault();
24610				}
24611			}, this),
24612			'refreshed.owl.carousel': $.proxy(function(e) {
24613				if (e.namespace && this._core.is('resizing')) {
24614					this._core.$stage.find('.cloned .owl-video-frame').remove();
24615				}
24616			}, this),
24617			'changed.owl.carousel': $.proxy(function(e) {
24618				if (e.namespace && e.property.name === 'position' && this._playing) {
24619					this.stop();
24620				}
24621			}, this),
24622			'prepared.owl.carousel': $.proxy(function(e) {
24623				if (!e.namespace) {
24624					return;
24625				}
24626
24627				var $element = $(e.content).find('.owl-video');
24628
24629				if ($element.length) {
24630					$element.css('display', 'none');
24631					this.fetch($element, $(e.content));
24632				}
24633			}, this)
24634		};
24635
24636		// set default options
24637		this._core.options = $.extend({}, Video.Defaults, this._core.options);
24638
24639		// register event handlers
24640		this._core.$element.on(this._handlers);
24641
24642		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
24643			this.play(e);
24644		}, this));
24645	};
24646
24647	/**
24648	 * Default options.
24649	 * @public
24650	 */
24651	Video.Defaults = {
24652		video: false,
24653		videoHeight: false,
24654		videoWidth: false
24655	};
24656
24657	/**
24658	 * Gets the video ID and the type (YouTube/Vimeo only).
24659	 * @protected
24660	 * @param {jQuery} target - The target containing the video data.
24661	 * @param {jQuery} item - The item containing the video.
24662	 */
24663	Video.prototype.fetch = function(target, item) {
24664		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
24665			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
24666			width = target.attr('data-width') || this._core.settings.videoWidth,
24667			height = target.attr('data-height') || this._core.settings.videoHeight,
24668			url = target.attr('href');
24669
24670		if (url) {
24671			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+)?/);
24672
24673			if (id[3].indexOf('youtu') > -1) {
24674				type = 'youtube';
24675			} else if (id[3].indexOf('vimeo') > -1) {
24676				type = 'vimeo';
24677			} else {
24678				throw new Error('Video URL not supported.');
24679			}
24680			id = id[6];
24681		} else {
24682			throw new Error('Missing video URL.');
24683		}
24684
24685		this._videos[url] = {
24686			type: type,
24687			id: id,
24688			width: width,
24689			height: height
24690		};
24691
24692		item.attr('data-video', url);
24693
24694		this.thumbnail(target, this._videos[url]);
24695	};
24696
24697	/**
24698	 * Creates video thumbnail.
24699	 * @protected
24700	 * @param {jQuery} target - The target containing the video data.
24701	 * @param {Object} info - The video info object.
24702	 * @see `fetch`
24703	 */
24704	Video.prototype.thumbnail = function(target, video) {
24705		var tnLink,
24706			icon,
24707			path,
24708			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
24709			customTn = target.find('img'),
24710			srcType = 'src',
24711			lazyClass = '',
24712			settings = this._core.settings,
24713			create = function(path) {
24714				icon = '<div class="owl-video-play-icon"></div>';
24715
24716				if (settings.lazyLoad) {
24717					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
24718				} else {
24719					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
24720				}
24721				target.after(tnLink);
24722				target.after(icon);
24723			};
24724
24725		// wrap video content into owl-video-wrapper div
24726		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
24727
24728		if (this._core.settings.lazyLoad) {
24729			srcType = 'data-src';
24730			lazyClass = 'owl-lazy';
24731		}
24732
24733		// custom thumbnail
24734		if (customTn.length) {
24735			create(customTn.attr(srcType));
24736			customTn.remove();
24737			return false;
24738		}
24739
24740		if (video.type === 'youtube') {
24741			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
24742			create(path);
24743		} else if (video.type === 'vimeo') {
24744			$.ajax({
24745				type: 'GET',
24746				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
24747				jsonp: 'callback',
24748				dataType: 'jsonp',
24749				success: function(data) {
24750					path = data[0].thumbnail_large;
24751					create(path);
24752				}
24753			});
24754		}
24755	};
24756
24757	/**
24758	 * Stops the current video.
24759	 * @public
24760	 */
24761	Video.prototype.stop = function() {
24762		this._core.trigger('stop', null, 'video');
24763		this._playing.find('.owl-video-frame').remove();
24764		this._playing.removeClass('owl-video-playing');
24765		this._playing = null;
24766		this._core.leave('playing');
24767		this._core.trigger('stopped', null, 'video');
24768	};
24769
24770	/**
24771	 * Starts the current video.
24772	 * @public
24773	 * @param {Event} event - The event arguments.
24774	 */
24775	Video.prototype.play = function(event) {
24776		var target = $(event.target),
24777			item = target.closest('.' + this._core.settings.itemClass),
24778			video = this._videos[item.attr('data-video')],
24779			width = video.width || '100%',
24780			height = video.height || this._core.$stage.height(),
24781			html;
24782
24783		if (this._playing) {
24784			return;
24785		}
24786
24787		this._core.enter('playing');
24788		this._core.trigger('play', null, 'video');
24789
24790		item = this._core.items(this._core.relative(item.index()));
24791
24792		this._core.reset(item.index());
24793
24794		if (video.type === 'youtube') {
24795			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
24796				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
24797		} else if (video.type === 'vimeo') {
24798			html = '<iframe src="//player.vimeo.com/video/' + video.id +
24799				'?autoplay=1" width="' + width + '" height="' + height +
24800				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
24801		}
24802
24803		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
24804
24805		this._playing = item.addClass('owl-video-playing');
24806	};
24807
24808	/**
24809	 * Checks whether an video is currently in full screen mode or not.
24810	 * @todo Bad style because looks like a readonly method but changes members.
24811	 * @protected
24812	 * @returns {Boolean}
24813	 */
24814	Video.prototype.isInFullScreen = function() {
24815		var element = document.fullscreenElement || document.mozFullScreenElement ||
24816				document.webkitFullscreenElement;
24817
24818		return element && $(element).parent().hasClass('owl-video-frame');
24819	};
24820
24821	/**
24822	 * Destroys the plugin.
24823	 */
24824	Video.prototype.destroy = function() {
24825		var handler, property;
24826
24827		this._core.$element.off('click.owl.video');
24828
24829		for (handler in this._handlers) {
24830			this._core.$element.off(handler, this._handlers[handler]);
24831		}
24832		for (property in Object.getOwnPropertyNames(this)) {
24833			typeof this[property] != 'function' && (this[property] = null);
24834		}
24835	};
24836
24837	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
24838
24839})(window.Zepto || window.jQuery, window, document);
24840
24841/**
24842 * Animate Plugin
24843 * @version 2.0.0-beta.3
24844 * @author Bartosz Wojciechowski
24845 * @license The MIT License (MIT)
24846 */
24847;(function($, window, document, undefined) {
24848
24849	/**
24850	 * Creates the animate plugin.
24851	 * @class The Navigation Plugin
24852	 * @param {Owl} scope - The Owl Carousel
24853	 */
24854	var Animate = function(scope) {
24855		this.core = scope;
24856		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
24857		this.swapping = true;
24858		this.previous = undefined;
24859		this.next = undefined;
24860
24861		this.handlers = {
24862			'change.owl.carousel': $.proxy(function(e) {
24863				if (e.namespace && e.property.name == 'position') {
24864					this.previous = this.core.current();
24865					this.next = e.property.value;
24866				}
24867			}, this),
24868			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24869				if (e.namespace) {
24870					this.swapping = e.type == 'translated';
24871				}
24872			}, this),
24873			'translate.owl.carousel': $.proxy(function(e) {
24874				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24875					this.swap();
24876				}
24877			}, this)
24878		};
24879
24880		this.core.$element.on(this.handlers);
24881	};
24882
24883	/**
24884	 * Default options.
24885	 * @public
24886	 */
24887	Animate.Defaults = {
24888		animateOut: false,
24889		animateIn: false
24890	};
24891
24892	/**
24893	 * Toggles the animation classes whenever an translations starts.
24894	 * @protected
24895	 * @returns {Boolean|undefined}
24896	 */
24897	Animate.prototype.swap = function() {
24898
24899		if (this.core.settings.items !== 1) {
24900			return;
24901		}
24902
24903		if (!$.support.animation || !$.support.transition) {
24904			return;
24905		}
24906
24907		this.core.speed(0);
24908
24909		var left,
24910			clear = $.proxy(this.clear, this),
24911			previous = this.core.$stage.children().eq(this.previous),
24912			next = this.core.$stage.children().eq(this.next),
24913			incoming = this.core.settings.animateIn,
24914			outgoing = this.core.settings.animateOut;
24915
24916		if (this.core.current() === this.previous) {
24917			return;
24918		}
24919
24920		if (outgoing) {
24921			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24922			previous.css( { 'left': left + 'px' } )
24923				.addClass('animated owl-animated-out')
24924				.addClass(outgoing)
24925				.on($.support.animation.end, clear);
24926		}
24927
24928		if (incoming) {
24929			next.addClass('animated owl-animated-in')
24930				.addClass(incoming)
24931				.on($.support.animation.end, clear);
24932		}
24933	};
24934
24935	Animate.prototype.clear = function(e) {
24936		if ($(e.target).hasClass('animated')) {
24937			$(e.target).css( { 'left': '' } )
24938				.removeClass('animated owl-animated-out owl-animated-in')
24939				.removeClass(this.core.settings.animateIn)
24940				.removeClass(this.core.settings.animateOut);
24941			this.core.onTransitionEnd();
24942		}
24943	};
24944
24945	/**
24946	 * Destroys the plugin.
24947	 * @public
24948	 */
24949	Animate.prototype.destroy = function() {
24950		var handler, property;
24951
24952		for (handler in this.handlers) {
24953			this.core.$element.off(handler, this.handlers[handler]);
24954		}
24955		for (property in Object.getOwnPropertyNames(this)) {
24956			typeof this[property] != 'function' && (this[property] = null);
24957		}
24958	};
24959
24960	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
24961
24962})(window.Zepto || window.jQuery, window, document);
24963
24964/**
24965 * Autoplay Plugin
24966 * @version 2.0.0-beta.3
24967 * @author Bartosz Wojciechowski
24968 * @author Artus Kolanowski
24969 * @license The MIT License (MIT)
24970 */
24971;(function($, window, document, undefined) {
24972
24973	/**
24974	 * Creates the autoplay plugin.
24975	 * @class The Autoplay Plugin
24976	 * @param {Owl} scope - The Owl Carousel
24977	 */
24978	var Autoplay = function(carousel) {
24979		/**
24980		 * Reference to the core.
24981		 * @protected
24982		 * @type {Owl}
24983		 */
24984		this._core = carousel;
24985
24986		/**
24987		 * The autoplay interval.
24988		 * @type {Number}
24989		 */
24990		this._interval = null;
24991
24992		/**
24993		 * Indicates whenever the autoplay is paused.
24994		 * @type {Boolean}
24995		 */
24996		this._paused = false;
24997
24998		/**
24999		 * All event handlers.
25000		 * @protected
25001		 * @type {Object}
25002		 */
25003		this._handlers = {
25004			'changed.owl.carousel': $.proxy(function(e) {
25005				if (e.namespace && e.property.name === 'settings') {
25006					if (this._core.settings.autoplay) {
25007						this.play();
25008					} else {
25009						this.stop();
25010					}
25011				}
25012			}, this),
25013			'initialized.owl.carousel': $.proxy(function(e) {
25014				if (e.namespace && this._core.settings.autoplay) {
25015					this.play();
25016				}
25017			}, this),
25018			'play.owl.autoplay': $.proxy(function(e, t, s) {
25019				if (e.namespace) {
25020					this.play(t, s);
25021				}
25022			}, this),
25023			'stop.owl.autoplay': $.proxy(function(e) {
25024				if (e.namespace) {
25025					this.stop();
25026				}
25027			}, this),
25028			'mouseover.owl.autoplay': $.proxy(function() {
25029				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25030					this.pause();
25031				}
25032			}, this),
25033			'mouseleave.owl.autoplay': $.proxy(function() {
25034				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25035					this.play();
25036				}
25037			}, this)
25038		};
25039
25040		// register event handlers
25041		this._core.$element.on(this._handlers);
25042
25043		// set default options
25044		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
25045	};
25046
25047	/**
25048	 * Default options.
25049	 * @public
25050	 */
25051	Autoplay.Defaults = {
25052		autoplay: false,
25053		autoplayTimeout: 5000,
25054		autoplayHoverPause: false,
25055		autoplaySpeed: false
25056	};
25057
25058	/**
25059	 * Starts the autoplay.
25060	 * @public
25061	 * @param {Number} [timeout] - The interval before the next animation starts.
25062	 * @param {Number} [speed] - The animation speed for the animations.
25063	 */
25064	Autoplay.prototype.play = function(timeout, speed) {
25065		this._paused = false;
25066
25067		if (this._core.is('rotating')) {
25068			return;
25069		}
25070
25071		this._core.enter('rotating');
25072
25073		this._interval = window.setInterval($.proxy(function() {
25074			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
25075				return;
25076			}
25077			this._core.next(speed || this._core.settings.autoplaySpeed);
25078		}, this), timeout || this._core.settings.autoplayTimeout);
25079	};
25080
25081	/**
25082	 * Stops the autoplay.
25083	 * @public
25084	 */
25085	Autoplay.prototype.stop = function() {
25086		if (!this._core.is('rotating')) {
25087			return;
25088		}
25089
25090		window.clearInterval(this._interval);
25091		this._core.leave('rotating');
25092	};
25093
25094	/**
25095	 * Stops the autoplay.
25096	 * @public
25097	 */
25098	Autoplay.prototype.pause = function() {
25099		if (!this._core.is('rotating')) {
25100			return;
25101		}
25102
25103		this._paused = true;
25104	};
25105
25106	/**
25107	 * Destroys the plugin.
25108	 */
25109	Autoplay.prototype.destroy = function() {
25110		var handler, property;
25111
25112		this.stop();
25113
25114		for (handler in this._handlers) {
25115			this._core.$element.off(handler, this._handlers[handler]);
25116		}
25117		for (property in Object.getOwnPropertyNames(this)) {
25118			typeof this[property] != 'function' && (this[property] = null);
25119		}
25120	};
25121
25122	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
25123
25124})(window.Zepto || window.jQuery, window, document);
25125
25126/**
25127 * Navigation Plugin
25128 * @version 2.0.0-beta.3
25129 * @author Artus Kolanowski
25130 * @license The MIT License (MIT)
25131 */
25132;(function($, window, document, undefined) {
25133	'use strict';
25134
25135	/**
25136	 * Creates the navigation plugin.
25137	 * @class The Navigation Plugin
25138	 * @param {Owl} carousel - The Owl Carousel.
25139	 */
25140	var Navigation = function(carousel) {
25141		/**
25142		 * Reference to the core.
25143		 * @protected
25144		 * @type {Owl}
25145		 */
25146		this._core = carousel;
25147
25148		/**
25149		 * Indicates whether the plugin is initialized or not.
25150		 * @protected
25151		 * @type {Boolean}
25152		 */
25153		this._initialized = false;
25154
25155		/**
25156		 * The current paging indexes.
25157		 * @protected
25158		 * @type {Array}
25159		 */
25160		this._pages = [];
25161
25162		/**
25163		 * All DOM elements of the user interface.
25164		 * @protected
25165		 * @type {Object}
25166		 */
25167		this._controls = {};
25168
25169		/**
25170		 * Markup for an indicator.
25171		 * @protected
25172		 * @type {Array.<String>}
25173		 */
25174		this._templates = [];
25175
25176		/**
25177		 * The carousel element.
25178		 * @type {jQuery}
25179		 */
25180		this.$element = this._core.$element;
25181
25182		/**
25183		 * Overridden methods of the carousel.
25184		 * @protected
25185		 * @type {Object}
25186		 */
25187		this._overrides = {
25188			next: this._core.next,
25189			prev: this._core.prev,
25190			to: this._core.to
25191		};
25192
25193		/**
25194		 * All event handlers.
25195		 * @protected
25196		 * @type {Object}
25197		 */
25198		this._handlers = {
25199			'prepared.owl.carousel': $.proxy(function(e) {
25200				if (e.namespace && this._core.settings.dotsData) {
25201					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
25202						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
25203				}
25204			}, this),
25205			'added.owl.carousel': $.proxy(function(e) {
25206				if (e.namespace && this._core.settings.dotsData) {
25207					this._templates.splice(e.position, 0, this._templates.pop());
25208				}
25209			}, this),
25210			'remove.owl.carousel': $.proxy(function(e) {
25211				if (e.namespace && this._core.settings.dotsData) {
25212					this._templates.splice(e.position, 1);
25213				}
25214			}, this),
25215			'changed.owl.carousel': $.proxy(function(e) {
25216				if (e.namespace && e.property.name == 'position') {
25217					this.draw();
25218				}
25219			}, this),
25220			'initialized.owl.carousel': $.proxy(function(e) {
25221				if (e.namespace && !this._initialized) {
25222					this._core.trigger('initialize', null, 'navigation');
25223					this.initialize();
25224					this.update();
25225					this.draw();
25226					this._initialized = true;
25227					this._core.trigger('initialized', null, 'navigation');
25228				}
25229			}, this),
25230			'refreshed.owl.carousel': $.proxy(function(e) {
25231				if (e.namespace && this._initialized) {
25232					this._core.trigger('refresh', null, 'navigation');
25233					this.update();
25234					this.draw();
25235					this._core.trigger('refreshed', null, 'navigation');
25236				}
25237			}, this)
25238		};
25239
25240		// set default options
25241		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
25242
25243		// register event handlers
25244		this.$element.on(this._handlers);
25245	};
25246
25247	/**
25248	 * Default options.
25249	 * @public
25250	 * @todo Rename `slideBy` to `navBy`
25251	 */
25252	Navigation.Defaults = {
25253		nav: false,
25254		navText: [ 'prev', 'next' ],
25255		navSpeed: false,
25256		navElement: 'div',
25257		navContainer: false,
25258		navContainerClass: 'owl-nav',
25259		navClass: [ 'owl-prev', 'owl-next' ],
25260		slideBy: 1,
25261		dotClass: 'owl-dot',
25262		dotsClass: 'owl-dots',
25263		dots: true,
25264		dotsEach: false,
25265		dotsData: false,
25266		dotsSpeed: false,
25267		dotsContainer: false
25268	};
25269
25270	/**
25271	 * Initializes the layout of the plugin and extends the carousel.
25272	 * @protected
25273	 */
25274	Navigation.prototype.initialize = function() {
25275		var override,
25276			settings = this._core.settings;
25277
25278		// create DOM structure for relative navigation
25279		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
25280			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
25281
25282		this._controls.$previous = $('<' + settings.navElement + '>')
25283			.addClass(settings.navClass[0])
25284			.html(settings.navText[0])
25285			.prependTo(this._controls.$relative)
25286			.on('click', $.proxy(function(e) {
25287				this.prev(settings.navSpeed);
25288			}, this));
25289		this._controls.$next = $('<' + settings.navElement + '>')
25290			.addClass(settings.navClass[1])
25291			.html(settings.navText[1])
25292			.appendTo(this._controls.$relative)
25293			.on('click', $.proxy(function(e) {
25294				this.next(settings.navSpeed);
25295			}, this));
25296
25297		// create DOM structure for absolute navigation
25298		if (!settings.dotsData) {
25299			this._templates = [ $('<div>')
25300				.addClass(settings.dotClass)
25301				.append($('<span>'))
25302				.prop('outerHTML') ];
25303		}
25304
25305		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
25306			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
25307
25308		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
25309			var index = $(e.target).parent().is(this._controls.$absolute)
25310				? $(e.target).index() : $(e.target).parent().index();
25311
25312			e.preventDefault();
25313
25314			this.to(index, settings.dotsSpeed);
25315		}, this));
25316
25317		// override public methods of the carousel
25318		for (override in this._overrides) {
25319			this._core[override] = $.proxy(this[override], this);
25320		}
25321	};
25322
25323	/**
25324	 * Destroys the plugin.
25325	 * @protected
25326	 */
25327	Navigation.prototype.destroy = function() {
25328		var handler, control, property, override;
25329
25330		for (handler in this._handlers) {
25331			this.$element.off(handler, this._handlers[handler]);
25332		}
25333		for (control in this._controls) {
25334			this._controls[control].remove();
25335		}
25336		for (override in this.overides) {
25337			this._core[override] = this._overrides[override];
25338		}
25339		for (property in Object.getOwnPropertyNames(this)) {
25340			typeof this[property] != 'function' && (this[property] = null);
25341		}
25342	};
25343
25344	/**
25345	 * Updates the internal state.
25346	 * @protected
25347	 */
25348	Navigation.prototype.update = function() {
25349		var i, j, k,
25350			lower = this._core.clones().length / 2,
25351			upper = lower + this._core.items().length,
25352			maximum = this._core.maximum(true),
25353			settings = this._core.settings,
25354			size = settings.center || settings.autoWidth || settings.dotsData
25355				? 1 : settings.dotsEach || settings.items;
25356
25357		if (settings.slideBy !== 'page') {
25358			settings.slideBy = Math.min(settings.slideBy, settings.items);
25359		}
25360
25361		if (settings.dots || settings.slideBy == 'page') {
25362			this._pages = [];
25363
25364			for (i = lower, j = 0, k = 0; i < upper; i++) {
25365				if (j >= size || j === 0) {
25366					this._pages.push({
25367						start: Math.min(maximum, i - lower),
25368						end: i - lower + size - 1
25369					});
25370					if (Math.min(maximum, i - lower) === maximum) {
25371						break;
25372					}
25373					j = 0, ++k;
25374				}
25375				j += this._core.mergers(this._core.relative(i));
25376			}
25377		}
25378	};
25379
25380	/**
25381	 * Draws the user interface.
25382	 * @todo The option `dotsData` wont work.
25383	 * @protected
25384	 */
25385	Navigation.prototype.draw = function() {
25386		var difference,
25387			settings = this._core.settings,
25388			disabled = this._core.items().length <= settings.items,
25389			index = this._core.relative(this._core.current()),
25390			loop = settings.loop || settings.rewind;
25391
25392		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
25393
25394		if (settings.nav) {
25395			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
25396			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
25397		}
25398
25399		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
25400
25401		if (settings.dots) {
25402			difference = this._pages.length - this._controls.$absolute.children().length;
25403
25404			if (settings.dotsData && difference !== 0) {
25405				this._controls.$absolute.html(this._templates.join(''));
25406			} else if (difference > 0) {
25407				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
25408			} else if (difference < 0) {
25409				this._controls.$absolute.children().slice(difference).remove();
25410			}
25411
25412			this._controls.$absolute.find('.active').removeClass('active');
25413			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
25414		}
25415	};
25416
25417	/**
25418	 * Extends event data.
25419	 * @protected
25420	 * @param {Event} event - The event object which gets thrown.
25421	 */
25422	Navigation.prototype.onTrigger = function(event) {
25423		var settings = this._core.settings;
25424
25425		event.page = {
25426			index: $.inArray(this.current(), this._pages),
25427			count: this._pages.length,
25428			size: settings && (settings.center || settings.autoWidth || settings.dotsData
25429				? 1 : settings.dotsEach || settings.items)
25430		};
25431	};
25432
25433	/**
25434	 * Gets the current page position of the carousel.
25435	 * @protected
25436	 * @returns {Number}
25437	 */
25438	Navigation.prototype.current = function() {
25439		var current = this._core.relative(this._core.current());
25440		return $.grep(this._pages, $.proxy(function(page, index) {
25441			return page.start <= current && page.end >= current;
25442		}, this)).pop();
25443	};
25444
25445	/**
25446	 * Gets the current succesor/predecessor position.
25447	 * @protected
25448	 * @returns {Number}
25449	 */
25450	Navigation.prototype.getPosition = function(successor) {
25451		var position, length,
25452			settings = this._core.settings;
25453
25454		if (settings.slideBy == 'page') {
25455			position = $.inArray(this.current(), this._pages);
25456			length = this._pages.length;
25457			successor ? ++position : --position;
vendor: 5,678 bytes, lines 25458-25682
25458			position = this._pages[((position % length) + length) % length].start;
25459		} else {
25460			position = this._core.relative(this._core.current());
25461			length = this._core.items().length;
25462			successor ? position += settings.slideBy : position -= settings.slideBy;
25463		}
25464
25465		return position;
25466	};
25467
25468	/**
25469	 * Slides to the next item or page.
25470	 * @public
25471	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25472	 */
25473	Navigation.prototype.next = function(speed) {
25474		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
25475	};
25476
25477	/**
25478	 * Slides to the previous item or page.
25479	 * @public
25480	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25481	 */
25482	Navigation.prototype.prev = function(speed) {
25483		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
25484	};
25485
25486	/**
25487	 * Slides to the specified item or page.
25488	 * @public
25489	 * @param {Number} position - The position of the item or page.
25490	 * @param {Number} [speed] - The time in milliseconds for the transition.
25491	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
25492	 */
25493	Navigation.prototype.to = function(position, speed, standard) {
25494		var length;
25495
25496		if (!standard) {
25497			length = this._pages.length;
25498			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
25499		} else {
25500			$.proxy(this._overrides.to, this._core)(position, speed);
25501		}
25502	};
25503
25504	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
25505
25506})(window.Zepto || window.jQuery, window, document);
25507
25508/**
25509 * Hash Plugin
25510 * @version 2.0.0-beta.3
25511 * @author Artus Kolanowski
25512 * @license The MIT License (MIT)
25513 */
25514;(function($, window, document, undefined) {
25515	'use strict';
25516
25517	/**
25518	 * Creates the hash plugin.
25519	 * @class The Hash Plugin
25520	 * @param {Owl} carousel - The Owl Carousel
25521	 */
25522	var Hash = function(carousel) {
25523		/**
25524		 * Reference to the core.
25525		 * @protected
25526		 * @type {Owl}
25527		 */
25528		this._core = carousel;
25529
25530		/**
25531		 * Hash index for the items.
25532		 * @protected
25533		 * @type {Object}
25534		 */
25535		this._hashes = {};
25536
25537		/**
25538		 * The carousel element.
25539		 * @type {jQuery}
25540		 */
25541		this.$element = this._core.$element;
25542
25543		/**
25544		 * All event handlers.
25545		 * @protected
25546		 * @type {Object}
25547		 */
25548		this._handlers = {
25549			/*'initialized.owl.carousel': $.proxy(function(e) {
25550				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
25551					$(window).trigger('hashchange.owl.navigation');
25552				}
25553			}, this),*/
25554			'prepared.owl.carousel': $.proxy(function(e) {
25555				if (e.namespace) {
25556					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
25557
25558					if (!hash) {
25559						return;
25560					}
25561
25562					this._hashes[hash] = e.content;
25563				}
25564			}, this),
25565			'changed.owl.carousel': $.proxy(function(e) {
25566				if (e.namespace && e.property.name === 'position') {
25567					var current = this._core.items(this._core.relative(this._core.current())),
25568						hash = $.map(this._hashes, function(item, hash) {
25569							return item === current ? hash : null;
25570						}).join();
25571
25572					if (!hash || window.location.hash.slice(1) === hash) {
25573						return;
25574					}
25575
25576					window.location.hash = hash;
25577				}
25578			}, this)
25579		};
25580
25581		// set default options
25582		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
25583
25584		// register the event handlers
25585		this.$element.on(this._handlers);
25586
25587		// register event listener for hash navigation
25588		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
25589			var hash = window.location.hash.substring(1),
25590				items = this._core.$stage.children(),
25591				position = this._hashes[hash] && items.index(this._hashes[hash]);
25592
25593			if (position === undefined || position === this._core.current()) {
25594				return;
25595			}
25596
25597			this._core.to(this._core.relative(position), false, true);
25598		}, this));*/
25599	};
25600
25601	/**
25602	 * Default options.
25603	 * @public
25604	 */
25605	Hash.Defaults = {
25606		URLhashListener: false
25607	};
25608
25609	/**
25610	 * Destroys the plugin.
25611	 * @public
25612	 */
25613	Hash.prototype.destroy = function() {
25614		var handler, property;
25615
25616		$(window).off('hashchange.owl.navigation');
25617
25618		for (handler in this._handlers) {
25619			this._core.$element.off(handler, this._handlers[handler]);
25620		}
25621		for (property in Object.getOwnPropertyNames(this)) {
25622			typeof this[property] != 'function' && (this[property] = null);
25623		}
25624	};
25625
25626	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
25627
25628})(window.Zepto || window.jQuery, window, document);
25629
25630/**
25631 * Support Plugin
25632 *
25633 * @version 2.0.0-beta.3
25634 * @author Vivid Planet Software GmbH
25635 * @author Artus Kolanowski
25636 * @license The MIT License (MIT)
25637 */
25638;(function($, window, document, undefined) {
25639
25640	var style = $('<support>').get(0).style,
25641		prefixes = 'Webkit Moz O ms'.split(' '),
25642		events = {
25643			transition: {
25644				end: {
25645					WebkitTransition: 'webkitTransitionEnd',
25646					MozTransition: 'transitionend',
25647					OTransition: 'oTransitionEnd',
25648					transition: 'transitionend'
25649				}
25650			},
25651			animation: {
25652				end: {
25653					WebkitAnimation: 'webkitAnimationEnd',
25654					MozAnimation: 'animationend',
25655					OAnimation: 'oAnimationEnd',
25656					animation: 'animationend'
25657				}
25658			}
25659		},
25660		tests = {
25661			csstransforms: function() {
25662				return !!test('transform');
25663			},
25664			csstransforms3d: function() {
25665				return !!test('perspective');
25666			},
25667			csstransitions: function() {
25668				return !!test('transition');
25669			},
25670			cssanimations: function() {
25671				return !!test('animation');
25672			}
25673		};
25674
25675	function test(property, prefixed) {
25676		var result = false,
25677			upper = property.charAt(0).toUpperCase() + property.slice(1);
25678
25679		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
25680			if (style[property] !== undefined) {
25681				result = prefixed ? property : true;
25682				return false;
25683			}
25684		});
25685
25686		return result;
25687	}
25688
25689	function prefixed(property) {
25690		return test(property, true);
25691	}
25692
25693	if (tests.csstransitions()) {
25694		/* jshint -W053 */
25695		$.support.transition = new String(prefixed('transition'))
25696		$.support.transition.end = events.transition.end[ $.support.transition ];
25697	}
25698
25699	if (tests.cssanimations()) {
25700		/* jshint -W053 */
25701		$.support.animation = new String(prefixed('animation'))
25702		$.support.animation.end = events.animation.end[ $.support.animation ];
25703	}
25704
25705	if (tests.csstransforms()) {
25706		/* jshint -W053 */
25707		$.support.transform = new String(prefixed('transform'));
25708		$.support.transform3d = tests.csstransforms3d();
25709	}
25710
25711})(window.Zepto || window.jQuery, window, document);
25712
25713(function(window, document, undefined) {
25714
25715	/**
25716	 * Find the absolute position of an element
25717	 */
25718	var absPos = function(element) {
25719		var offsetLeft, offsetTop;
25720		offsetLeft = offsetTop = 0;
25721		if (element.offsetParent) {
25722			do {
25723				offsetLeft += element.offsetLeft;
25724				offsetTop += element.offsetTop;
25725			} while (element = element.offsetParent);
25726		}
25727		return [offsetLeft, offsetTop];
25728	};
25729
25730	/**
25731	 * @constructor Progress Circle class
25732	 * @param params.canvas Canvas on which the circles will be drawn.
25733	 * @param params.minRadius Inner radius of the innermost circle, in px.
25734	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
25735	 * @param params.gapWidth Space between each circle.
25736	 * @param params.centerX X coordinate of the center of circles.
25737	 * @param params.centerY Y coordinate of the center of circles.
25738	 * @param params.infoLineBaseAngle Base angle of the info line.
25739	 * @param params.infoLineAngleInterval Angles between the info lines.
25740	 */
25741	var ProgressCircle = function(params) {
25742		this.canvas = params.canvas;
25743		this.minRadius = params.minRadius || 15;
25744		this.arcWidth = params.arcWidth || 5;
25745		this.gapWidth = params.gapWidth || 3;
25746		this.centerX = params.centerX || this.canvas.width / 2;
25747		this.centerY = params.centerY || this.canvas.height / 2;
25748		this.infoLineLength = params.infoLineLength || 60;
25749		this.horizLineLength = params.horizLineLength || 10;
25750		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
25751		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
25752
25753		this.context = this.canvas.getContext('2d');
25754
25755		this.width = this.canvas.width;
25756		this.height = this.canvas.height;
25757
25758		this.circles = [];
25759		this.runningCount = 0;
25760	};
25761
25762	ProgressCircle.prototype = {
25763		constructor: ProgressCircle,
25764
25765		/**
25766		 * @method Adds an progress monitor entry.
25767		 * @param params.fillColor Color to fill in the circle.
25768		 * @param params.outlineColor Color to outline the circle.
25769		 * @param params.progressListener Callback function to fetch the progress.
25770		 * @param params.infoListener Callback function to fetch the info.
25771		 * @returns this
25772		 */
25773		addEntry: function(params) {
25774			this.circles.push(new Circle({
25775				canvas: this.canvas,
25776				context: this.context,
25777				centerX: this.centerX,
25778				centerY: this.centerY,
25779				innerRadius: this.minRadius + this.circles.length *
25780					(this.gapWidth + this.arcWidth),
25781				arcWidth: this.arcWidth,
25782				infoLineLength: this.infoLineLength,
25783				horizLineLength: this.horizLineLength,
25784
25785				id: this.circles.length,
25786				fillColor: params.fillColor,
25787				outlineColor: params.outlineColor,
25788				progressListener: params.progressListener,
25789				infoListener: params.infoListener,
25790				infoLineAngle: this.infoLineBaseAngle +
25791					this.circles.length * this.infoLineAngleInterval,
25792			}));
25793
25794			return this;
25795		},
25796
25797		/**
25798		 * @method Starts the monitor and updates with the given interval.
25799		 * @param interval Interval between updates, in millisecond.
25800		 * @returns this
25801		 */
25802		start: function(interval) {
25803			var self = this;
25804			this.timer = setInterval(function() {
25805				self._update();
25806			}, interval || 33);
25807
25808			return this;
25809		},
25810
25811		/**
25812		 * @method Stop the animation.
25813		 */
25814		stop: function() {
25815			clearTimeout(this.timer);
25816		},
25817
25818		/**
25819		 * @private
25820		 * @method Call update on each circle and redraw them.
25821		 * @returns this
25822		 */
25823		_update: function() {
25824			this._clear();
25825			this.circles.forEach(function(circle, idx, array) {
25826				circle.update();
25827			});
25828
25829			return this;
25830		},
25831
25832		/**
25833		 * @private
25834		 * @method Clear the canvas.
25835		 * @returns this
25836		 */
25837		_clear: function() {
25838			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
25839
25840			return this;
25841		},
25842
25843	};
25844
25845	/**
25846	 * @private
25847	 * @class Individual progress circle.
25848	 * @param params.canvas Canvas on which the circle will be drawn.
25849	 * @param params.context Context of the canvas.
25850	 * @param params.innerRadius Inner radius of the circle, in px.
25851	 * @param params.arcWidth Width of each arc(circle).
25852	 * @param params.gapWidth Distance between each arc.
25853	 * @param params.centerX X coordinate of the center of circles.
25854	 * @param params.centerY Y coordinate of the center of circles.
25855	 * @param params.fillColor Color to fill in the circle.
25856	 * @param params.outlineColor Color to outline the circle.
25857	 * @param params.progressListener Callback function to fetch the progress.
25858	 * @param params.infoListener Callback function to fetch the info.
25859	 * @param params.infoLineAngle Angle of info line.
25860	 */
25861	var Circle = function(params) {
25862		this.id = params.id;
25863		this.canvas = params.canvas;
25864		this.context = params.context;
25865		this.centerX = params.centerX;
25866		this.centerY = params.centerY;
25867		this.arcWidth = params.arcWidth;
25868		this.innerRadius = params.innerRadius || 0;
25869		this.fillColor = params.fillColor || '#fff';
25870		this.outlineColor = params.outlineColor || this.fillColor;
25871		this.progressListener = params.progressListener;
25872		this.infoLineLength = params.infoLineLength || 250;
25873		this.horizLineLength = params.horizLineLength || 50;
25874		this.infoListener = params.infoListener;
25875		this.infoLineAngle = params.infoLineAngle;
25876
25877		this.outerRadius = this.innerRadius + this.arcWidth;
25878
25879		// If the info listener is not registered, then don't calculate
25880		// the related coordinates
25881		if (!this.infoListener) return;
25882
25883		// calculate the info-line turning points
25884		var angle = this.infoLineAngle,
25885			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25886
25887			sinA = Math.sin(angle),
25888			cosA = Math.cos(angle);
25889
25890		this.infoLineStartX = this.centerX + sinA * arcDistance;
25891		this.infoLineStartY = this.centerY - cosA * arcDistance;
25892
25893		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25894		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25895
25896		this.infoLineEndX = this.infoLineMidX +
25897			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25898		this.infoLineEndY = this.infoLineMidY;
25899
25900		var infoText = document.createElement('div'),
25901			style = infoText.style;
25902
25903		style.color = this.fillColor;
25904		style.position = 'absolute';
25905		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25906		// style.top will be calculated in the `drawInfo` method. Since
25907		// user may want to change the size of the font, so the top offset
25908		// must be updated in each loop.
25909		infoText.className = 'ProgressCircleInfo'; // For css styling
25910		infoText.id = 'progress_circle_info_' + this.id;
25911		document.body.appendChild(infoText);
25912		this.infoText = infoText;
25913	};
25914
25915	Circle.prototype = {
25916		constructor: Circle,
25917
25918		update: function() {
25919			this.progress = this.progressListener();
25920			this._draw();
25921
25922			if (this.infoListener) {
25923				this.info = this.infoListener();
25924				this._drawInfo();
25925			}
25926		},
25927
25928		/**
25929		 * @private
25930		 * @method Draw the circle on the canvas.
25931		 * @returns this
25932		 */
25933		_draw: function() {
25934			var ctx = this.context,
25935
25936				ANGLE_OFFSET = -Math.PI / 2,
25937
25938				startAngle = 0 + ANGLE_OFFSET,
25939				endAngle= startAngle + this.progress * Math.PI * 2,
25940
25941				x = this.centerX,
25942				y = this.centerY,
25943
25944				innerRadius = this.innerRadius - this.arcWidth - 1,
25945				outerRadius = this.outerRadius - this.arcWidth - 1;
25946
25947			if ( innerRadius < 0 )
25948				return;
25949
25950			ctx.fillStyle = this.fillColor;
25951			ctx.strokeStyle = this.outlineColor;
25952
25953			ctx.beginPath();
25954			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
25955			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
25956			ctx.closePath();
25957			ctx.stroke();
25958			ctx.fill();
25959
25960			return this;
25961		},
25962
25963		/**
25964		 * @private
25965		 * @method Draw the info lines and info text.
25966		 * @returns this
25967		 */
25968		_drawInfo: function() {
25969
25970			var pointList, lineHeight;
25971
25972			pointList = [
25973				[this.infoLineStartX, this.infoLineStartY],
25974				[this.infoLineMidX, this.infoLineMidY],
25975				[this.infoLineEndX, this.infoLineEndY],
25976			];
25977			this._drawSegments(pointList, false);
25978
25979			this.infoText.innerHTML = this.info;
25980
25981			lineHeight = this.infoText.offsetHeight;
25982			this.infoText.style.top = this.infoLineEndY +
25983				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
25984
25985			return this;
25986		},
25987
25988		/**
25989		 * @private
25990		 * @method Helper function to draw the segments
25991		 * @param pointList An array of points in the form of [x, y].
25992		 * @param close Whether to connect the first and last point.
25993		 */
25994		_drawSegments: function(pointList, close) {
25995			var ctx = this.context;
25996
25997			ctx.beginPath();
25998			ctx.moveTo(pointList[0][0], pointList[0][1]);
25999			for (var i = 1; i < pointList.length; ++i) {
26000				ctx.lineTo(pointList[i][0], pointList[i][1]);
26001			}
26002
26003			if (close) {
26004				ctx.closePath();
26005			}
26006			ctx.stroke();
26007		},
26008	};
26009
26010	window.ProgressCircle = ProgressCircle;
26011
26012})(window, document);
26013
26014
26015
26016
26017/* =========================================================
26018 * jquery.vc_chart.js v1.0
26019 * =========================================================
26020 * Copyright 2013 Wpbakery
26021 *
26022 * Jquery chart plugin for the Visual Composer.
26023 * ========================================================= */
26024(function($){
26025	/**
26026	 * Pie chart animated.
26027	 * @param element - DOM element
26028	 * @param options - settings object.
26029	 * @constructor
26030	 */
26031	var VcChart = function(element, options) {
26032		this.el = element;
26033		this.$el = $(this.el);
26034		var $this = this;
26035		$this.options = $.extend({
26036			color: 'wpb_button',
26037			units: '',
26038			width: '',
26039			label_selector: '.vc_pie_chart_value',
26040			back_selector: '.vc_pie_chart_back',
26041			responsive: true
26042		}, options);
26043		$this.init();
26044	};
26045	VcChart.prototype = {
26046		constructor: VcChart,
26047		_progress_v: 0,
26048		animated: false,
26049		colors: {
26050			'wpb_button': 'rgba(247, 247, 247, 1)',
26051			'btn-primary': 'rgba(0, 136, 204, 1)',
26052			'btn-info': 'rgba(88, 185, 218, 1)',
26053			'btn-success': 'rgba(106, 177, 101, 1)',
26054			'btn-warning': 'rgba(255, 153, 0, 1)',
26055			'btn-danger': 'rgba(255, 103, 91, 1)',
26056			'btn-inverse': 'rgba(85, 85, 85, 1)'
26057		},
26058		init: function() {
26059			this.setupColor();
26060			this.value = this.$el.data('pie-value')/100;
26061			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
26062			this.$wrapper = $('.vc_pie_wrapper', this.$el);
26063			this.$label = $(this.options.label_selector, this.$el);
26064			this.$back = $(this.options.back_selector, this.$el);
26065			this.$canvas = this.$el.find('canvas');
26066			this.arcWidth = this.$el.data('pie-width') * 2;
26067			this.draw();
26068			this.setWayPoint();
26069			if(this.options.responsive === true) this.setResponsive();
26070			if (UNCODE.isMobile) this._progress_v = this.value;
26071		},
26072		setupColor: function() {
26073			// if(typeof this.colors[this.options.color] !== 'undefined') {
26074			//     this.color = this.colors[this.options.color];
26075			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
26076			//     this.color = this.options.color;
26077			// } else {
26078			//     this.color = 'rgba(247, 247, 247, 0.2)';
26079			// }
26080			if(typeof this.options.color !== 'undefined') {
26081				this.color = this.options.color;
26082			} else this.color = 'rgba(247, 247, 247, 0.2)';
26083
26084		},
26085		setResponsive: function() {
26086			var that = this;
26087			if (!UNCODE.isMobile) {
26088				$(window).resize(function(){
26089					if(that.animated === true) that.circle.stop();
26090					that.draw(true);
26091				});
26092			}
26093		},
26094		draw: function(redraw) {
26095			var w = this.$el.addClass('vc_ready').width() * 2,
26096				border_w = this.arcWidth,
26097				radius;
26098			if(!w) w = this.$el.parents(':visible').first().width()-2;
26099			//w = Math.round(w/100*80);
26100			//if (w < 250) w = 250;
26101			radius = w/2;
26102			this.$wrapper.css({"width" : (w / 2) + "px"});
26103			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
26104			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
26105			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
26106			this.$el.addClass('vc_ready');
26107			this.circle = new ProgressCircle({
26108				canvas: this.$canvas.get(0),
26109				minRadius: radius,
26110				arcWidth: border_w
26111			});
26112			if(redraw === true && this.animated === true) {
26113				this._progress_v = this.value;
26114				this.circle.addEntry({
26115					fillColor: this.color,
26116					progressListener: $.proxy(this.setProgress, this)
26117				}).start();
26118			}
26119		},
26120		setProgress: function() {
26121			if (this._progress_v >= this.value) {
26122				this.circle.stop();
26123				this.animated = true;
26124				this.$label.html(this.label_value + this.options.units);
26125				return this._progress_v;
26126			}
26127			this._progress_v += 0.01;
26128			if (!isNaN(this.label_value)) {
26129				var label_value = this._progress_v/this.value*this.label_value;
26130				var val = Math.round(label_value) + this.options.units;
26131				this.$label.html(val);
26132			} else this.$label.html(this.label_value + this.options.units);
26133			return this._progress_v;
26134		},
26135		animate: function() {
26136			if(this.animated !== true) {
26137				this.circle.addEntry({
26138					fillColor: this.color,
26139					progressListener: $.proxy(this.setProgress, this)
26140				}).start(10);
26141			}
26142		},
26143		setWayPoint: function() {
26144			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
26145				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
26146			} else {
26147				this.animate();
26148			}
26149		}
26150	};
26151	/**
26152	 * jQuery plugin
26153	 * @param option - object with settings
26154	 * @return {*}
26155	 */
26156	$.fn.vcChat = function(option, value) {
26157		return this.each(function () {
26158			var $this = $(this),
26159				data = $this.data('vc_chart'),
26160				options = typeof option === 'object' ? option : {
26161					color: $this.data('pie-color'),
26162					units: $this.data('pie-units')
26163				};
26164			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
26165			if (typeof option == 'string') data[option](value);
26166		});
26167	};
26168	/**
26169	 * Allows users to rewrite function inside theme.
26170	 */
26171	if ( typeof window['vc_pieChart'] !== 'function' ) {
26172		window.vc_pieChart = function() {
26173			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
26174		}
26175	}
26176	$(document).ready(function(){
26177		!window.vc_iframe && vc_pieChart();
26178
26179		/**
26180		* Tab and collapse integration.
26181		*/
26182		$('.nav-tabs a').on('shown.bs.tab', function(e){
26183			var $cont = $(e.target).closest('.tab-container'),
26184				$active = $('.tab-pane.active', $cont);
26185			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
26186		});
26187
26188		$('.panel-collapse').on('shown.bs.collapse', function (e) {
26189			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
26190		})
26191	});
26192
26193})(window.jQuery);
26194
26195/* Progress bar
26196 ---------------------------------------------------------- */
26197function uncode_progress_bar() {
26198	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
26199		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
26200			return;
26201		}
26202		if (!UNCODE.isMobile) {
26203			new Waypoint({
26204				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26205				element: val,
26206				handler: function() {
26207					var element = jQuery(this.element);
26208					element.find('.vc_single_bar').each(function(index) {
26209						var $this = jQuery(this),
26210							bar = $this.find('.vc_bar'),
26211							val = bar.data('percentage-value');
26212						setTimeout(function() {
26213							bar.css({
26214								"width": val + '%'
26215							});
26216						}, index * 200);
26217					});
26218				},
26219				offset: '80%'
26220			});
26221		} else {
26222			var element = jQuery(val);
26223			element.find('.vc_single_bar').each(function(index) {
26224				var $this = jQuery(this),
26225					bar = $this.find('.vc_bar'),
26226					val = bar.data('percentage-value');
26227				setTimeout(function() {
26228					bar.css({
26229						"width": val + '%'
26230					});
26231				}, index * 200);
26232			});
26233		}
26234	});
26235};
26236uncode_progress_bar();
26237
26238/*!
26239 * jquery.counterup.js 1.0
26240 *
26241 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
26242 * Released under the GPL v2 License
26243 *
26244 * Date: Nov 26, 2013
26245 */
26246(function($) {
26247	"use strict";
26248	$.fn.counterUp = function(options) {
26249		// Defaults
26250		var settings = $.extend({
26251			'time': 400,
26252			'delay': 10
26253		}, options);
26254		return this.each(function() {
26255			// Store the object
26256			var $this = $(this);
26257			var $settings = settings;
26258			var counterUpper = function() {
26259				var nums = [];
26260				var divisions = $settings.time / $settings.delay;
26261				var numReal = $this.attr('data-val'),
26262				num = numReal;
26263				var isComma = /[0-9]+,[0-9]+/.test(num);
26264				num = num.replace(/,/g, '');
26265				var isInt = /^[0-9]+$/.test(num);
26266				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
26267				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
26268				// Generate list of incremental numbers to display
26269				for (var i = divisions; i >= 1; i--) {
26270					// Preserve as int if input was int
26271					var newNum = parseInt(num / divisions * i);
26272					// Preserve float if input was float
26273					if (isFloat) {
26274						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
26275					}
26276					// Preserve commas if input had commas
26277					if (isComma) {
26278						while (/(\d+)(\d{3})/.test(newNum.toString())) {
26279							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
26280						}
26281					}
26282					nums.unshift(newNum);
26283				}
26284				nums.push(numReal);
26285				$this.data('counterup-nums', nums);
26286				$this.text('0');
26287				// Updates the number until we're done
26288				var f = function() {
26289					if ($this.data('counterup-nums') != null) {
26290						$this.text($this.data('counterup-nums').shift());
26291						if ($this.data('counterup-nums').length) {
26292							setTimeout($this.data('counterup-func'), $settings.delay);
26293						} else {
26294							delete $this.data('counterup-nums');
26295							$this.data('counterup-nums', null);
26296							$this.data('counterup-func', null);
26297						}
26298					}
26299				};
26300				$this.data('counterup-func', f);
26301				// Start the count up
26302				setTimeout($this.data('counterup-func'), $settings.delay);
26303			};
26304			// Perform counts when the element gets into view
26305			new Waypoint({
26306				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26307				element: this,
26308				handler: function() {
26309					counterUpper();
26310					if (!UNCODE.isUnmodalOpen) {
26311						this.destroy();
26312					}
26313				},
26314				offset: '100%'
26315			});
26316		});
26317	};
26318})(jQuery);
26319
26320/*!
26321 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
26322 * Copyright (c) 2016 Edson Hilios
26323 *
26324 * Permission is hereby granted, free of charge, to any person obtaining a copy of
26325 * this software and associated documentation files (the "Software"), to deal in
26326 * the Software without restriction, including without limitation the rights to
26327 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
26328 * the Software, and to permit persons to whom the Software is furnished to do so,
26329 * subject to the following conditions:
26330 *
26331 * The above copyright notice and this permission notice shall be included in all
26332 * copies or substantial portions of the Software.
26333 *
26334 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26335 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26336 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26337 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26338 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26339 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26340 */
26341(function(factory) {
26342	"use strict";
26343	if (typeof define === "function" && define.amd) {
26344		define([ "jquery" ], factory);
26345	} else {
26346		factory(jQuery);
26347	}
26348})(function($) {
26349	"use strict";
26350	var instances = [], matchers = [], defaultOptions = {
26351		precision: 100,
26352		elapse: false,
26353		defer: false
26354	};
26355	matchers.push(/^[0-9]*$/.source);
26356	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26357	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26358	matchers = new RegExp(matchers.join("|"));
26359	function parseDateString(dateString) {
26360		if (dateString instanceof Date) {
26361			return dateString;
26362		}
26363		if (String(dateString).match(matchers)) {
26364			if (String(dateString).match(/^[0-9]*$/)) {
26365				dateString = Number(dateString);
26366			}
26367			if (String(dateString).match(/\-/)) {
26368				dateString = String(dateString).replace(/\-/g, "/");
26369			}
26370			return new Date(dateString);
26371		} else {
26372			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
26373		}
26374	}
26375	var DIRECTIVE_KEY_MAP = {
26376		Y: "years",
26377		m: "months",
26378		n: "daysToMonth",
26379		d: "daysToWeek",
26380		w: "weeks",
26381		W: "weeksToMonth",
26382		H: "hours",
26383		M: "minutes",
26384		S: "seconds",
26385		D: "totalDays",
26386		I: "totalHours",
26387		N: "totalMinutes",
26388		T: "totalSeconds"
26389	};
26390	function escapedRegExp(str) {
26391		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
26392		return new RegExp(sanitize);
26393	}
26394	function strftime(offsetObject) {
26395		return function(format) {
26396			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
26397			if (directives) {
26398				for (var i = 0, len = directives.length; i < len; ++i) {
26399					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
26400					directive = directive[2];
26401					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
26402						value = DIRECTIVE_KEY_MAP[directive];
26403						value = Number(offsetObject[value]);
26404					}
26405					if (value !== null) {
26406						if (modifier === "!") {
26407							value = pluralize(plural, value);
26408						}
26409						if (modifier === "") {
26410							if (value < 10) {
26411								value = "0" + value.toString();
26412							}
26413						}
26414						format = format.replace(regexp, value.toString());
26415					}
26416				}
26417			}
26418			format = format.replace(/%%/, "%");
26419			return format;
26420		};
26421	}
26422	function pluralize(format, count) {
26423		var plural = "s", singular = "";
26424		if (format) {
26425			format = format.rep
vendor: 8,618 bytes, lines 26425-26569
26425lace(/(:|;|\s)/gi, "").split(/\,/);
26426			if (format.length === 1) {
26427				plural = format[0];
26428			} else {
26429				singular = format[0];
26430				plural = format[1];
26431			}
26432		}
26433		if (Math.abs(count) > 1) {
26434			return plural;
26435		} else {
26436			return singular;
26437		}
26438	}
26439	var Countdown = function(el, finalDate, options) {
26440		this.el = el;
26441		this.$el = $(el);
26442		this.interval = null;
26443		this.offset = {};
26444		this.options = $.extend({}, defaultOptions);
26445		this.instanceNumber = instances.length;
26446		instances.push(this);
26447		this.$el.data("countdown-instance", this.instanceNumber);
26448		if (options) {
26449			if (typeof options === "function") {
26450				this.$el.on("update.countdown", options);
26451				this.$el.on("stoped.countdown", options);
26452				this.$el.on("finish.countdown", options);
26453			} else {
26454				this.options = $.extend({}, defaultOptions, options);
26455			}
26456		}
26457		this.setFinalDate(finalDate);
26458		if (this.options.defer === false) {
26459			this.start();
26460		}
26461	};
26462	$.extend(Countdown.prototype, {
26463		start: function() {
26464			if (this.interval !== null) {
26465				clearInterval(this.interval);
26466			}
26467			var self = this;
26468			this.update();
26469			this.interval = setInterval(function() {
26470				self.update.call(self);
26471			}, this.options.precision);
26472		},
26473		stop: function() {
26474			clearInterval(this.interval);
26475			this.interval = null;
26476			this.dispatchEvent("stoped");
26477		},
26478		toggle: function() {
26479			if (this.interval) {
26480				this.stop();
26481			} else {
26482				this.start();
26483			}
26484		},
26485		pause: function() {
26486			this.stop();
26487		},
26488		resume: function() {
26489			this.start();
26490		},
26491		remove: function() {
26492			this.stop.call(this);
26493			instances[this.instanceNumber] = null;
26494			delete this.$el.data().countdownInstance;
26495		},
26496		setFinalDate: function(value) {
26497			this.finalDate = parseDateString(value);
26498		},
26499		update: function() {
26500			if (this.$el.closest("html").length === 0) {
26501				this.remove();
26502				return;
26503			}
26504			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
26505			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
26506			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
26507			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
26508			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
26509				return;
26510			} else {
26511				this.totalSecsLeft = newTotalSecsLeft;
26512			}
26513			this.elapsed = now >= this.finalDate;
26514			this.offset = {
26515				seconds: this.totalSecsLeft % 60,
26516				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
26517				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
26518				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26519				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26520				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
26521				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
26522				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
26523				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
26524				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
26525				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
26526				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
26527				totalMinutes: Math.floor(this.totalSecsLeft / 60),
26528				totalSeconds: this.totalSecsLeft
26529			};
26530			if (!this.options.elapse && this.totalSecsLeft === 0) {
26531				this.stop();
26532				this.dispatchEvent("finish");
26533			} else {
26534				this.dispatchEvent("update");
26535			}
26536		},
26537		dispatchEvent: function(eventName) {
26538			var event = $.Event(eventName + ".countdown");
26539			event.finalDate = this.finalDate;
26540			event.elapsed = this.elapsed;
26541			event.offset = $.extend({}, this.offset);
26542			event.strftime = strftime(this.offset);
26543			this.$el.trigger(event);
26544		}
26545	});
26546	$.fn.countdown = function() {
26547		var argumentsArray = Array.prototype.slice.call(arguments, 0);
26548		return this.each(function() {
26549			var instanceNumber = $(this).data("countdown-instance");
26550			if (instanceNumber !== undefined) {
26551				var instance = instances[instanceNumber], method = argumentsArray[0];
26552				if (Countdown.prototype.hasOwnProperty(method)) {
26553					instance[method].apply(instance, argumentsArray.slice(1));
26554				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
26555					instance.setFinalDate.call(instance, method);
26556					instance.start();
26557				} else {
26558					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
26559				}
26560			} else {
26561				new Countdown(this, argumentsArray[0], argumentsArray[1]);
26562			}
26563		});
26564	};
26565});
26566
26567!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;
26568function getStyles(config){
26569  // 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;
26569left: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+"}"
26570};
26571  var ShareUtils;
26572
26573if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
26574  Object.defineProperty(HTMLElement.prototype, "classList", {
26575    get: function() {
26576      var ret, self, update;
26577      update = function(fn) {
26578        return function(value) {
26579          var classes, index;
26580          classes = self.className.split(/\s+/);
26581          index = classes.indexOf(value);
26582          fn(classes, index, value);
26583          self.className = classes.join(" ");
26584        };
26585      };
26586      self = this;
26587      ret = {
26588        add: update(function(classes, index, value) {
26589          ~index || classes.push(value);
26590        }),
26591        remove: update(function(classes, index) {
26592          ~index && classes.splice(index, 1);
26593        }),
26594        toggle: update(function(classes, index, value) {
26595          if (~index) {
26596            classes.splice(index, 1);
26597          } else {
26598            classes.push(value);
26599          }
26600        }),
26601        contains: function(value) {
26602          return !!~self.className.split(/\s+/).indexOf(value);
26603        },
26604        item: function(i) {
26605          return self.className.split(/\s+/)[i] || null;
26606        }
26607      };
26608      Object.defineProperty(ret, "length", {
26609        get: function() {
26610          return self.className.split(/\s+/).length;
26611        }
26612      });
26613      return ret;
26614    }
26615  });
26616}
26617
26618String.prototype.to_rfc3986 = function() {
26619  var tmp;
26620  tmp = encodeURIComponent(this);
26621  return tmp.replace(/[!'()*]/g, function(c) {
26622    return "%" + c.charCodeAt(0).toString(16);
26623  });
26624};
26625
26626ShareUtils = (function() {
26627  function ShareUtils() {}
26628
26629  ShareUtils.prototype.extend = function(to, from, overwrite) {
26630    var hasProp, prop;
26631    for (prop in from) {
26632      hasProp = to[prop] !== undefined;
26633      if (hasProp && typeof from[prop] === "object") {
26634        this.extend(to[prop], from[prop], overwrite);
26635      } else {
26636        if (overwrite || !hasProp) {
26637          to[prop] = from[prop];
26638        }
26639      }
26640    }
26641  };
26642
26643  ShareUtils.prototype.hide = function(el) {
26644    return el.style.display = "none";
26645  };
26646
26647  ShareUtils.prototype.show = function(el) {
26648    return el.style.display = "block";
26649  };
26650
26651  ShareUtils.prototype.has_class = function(el, class_name) {
26652    return el.classList.contains(class_name);
26653  };
26654
26655  ShareUtils.prototype.add_class = function(el, class_name) {
26656    return el.classList.add(class_name);
26657  };
26658
26659  ShareUtils.prototype.remove_class = function(el, class_name) {
26660    return el.classList.remove(class_name);
26661  };
26662
26663  ShareUtils.prototype.is_encoded = function(str) {
26664    str = str.to_rfc3986();
26665    return decodeURIComponent(str) !== str;
26666  };
26667
26668  ShareUtils.prototype.encode = function(str) {
26669    if (typeof str === "undefined" || this.is_encoded(str)) {
26670      return str;
26671    } else {
26672      return str.to_rfc3986();
26673    }
26674  };
26675
26676  ShareUtils.prototype.popup = function(url, params) {
26677    var k, popup, qs, v;
26678    if (params == null) {
26679      params = {};
26680    }
26681    popup = {
26682      width: 500,
26683      height: 350
26684    };
26685    popup.top = (screen.height / 2) - (popup.height / 2);
26686    popup.left = (screen.width / 2) - (popup.width / 2);
26687    qs = ((function() {
26688      var _results;
26689      _results = [];
26690      for (k in params) {
26691        v = params[k];
26692        _results.push("" + k + "=" + (this.encode(v)));
26693      }
26694      return _results;
26695    }).call(this)).join('&');
26696    if (qs) {
26697      qs = "?" + qs;
26698    }
26699    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=" 
26699+ popup.width + ",height=" + popup.height);
26700  };
26701
26702  return ShareUtils;
26703
26704})();
26705var Share,
26706  __hasProp = {}.hasOwnProperty,
26707  __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; };
26708
26709Share = (function(_super) {
26710  __extends(Share, _super);
26711
26712  function Share(element, options) {
26713    this.element = element;
26714    this.el = {
26715      head: document.getElementsByTagName('head')[0],
26716      body: document.getElementsByTagName('body')[0]
26717    };
26718    this.config = {
26719      enabled_networks: 0,
26720      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
26721      url: window.location.href.replace("&", "%26"),
26722      caption: null,
26723      title: this.default_title(),
26724      image: this.default_image(),
26725      description: this.default_description(),
26726      ui: {
26727        flyout: 'top center',
26728        button_text: 'Share',
26729        button_font: true,
26730        icon_font: true
26731      },
26732      networks: {
26733        twitter: {
26734          enabled: true,
26735          url: null,
26736          title: null,
26737          description: null
26738        },
26739        facebook: {
26740          enabled: true,
26741          load_sdk: true,
26742          url: null,
26743          app_id: null,
26744          title: null,
26745          caption: null,
26746          description: null,
26747          image: null
26748        },
26749        pinterest: {
26750          enabled: true,
26751          url: null,
26752          image: null,
26753          description: null
26754        },
26755        reddit: {
26756          enabled: true,
26757          url: null,
26758          title: null
26759        },
26760        linkedin: {
26761          enabled: true,
26762          url: null,
26763          title: null,
26764          description: null
26765        },
26766        xing: {
26767          enabled: true,
26768          url: null,
26769          title: null,
26770          image: null,
26771          description: null
26772        },
26773        whatsapp: {
26774          enabled: true,
26775          title: null,
26776          url: null
26777        },
26778        email: {
26779          enabled: true,
26780          title: null,
26781          description: null,
26782          url: null
26783        }
26784      }
26785    };
26786    this.setup(element, options);
26787    return this;
26788  }
26789
26790  Share.prototype.setup = function(element, opts) {
26791    var index, instance, instances, _i, _len;
26792    instances = document.querySelectorAll(element);
26793    this.extend(this.config, opts, true);
26794    this.set_global_configuration();
26795    this.normalize_network_configuration();
26796    if (this.config.ui.icon_font) {
26797      this.inject_icons();
26798    }
26799    if (this.config.ui.button_font) {
26800      this.inject_fonts();
26801    }
26802    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
26803      this.inject_facebook_sdk();
26804    }
26805    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
26806      instance = instances[index];
26807      this.setup_instance(element, index);
26808    }
26809  };
26810
26811  Share.prototype.setup_instance = function(element, index) {
26812    var button, instance, label, network, networks, _i, _len, _results,
26813      _this = this;
26814    instance = document.querySelectorAll(element)[index];
26815    this.hide(instance);
26816    this.add_class(instance, "sharer-" + index);
26817    instance = document.querySelectorAll(element)[index];
26818    this.inject_css(instance);
26819    this.inject_html(instance);
26820    this.show(instance);
26821    label = instance.getElementsByTagName("label")[0];
26822    button = instance.getElementsByClassName("social")[0];
26823    networks = instance.getElementsByTagName('li');
26824    this.add_class(button, "networks-" + this.config.enabled_networks);
26825    label.addEventListener("click", function() {
26826      return _this.event_toggle(button);
26827    });
26828    _this = this;
26829    _results = [];
26830    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
26831      network = networks[index];
26832      _results.push(network.addEventListener("click", function() {
26833        _this.event_network(instance, this);
26834        return _this.event_close(button);
26835      }));
26836    }
26837    return _results;
26838  };
26839
26840  Share.prototype.event_toggle = function(button) {
26841    if (this.has_class(button, "active")) {
26842      return this.event_close(button);
26843    } else {
26844      return this.event_open(button);
26845    }
26846  };
26847
26848  Share.prototype.event_open = function(button) {
26849    if (this.has_class(button, "load")) {
26850      this.remove_class(button, "load");
26851    }
26852    return this.add_class(button, "active");
26853  };
26854
26855  Share.prototype.event_close = function(button) {
26856    return this.remove_class(button, "active");
26857  };
26858
26859  Share.prototype.event_network = function(instance, network) {
26860    var name;
26861    name = network.getAttribute("data-network");
26862    this.hook("before", name, instance);
26863    this["network_" + name]();
26864    return this.hook("after", name, instance);
26865  };
26866
26867  Share.prototype.open = function() {
26868    return this["public"]("open");
26869  };
26870
26871  Share.prototype.close = function() {
26872    return this["public"]("close");
26873  };
26874
26875  Share.prototype.toggle = function() {
26876    return this["public"]("toggle");
26877  };
26878
26879  Share.prototype["public"] = function(action) {
26880    var button, index, instance, _i, _len, _ref, _results;
26881    _ref = document.querySelectorAll(this.element);
26882    _results = [];
26883    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26884      instance = _ref[index];
26885      button = instance.getElementsByClassName("social")[0];
26886      _results.push(this["event_" + action](button));
26887    }
26888    return _results;
26889  };
26890
26891  Share.prototype.network_facebook = function() {
26892    if (this.config.networks.facebook.load_sdk) {
26893      if (!window.FB) {
26894        return console.error("The Facebook JS SDK hasn't loaded yet.");
26895      }
26896      return FB.ui({
26897        method: 'feed',
26898        name: this.config.networks.facebook.title,
26899        link: this.config.networks.facebook.url,
26900        picture: this.config.networks.facebook.image,
26901        caption: this.config.networks.facebook.caption,
26902        description: this.config.networks.facebook.description
26903      });
26904    } else {
26905      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26906        u: this.config.networks.facebook.url
26907      });
26908    }
26909  };
26910
26911  Share.prototype.network_twitter = function() {
26912    return this.popup('https://twitter.com/intent/tweet', {
26913      text: this.config.networks.twitter.title,
26914      url: this.config.networks.twitter.url
26915    });
26916  };
26917
26918  Share.prototype.network_pinterest = function() {
26919    return this.popup('https://www.pinterest.com/pin/create/button', {
26920      url: this.config.networks.pinterest.url,
26921      media: this.config.networks.pinterest.image,
26922      description: this.config.networks.pinterest.description
26923    });
26924  };
26925
26926  Share.prototype.network_linkedin = function() {
26927    return this.popup('https://www.linkedin.com/shareArticle', {
26928      url: this.config.networks.linkedin.url,
26929      title: this.config.networks.linkedin.title,
26930      summary: this.config.networks.linkedin.description
26931    });
26932  }
26933
26934  Share.prototype.network_xing = function() {
26935    return this.popup('https://www.xing.com/spi/shares/new', {
26936      url: this.config.networks.xing.url,
26937      image: this.config.networks.xing.image,
26938      title: this.config.networks.xing.title,
26939      summary: this.config.networks.xing.description
26940    });
26941  }
26942
26943  Share.prototype.network_whatsapp = function() {
26944    return this.popup('https://api.whatsapp.com/send', {
26945      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
26946    });
26947  }
26948
26949  Share.prototype.network_email = function() {
26950    return this.popup('mailto:', {
26951      subject: this.config.networks.email.title,
26952      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26953    });
26954  };
26955
26956  Share.prototype.inject_icons = function() {
26957  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
26958  };
26959
26960  Share.prototype.inject_fonts = function() {
26961   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
26962  };
26963
26964  Share.prototype.inject_stylesheet = function(url) {
26965    var link;
26966    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
26967      link = document.createElement("link");
26968      link.setAttribute("rel", "stylesheet");
26969      link.setAttribute("href", url);
26970      return this.el.head.appendChild(link);
26971    }
26972  };
26973
26974  Share.prototype.inject_css = function(instance) {
26975    var css, meta, selector, style;
26976    selector = "." + (instance.getAttribute('class').split(" ").join("."));
26977    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
26978      this.config.selector = selector;
26979      css = getStyles(this.config);
26980      style = document.createElement("style");
26981      style.type = "text/css";
26982      if (style.styleSheet) {
26983        style.styleSheet.cssText = css;
26984      } else {
26985        style.appendChild(document.createTextNode(css));
26986      }
26987      this.el.head.appendChild(style);
26988      delete this.config.selector;
26989      meta = document.createElement("meta");
26990      meta.setAttribute("name", "sharer" + selector);
26991      return this.el.head.appendChild(meta);
26992    }
26993  };
26994
26995  Share.prototype.inject_html = function(instance) {
26996    //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>";
26997    return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-whatsapp' data-network='whatsapp' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
26998  };
26999
27000  Share.prototype.inject_facebook_sdk = function() {
27001    var fb_root, script;
27002    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
27003      script = document.createElement("script");
27004      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')";
27005      fb_root = document.createElement("div");
27006      fb_root.id = "fb-root";
27007      this.el.body.appendChild(fb_root);
27008      return this.el.body.appendChild(script);
27009    }
27010  };
27011
27012  Share.prototype.hook = function(type, network, instance) {
27013    var fn, opts;
27014    fn = this.config.networks[network][type];
27015    if (typeof fn === "function") {
27016      opts = fn.call(this.config.networks[network], instance);
27017      if (opts !== void 0) {
27018        opts = this.normalize_filter_config_updates(opts);
27019        this.extend(this.config.networks[network], opts, true);
27020        this.normalize_network_configuration();
27021      }
27022    }
27023  };
27024
27025  Share.prototype.default_title = function() {
27026    var content;
27027    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27028      return encodeURIComponent(content.getAttribute('content'));
27029    } else if (content = document.querySelector('title')) {
27030      return encodeURIComponent(content.innerText);
27031    }
27032  };
27033
27034  Share.prototype.default_image = function() {
27035    var content;
27036    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27037      return content.getAttribute('content');
27038    }
27039  };
27040
27041  Share.prototype.default_description = function() {
27042    var content;
27043    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27044      return encodeURIComponent(content.getAttribute('content'));
27045    } else {
27046      return '';
27047    }
27048  };
27049
27050  Share.prototype.set_global_configuration = function() {
27051    var display, network, option, options, _ref, _results;
27052    _ref = this.config.networks;
27053    _results = [];
27054    for (network in _ref) {
27055      options = _ref[network];
27056      for (option in options) {
27057        if (this.config.networks[network][option] == null) {
27058          this.config.networks[network][option] = this.config[option];
27059        }
27060      }
27061      if (this.config.networks[network].enabled) {
27062        display = 'block';
27063        this.config.enabled_networks += 1;
27064      } else {
27065        display = 'none';
27066      }
27067      _results.push(this.config.networks[network].display = display);
27068    }
27069    return _results;
27070  };
27071
27072  Share.prototype.normalize_network_configuration = function() {
27073    if (!this.config.networks.facebook.app_id) {
27074      this.config.networks.facebook.load_sdk = false;
27075    }
27076    if (!this.is_encoded(this.config.networks.twitter.description)) {
27077      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
27078    }
27079    if (typeof this.config.networks.facebook.app_id === 'number') {
27080      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
27081    }
27082  };
27083
27084  Share.prototype.normalize_filter_config_updates = function(opts) {
27085    if (this.config.networks.facebook.app_id !== opts.app_id) {
27086      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.");
27087      delete opts.app_id;
27088    }
27089    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
27090      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.");
27091      delete opts.app_id;
27092    }
27093    return opts;
27094  };
27095
27096  return Share;
27097
27098})(ShareUtils);
27099 return Share;
27100});
27101
27102// Generated by CoffeeScript 1.9.2
27103
27104// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
27105
27106(function() {
27107  var $, win;
27108
27109  $ = this.jQuery || window.jQuery;
27110
27111  win = $(window);
27112
27113  $.fn.stick_in_parent = function(opts) {
27114    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
27115    if (opts == null) {
27116      opts = {};
27117    }
27118    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;
27119    if (offset_top == null) {
27120      offset_top = 0;
27121    }
27122    if (parent_selector == null) {
27123      parent_selector = void 0;
27124    }
27125    if (inner_scrolling == null) {
27126      inner_scrolling = true;
27127    }
27128    if (sticky_class == null) {
27129      sticky_class = "is_stuck";
27130    }
27131    doc = $(document);
27132    if (enable_bottoming == null) {
27133      enable_bottoming = true;
27134    }
27135    outer_width = function(el) {
27136      var _el, computed, w;
27137      if (window.getComputedStyle) {
27138        _el = el[0];
27139        computed = window.getComputedStyle(el[0]);
27140        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
27141        if (computed.getPropertyValue("box-sizing") !== "border-box") {
27142          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
27143        }
27144        return w;
27145      } else {
27146        return el.outerWidth(true);
27147      }
27148    };
27149    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
27150      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
27151      if (elm.data("sticky_kit")) {
27152        return;
27153      }
27154      elm.data("sticky_kit", true);
27155      last_scroll_height = doc.height();
27156      parent = elm.parent();
27157      if (parent_selector != null) {
27158        parent = parent.closest(parent_selector);
27159      }
27160      if (!parent.length) {
27161        throw "failed to find stick parent";
27162      }
27163      fixed = false;
27164      bottomed = false;
27165      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
27166      if (spacer) {
27167        spacer.css('position', elm.css('position'));
27168      }
27169      recalc = function() {
27170        var border_top, padding_top, restore;
27171        if (detached) {
27172          return;
27173        }
27174        last_scroll_height = doc.height();
27175        border_top = parseInt(parent.css("border-top-width"), 10);
27176        padding_top = parseInt(parent.css("padding-top"), 10);
27177        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
27178        parent_top = parent.offset().top + border_top + padding_top;
27179        parent_height = parent.height();
27180        if (fixed) {
27181          fixed = false;
vendor: 6,068 bytes, lines 27182-27376
27182          bottomed = false;
27183          if (manual_spacer == null) {
27184            elm.insertAfter(spacer);
27185            spacer.detach();
27186          }
27187          elm.css({
27188            position: "",
27189            top: "",
27190            width: "",
27191            bottom: ""
27192          }).removeClass(sticky_class);
27193          restore = true;
27194        }
27195        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
27196        height = elm.outerHeight(true);
27197        el_float = elm.css("float");
27198        if (spacer) {
27199          spacer.css({
27200            width: outer_width(elm),
27201            height: height,
27202            display: elm.css("display"),
27203            "vertical-align": elm.css("vertical-align"),
27204            "float": el_float
27205          });
27206        }
27207        if (restore) {
27208          return tick();
27209        }
27210      };
27211      recalc();
27212      if (height === parent_height) {
27213        return;
27214      }
27215      last_pos = void 0;
27216      offset = offset_top;
27217      recalc_counter = recalc_every;
27218      tick = function() {
27219        var css, delta, recalced, scroll, will_bottom, win_height;
27220        if (detached) {
27221          return;
27222        }
27223        recalced = false;
27224        if (recalc_counter != null) {
27225          recalc_counter -= 1;
27226          if (recalc_counter <= 0) {
27227            recalc_counter = recalc_every;
27228            recalc();
27229            recalced = true;
27230          }
27231        }
27232        if (!recalced && doc.height() !== last_scroll_height) {
27233          recalc();
27234          recalced = true;
27235        }
27236        scroll = win.scrollTop();
27237        if (last_pos != null) {
27238          delta = scroll - last_pos;
27239        }
27240        last_pos = scroll;
27241        if (fixed) {
27242          if (enable_bottoming) {
27243            will_bottom = scroll + height + offset > parent_height + parent_top;
27244            if (bottomed && !will_bottom) {
27245              bottomed = false;
27246              elm.css({
27247                position: "fixed",
27248                bottom: "",
27249                top: offset
27250              }).trigger("sticky_kit:unbottom");
27251            }
27252          }
27253          if (scroll < top) {
27254            fixed = false;
27255            offset = offset_top;
27256            if (manual_spacer == null) {
27257              if (el_float === "left" || el_float === "right") {
27258                elm.insertAfter(spacer);
27259              }
27260              spacer.detach();
27261            }
27262            css = {
27263              position: "",
27264              width: "",
27265              top: ""
27266            };
27267            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
27268          }
27269          if (inner_scrolling) {
27270            win_height = win.height();
27271            if (height + offset_top > win_height) {
27272              if (!bottomed) {
27273                offset -= delta;
27274                offset = Math.max(win_height - height, offset);
27275                offset = Math.min(offset_top, offset);
27276                if (fixed) {
27277                  elm.css({
27278                    top: offset + "px"
27279                  });
27280                }
27281              }
27282            }
27283          }
27284        } else {
27285          if (scroll > top) {
27286            fixed = true;
27287            css = {
27288              position: "fixed",
27289              top: offset
27290            };
27291            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
27292            elm.css(css).addClass(sticky_class);
27293            if (manual_spacer == null) {
27294              elm.after(spacer);
27295              if (el_float === "left" || el_float === "right") {
27296                spacer.append(elm);
27297              }
27298            }
27299            elm.trigger("sticky_kit:stick");
27300          }
27301        }
27302        if (fixed && enable_bottoming) {
27303          if (will_bottom == null) {
27304            will_bottom = scroll + height + offset > parent_height + parent_top;
27305          }
27306          if (!bottomed && will_bottom) {
27307            bottomed = true;
27308            if (parent.css("position") === "static") {
27309              parent.css({
27310                position: "relative"
27311              });
27312            }
27313            return elm.css({
27314              position: "absolute",
27315              bottom: padding_bottom,
27316              top: "auto"
27317            }).trigger("sticky_kit:bottom");
27318          }
27319        }
27320      };
27321      recalc_and_tick = function() {
27322        recalc();
27323        return tick();
27324      };
27325      detach = function() {
27326        detached = true;
27327        win.off("touchmove", tick);
27328        win.off("scroll", tick);
27329        win.off("resize", recalc_and_tick);
27330        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
27331        elm.off("sticky_kit:detach", detach);
27332        elm.removeData("sticky_kit");
27333        elm.css({
27334          position: "",
27335          bottom: "",
27336          top: "",
27337          width: ""
27338        });
27339        parent.position("position", "");
27340        if (fixed) {
27341          if (manual_spacer == null) {
27342            if (el_float === "left" || el_float === "right") {
27343              elm.insertAfter(spacer);
27344            }
27345            spacer.remove();
27346          }
27347          return elm.removeClass(sticky_class);
27348        }
27349      };
27350      win.on("touchmove", tick);
27351      win.on("scroll", tick);
27352      win.on("resize", recalc_and_tick);
27353      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
27354      elm.on("sticky_kit:detach", detach);
27355      return setTimeout(tick, 0);
27356    };
27357    for (i = 0, len = this.length; i < len; i++) {
27358      elm = this[i];
27359      fn($(elm));
27360    }
27361    return this;
27362  };
27363
27364}).call(this);
27365/* ==========================================================================
27366 * bootstrap-tab-history.js
27367 * Author: Michael Narayan <[email protected]>
27368 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
27369 * ==========================================================================
27370 * Licensed under the Apache License, Version 2.0 (the "License"); you may
27371 * not use this file except in compliance with the License. You may obtain a
27372 * copy of the License at
27373 *
27374 * http://www.apache.org/licenses/LICENSE-2.0
27375 *
27376 * Unless required by applicable law or agreed to in writing, softw
27376are
27377 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
27378 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
27379 * License for the specific language governing permissions and limitations
27380 * under the License.
27381 * ========================================================================== */
27382
27383/* ========================================================================== */
27384/* JSHint directives                                                          */
27385/*                                                                            */
27386/* global BootstrapTabHistory: true                                           */
27387/*                                                                            */
27388/* global document                                                            */
27389/* global jQuery                                                              */
27390/* global history                                                             */
27391/* global window                                                              */
27392/* ========================================================================== */
27393
27394/**
27395 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
27396 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
27397 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
27398 *
27399 * See the README for additional information.
27400 *
27401 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
27402 */
27403
27404BootstrapTabHistory = {
27405  options: {
27406    /**
27407     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
27408     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
27409     *
27410     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
27411     *
27412     * @public
27413     * @type {?number}
27414     */
27415    defaultAnchorYOffset: 0,
27416    /**
27417     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
27418     *
27419     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
27420     *
27421     * @public
27422     * @type {string}
27423     */
27424    defaultChanger: 'replace',
27425    /**
27426     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
27427     * `null` is passed as the third parameter to these calls.
27428     *
27429     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
27430     *
27431     * @public
27432     * @type {boolean}
27433     */
27434    defaultUpdateURL: false,
27435    /**
27436     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
27437     * load.
27438     *
27439     * @public
27440     * @type {boolean}
27441     */
27442    showTabsBasedOnAnchor: true
27443  }
27444};
27445
27446(function () {
27447  'use strict';
27448
27449  jQuery(function () {
27450    if(history && history.pushState && history.replaceState) {
27451      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27452
27453      if(bootstrapTabHistory) {
27454        showTabsBasedOnState(bootstrapTabHistory);
27455      } else {
27456        showTabsBasedOnAnchor();
27457      }
27458
27459      backfillHistoryState();
27460
27461      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
27462      jQuery(window).on('popstate', onPopState);
27463    } else {
27464      showTabsBasedOnAnchor();
27465    }
27466  });
27467
27468  /**
27469   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
27470   *
27471   * @type {boolean}
27472   */
27473  var showingTabsBasedOnState = false;
27474
27475  /**
27476   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
27477   * `history.back` handling when `data-tab-history-update-url` is true.
27478   */
27479  function backfillHistoryState() {
27480    var newState = null;
27481
27482    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
27483      var $activeTabElement = jQuery(this);
27484      var selector = getTabSelector($activeTabElement);
27485
27486      if(selector) {
27487        var tabGroup = getTabGroup($activeTabElement);
27488
27489        if(tabGroup) {
27490          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
27491        }
27492      }
27493    });
27494
27495    if(newState) {
27496      history.replaceState(newState, '', null);
27497    }
27498  }
27499
27500  /**
27501   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
27502   * said bootstrapTabHistory attribute.
27503   *
27504   * @param {?object} existingState
27505   * @param {!string} tabGroup
27506   * @param {!string} selector
27507   * @returns {!object}
27508   */
27509  function createNewHistoryState(existingState, tabGroup, selector) {
27510    // Clone history.state and ensure it has a bootstrapTabHistory entry.
27511    var newState = jQuery.extend(true, {}, existingState, {
27512      bootstrapTabHistory: {}
27513    });
27514
27515    newState.bootstrapTabHistory[tabGroup] = selector;
27516
27517    return newState;
27518  }
27519
27520  /**
27521   * @param {jQuery} $tab
27522   * @returns {?string}
27523   */
27524  function getTabGroup($tab) {
27525    return parseTruthyAttributeValue($tab.data('tab-history'));
27526  }
27527
27528  /**
27529   * @param {jQuery} $tab
27530   * @returns {?string}
27531   */
27532  function getTabSelector($tab) {
27533    return $tab.data('target') || $tab.attr('href');
27534  }
27535
27536  /**
27537   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
27538   *
27539   * @param {jQuery.Event} shownEvt
27540   */
27541  function onShownTab(shownEvt) {
27542    if(!showingTabsBasedOnState) {
27543      var $activatedTab = jQuery(shownEvt.target);
27544      if ( $activatedTab.hasClass('panel-collapse') )
27545        $activatedTab = $activatedTab.closest('.panel').find('a');
27546      var selector = getTabSelector($activatedTab);
27547
27548      if(selector) {
27549        var tabGroup = getTabGroup($activatedTab);
27550
27551        if(tabGroup) {
27552          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
27553          var newState = createNewHistoryState(history.state, tabGroup, selector);
27554          var updateURL = (function ($activatedTab) {
27555            if(selector[0] === '#') {
27556              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
27557
27558              if(elementUpdateURLOption === undefined) {
27559                return BootstrapTabHistory.options.defaultUpdateURL;
27560              } else {
27561                return elementUpdateURLOption;
27562              }
27563            } else {
27564              return false;
27565            }
27566          })($activatedTab);
27567
27568          switch(historyChanger) {
27569            case 'push':
27570              history.pushState(newState, '', updateURL ? selector : null);
27571              break;
27572            case 'replace':
27573              history.replaceState(newState, '', updateURL ? selector : null);
27574              break;
27575            default:
27576              throw new Error('Unknown tab-history-changer: ' + historyChanger);
27577          }
27578        }
27579      }
27580    }
27581  }
27582
27583  /**
27584   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
27585   */
27586  function onPopState() {
27587    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27588
27589    if(bootstrapTabHistory) {
27590      showTabsBasedOnState(bootstrapTabHistory);
27591    }
27592  }
27593
27594  /**
27595   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
27596   *
27597   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
27598   *
27599   * @param {*} value
27600   * @returns {*}
27601   */
27602  function parseTruthyAttributeValue(value) {
27603    if(value) {
27604      return value;
27605    } else if(value === '') {
27606      return true;
27607    } else {
27608      return value;
27609    }
27610  }
27611
27612  /**
27613   * Show tabs based upon the anchor component of `window.location`.
27614   */
27615  function showTabsBasedOnAnchor() {
27616    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
27617      var anchor = window.location && window.location.hash;
27618
27619      if(anchor) {
27620        var $tabElement = showTabForSelector(anchor);
27621
27622        if($tabElement && window.addEventListener && window.removeEventListener) {
27623          var anchorYOffset = (function ($tabElement) {
27624            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
27625
27626            if(elementSetting === undefined) {
27627              return BootstrapTabHistory.options.defaultAnchorYOffset;
27628            } else {
27629              return elementSetting;
27630            }
27631          })($tabElement);
27632
27633          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
27634          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
27635          //   `history.state` object should have been used (unless the browser did not support the modern History API).
27636          if(anchorYOffset || anchorYOffset === 0) {
27637            var scrollListener = function resetAnchorScroll () {
27638              window.removeEventListener('scroll', scrollListener);
27639              window.scrollTo(0, anchorYOffset);
27640            };
27641
27642            window.addEventListener('scroll', scrollListener);
27643          }
27644        }
27645      }
27646    }
27647  }
27648
27649  /**
27650   * Show a tab which corresponds to the provided selector.
27651   *
27652   * @param {string} selector - A CSS selector.
27653   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
27654   */
27655  function showTabForSelector(selector) {
27656    var $tabElement = (function (selector) {
27657      var $ret = null;
27658
27659      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
27660        var $potentialTab = jQuery(this);
27661
27662        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
27663          $ret = $potentialTab;
27664          return false;
vendor: 43,483 bytes, lines 27665-28881
27665        } else {
27666         return null;
27667        }
27668      });
27669
27670      return $ret;
27671    })(selector);
27672
27673    if($tabElement) {
27674      if ( !$tabElement.parent().hasClass('active') ) {
27675        $tabElement.trigger('click');
27676      }
27677      //$tabElement.tab('show');
27678    }
27679
27680    return $tabElement;
27681  }
27682
27683  /**
27684   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
27685   *
27686   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
27687   */
27688  function showTabsBasedOnState(bootstrapTabHistory) {
27689    showingTabsBasedOnState = true;
27690
27691    try {
27692      for(var k in bootstrapTabHistory) {
27693        if(bootstrapTabHistory.hasOwnProperty(k)) {
27694          showTabForSelector(bootstrapTabHistory[k]);
27695        }
27696      }
27697    } finally {
27698      showingTabsBasedOnState = false;
27699    }
27700  }
27701})();
27702
27703/*!
27704 * justifiedGallery - v3.8.1
27705 * http://miromannino.github.io/Justified-Gallery/
27706 * Copyright (c) 2020 Miro Mannino
27707 * Licensed under the MIT license.
27708 */
27709(function (factory) {
27710  if (typeof define === 'function' && define.amd) {
27711    // AMD. Register as an anonymous module.
27712    define(['jquery'], factory);
27713  } else if (typeof module === 'object' && module.exports) {
27714    // Node/CommonJS
27715    module.exports = function (root, jQuery) {
27716      if (jQuery === undefined) {
27717        // require('jQuery') returns a factory that requires window to
27718        // build a jQuery instance, we normalize how we use modules
27719        // that require this pattern but the window provided is a noop
27720        // if it's defined (how jquery works)
27721        if (typeof window !== 'undefined') {
27722          jQuery = require('jquery');
27723        }
27724        else {
27725          jQuery = require('jquery')(root);
27726        }
27727      }
27728      factory(jQuery);
27729      return jQuery;
27730    };
27731  } else {
27732    // Browser globals
27733    factory(jQuery);
27734  }
27735}(function ($) {
27736
27737  /**
27738   * Justified Gallery controller constructor
27739   *
27740   * @param $gallery the gallery to build
27741   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
27742   * @constructor
27743   */
27744  var JustifiedGallery = function ($gallery, settings) {
27745
27746    this.settings = settings;
27747    this.checkSettings();
27748
27749    this.imgAnalyzerTimeout = null;
27750    this.entries = null;
27751    this.buildingRow = {
27752      entriesBuff: [],
27753      width: 0,
27754      height: 0,
27755      aspectRatio: 0
27756    };
27757    this.lastFetchedEntry = null;
27758    this.lastAnalyzedIndex = -1;
27759    this.yield = {
27760      every: 2, // do a flush every n flushes (must be greater than 1)
27761      flushed: 0 // flushed rows without a yield
27762    };
27763    this.border = settings.border >= 0 ? settings.border : settings.margins;
27764    this.maxRowHeight = this.retrieveMaxRowHeight();
27765    this.suffixRanges = this.retrieveSuffixRanges();
27766    this.offY = this.border;
27767    this.rows = 0;
27768    this.spinner = {
27769      phase: 0,
27770      timeSlot: 150,
27771      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
27772      intervalId: null
27773    };
27774    this.scrollBarOn = false;
27775    this.checkWidthIntervalId = null;
27776    this.galleryWidth = $gallery.width();
27777    this.$gallery = $gallery;
27778
27779  };
27780
27781  /** @returns {String} the best suffix given the width and the height */
27782  JustifiedGallery.prototype.getSuffix = function (width, height) {
27783    var longestSide, i;
27784    longestSide = (width > height) ? width : height;
27785    for (i = 0; i < this.suffixRanges.length; i++) {
27786      if (longestSide <= this.suffixRanges[i]) {
27787        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27788      }
27789    }
27790    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27791  };
27792
27793  /**
27794   * Remove the suffix from the string
27795   *
27796   * @returns {string} a new string without the suffix
27797   */
27798  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27799    return str.substring(0, str.length - suffix.length);
27800  };
27801
27802  /**
27803   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27804   */
27805  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27806    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27807  };
27808
27809  /**
27810   * Get the used suffix of a particular url
27811   *
27812   * @param str
27813   * @returns {String} return the used suffix
27814   */
27815  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27816    for (var si in this.settings.sizeRangeSuffixes) {
27817      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27818        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27819        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27820      }
27821    }
27822    return '';
27823  };
27824
27825  /**
27826   * Given an image src, with the width and the height, returns the new image src with the
27827   * best suffix to show the best quality thumbnail.
27828   *
27829   * @returns {String} the suffix to use
27830   */
27831  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27832    var newImageSrc;
27833
27834    if (this.settings.thumbnailPath) {
27835      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27836    } else {
27837      var matchRes = imageSrc.match(this.settings.extension);
27838      var ext = (matchRes !== null) ? matchRes[0] : '';
27839      newImageSrc = imageSrc.replace(this.settings.extension, '');
27840      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27841      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27842    }
27843
27844    return newImageSrc;
27845  };
27846
27847  /**
27848   * Shows the images that is in the given entry
27849   *
27850   * @param $entry the entry
27851   * @param callback the callback that is called when the show animation is finished
27852   */
27853  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27854    if (this.settings.cssAnimation) {
27855      $entry.addClass('jg-entry-visible');
27856      if (callback) callback();
27857    } else {
27858      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27859      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27860    }
27861  };
27862
27863  /**
27864   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27865   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27866   *
27867   * @param $image the image to analyze
27868   * @returns {String} the extracted src
27869   */
27870  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27871    var imageSrc = $image.data('safe-src');
27872    var imageSrcLoc = 'data-safe-src';
27873    // Begin Uncode edit
27874    if (typeof imageSrc === 'undefined') {
27875    	var imageCurrentSrc = $image[0].currentSrc;
27876    	if (imageCurrentSrc) {
27877    		imageSrc = imageCurrentSrc;
27878    	} else {
27879    		imageSrc = $image.attr('src');
27880    	}
27881		imageSrcLoc = 'src';
27882    }
27883    // End Uncode edit
27884    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27885    $image.data('jg.src', imageSrc); // this will change overtime
27886    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27887    return imageSrc;
27888  };
27889
27890  /** @returns {jQuery} the image in the given entry */
27891  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27892    var $img = $entry.find(this.settings.imgSelector);
27893    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27894    return $img.length === 0 ? null : $img;
27895  };
27896
27897  /** @returns {jQuery} the caption in the given entry */
27898  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27899    var $caption = $entry.find('> .jg-caption');
27900    return $caption.length === 0 ? null : $caption;
27901  };
27902
27903  /**
27904   * Display the entry
27905   *
27906   * @param {jQuery} $entry the entry to display
27907   * @param {int} x the x position where the entry must be positioned
27908   * @param y the y position where the entry must be positioned
27909   * @param imgWidth the image width
27910   * @param imgHeight the image height
27911   * @param rowHeight the row height of the row that owns the entry
27912   */
27913  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27914    $entry.width(imgWidth);
27915    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27916    $entry.css('top', Math.floor(y));//hacked by Uncode
27917    $entry.css('left', x);
27918
27919    var $image = this.imgFromEntry($entry);
27920    if ($image !== null) {
27921      $image.css('width', imgWidth);
27922      $image.css('height', imgHeight);
27923      $image.css('margin-left', - imgWidth / 2);
27924      $image.css('margin-top', - imgHeight / 2);
27925
27926      // Image reloading for an high quality of thumbnails
27927      var imageSrc = $image.data('jg.src');
27928      if (imageSrc) {
27929        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27930
27931        $image.one('error', function () {
27932           this.resetImgSrc($image); //revert to the original thumbnail
27933        });
27934
27935        var loadNewImage = function () {
27936          // if (imageSrc !== newImageSrc) {
27937            $image.attr('src', imageSrc);
27938          // }
27939        };
27940
27941        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27942          this.onImageEvent(imageSrc, (function() {
27943            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27944            $entry.data('jg.loaded', true);
27945          }).bind(this));
27946        } else {
27947          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27948        }
27949
27950      }
27951
27952    } else {
27953      this.showImg($entry);
27954    }
27955
27956    this.displayEntryCaption($entry);
27957  };
27958
27959  /**
27960   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
27961   * or the 'title' attributes.
27962   *
27963   * @param {jQuery} $entry the entry to process
27964   */
27965  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
27966    var $image = this.imgFromEntry($entry);
27967    if ($image !== null && this.settings.captions) {
27968      var $imgCaption = this.captionFromEntry($entry);
27969
27970      // Create it if it doesn't exists
27971      if ($imgCaption === null) {
27972        var caption = $image.attr('alt');
27973        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
27974        if (this.isValidCaption(caption)) { // Create only we found something
27975          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
27976          $entry.append($imgCaption);
27977          $entry.data('jg.createdCaption', true);
27978        }
27979      }
27980
27981      // Create events (we check again the $imgCaption because it can be still inexistent)
27982      if ($imgCaption !== null) {
27983        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
27984        this.addCaptionEventsHandlers($entry);
27985      }
27986    } else {
27987      this.removeCaptionEventsHandlers($entry);
27988    }
27989  };
27990
27991  /**
27992   * Validates the caption
27993   *
27994   * @param caption The caption that should be validated
27995   * @return {boolean} Validation result
27996   */
27997  JustifiedGallery.prototype.isValidCaption = function (caption) {
27998    return (typeof caption !== 'undefined' && caption.length > 0);
27999  };
28000
28001  /**
28002   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
28003   * It shows the caption using jQuery (or using CSS if it is configured so)
28004   *
28005   * @param {Event} eventObject the event object
28006   */
28007  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
28008    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28009    if (this.settings.cssAnimation) {
28010      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28011    } else {
28012      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28013        this.settings.captionSettings.visibleOpacity);
28014    }
28015  };
28016
28017  /**
28018   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28019   * It hides the caption using jQuery (or using CSS if it is configured so)
28020   *
28021   * @param {Event} eventObject the event object
28022   */
28023  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28024    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28025    if (this.settings.cssAnimation) {
28026      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28027    } else {
28028      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28029        this.settings.captionSettings.nonVisibleOpacity);
28030    }
28031  };
28032
28033  /**
28034   * Add the handlers of the entry for the caption
28035   *
28036   * @param $entry the entry to modify
28037   */
28038  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28039    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28040    if (typeof captionMouseEvents === 'undefined') {
28041      captionMouseEvents = {
28042        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28043        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28044      };
28045      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28046      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28047      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28048    }
28049  };
28050
28051  /**
28052   * Remove the handlers of the entry for the caption
28053   *
28054   * @param $entry the entry to modify
28055   */
28056  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28057    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28058    if (typeof captionMouseEvents !== 'undefined') {
28059      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28060      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28061      $entry.removeData('jg.captionMouseEvents');
28062    }
28063  };
28064
28065  /**
28066   * Clear the building row data to be used for a new row
28067   */
28068  JustifiedGallery.prototype.clearBuildingRow = function () {
28069    this.buildingRow.entriesBuff = [];
28070    this.buildingRow.aspectRatio = 0;
28071    this.buildingRow.width = 0;
28072  };
28073
28074  /**
28075   * Justify the building row, preparing it to
28076   *
28077   * @param isLastRow
28078   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28079   * @returns a boolean to know if the row has been justified or not
28080   */
28081  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
28082    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
28083    var minHeight = 0;
28084    var availableWidth = this.galleryWidth - 2 * this.border - (
28085      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28086    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
28087    var defaultRowHeight = this.settings.rowHeight;
28088    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
28089
28090    //Skip the last row if we can't justify it and the lastRow == 'hide'
28091    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
28092      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28093        $entry = this.buildingRow.entriesBuff[i];
28094        if (this.settings.cssAnimation)
28095          $entry.removeClass('jg-entry-visible');
28096        else {
28097          $entry.stop().fadeTo(0, 0.1);
28098          $entry.find('> img, > a > img').fadeTo(0, 0);
28099        }
28100      }
28101      return -1;
28102    }
28103
28104    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
28105    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
28106      justify = false;
28107
28108      if (this.rows > 0) {
28109        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
28110        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
28111      }
28112    }
28113
28114    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28115      $entry = this.buildingRow.entriesBuff[i];
28116      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28117
28118      if (justify) {
28119        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
28120        newImgH = rowHeight;
28121      } else {
28122        newImgW = defaultRowHeight * imgAspectRatio;
28123        newImgH = defaultRowHeight;
28124      }
28125
28126      availableWidth -= Math.round(newImgW);
28127      $entry.data('jg.jwidth', Math.round(newImgW));
28128      $entry.data('jg.jheight', Math.ceil(newImgH));
28129      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
28130    }
28131
28132    this.buildingRow.height = minHeight;
28133    return justify;
28134  };
28135
28136  /**
28137   * Flush a row: justify it, modify the gallery height accordingly to the row height
28138   *
28139   * @param isLastRow
28140   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28141   */
28142  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
28143    var settings = this.settings;
28144    var $entry, buildingRowRes, offX = this.border, i;
28145
28146    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
28147    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
28148      this.clearBuildingRow();
28149      return;
28150    }
28151
28152    if (this.maxRowHeight) {
28153      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
28154    }
28155
28156    //Align last (unjustified) row
28157    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
28158      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
28159
28160      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28161        $entry = this.buildingRow.entriesBuff[i];
28162        availableWidth -= $entry.data('jg.jwidth');
28163      }
28164
28165      if (settings.lastRow === 'center')
28166        offX += Math.round(availableWidth / 2);
28167      else if (settings.lastRow === 'right')
28168        offX += availableWidth;
28169    }
28170
28171    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
28172    for (i = 0; i <= lastEntryIdx; i++) {
28173      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
28174      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
28175      offX += $entry.data('jg.jwidth') + settings.margins;
28176    }
28177
28178    //Gallery Height
28179    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
28180    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
28181
28182    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
28183      //Ready for a new row
28184      this.offY += this.buildingRow.height + settings.margins;
28185      this.rows += 1;
28186      this.clearBuildingRow();
28187      this.settings.triggerEvent.call(this, 'jg.rowflush');
28188    }
28189  };
28190
28191
28192  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
28193  var galleryPrevStaticHeight = 0;
28194
28195  JustifiedGallery.prototype.rememberGalleryHeight = function () {
28196    galleryPrevStaticHeight = this.$gallery.height();
28197    this.$gallery.height(galleryPrevStaticHeight);
28198  };
28199
28200  // grow only
28201  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
28202    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
28203    this.$gallery.height(galleryPrevStaticHeight);
28204  };
28205
28206  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
28207    galleryPrevStaticHeight = height;
28208    this.$gallery.height(height);
28209  };
28210
28211  /**
28212   * Checks the width of the gallery container, to know if a new justification is needed
28213   */
28214  JustifiedGallery.prototype.checkWidth = function () {
28215    this.checkWidthIntervalId = setInterval($.proxy(function () {
28216
28217      // if the gallery is not currently visible, abort.
28218      if (!this.$gallery.is(":visible")) return;
28219
28220      var galleryWidth = parseFloat(this.$gallery.width());
28221      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
28222        this.galleryWidth = galleryWidth;
28223        this.rewind();
28224
28225        this.rememberGalleryHeight();
28226
28227        // Restart to analyze
28228        this.startImgAnalyzer(true);
28229      }
28230    }, this), this.settings.refreshTime);
28231  };
28232
28233  /**
28234   * @returns {boolean} a boolean saying if the spinner is active or not
28235   */
28236  JustifiedGallery.prototype.isSpinnerActive = function () {
28237    return this.spinner.intervalId !== null;
28238  };
28239
28240  /**
28241   * @returns {int} the spinner height
28242   */
28243  JustifiedGallery.prototype.getSpinnerHeight = function () {
28244    return this.spinner.$el.innerHeight();
28245  };
28246
28247  /**
28248   * Stops the spinner animation and modify the gallery height to exclude the spinner
28249   */
28250  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
28251    clearInterval(this.spinner.intervalId);
28252    this.spinner.intervalId = null;
28253    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
28254    this.spinner.$el.detach();
28255  };
28256
28257  /**
28258   * Starts the spinner animation
28259   */
28260  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
28261    var spinnerContext = this.spinner;
28262    var $spinnerPoints = spinnerContext.$el.find('span');
28263    clearInterval(spinnerContext.intervalId);
28264    this.$gallery.append(spinnerContext.$el);
28265    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
28266    spinnerContext.intervalId = setInterval(function () {
28267      if (spinnerContext.phase < $spinnerPoints.length) {
28268        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
28269      } else {
28270        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
28271      }
28272      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
28273    }, spinnerContext.timeSlot);
28274  };
28275
28276  /**
28277   * Rewind the image analysis to start from the first entry.
28278   */
28279  JustifiedGallery.prototype.rewind = function () {
28280    this.lastFetchedEntry = null;
28281    this.lastAnalyzedIndex = -1;
28282    this.offY = this.border;
28283    this.rows = 0;
28284    this.clearBuildingRow();
28285  };
28286
28287  /**
28288   * @returns {String} `settings.selector` rejecting spinner element
28289   */
28290  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
28291    return this.settings.selector + ', div:not(.jg-spinner)';
28292  };
28293
28294  /**
28295   * @returns {Array} all entries matched by `settings.selector`
28296   */
28297  JustifiedGallery.prototype.getAllEntries = function () {
28298    var selector = this.getSelectorWithoutSpinner();
28299    return this.$gallery.children(selector).toArray();
28300  };
28301
28302  /**
28303   * Update the entries searching it from the justified gallery HTML element
28304   *
28305   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
28306   * @returns {boolean} true if some entries has been founded
28307   */
28308  JustifiedGallery.prototype.updateEntries = function (norewind) {
28309    var newEntries;
28310
28311    if (norewind && this.lastFetchedEntry != null) {
28312      var selector = this.getSelectorWithoutSpinner();
28313      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
28314    } else {
28315      this.entries = [];
28316      newEntries = this.getAllEntries();
28317    }
28318
28319    if (newEntries.length > 0) {
28320
28321      // Sort or randomize
28322      if ($.isFunction(this.settings.sort)) {
28323        newEntries = this.sortArray(newEntries);
28324      } else if (this.settings.randomize) {
28325        newEntries = this.shuffleArray(newEntries);
28326      }
28327      this.lastFetchedEntry = newEntries[newEntries.length - 1];
28328
28329      // Filter
28330      if (this.settings.filter) {
28331        newEntries = this.filterArray(newEntries);
28332      } else {
28333        this.resetFilters(newEntries);
28334      }
28335
28336    }
28337
28338    this.entries = this.entries.concat(newEntries);
28339    return true;
28340  };
28341
28342  /**
28343   * Apply the entries order to the DOM, iterating the entries and appending the images
28344   *
28345   * @param entries the entries that has been modified and that must be re-ordered in the DOM
28346   */
28347  JustifiedGallery.prototype.insertToGallery = function (entries) {
28348    var that = this;
28349    $.each(entries, function () {
28350      $(this).appendTo(that.$gallery);
28351    });
28352  };
28353
28354  /**
28355   * Shuffle the array using the Fisher-Yates shuffle algorithm
28356   *
28357   * @param a the array to shuffle
28358   * @return the shuffled array
28359   */
28360  JustifiedGallery.prototype.shuffleArray = function (a) {
28361    var i, j, temp;
28362    for (i = a.length - 1; i > 0; i--) {
28363      j = Math.floor(Math.random() * (i + 1));
28364      temp = a[i];
28365      a[i] = a[j];
28366      a[j] = temp;
28367    }
28368    this.insertToGallery(a);
28369    return a;
28370  };
28371
28372  /**
28373   * Sort the array using settings.comparator as comparator
28374   *
28375   * @param a the array to sort (it is sorted)
28376   * @return the sorted array
28377   */
28378  JustifiedGallery.prototype.sortArray = function (a) {
28379    a.sort(this.settings.sort);
28380    this.insertToGallery(a);
28381    return a;
28382  };
28383
28384  /**
28385   * Reset the filters removing the 'jg-filtered' class from all the entries
28386   *
28387   * @param a the array to reset
28388   */
28389  JustifiedGallery.prototype.resetFilters = function (a) {
28390    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
28391  };
28392
28393  /**
28394   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
28395   *
28396   * @param a the array to filter
28397   * @return the filtered array
28398   */
28399  JustifiedGallery.prototype.filterArray = function (a) {
28400    var settings = this.settings;
28401    if ($.type(settings.filter) === 'string') {
28402      // Filter only keeping the entries passed in the string
28403      return a.filter(function (el) {
28404        var $el = $(el);
28405        if ($el.is(settings.filter)) {
28406          $el.removeClass('jg-filtered');
28407          return true;
28408        } else {
28409          $el.addClass('jg-filtered').removeClass('jg-visible');
28410          return false;
28411        }
28412      });
28413    } else if ($.isFunction(settings.filter)) {
28414      // Filter using the passed function
28415      var filteredArr = a.filter(settings.filter);
28416      for (var i = 0; i < a.length; i++) {
28417        if (filteredArr.indexOf(a[i]) === -1) {
28418          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
28419        } else {
28420          $(a[i]).removeClass('jg-filtered');
28421        }
28422      }
28423      return filteredArr;
28424    }
28425  };
28426
28427  /**
28428   * Revert the image src to the default value.
28429   */
28430  JustifiedGallery.prototype.resetImgSrc = function ($img) {
28431    if ($img.data('jg.originalSrcLoc') === 'src') {
28432      $img.attr('src', $img.data('jg.originalSrc'));
28433    } else {
28434      $img.attr('src', '');
28435    }
28436  };
28437
28438  /**
28439   * Destroy the Justified Gallery instance.
28440   *
28441   * It clears all the css properties added in the style attributes. We doesn't backup the original
28442   * values for those css attributes, because it costs (performance) and because in general one
28443   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
28444   * classes). Creating a backup is also difficult because JG could be called multiple times and
28445   * with different style attributes.
28446   */
28447  JustifiedGallery.prototype.destroy = function () {
28448    clearInterval(this.checkWidthIntervalId);
28449    this.stopImgAnalyzerStarter();
28450
28451    // Get fresh entries list since filtered entries are absent in `this.entries`
28452    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
28453      var $entry = $(entry);
28454
28455      // Reset entry style
28456      $entry.css('width', '');
28457      $entry.css('height', '');
28458      $entry.css('top', '');
28459      $entry.css('left', '');
28460      $entry.data('jg.loaded', undefined);
28461      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
28462
28463      // Reset image style
28464      var $img = this.imgFromEntry($entry);
28465      if ($img) {
28466        $img.css('width', '');
28467        $img.css('height', '');
28468        $img.css('margin-left', '');
28469        $img.css('margin-top', '');
28470        this.resetImgSrc($img);
28471        $img.data('jg.originalSrc', undefined);
28472        $img.data('jg.originalSrcLoc', undefined);
28473        $img.data('jg.src', undefined);
28474      }
28475
28476      // Remove caption
28477      this.removeCaptionEventsHandlers($entry);
28478      var $caption = this.captionFromEntry($entry);
28479      if ($entry.data('jg.createdCaption')) {
28480        // remove also the caption element (if created by jg)
28481        $entry.data('jg.createdCaption', undefined);
28482        if ($caption !== null) $caption.remove();
28483      } else {
28484        if ($caption !== null) $caption.fadeTo(0, 1);
28485      }
28486
28487    }, this));
28488
28489    this.$gallery.css('height', '');
28490    this.$gallery.removeClass('justified-gallery');
28491    this.$gallery.data('jg.controller', undefined);
28492    this.settings.triggerEvent.call(this, 'jg.destroy');
28493  };
28494
28495  /**
28496   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
28497   *
28498   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
28499   */
28500  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
28501    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
28502      var $entry = $(this.entries[i]);
28503      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
28504        var availableWidth = this.galleryWidth - 2 * this.border - (
28505          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28506        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28507
28508        this.buildingRow.entriesBuff.push($entry);
28509        this.buildingRow.aspectRatio += imgAspectRatio;
28510        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
28511        this.lastAnalyzedIndex = i;
28512
28513        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
28514          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28515
28516          if (++this.yield.flushed >= this.yield.every) {
28517            this.startImgAnalyzer(isForResize);
28518            return;
28519          }
28520        }
28521      } else if ($entry.data('jg.loaded') !== 'error') {
28522        return;
28523      }
28524    }
28525
28526    // Last row flush (the row is not full)
28527    if (this.buildingRow.entriesBuff.length > 0) {
28528      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28529    }
28530
28531    if (this.isSpinnerActive()) {
28532      this.stopLoadingSpinnerAnimation();
28533    }
28534
28535    /* Stop, if there is, the timeout to start the analyzeImages.
28536     This is because an image can be set loaded, and the timeout can be set,
28537     but this image can be analyzed yet.
28538     */
28539    this.stopImgAnalyzerStarter();
28540
28541    this.setGalleryFinalHeight(this.galleryHeightToSet);
28542
28543    //On complete callback
28544    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
28545  };
28546
28547  /**
28548   * Stops any ImgAnalyzer starter (that has an assigned timeout)
28549   */
28550  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
28551    this.yield.flushed = 0;
28552    if (this.imgAnalyzerTimeout !== null) {
28553      clearTimeout(this.imgAnalyzerTimeout);
28554      this.imgAnalyzerTimeout = null;
28555    }
28556  };
28557
28558  /**
28559   * Starts the image analyzer. It is not immediately called to let the browser to update the view
28560   *
28561   * @param isForResize specifies if the image analyzer must be called for resizing or not
28562   */
28563  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
28564    var that = this;
28565    this.stopImgAnalyzerStarter();
28566    this.imgAnalyzerTimeout = setTimeout(function () {
28567      that.analyzeImages(isForResize);
28568    }, 0.001); // we can't start it immediately due to a IE different behaviour
28569  };
28570
28571  /**
28572   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
28573   * because some browsers, with a 404 set complete = true.
28574   *
28575   * @param imageSrc the image src to load
28576   * @param onLoad callback that is called when the image has been loaded
28577   * @param onError callback that is called in case of an error
28578   */
28579  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
28580    if (!onLoad && !onError) return;
28581
28582    var memImage = new Image();
28583    var $memImage = $(memImage);
28584    if (onLoad) {
28585      $memImage.one('load', function () {
28586        $memImage.off('load error');
28587        onLoad(memImage);
28588      });
28589    }
28590    if (onError) {
28591      $memImage.one('error', function () {
28592        $memImage.off('load error');
28593        onError(memImage);
28594      });
28595    }
28596    memImage.src = imageSrc;
28597  };
28598
28599  /**
28600   * Init of Justified Gallery controlled
28601   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
28602   */
28603  JustifiedGallery.prototype.init = function () {
28604    var imagesToLoad = false, skippedImages = false, that = this;
28605    $.each(this.entries, function (index, entry) {
28606      var $entry = $(entry);
28607      var $image = that.imgFromEntry($entry);
28608
28609      $entry.addClass('jg-entry');
28610
28611      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
28612
28613        // Link Rel global overwrite
28614        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
28615
28616        // Link Target global overwrite
28617        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
28618
28619        if ($image !== null) {
28620
28621          // Image src
28622          var imageSrc = that.extractImgSrcFromImage($image);
28623
28624          /* If we have the height and the width, we don't wait that the image is loaded,
28625             but we start directly with the justification */
28626          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
28627            var width = parseFloat($image.attr('width'));
28628            var height = parseFloat($image.attr('height'));
28629            if ($image.prop('tagName') === 'svg') {
28630              width = parseFloat($image[0].getBBox().width);
28631              height = parseFloat($image[0].getBBox().height);
28632            }
28633            if (!isNaN(width) && !isNaN(height)) {
28634              $entry.data('jg.width', width);
28635              $entry.data('jg.height', height);
28636              $entry.data('jg.loaded', 'skipped');
28637              skippedImages = true;
28638              that.startImgAnalyzer(false);
28639              return true; // continue
28640            }
28641          }
28642
28643          $entry.data('jg.loaded', false);
28644          imagesToLoad = true;
28645
28646          // Spinner start
28647          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
28648
28649          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
28650            $entry.data('jg.width', loadImg.width);
28651            $entry.data('jg.height', loadImg.height);
28652            $entry.data('jg.loaded', true);
28653            that.startImgAnalyzer(false);
28654          }, function () { // image load error
28655            $entry.data('jg.loaded', 'error');
28656            that.startImgAnalyzer(false);
28657          });
28658
28659        } else {
28660          $entry.data('jg.loaded', true);
28661          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
28662          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
28663        }
28664
28665      }
28666
28667    });
28668
28669    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
28670    this.checkWidth();
28671  };
28672
28673  /**
28674   * Checks that it is a valid number. If a string is passed it is converted to a number
28675   *
28676   * @param settingContainer the object that contains the setting (to allow the conversion)
28677   * @param settingName the setting name
28678   */
28679  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
28680    if ($.type(settingContainer[settingName]) === 'string') {
28681      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
28682    }
28683
28684    if ($.type(settingContainer[settingName]) === 'number') {
28685      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
28686    } else {
28687      throw settingName + ' must be a number';
28688    }
28689  };
28690
28691  /**
28692   * Checks the sizeRangeSuffixes and, if necessary, converts
28693   * its keys from string (e.g. old settings with 'lt100') to int.
28694   */
28695  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
28696    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
28697      throw 'sizeRangeSuffixes must be defined and must be an object';
28698    }
28699
28700    var suffixRanges = [];
28701    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28702      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
28703    }
28704
28705    var newSizeRngSuffixes = { 0: '' };
28706    for (var i = 0; i < suffixRanges.length; i++) {
28707      if ($.type(suffixRanges[i]) === 'string') {
28708        try {
28709          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
28710          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28711        } catch (e) {
28712          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
28713        }
28714      } else {
28715        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28716      }
28717    }
28718
28719    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
28720  };
28721
28722  /**
28723   * check and convert the maxRowHeight setting
28724   * requires rowHeight to be already set
28725   * TODO: should be always called when only rowHeight is changed
28726   * @return number or null
28727   */
28728  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
28729    var newMaxRowHeight = null;
28730    var rowHeight = this.settings.rowHeight;
28731
28732    if ($.type(this.settings.maxRowHeight) === 'string') {
28733      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
28734        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
28735      } else {
28736        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
28737      }
28738    } else if ($.type(this.settings.maxRowHeight) === 'number') {
28739      newMaxRowHeight = this.settings.maxRowHeight;
28740    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
28741      return null;
28742    } else {
28743      throw 'maxRowHeight must be a number or a percentage';
28744    }
28745
28746    // check if the converted value is not a number
28747    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
28748
28749    // check values, maxRowHeight must be >= rowHeight
28750    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
28751
28752    return newMaxRowHeight;
28753  };
28754
28755  /**
28756   * Checks the settings
28757   */
28758  JustifiedGallery.prototype.checkSettings = function () {
28759    this.checkSizeRangesSuffixes();
28760
28761    this.checkOrConvertNumber(this.settings, 'rowHeight');
28762    this.checkOrConvertNumber(this.settings, 'margins');
28763    this.checkOrConvertNumber(this.settings, 'border');
28764    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
28765
28766    var lastRowModes = [
28767      'justify',
28768      'nojustify',
28769      'left',
28770      'center',
28771      'right',
28772      'hide'
28773    ];
28774    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
28775      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
28776    }
28777
28778    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28779    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28780      throw 'justifyThreshold must be in the interval [0,1]';
28781    }
28782    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28783      throw 'cssAnimation must be a boolean';
28784    }
28785
28786    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28787    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28788
28789    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28790    if (this.settings.captionSettings.visibleOpacity < 0 ||
28791      this.settings.captionSettings.visibleOpacity > 1) {
28792      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28793    }
28794
28795    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28796    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28797      this.settings.captionSettings.nonVisibleOpacity > 1) {
28798      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28799    }
28800
28801    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28802    this.checkOrConvertNumber(this.settings, 'refreshTime');
28803    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28804    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28805    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28806
28807    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28808      throw 'sort must be false or a comparison function';
28809    }
28810
28811    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28812      $.type(this.settings.filter) !== 'string') {
28813      throw 'filter must be false, a string or a filter function';
28814    }
28815  };
28816
28817  /**
28818   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28819   * @returns {Array} sorted suffix ranges
28820   */
28821  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28822    var suffixRanges = [];
28823    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28824      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28825    }
28826    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28827    return suffixRanges;
28828  };
28829
28830  /**
28831   * Update the existing settings only changing some of them
28832   *
28833   * @param newSettings the new settings (or a subgroup of them)
28834   */
28835  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28836    // In this case Justified Gallery has been called again changing only some options
28837    this.settings = $.extend({}, this.settings, newSettings);
28838    this.checkSettings();
28839
28840    // As reported in the settings: negative value = same as margins, 0 = disabled
28841    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28842
28843    this.maxRowHeight = this.retrieveMaxRowHeight();
28844    this.suffixRanges = this.retrieveSuffixRanges();
28845  };
28846
28847  JustifiedGallery.prototype.defaults = {
28848    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28849        {
28850          100: '_t',  // used when longest is less than 100px
28851          240: '_m',  // used when longest is between 101px and 240px
28852          320: '_n',  // ...
28853          500: '',
28854          640: '_z',
28855          1024: '_b'  // used as else case because it is the last
28856        }
28857    */
28858    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28859    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28860    current path, width and height */
28861    rowHeight: 120, // required? required to be > 0?
28862    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28863    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28864    // can't exceed 3 * rowHeight)
28865    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28866    margins: 1,
28867    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28868
28869    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28870
28871    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28872                             * (i.e. lastRow setting is not considered) */
28873    waitThumbnailsLoad: true,
28874    captions: true,
28875    cssAnimation: true,
28876    imagesAnimationDuration: 500, // ignored with css animations
28877    captionSettings: { // ignored with css animations
28878      animationDuration: 500,
28879      visibleOpacity: 0.7,
28880      nonVisibleOpacity: 0.0
28881    },
28882    rel: null, // rewrite the rel of each analyzed links
28883    target: null, // rewrite the target of all links
28884    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28885    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28886    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28887    randomize: false,
28888    rtl: false, // right-to-left mode
28889    sort: false, /*
28890      - false: to do not sort
28891      - function: to sort them using the function as comparator (see Array.prototype.sort())
28892    */
28893    filter: false, /*
28894      - false, null or undefined: for a disabled filter
28895      - a string: an entry is kept if entry.is(filter string) returns true
28896                  see jQuery's .is() function for further information
28897      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28898                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28899    */
28900    selector: 'a', // The selector that is used to know what are the entries of the gallery
28901    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28902    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28903      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28904    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28905  };
28906
28907
28908  /**
28909   * Justified Gallery plugin for jQuery
28910   *
28911   * Events
28912   *  - jg.complete : called when all the gallery has been created
28913   *  - jg.resize : called when the gallery has been resized
28914   *  - jg.rowflush : when a new row appears
28915   *
28916   * @param arg the action (or the settings) passed when the plugin is called
28917   * @returns {*} the object itself
28918   */
28919  $.fn.justifiedGallery = function (arg) {
28920    return this.each(function (index, gallery) {
28921
28922      var $gallery = $(gallery);
28923      $gallery.addClass('justified-gallery');
28924
28925      var controller = $gallery.data('jg.controller');
28926      if (typeof controller === 'undefined') {
28927        // Create controller and assign it to the object data
28928        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28929          if (arg === 'destroy') return; // Just a call to an unexisting object
28930          throw 'The argument must be an object';
28931        }
28932        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28933        $gallery.data('jg.controller', controller);
28934      } else if (arg === 'norewind') {
28935        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28936        // ... left to be more readable
28937      } else if (arg === 'destroy') {
28938        controller.destroy();
28939        return;
28940      } else {
28941        // In this case Justified Gallery has been called again changing only some options
28942        controller.updateSettings(arg);
28943        controller.rewind();
28944      }
28945
28946      // Update the entries list
28947      if (!controller.updateEntries(arg === 'norewind')) return;
28948
28949      // Init justified gallery
28950      controller.init();
28951
28952    });
28953  };
28954
28955}));
28956
28957/*!
28958* Customized version of iScroll.js 0.0.1
28959* It fixes bugs affecting its integration with fullpage.js
28960*/
28961/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
28962(function (window, document, Math) {
28963var rAF = window.requestAnimationFrame  ||
28964    window.webkitRequestAnimationFrame  ||
28965    window.mozRequestAnimationFrame     ||
28966    window.oRequestAnimationFrame       ||
28967    window.msRequestAnimationFrame      ||
28968    function (callback) { window.setTimeout(callback, 1000 / 60); };
28969
28970var utils = (function () {
28971    var me = {};
28972
28973    var _elementStyle = document.createElement('div').style;
28974    var _vendor = (function () {
28975        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
28976            transform,
28977            i = 0,
28978            l = vendors.length;
28979
28980        for ( ; i < l; i++ ) {
28981            transform = vendors[i] + 'ransform';
28982            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
28983        }
28984
28985        return false;
vendor: 5,154 bytes, lines 28986-29138
28986    })();
28987
28988    function _prefixStyle (style) {
28989        if ( _vendor === false ) return false;
28990        if ( _vendor === '' ) return style;
28991        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
28992    }
28993
28994    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
28995
28996    me.extend = function (target, obj) {
28997        for ( var i in obj ) {
28998            target[i] = obj[i];
28999        }
29000    };
29001
29002    me.addEvent = function (el, type, fn, capture) {
29003        el.addEventListener(type, fn, !!capture);
29004    };
29005
29006    me.removeEvent = function (el, type, fn, capture) {
29007        el.removeEventListener(type, fn, !!capture);
29008    };
29009
29010    me.prefixPointerEvent = function (pointerEvent) {
29011        return window.MSPointerEvent ?
29012            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29013            pointerEvent;
29014    };
29015
29016    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29017        var distance = current - start,
29018            speed = Math.abs(distance) / time,
29019            destination,
29020            duration;
29021
29022        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29023
29024        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29025        duration = speed / deceleration;
29026
29027        if ( destination < lowerMargin ) {
29028            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29029            distance = Math.abs(destination - current);
29030            duration = distance / speed;
29031        } else if ( destination > 0 ) {
29032            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29033            distance = Math.abs(current) + destination;
29034            duration = distance / speed;
29035        }
29036
29037        return {
29038            destination: Math.round(destination),
29039            duration: duration
29040        };
29041    };
29042
29043    var _transform = _prefixStyle('transform');
29044
29045    me.extend(me, {
29046        hasTransform: _transform !== false,
29047        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29048        hasTouch: 'ontouchstart' in window,
29049        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29050        hasTransition: _prefixStyle('transition') in _elementStyle
29051    });
29052
29053    /*
29054    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29055    - galaxy S2 is ok
29056    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29057    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29058   - galaxy S3 is badAndroid (stock brower, webview)
29059     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29060   - galaxy S4 is badAndroid (stock brower, webview)
29061     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29062   - galaxy S5 is OK
29063     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29064   - galaxy S6 is OK
29065     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29066  */
29067    me.isBadAndroid = (function() {
29068        var appVersion = window.navigator.appVersion;
29069        // Android browser is not a chrome browser.
29070        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29071            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
29072            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
29073                return parseFloat(safariVersion[1]) < 535.19;
29074            } else {
29075                return true;
29076            }
29077        } else {
29078            return false;
29079        }
29080    })();
29081
29082    me.extend(me.style = {}, {
29083        transform: _transform,
29084        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
29085        transitionDuration: _prefixStyle('transitionDuration'),
29086        transitionDelay: _prefixStyle('transitionDelay'),
29087        transformOrigin: _prefixStyle('transformOrigin')
29088    });
29089
29090    me.hasClass = function (e, c) {
29091        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
29092        return re.test(e.className);
29093    };
29094
29095    me.addClass = function (e, c) {
29096        if ( me.hasClass(e, c) ) {
29097            return;
29098        }
29099
29100        var newclass = e.className.split(' ');
29101        newclass.push(c);
29102        e.className = newclass.join(' ');
29103    };
29104
29105    me.removeClass = function (e, c) {
29106        if ( !me.hasClass(e, c) ) {
29107            return;
29108        }
29109
29110        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
29111        e.className = e.className.replace(re, ' ');
29112    };
29113
29114    me.offset = function (el) {
29115        var left = -el.offsetLeft,
29116            top = -el.offsetTop;
29117
29118        // jshint -W084
29119        while (el = el.offsetParent) {
29120            left -= el.offsetLeft;
29121            top -= el.offsetTop;
29122        }
29123        // jshint +W084
29124
29125        return {
29126            left: left,
29127            top: top
29128        };
29129    };
29130
29131    me.preventDefaultException = function (el, exceptions) {
29132        for ( var i in exceptions ) {
29133            if ( exceptions[i].test(el[i]) ) {
29134                return true;
29135            }
29136        }
29137
29138        return false;
vendor: 5,660 bytes, lines 29139-29304
29139    };
29140
29141    me.extend(me.eventType = {}, {
29142        touchstart: 1,
29143        touchmove: 1,
29144        touchend: 1,
29145
29146        mousedown: 2,
29147        mousemove: 2,
29148        mouseup: 2,
29149
29150        pointerdown: 3,
29151        pointermove: 3,
29152        pointerup: 3,
29153
29154        MSPointerDown: 3,
29155        MSPointerMove: 3,
29156        MSPointerUp: 3
29157    });
29158
29159    me.extend(me.ease = {}, {
29160        quadratic: {
29161            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
29162            fn: function (k) {
29163                return k * ( 2 - k );
29164            }
29165        },
29166        circular: {
29167            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)
29168            fn: function (k) {
29169                return Math.sqrt( 1 - ( --k * k ) );
29170            }
29171        },
29172        back: {
29173            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
29174            fn: function (k) {
29175                var b = 4;
29176                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
29177            }
29178        },
29179        bounce: {
29180            style: '',
29181            fn: function (k) {
29182                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
29183                    return 7.5625 * k * k;
29184                } else if ( k < ( 2 / 2.75 ) ) {
29185                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
29186                } else if ( k < ( 2.5 / 2.75 ) ) {
29187                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
29188                } else {
29189                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
29190                }
29191            }
29192        },
29193        elastic: {
29194            style: '',
29195            fn: function (k) {
29196                var f = 0.22,
29197                    e = 0.4;
29198
29199                if ( k === 0 ) { return 0; }
29200                if ( k == 1 ) { return 1; }
29201
29202                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
29203            }
29204        }
29205    });
29206
29207    me.tap = function (e, eventName) {
29208        var ev = document.createEvent('Event');
29209        ev.initEvent(eventName, true, true);
29210        ev.pageX = e.pageX;
29211        ev.pageY = e.pageY;
29212        e.target.dispatchEvent(ev);
29213    };
29214
29215    me.click = function (e) {
29216        var target = e.target,
29217            ev;
29218
29219        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
29220            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
29221            // initMouseEvent is deprecated.
29222            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
29223            ev.initEvent('click', true, true);
29224            ev.view = e.view || window;
29225            ev.detail = 1;
29226            ev.screenX = target.screenX || 0;
29227            ev.screenY = target.screenY || 0;
29228            ev.clientX = target.clientX || 0;
29229            ev.clientY = target.clientY || 0;
29230            ev.ctrlKey = !!e.ctrlKey;
29231            ev.altKey = !!e.altKey;
29232            ev.shiftKey = !!e.shiftKey;
29233            ev.metaKey = !!e.metaKey;
29234            ev.button = 0;
29235            ev.relatedTarget = null;
29236            ev._constructed = true;
29237            target.dispatchEvent(ev);
29238        }
29239    };
29240
29241    return me;
29242})();
29243function IScroll (el, options) {
29244    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
29245    this.scroller = this.wrapper.children[0];
29246    this.scrollerStyle = this.scroller.style;       // cache style for better performance
29247
29248    this.options = {
29249
29250        resizeScrollbars: true,
29251
29252        mouseWheelSpeed: 20,
29253
29254        snapThreshold: 0.334,
29255
29256// INSERT POINT: OPTIONS
29257        disablePointer : !utils.hasPointer,
29258        disableTouch : utils.hasPointer || !utils.hasTouch,
29259        disableMouse : utils.hasPointer || utils.hasTouch,
29260        startX: 0,
29261        startY: 0,
29262        scrollY: true,
29263        directionLockThreshold: 5,
29264        momentum: true,
29265
29266        bounce: true,
29267        bounceTime: 600,
29268        bounceEasing: '',
29269
29270        preventDefault: true,
29271        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
29272
29273        HWCompositing: true,
29274        useTransition: true,
29275        useTransform: true,
29276        bindToWrapper: typeof window.onmousedown === "undefined"
29277    };
29278
29279    for ( var i in options ) {
29280        this.options[i] = options[i];
29281    }
29282
29283    // Normalize options
29284    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
29285
29286    this.options.useTransition = utils.hasTransition && this.options.useTransition;
29287    this.options.useTransform = utils.hasTransform && this.options.useTransform;
29288
29289    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
29290    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
29291
29292    // If you want eventPassthrough I have to lock one of the axes
29293    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
29294    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
29295
29296    // With eventPassthrough we also need lockDirection mechanism
29297    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
29298    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
29299
29300    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
29301
29302    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
29303
29304    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 29305-29476
29305        this.options.tap = 'tap';
29306    }
29307
29308    // https://github.com/cubiq/iscroll/issues/1029
29309    if (!this.options.useTransition && !this.options.useTransform) {
29310        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
29311            this.scrollerStyle.position = "relative";
29312        }
29313    }
29314
29315    if ( this.options.shrinkScrollbars == 'scale' ) {
29316        this.options.useTransition = false;
29317    }
29318
29319    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
29320
29321// INSERT POINT: NORMALIZATION
29322
29323    // Some defaults
29324    this.x = 0;
29325    this.y = 0;
29326    this.directionX = 0;
29327    this.directionY = 0;
29328    this._events = {};
29329
29330// INSERT POINT: DEFAULTS
29331
29332    this._init();
29333    this.refresh();
29334
29335    this.scrollTo(this.options.startX, this.options.startY);
29336    this.enable();
29337}
29338
29339IScroll.prototype = {
29340    version: '5.2.0',
29341
29342    _init: function () {
29343        this._initEvents();
29344
29345        if ( this.options.scrollbars || this.options.indicators ) {
29346            this._initIndicators();
29347        }
29348
29349        if ( this.options.mouseWheel ) {
29350            this._initWheel();
29351        }
29352
29353        if ( this.options.snap ) {
29354            this._initSnap();
29355        }
29356
29357        if ( this.options.keyBindings ) {
29358            this._initKeys();
29359        }
29360
29361// INSERT POINT: _init
29362
29363    },
29364
29365    destroy: function () {
29366        this._initEvents(true);
29367        clearTimeout(this.resizeTimeout);
29368        this.resizeTimeout = null;
29369        this._execEvent('destroy');
29370    },
29371
29372    _transitionEnd: function (e) {
29373        if ( e.target != this.scroller || !this.isInTransition ) {
29374            return;
29375        }
29376
29377        this._transitionTime();
29378        if ( !this.resetPosition(this.options.bounceTime) ) {
29379            this.isInTransition = false;
29380            this._execEvent('scrollEnd');
29381        }
29382    },
29383
29384    _start: function (e) {
29385        // React to left mouse button only
29386        if ( utils.eventType[e.type] != 1 ) {
29387          // for button property
29388          // http://unixpapa.com/js/mouse.html
29389          var button;
29390        if (!e.which) {
29391          /* IE case */
29392          button = (e.button < 2) ? 0 :
29393                   ((e.button == 4) ? 1 : 2);
29394        } else {
29395          /* All others */
29396          button = e.button;
29397        }
29398            if ( button !== 0 ) {
29399                return;
29400            }
29401        }
29402
29403        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
29404            return;
29405        }
29406
29407        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29408            e.preventDefault();
29409        }
29410
29411        var point = e.touches ? e.touches[0] : e,
29412            pos;
29413
29414        this.initiated  = utils.eventType[e.type];
29415        this.moved      = false;
29416        this.distX      = 0;
29417        this.distY      = 0;
29418        this.directionX = 0;
29419        this.directionY = 0;
29420        this.directionLocked = 0;
29421
29422        this.startTime = utils.getTime();
29423
29424        if ( this.options.useTransition && this.isInTransition ) {
29425            this._transitionTime();
29426            this.isInTransition = false;
29427            pos = this.getComputedPosition();
29428            this._translate(Math.round(pos.x), Math.round(pos.y));
29429            this._execEvent('scrollEnd');
29430        } else if ( !this.options.useTransition && this.isAnimating ) {
29431            this.isAnimating = false;
29432            this._execEvent('scrollEnd');
29433        }
29434
29435        this.startX    = this.x;
29436        this.startY    = this.y;
29437        this.absStartX = this.x;
29438        this.absStartY = this.y;
29439        this.pointX    = point.pageX;
29440        this.pointY    = point.pageY;
29441
29442        this._execEvent('beforeScrollStart');
29443    },
29444
29445    _move: function (e) {
29446        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29447            return;
29448        }
29449
29450        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
29451            e.preventDefault();
29452        }
29453
29454        var point       = e.touches ? e.touches[0] : e,
29455            deltaX      = point.pageX - this.pointX,
29456            deltaY      = point.pageY - this.pointY,
29457            timestamp   = utils.getTime(),
29458            newX, newY,
29459            absDistX, absDistY;
29460
29461        this.pointX     = point.pageX;
29462        this.pointY     = point.pageY;
29463
29464        this.distX      += deltaX;
29465        this.distY      += deltaY;
29466        absDistX        = Math.abs(this.distX);
29467        absDistY        = Math.abs(this.distY);
29468
29469        // We need to move at least 10 pixels for the scrolling to initiate
29470        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
29471            return;
29472        }
29473
29474        // If you are scrolling in one direction lock the other
29475        if ( !this.directionLocked && !this.options.freeScroll ) {
29476            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 29477-29663
29477                this.directionLocked = 'h';     // lock horizontally
29478            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
29479                this.directionLocked = 'v';     // lock vertically
29480            } else {
29481                this.directionLocked = 'n';     // no lock
29482            }
29483        }
29484
29485        if ( this.directionLocked == 'h' ) {
29486            if ( this.options.eventPassthrough == 'vertical' ) {
29487                e.preventDefault();
29488            } else if ( this.options.eventPassthrough == 'horizontal' ) {
29489                this.initiated = false;
29490                return;
29491            }
29492
29493            deltaY = 0;
29494        } else if ( this.directionLocked == 'v' ) {
29495            if ( this.options.eventPassthrough == 'horizontal' ) {
29496                e.preventDefault();
29497            } else if ( this.options.eventPassthrough == 'vertical' ) {
29498                this.initiated = false;
29499                return;
29500            }
29501
29502            deltaX = 0;
29503        }
29504
29505        deltaX = this.hasHorizontalScroll ? deltaX : 0;
29506        deltaY = this.hasVerticalScroll ? deltaY : 0;
29507
29508        newX = this.x + deltaX;
29509        newY = this.y + deltaY;
29510
29511        // Slow down if outside of the boundaries
29512        if ( newX > 0 || newX < this.maxScrollX ) {
29513            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
29514        }
29515        if ( newY > 0 || newY < this.maxScrollY ) {
29516            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
29517        }
29518
29519        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
29520        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
29521
29522        if ( !this.moved ) {
29523            this._execEvent('scrollStart');
29524        }
29525
29526        this.moved = true;
29527
29528        this._translate(newX, newY);
29529
29530/* REPLACE START: _move */
29531
29532        if ( timestamp - this.startTime > 300 ) {
29533            this.startTime = timestamp;
29534            this.startX = this.x;
29535            this.startY = this.y;
29536        }
29537
29538/* REPLACE END: _move */
29539
29540    },
29541
29542    _end: function (e) {
29543        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29544            return;
29545        }
29546
29547        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29548            e.preventDefault();
29549        }
29550
29551        var point = e.changedTouches ? e.changedTouches[0] : e,
29552            momentumX,
29553            momentumY,
29554            duration = utils.getTime() - this.startTime,
29555            newX = Math.round(this.x),
29556            newY = Math.round(this.y),
29557            distanceX = Math.abs(newX - this.startX),
29558            distanceY = Math.abs(newY - this.startY),
29559            time = 0,
29560            easing = '';
29561
29562        this.isInTransition = 0;
29563        this.initiated = 0;
29564        this.endTime = utils.getTime();
29565
29566        // reset if we are outside of the boundaries
29567        if ( this.resetPosition(this.options.bounceTime) ) {
29568            return;
29569        }
29570
29571        this.scrollTo(newX, newY);  // ensures that the last position is rounded
29572
29573        // we scrolled less than 10 pixels
29574        if ( !this.moved ) {
29575            if ( this.options.tap ) {
29576                utils.tap(e, this.options.tap);
29577            }
29578
29579            if ( this.options.click ) {
29580                utils.click(e);
29581            }
29582
29583            this._execEvent('scrollCancel');
29584            return;
29585        }
29586
29587        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
29588            this._execEvent('flick');
29589            return;
29590        }
29591
29592        // start momentum animation if needed
29593        if ( this.options.momentum && duration < 300 ) {
29594            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 };
29595            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 };
29596            newX = momentumX.destination;
29597            newY = momentumY.destination;
29598            time = Math.max(momentumX.duration, momentumY.duration);
29599            this.isInTransition = 1;
29600        }
29601
29602
29603        if ( this.options.snap ) {
29604            var snap = this._nearestSnap(newX, newY);
29605            this.currentPage = snap;
29606            time = this.options.snapSpeed || Math.max(
29607                    Math.max(
29608                        Math.min(Math.abs(newX - snap.x), 1000),
29609                        Math.min(Math.abs(newY - snap.y), 1000)
29610                    ), 300);
29611            newX = snap.x;
29612            newY = snap.y;
29613
29614            this.directionX = 0;
29615            this.directionY = 0;
29616            easing = this.options.bounceEasing;
29617        }
29618
29619// INSERT POINT: _end
29620
29621        if ( newX != this.x || newY != this.y ) {
29622            // change easing function when scroller goes out of the boundaries
29623            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
29624                easing = utils.ease.quadratic;
29625            }
29626
29627            this.scrollTo(newX, newY, time, easing);
29628            return;
29629        }
29630
29631        this._execEvent('scrollEnd');
29632    },
29633
29634    _resize: function () {
29635        var that = this;
29636
29637        clearTimeout(this.resizeTimeout);
29638
29639        this.resizeTimeout = setTimeout(function () {
29640            that.refresh();
29641        }, this.options.resizePolling);
29642    },
29643
29644    resetPosition: function (time) {
29645        var x = this.x,
29646            y = this.y;
29647
29648        time = time || 0;
29649
29650        if ( !this.hasHorizontalScroll || this.x > 0 ) {
29651            x = 0;
29652        } else if ( this.x < this.maxScrollX ) {
29653            x = this.maxScrollX;
29654        }
29655
29656        if ( !this.hasVerticalScroll || this.y > 0 ) {
29657            y = 0;
29658        } else if ( this.y < this.maxScrollY ) {
29659            y = this.maxScrollY;
29660        }
29661
29662        if ( x == this.x && y == this.y ) {
29663            return false;
vendor: 5,509 bytes, lines 29664-29868
29664        }
29665
29666        this.scrollTo(x, y, time, this.options.bounceEasing);
29667
29668        return true;
29669    },
29670
29671    disable: function () {
29672        this.enabled = false;
29673    },
29674
29675    enable: function () {
29676        this.enabled = true;
29677    },
29678
29679    refresh: function () {
29680        var rf = this.wrapper.offsetHeight;     // Force reflow
29681
29682        this.wrapperWidth   = this.wrapper.clientWidth;
29683        this.wrapperHeight  = this.wrapper.clientHeight;
29684
29685/* REPLACE START: refresh */
29686
29687        this.scrollerWidth  = this.scroller.offsetWidth;
29688        this.scrollerHeight = this.scroller.offsetHeight;
29689
29690        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
29691        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
29692
29693/* REPLACE END: refresh */
29694
29695        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
29696        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
29697
29698        if ( !this.hasHorizontalScroll ) {
29699            this.maxScrollX = 0;
29700            this.scrollerWidth = this.wrapperWidth;
29701        }
29702
29703        if ( !this.hasVerticalScroll ) {
29704            this.maxScrollY = 0;
29705            this.scrollerHeight = this.wrapperHeight;
29706        }
29707
29708        this.endTime = 0;
29709        this.directionX = 0;
29710        this.directionY = 0;
29711
29712        this.wrapperOffset = utils.offset(this.wrapper);
29713
29714        this._execEvent('refresh');
29715
29716        this.resetPosition();
29717
29718// INSERT POINT: _refresh
29719
29720    },
29721
29722
29723    on: function (type, fn) {
29724        if ( !this._events[type] ) {
29725            this._events[type] = [];
29726        }
29727
29728        this._events[type].push(fn);
29729    },
29730
29731    off: function (type, fn) {
29732        if ( !this._events[type] ) {
29733            return;
29734        }
29735
29736        var index = this._events[type].indexOf(fn);
29737
29738        if ( index > -1 ) {
29739            this._events[type].splice(index, 1);
29740        }
29741    },
29742
29743    _execEvent: function (type) {
29744        if ( !this._events[type] ) {
29745            return;
29746        }
29747
29748        var i = 0,
29749            l = this._events[type].length;
29750
29751        if ( !l ) {
29752            return;
29753        }
29754
29755        for ( ; i < l; i++ ) {
29756            this._events[type][i].apply(this, [].slice.call(arguments, 1));
29757        }
29758    },
29759
29760    scrollBy: function (x, y, time, easing) {
29761        x = this.x + x;
29762        y = this.y + y;
29763        time = time || 0;
29764
29765        this.scrollTo(x, y, time, easing);
29766    },
29767
29768    scrollTo: function (x, y, time, easing) {
29769        easing = easing || utils.ease.circular;
29770
29771        this.isInTransition = this.options.useTransition && time > 0;
29772        var transitionType = this.options.useTransition && easing.style;
29773        if ( !time || transitionType ) {
29774                if(transitionType) {
29775                    this._transitionTimingFunction(easing.style);
29776                    this._transitionTime(time);
29777                }
29778            this._translate(x, y);
29779        } else {
29780            this._animate(x, y, time, easing.fn);
29781        }
29782    },
29783
29784    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29785        el = el.nodeType ? el : this.scroller.querySelector(el);
29786
29787        if ( !el ) {
29788            return;
29789        }
29790
29791        var pos = utils.offset(el);
29792
29793        pos.left -= this.wrapperOffset.left;
29794        pos.top  -= this.wrapperOffset.top;
29795
29796        // if offsetX/Y are true we center the element to the screen
29797        if ( offsetX === true ) {
29798            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29799        }
29800        if ( offsetY === true ) {
29801            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29802        }
29803
29804        pos.left -= offsetX || 0;
29805        pos.top  -= offsetY || 0;
29806
29807        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29808        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29809
29810        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29811
29812        this.scrollTo(pos.left, pos.top, time, easing);
29813    },
29814
29815    _transitionTime: function (time) {
29816        if (!this.options.useTransition) {
29817            return;
29818        }
29819        time = time || 0;
29820        var durationProp = utils.style.transitionDuration;
29821        if(!durationProp) {
29822            return;
29823        }
29824
29825        this.scrollerStyle[durationProp] = time + 'ms';
29826
29827        if ( !time && utils.isBadAndroid ) {
29828            this.scrollerStyle[durationProp] = '0.0001ms';
29829            // remove 0.0001ms
29830            var self = this;
29831            rAF(function() {
29832                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29833                    self.scrollerStyle[durationProp] = '0s';
29834                }
29835            });
29836        }
29837
29838
29839        if ( this.indicators ) {
29840            for ( var i = this.indicators.length; i--; ) {
29841                this.indicators[i].transitionTime(time);
29842            }
29843        }
29844
29845
29846// INSERT POINT: _transitionTime
29847
29848    },
29849
29850    _transitionTimingFunction: function (easing) {
29851        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29852
29853
29854        if ( this.indicators ) {
29855            for ( var i = this.indicators.length; i--; ) {
29856                this.indicators[i].transitionTimingFunction(easing);
29857            }
29858        }
29859
29860
29861// INSERT POINT: _transitionTimingFunction
29862
29863    },
29864
29865    _translate: function (x, y) {
29866        //Uncode addition
29867        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29868            return false;
vendor: 9,939 bytes, lines 29869-30180
29869
29870        if ( this.options.useTransform ) {
29871
29872/* REPLACE START: _translate */
29873
29874            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29875
29876/* REPLACE END: _translate */
29877
29878        } else {
29879            x = Math.round(x);
29880            y = Math.round(y);
29881            this.scrollerStyle.left = x + 'px';
29882            this.scrollerStyle.top = y + 'px';
29883        }
29884
29885        this.x = x;
29886        this.y = y;
29887
29888
29889        if ( this.indicators ) {
29890            for ( var i = this.indicators.length; i--; ) {
29891                this.indicators[i].updatePosition();
29892            }
29893        }
29894
29895        //Uncode addition
29896        var uncodevent = new CustomEvent('fp-slide-scroll');
29897        window.dispatchEvent(uncodevent);
29898
29899// INSERT POINT: _translate
29900
29901    },
29902
29903    _initEvents: function (remove) {
29904        var eventType = remove ? utils.removeEvent : utils.addEvent,
29905            target = this.options.bindToWrapper ? this.wrapper : window;
29906
29907        eventType(window, 'orientationchange', this);
29908        eventType(window, 'resize', this);
29909
29910        if ( this.options.click ) {
29911            eventType(this.wrapper, 'click', this, true);
29912        }
29913
29914        if ( !this.options.disableMouse ) {
29915            eventType(this.wrapper, 'mousedown', this);
29916            eventType(target, 'mousemove', this);
29917            eventType(target, 'mousecancel', this);
29918            eventType(target, 'mouseup', this);
29919        }
29920
29921        if ( utils.hasPointer && !this.options.disablePointer ) {
29922            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29923            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29924            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29925            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29926        }
29927
29928        if ( utils.hasTouch && !this.options.disableTouch ) {
29929            eventType(this.wrapper, 'touchstart', this);
29930            eventType(target, 'touchmove', this);
29931            eventType(target, 'touchcancel', this);
29932            eventType(target, 'touchend', this);
29933        }
29934
29935        eventType(this.scroller, 'transitionend', this);
29936        eventType(this.scroller, 'webkitTransitionEnd', this);
29937        eventType(this.scroller, 'oTransitionEnd', this);
29938        eventType(this.scroller, 'MSTransitionEnd', this);
29939    },
29940
29941    getComputedPosition: function () {
29942        var matrix = window.getComputedStyle(this.scroller, null),
29943            x, y;
29944
29945        if ( this.options.useTransform ) {
29946            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29947            x = +(matrix[12] || matrix[4]);
29948            y = +(matrix[13] || matrix[5]);
29949        } else {
29950            x = +matrix.left.replace(/[^-\d.]/g, '');
29951            y = +matrix.top.replace(/[^-\d.]/g, '');
29952        }
29953
29954        return { x: x, y: y };
29955    },
29956    _initIndicators: function () {
29957        var interactive = this.options.interactiveScrollbars,
29958            customStyle = typeof this.options.scrollbars != 'string',
29959            indicators = [],
29960            indicator;
29961
29962        var that = this;
29963
29964        this.indicators = [];
29965
29966        if ( this.options.scrollbars ) {
29967            // Vertical scrollbar
29968            if ( this.options.scrollY ) {
29969                indicator = {
29970                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
29971                    interactive: interactive,
29972                    defaultScrollbars: true,
29973                    customStyle: customStyle,
29974                    resize: this.options.resizeScrollbars,
29975                    shrink: this.options.shrinkScrollbars,
29976                    fade: this.options.fadeScrollbars,
29977                    listenX: false
29978                };
29979
29980                this.wrapper.appendChild(indicator.el);
29981                indicators.push(indicator);
29982            }
29983
29984            // Horizontal scrollbar
29985            if ( this.options.scrollX ) {
29986                indicator = {
29987                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
29988                    interactive: interactive,
29989                    defaultScrollbars: true,
29990                    customStyle: customStyle,
29991                    resize: this.options.resizeScrollbars,
29992                    shrink: this.options.shrinkScrollbars,
29993                    fade: this.options.fadeScrollbars,
29994                    listenY: false
29995                };
29996
29997                this.wrapper.appendChild(indicator.el);
29998                indicators.push(indicator);
29999            }
30000        }
30001
30002        if ( this.options.indicators ) {
30003            // TODO: check concat compatibility
30004            indicators = indicators.concat(this.options.indicators);
30005        }
30006
30007        for ( var i = indicators.length; i--; ) {
30008            this.indicators.push( new Indicator(this, indicators[i]) );
30009        }
30010
30011        // TODO: check if we can use array.map (wide compatibility and performance issues)
30012        function _indicatorsMap (fn) {
30013            if (that.indicators) {
30014                for ( var i = that.indicators.length; i--; ) {
30015                    fn.call(that.indicators[i]);
30016                }
30017            }
30018        }
30019
30020        if ( this.options.fadeScrollbars ) {
30021            this.on('scrollEnd', function () {
30022                _indicatorsMap(function () {
30023                    this.fade();
30024                });
30025            });
30026
30027            this.on('scrollCancel', function () {
30028                _indicatorsMap(function () {
30029                    this.fade();
30030                });
30031            });
30032
30033            this.on('scrollStart', function () {
30034                _indicatorsMap(function () {
30035                    this.fade(1);
30036                });
30037            });
30038
30039            this.on('beforeScrollStart', function () {
30040                _indicatorsMap(function () {
30041                    this.fade(1, true);
30042                });
30043            });
30044        }
30045
30046
30047        this.on('refresh', function () {
30048            _indicatorsMap(function () {
30049                this.refresh();
30050            });
30051        });
30052
30053        this.on('destroy', function () {
30054            _indicatorsMap(function () {
30055                this.destroy();
30056            });
30057
30058            delete this.indicators;
30059        });
30060    },
30061
30062    _initWheel: function () {
30063        utils.addEvent(this.wrapper, 'wheel', this);
30064        utils.addEvent(this.wrapper, 'mousewheel', this);
30065        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30066
30067        this.on('destroy', function () {
30068            clearTimeout(this.wheelTimeout);
30069            this.wheelTimeout = null;
30070            utils.removeEvent(this.wrapper, 'wheel', this);
30071            utils.removeEvent(this.wrapper, 'mousewheel', this);
30072            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
30073        });
30074    },
30075
30076    _wheel: function (e) {
30077        if ( !this.enabled ) {
30078            return;
30079        }
30080
30081        var wheelDeltaX, wheelDeltaY,
30082            newX, newY,
30083            that = this;
30084
30085        if ( this.wheelTimeout === undefined ) {
30086            that._execEvent('scrollStart');
30087        }
30088
30089        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
30090        clearTimeout(this.wheelTimeout);
30091        this.wheelTimeout = setTimeout(function () {
30092            if(!that.options.snap) {
30093                that._execEvent('scrollEnd');
30094            }
30095            that.wheelTimeout = undefined;
30096        }, 400);
30097
30098        if ( 'deltaX' in e ) {
30099            if (e.deltaMode === 1) {
30100                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
30101                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
30102            } else {
30103                wheelDeltaX = -e.deltaX;
30104                wheelDeltaY = -e.deltaY;
30105            }
30106        } else if ( 'wheelDeltaX' in e ) {
30107            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
30108            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
30109        } else if ( 'wheelDelta' in e ) {
30110            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
30111        } else if ( 'detail' in e ) {
30112            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
30113        } else {
30114            return;
30115        }
30116
30117        wheelDeltaX *= this.options.invertWheelDirection;
30118        wheelDeltaY *= this.options.invertWheelDirection;
30119
30120        if ( !this.hasVerticalScroll ) {
30121            wheelDeltaX = wheelDeltaY;
30122            wheelDeltaY = 0;
30123        }
30124
30125        if ( this.options.snap ) {
30126            newX = this.currentPage.pageX;
30127            newY = this.currentPage.pageY;
30128
30129            if ( wheelDeltaX > 0 ) {
30130                newX--;
30131            } else if ( wheelDeltaX < 0 ) {
30132                newX++;
30133            }
30134
30135            if ( wheelDeltaY > 0 ) {
30136                newY--;
30137            } else if ( wheelDeltaY < 0 ) {
30138                newY++;
30139            }
30140
30141            this.goToPage(newX, newY);
30142
30143            return;
30144        }
30145
30146        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
30147        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
30148
30149        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
30150        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
30151
30152        if ( newX > 0 ) {
30153            newX = 0;
30154        } else if ( newX < this.maxScrollX ) {
30155            newX = this.maxScrollX;
30156        }
30157
30158        if ( newY > 0 ) {
30159            newY = 0;
30160        } else if ( newY < this.maxScrollY ) {
30161            newY = this.maxScrollY;
30162        }
30163
30164        this.scrollTo(newX, newY, 0);
30165
30166// INSERT POINT: _wheel
30167    },
30168
30169    _initSnap: function () {
30170        this.currentPage = {};
30171
30172        if ( typeof this.options.snap == 'string' ) {
30173            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
30174        }
30175
30176        this.on('refresh', function () {
30177            var i = 0, l,
30178                m = 0, n,
30179                cx, cy,
30180                x = 0, y,
vendor: 7,339 bytes, lines 30181-30434
30181                stepX = this.options.snapStepX || this.wrapperWidth,
30182                stepY = this.options.snapStepY || this.wrapperHeight,
30183                el;
30184
30185            this.pages = [];
30186
30187            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
30188                return;
30189            }
30190
30191            if ( this.options.snap === true ) {
30192                cx = Math.round( stepX / 2 );
30193                cy = Math.round( stepY / 2 );
30194
30195                while ( x > -this.scrollerWidth ) {
30196                    this.pages[i] = [];
30197                    l = 0;
30198                    y = 0;
30199
30200                    while ( y > -this.scrollerHeight ) {
30201                        this.pages[i][l] = {
30202                            x: Math.max(x, this.maxScrollX),
30203                            y: Math.max(y, this.maxScrollY),
30204                            width: stepX,
30205                            height: stepY,
30206                            cx: x - cx,
30207                            cy: y - cy
30208                        };
30209
30210                        y -= stepY;
30211                        l++;
30212                    }
30213
30214                    x -= stepX;
30215                    i++;
30216                }
30217            } else {
30218                el = this.options.snap;
30219                l = el.length;
30220                n = -1;
30221
30222                for ( ; i < l; i++ ) {
30223                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
30224                        m = 0;
30225                        n++;
30226                    }
30227
30228                    if ( !this.pages[m] ) {
30229                        this.pages[m] = [];
30230                    }
30231
30232                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
30233                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
30234                    cx = x - Math.round(el[i].offsetWidth / 2);
30235                    cy = y - Math.round(el[i].offsetHeight / 2);
30236
30237                    this.pages[m][n] = {
30238                        x: x,
30239                        y: y,
30240                        width: el[i].offsetWidth,
30241                        height: el[i].offsetHeight,
30242                        cx: cx,
30243                        cy: cy
30244                    };
30245
30246                    if ( x > this.maxScrollX ) {
30247                        m++;
30248                    }
30249                }
30250            }
30251
30252            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
30253
30254            // Update snap threshold if needed
30255            if ( this.options.snapThreshold % 1 === 0 ) {
30256                this.snapThresholdX = this.options.snapThreshold;
30257                this.snapThresholdY = this.options.snapThreshold;
30258            } else {
30259                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
30260                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
30261            }
30262        });
30263
30264        this.on('flick', function () {
30265            var time = this.options.snapSpeed || Math.max(
30266                    Math.max(
30267                        Math.min(Math.abs(this.x - this.startX), 1000),
30268                        Math.min(Math.abs(this.y - this.startY), 1000)
30269                    ), 300);
30270
30271            this.goToPage(
30272                this.currentPage.pageX + this.directionX,
30273                this.currentPage.pageY + this.directionY,
30274                time
30275            );
30276        });
30277    },
30278
30279    _nearestSnap: function (x, y) {
30280        if ( !this.pages.length ) {
30281            return { x: 0, y: 0, pageX: 0, pageY: 0 };
30282        }
30283
30284        var i = 0,
30285            l = this.pages.length,
30286            m = 0;
30287
30288        // Check if we exceeded the snap threshold
30289        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
30290            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
30291            return this.currentPage;
30292        }
30293
30294        if ( x > 0 ) {
30295            x = 0;
30296        } else if ( x < this.maxScrollX ) {
30297            x = this.maxScrollX;
30298        }
30299
30300        if ( y > 0 ) {
30301            y = 0;
30302        } else if ( y < this.maxScrollY ) {
30303            y = this.maxScrollY;
30304        }
30305
30306        for ( ; i < l; i++ ) {
30307            if ( x >= this.pages[i][0].cx ) {
30308                x = this.pages[i][0].x;
30309                break;
30310            }
30311        }
30312
30313        l = this.pages[i].length;
30314
30315        for ( ; m < l; m++ ) {
30316            if ( y >= this.pages[0][m].cy ) {
30317                y = this.pages[0][m].y;
30318                break;
30319            }
30320        }
30321
30322        if ( i == this.currentPage.pageX ) {
30323            i += this.directionX;
30324
30325            if ( i < 0 ) {
30326                i = 0;
30327            } else if ( i >= this.pages.length ) {
30328                i = this.pages.length - 1;
30329            }
30330
30331            x = this.pages[i][0].x;
30332        }
30333
30334        if ( m == this.currentPage.pageY ) {
30335            m += this.directionY;
30336
30337            if ( m < 0 ) {
30338                m = 0;
30339            } else if ( m >= this.pages[0].length ) {
30340                m = this.pages[0].length - 1;
30341            }
30342
30343            y = this.pages[0][m].y;
30344        }
30345
30346        return {
30347            x: x,
30348            y: y,
30349            pageX: i,
30350            pageY: m
30351        };
30352    },
30353
30354    goToPage: function (x, y, time, easing) {
30355        easing = easing || this.options.bounceEasing;
30356
30357        if ( x >= this.pages.length ) {
30358            x = this.pages.length - 1;
30359        } else if ( x < 0 ) {
30360            x = 0;
30361        }
30362
30363        if ( y >= this.pages[x].length ) {
30364            y = this.pages[x].length - 1;
30365        } else if ( y < 0 ) {
30366            y = 0;
30367        }
30368
30369        var posX = this.pages[x][y].x,
30370            posY = this.pages[x][y].y;
30371
30372        time = time === undefined ? this.options.snapSpeed || Math.max(
30373            Math.max(
30374                Math.min(Math.abs(posX - this.x), 1000),
30375                Math.min(Math.abs(posY - this.y), 1000)
30376            ), 300) : time;
30377
30378        this.currentPage = {
30379            x: posX,
30380            y: posY,
30381            pageX: x,
30382            pageY: y
30383        };
30384
30385        this.scrollTo(posX, posY, time, easing);
30386    },
30387
30388    next: function (time, easing) {
30389        var x = this.currentPage.pageX,
30390            y = this.currentPage.pageY;
30391
30392        x++;
30393
30394        if ( x >= this.pages.length && this.hasVerticalScroll ) {
30395            x = 0;
30396            y++;
30397        }
30398
30399        this.goToPage(x, y, time, easing);
30400    },
30401
30402    prev: function (time, easing) {
30403        var x = this.currentPage.pageX,
30404            y = this.currentPage.pageY;
30405
30406        x--;
30407
30408        if ( x < 0 && this.hasVerticalScroll ) {
30409            x = 0;
30410            y--;
30411        }
30412
30413        this.goToPage(x, y, time, easing);
30414    },
30415
30416    _initKeys: function (e) {
30417        // default key bindings
30418        var keys = {
30419            pageUp: 33,
30420            pageDown: 34,
30421            end: 35,
30422            home: 36,
30423            left: 37,
30424            up: 38,
30425            right: 39,
30426            down: 40
30427        };
30428        var i;
30429
30430        // if you give me characters I give you keycode
30431        if ( typeof this.options.keyBindings == 'object' ) {
30432            for ( i in this.options.keyBindings ) {
30433                if ( typeof this.options.keyBindings[i] == 'string' ) {
30434                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 30434-30787
30434deAt(0);
30435                }
30436            }
30437        } else {
30438            this.options.keyBindings = {};
30439        }
30440
30441        for ( i in keys ) {
30442            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
30443        }
30444
30445        utils.addEvent(window, 'keydown', this);
30446
30447        this.on('destroy', function () {
30448            utils.removeEvent(window, 'keydown', this);
30449        });
30450    },
30451
30452    _key: function (e) {
30453        if ( !this.enabled ) {
30454            return;
30455        }
30456
30457        var snap = this.options.snap,   // we are using this alot, better to cache it
30458            newX = snap ? this.currentPage.pageX : this.x,
30459            newY = snap ? this.currentPage.pageY : this.y,
30460            now = utils.getTime(),
30461            prevTime = this.keyTime || 0,
30462            acceleration = 0.250,
30463            pos;
30464
30465        if ( this.options.useTransition && this.isInTransition ) {
30466            pos = this.getComputedPosition();
30467
30468            this._translate(Math.round(pos.x), Math.round(pos.y));
30469            this.isInTransition = false;
30470        }
30471
30472        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
30473
30474        switch ( e.keyCode ) {
30475            case this.options.keyBindings.pageUp:
30476                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30477                    newX += snap ? 1 : this.wrapperWidth;
30478                } else {
30479                    newY += snap ? 1 : this.wrapperHeight;
30480                }
30481                break;
30482            case this.options.keyBindings.pageDown:
30483                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30484                    newX -= snap ? 1 : this.wrapperWidth;
30485                } else {
30486                    newY -= snap ? 1 : this.wrapperHeight;
30487                }
30488                break;
30489            case this.options.keyBindings.end:
30490                newX = snap ? this.pages.length-1 : this.maxScrollX;
30491                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
30492                break;
30493            case this.options.keyBindings.home:
30494                newX = 0;
30495                newY = 0;
30496                break;
30497            case this.options.keyBindings.left:
30498                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
30499                break;
30500            case this.options.keyBindings.up:
30501                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
30502                break;
30503            case this.options.keyBindings.right:
30504                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
30505                break;
30506            case this.options.keyBindings.down:
30507                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
30508                break;
30509            default:
30510                return;
30511        }
30512
30513        if ( snap ) {
30514            this.goToPage(newX, newY);
30515            return;
30516        }
30517
30518        if ( newX > 0 ) {
30519            newX = 0;
30520            this.keyAcceleration = 0;
30521        } else if ( newX < this.maxScrollX ) {
30522            newX = this.maxScrollX;
30523            this.keyAcceleration = 0;
30524        }
30525
30526        if ( newY > 0 ) {
30527            newY = 0;
30528            this.keyAcceleration = 0;
30529        } else if ( newY < this.maxScrollY ) {
30530            newY = this.maxScrollY;
30531            this.keyAcceleration = 0;
30532        }
30533
30534        this.scrollTo(newX, newY, 0);
30535
30536        this.keyTime = now;
30537    },
30538
30539    _animate: function (destX, destY, duration, easingFn) {
30540        var that = this,
30541            startX = this.x,
30542            startY = this.y,
30543            startTime = utils.getTime(),
30544            destTime = startTime + duration;
30545
30546        function step () {
30547            var now = utils.getTime(),
30548                newX, newY,
30549                easing;
30550
30551            if ( now >= destTime ) {
30552                that.isAnimating = false;
30553                that._translate(destX, destY);
30554
30555                if ( !that.resetPosition(that.options.bounceTime) ) {
30556                    that._execEvent('scrollEnd');
30557                }
30558
30559                return;
30560            }
30561
30562            now = ( now - startTime ) / duration;
30563            easing = easingFn(now);
30564            newX = ( destX - startX ) * easing + startX;
30565            newY = ( destY - startY ) * easing + startY;
30566            that._translate(newX, newY);
30567
30568            if ( that.isAnimating ) {
30569                rAF(step);
30570            }
30571        }
30572
30573        this.isAnimating = true;
30574        step();
30575    },
30576    handleEvent: function (e) {
30577        switch ( e.type ) {
30578            case 'touchstart':
30579            case 'pointerdown':
30580            case 'MSPointerDown':
30581            case 'mousedown':
30582                this._start(e);
30583                break;
30584            case 'touchmove':
30585            case 'pointermove':
30586            case 'MSPointerMove':
30587            case 'mousemove':
30588                this._move(e);
30589                break;
30590            case 'touchend':
30591            case 'pointerup':
30592            case 'MSPointerUp':
30593            case 'mouseup':
30594            case 'touchcancel':
30595            case 'pointercancel':
30596            case 'MSPointerCancel':
30597            case 'mousecancel':
30598                this._end(e);
30599                break;
30600            case 'orientationchange':
30601            case 'resize':
30602                this._resize();
30603                break;
30604            case 'transitionend':
30605            case 'webkitTransitionEnd':
30606            case 'oTransitionEnd':
30607            case 'MSTransitionEnd':
30608                this._transitionEnd(e);
30609                break;
30610            case 'wheel':
30611            case 'DOMMouseScroll':
30612            case 'mousewheel':
30613                this._wheel(e);
30614                break;
30615            case 'keydown':
30616                this._key(e);
30617                break;
30618            case 'click':
30619                if ( this.enabled && !e._constructed ) {
30620                    e.preventDefault();
30621                    e.stopPropagation();
30622                }
30623                break;
30624        }
30625    }
30626};
30627function createDefaultScrollbar (direction, interactive, type) {
30628    var scrollbar = document.createElement('div'),
30629        indicator = document.createElement('div');
30630
30631    if ( type === true ) {
30632        scrollbar.style.cssText = 'position:absolute;z-index:9999';
30633        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';
30634    }
30635
30636    indicator.className = 'iScrollIndicator';
30637
30638    if ( direction == 'h' ) {
30639        if ( type === true ) {
30640            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
30641            indicator.style.height = '100%';
30642        }
30643        scrollbar.className = 'iScrollHorizontalScrollbar';
30644    } else {
30645        if ( type === true ) {
30646            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
30647            indicator.style.width = '100%';
30648        }
30649        scrollbar.className = 'iScrollVerticalScrollbar';
30650    }
30651
30652    scrollbar.style.cssText += ';overflow:hidden';
30653
30654    if ( !interactive ) {
30655        scrollbar.style.pointerEvents = 'none';
30656    }
30657
30658    scrollbar.appendChild(indicator);
30659
30660    return scrollbar;
30661}
30662
30663function Indicator (scroller, options) {
30664    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
30665    this.wrapperStyle = this.wrapper.style;
30666    this.indicator = this.wrapper.children[0];
30667    this.indicatorStyle = this.indicator.style;
30668    this.scroller = scroller;
30669
30670    this.options = {
30671        listenX: true,
30672        listenY: true,
30673        interactive: false,
30674        resize: true,
30675        defaultScrollbars: false,
30676        shrink: false,
30677        fade: false,
30678        speedRatioX: 0,
30679        speedRatioY: 0
30680    };
30681
30682    for ( var i in options ) {
30683        this.options[i] = options[i];
30684    }
30685
30686    this.sizeRatioX = 1;
30687    this.sizeRatioY = 1;
30688    this.maxPosX = 0;
30689    this.maxPosY = 0;
30690
30691    if ( this.options.interactive ) {
30692        if ( !this.options.disableTouch ) {
30693            utils.addEvent(this.indicator, 'touchstart', this);
30694            utils.addEvent(window, 'touchend', this);
30695        }
30696        if ( !this.options.disablePointer ) {
30697            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30698            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
30699        }
30700        if ( !this.options.disableMouse ) {
30701            utils.addEvent(this.indicator, 'mousedown', this);
30702            utils.addEvent(window, 'mouseup', this);
30703        }
30704    }
30705
30706    if ( this.options.fade ) {
30707        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
30708        var durationProp = utils.style.transitionDuration;
30709        if(!durationProp) {
30710            return;
30711        }
30712        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
30713        // remove 0.0001ms
30714        var self = this;
30715        if(utils.isBadAndroid) {
30716            rAF(function() {
30717                if(self.wrapperStyle[durationProp] === '0.0001ms') {
30718                    self.wrapperStyle[durationProp] = '0s';
30719                }
30720            });
30721        }
30722        this.wrapperStyle.opacity = '0';
30723    }
30724}
30725
30726Indicator.prototype = {
30727    handleEvent: function (e) {
30728        switch ( e.type ) {
30729            case 'touchstart':
30730            case 'pointerdown':
30731            case 'MSPointerDown':
30732            case 'mousedown':
30733                this._start(e);
30734                break;
30735            case 'touchmove':
30736            case 'pointermove':
30737            case 'MSPointerMove':
30738            case 'mousemove':
30739                this._move(e);
30740                break;
30741            case 'touchend':
30742            case 'pointerup':
30743            case 'MSPointerUp':
30744            case 'mouseup':
30745            case 'touchcancel':
30746            case 'pointercancel':
30747            case 'MSPointerCancel':
30748            case 'mousecancel':
30749                this._end(e);
30750                break;
30751        }
30752    },
30753
30754    destroy: function () {
30755        if ( this.options.fadeScrollbars ) {
30756            clearTimeout(this.fadeTimeout);
30757            this.fadeTimeout = null;
30758        }
30759        if ( this.options.interactive ) {
30760            utils.removeEvent(this.indicator, 'touchstart', this);
30761            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30762            utils.removeEvent(this.indicator, 'mousedown', this);
30763
30764            utils.removeEvent(window, 'touchmove', this);
30765            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30766            utils.removeEvent(window, 'mousemove', this);
30767
30768            utils.removeEvent(window, 'touchend', this);
30769            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
30770            utils.removeEvent(window, 'mouseup', this);
30771        }
30772
30773        if ( this.options.defaultScrollbars ) {
30774            this.wrapper.parentNode.removeChild(this.wrapper);
30775        }
30776    },
30777
30778    _start: function (e) {
30779        var point = e.touches ? e.touches[0] : e;
30780
30781        e.preventDefault();
30782        e.stopPropagation();
30783
30784        this.transitionTime();
30785
30786        this.initiated = true;
30787        this.moved = false;
vendor: 9,615 bytes, lines 30788-31046
30788        this.lastPointX = point.pageX;
30789        this.lastPointY = point.pageY;
30790
30791        this.startTime  = utils.getTime();
30792
30793        if ( !this.options.disableTouch ) {
30794            utils.addEvent(window, 'touchmove', this);
30795        }
30796        if ( !this.options.disablePointer ) {
30797            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30798        }
30799        if ( !this.options.disableMouse ) {
30800            utils.addEvent(window, 'mousemove', this);
30801        }
30802
30803        this.scroller._execEvent('beforeScrollStart');
30804    },
30805
30806    _move: function (e) {
30807        var point = e.touches ? e.touches[0] : e,
30808            deltaX, deltaY,
30809            newX, newY,
30810            timestamp = utils.getTime();
30811
30812        if ( !this.moved ) {
30813            this.scroller._execEvent('scrollStart');
30814        }
30815
30816        this.moved = true;
30817
30818        deltaX = point.pageX - this.lastPointX;
30819        this.lastPointX = point.pageX;
30820
30821        deltaY = point.pageY - this.lastPointY;
30822        this.lastPointY = point.pageY;
30823
30824        newX = this.x + deltaX;
30825        newY = this.y + deltaY;
30826
30827        this._pos(newX, newY);
30828
30829// INSERT POINT: indicator._move
30830
30831        e.preventDefault();
30832        e.stopPropagation();
30833    },
30834
30835    _end: function (e) {
30836        if ( !this.initiated ) {
30837            return;
30838        }
30839
30840        this.initiated = false;
30841
30842        e.preventDefault();
30843        e.stopPropagation();
30844
30845        utils.removeEvent(window, 'touchmove', this);
30846        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30847        utils.removeEvent(window, 'mousemove', this);
30848
30849        if ( this.scroller.options.snap ) {
30850            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30851
30852            var time = this.options.snapSpeed || Math.max(
30853                    Math.max(
30854                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30855                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30856                    ), 300);
30857
30858            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30859                this.scroller.directionX = 0;
30860                this.scroller.directionY = 0;
30861                this.scroller.currentPage = snap;
30862                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30863            }
30864        }
30865
30866        if ( this.moved ) {
30867            this.scroller._execEvent('scrollEnd');
30868        }
30869    },
30870
30871    transitionTime: function (time) {
30872        time = time || 0;
30873        var durationProp = utils.style.transitionDuration;
30874        if(!durationProp) {
30875            return;
30876        }
30877
30878        this.indicatorStyle[durationProp] = time + 'ms';
30879
30880        if ( !time && utils.isBadAndroid ) {
30881            this.indicatorStyle[durationProp] = '0.0001ms';
30882            // remove 0.0001ms
30883            var self = this;
30884            rAF(function() {
30885                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30886                    self.indicatorStyle[durationProp] = '0s';
30887                }
30888            });
30889        }
30890    },
30891
30892    transitionTimingFunction: function (easing) {
30893        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30894    },
30895
30896    refresh: function () {
30897        this.transitionTime();
30898
30899        if ( this.options.listenX && !this.options.listenY ) {
30900            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30901        } else if ( this.options.listenY && !this.options.listenX ) {
30902            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30903        } else {
30904            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30905        }
30906
30907        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30908            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30909            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30910
30911            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30912                if ( this.options.listenX ) {
30913                    this.wrapper.style.right = '8px';
30914                } else {
30915                    this.wrapper.style.bottom = '8px';
30916                }
30917            }
30918        } else {
30919            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30920            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30921
30922            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30923                if ( this.options.listenX ) {
30924                    this.wrapper.style.right = '2px';
30925                } else {
30926                    this.wrapper.style.bottom = '2px';
30927                }
30928            }
30929        }
30930
30931        var r = this.wrapper.offsetHeight;  // force refresh
30932
30933        if ( this.options.listenX ) {
30934            this.wrapperWidth = this.wrapper.clientWidth;
30935            if ( this.options.resize ) {
30936                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30937                this.indicatorStyle.width = this.indicatorWidth + 'px';
30938            } else {
30939                this.indicatorWidth = this.indicator.clientWidth;
30940            }
30941
30942            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30943
30944            if ( this.options.shrink == 'clip' ) {
30945                this.minBoundaryX = -this.indicatorWidth + 8;
30946                this.maxBoundaryX = this.wrapperWidth - 8;
30947            } else {
30948                this.minBoundaryX = 0;
30949                this.maxBoundaryX = this.maxPosX;
30950            }
30951
30952            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30953        }
30954
30955        if ( this.options.listenY ) {
30956            this.wrapperHeight = this.wrapper.clientHeight;
30957            if ( this.options.resize ) {
30958                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
30959                this.indicatorStyle.height = this.indicatorHeight + 'px';
30960            } else {
30961                this.indicatorHeight = this.indicator.clientHeight;
30962            }
30963
30964            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30965
30966            if ( this.options.shrink == 'clip' ) {
30967                this.minBoundaryY = -this.indicatorHeight + 8;
30968                this.maxBoundaryY = this.wrapperHeight - 8;
30969            } else {
30970                this.minBoundaryY = 0;
30971                this.maxBoundaryY = this.maxPosY;
30972            }
30973
30974            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30975            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
30976        }
30977
30978        this.updatePosition();
30979    },
30980
30981    updatePosition: function () {
30982        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
30983            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
30984
30985        if ( !this.options.ignoreBoundaries ) {
30986            if ( x < this.minBoundaryX ) {
30987                if ( this.options.shrink == 'scale' ) {
30988                    this.width = Math.max(this.indicatorWidth + x, 8);
30989                    this.indicatorStyle.width = this.width + 'px';
30990                }
30991                x = this.minBoundaryX;
30992            } else if ( x > this.maxBoundaryX ) {
30993                if ( this.options.shrink == 'scale' ) {
30994                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
30995                    this.indicatorStyle.width = this.width + 'px';
30996                    x = this.maxPosX + this.indicatorWidth - this.width;
30997                } else {
30998                    x = this.maxBoundaryX;
30999                }
31000            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
31001                this.width = this.indicatorWidth;
31002                this.indicatorStyle.width = this.width + 'px';
31003            }
31004
31005            if ( y < this.minBoundaryY ) {
31006                if ( this.options.shrink == 'scale' ) {
31007                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
31008                    this.indicatorStyle.height = this.height + 'px';
31009                }
31010                y = this.minBoundaryY;
31011            } else if ( y > this.maxBoundaryY ) {
31012                if ( this.options.shrink == 'scale' ) {
31013                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31014                    this.indicatorStyle.height = this.height + 'px';
31015                    y = this.maxPosY + this.indicatorHeight - this.height;
31016                } else {
31017                    y = this.maxBoundaryY;
31018                }
31019            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31020                this.height = this.indicatorHeight;
31021                this.indicatorStyle.height = this.height + 'px';
31022            }
31023        }
31024
31025        this.x = x;
31026        this.y = y;
31027
31028        if ( this.scroller.options.useTransform ) {
31029            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31030        } else {
31031            this.indicatorStyle.left = x + 'px';
31032            this.indicatorStyle.top = y + 'px';
31033        }
31034    },
31035
31036    _pos: function (x, y) {
31037        if ( x < 0 ) {
31038            x = 0;
31039        } else if ( x > this.maxPosX ) {
31040            x = this.maxPosX;
31041        }
31042
31043        if ( y < 0 ) {
31044            y = 0;
31045        } else if ( y > this.maxPosY ) {
31046            y = this.maxPosY;
31047        }
31048
31049        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31050        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31051
31052        this.scroller.scrollTo(x, y);
31053    },
31054
31055    fade: function (val, hold) {
31056        if ( hold && !this.visible ) {
31057            return;
31058        }
31059
31060        clearTimeout(this.fadeTimeout);
31061        this.fadeTimeout = null;
31062
31063        var time = val ? 250 : 500,
31064            delay = val ? 0 : 300;
31065
31066        val = val ? '1' : '0';
31067
31068        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31069
31070        this.fadeTimeout = setTimeout((function (val) {
31071            this.wrapperStyle.opacity = val;
31072            this.visible = +val;
31073        }).bind(this, val), delay);
31074    }
31075};
31076
31077IScroll.utils = utils;
31078
31079if ( typeof module != 'undefined' && module.exports ) {
31080    module.exports = IScroll;
31081} else if ( typeof define == 'function' && define.amd ) {
31082        define( function () { return IScroll; } );
31083} else {
31084    window.IScroll = IScroll;
31085}
31086
31087})(window, document, Math);
31088/*!
31089 * fullPage 2.9.4
31090 * https://github.com/alvarotrigo/fullPage.js
31091 * @license MIT licensed
31092 *
31093 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
31094 */
31095(function(global, factory) {
31096    'use strict';
31097    if (typeof define === 'function' && define.amd) {
31098        define(['jquery'], function($) {
31099          return factory($, global, global.document, global.Math);
31100        });
31101    } else if (typeof exports === "object" && exports) {
31102        module.exports = factory(require('jquery'), global, global.document, global.Math);
31103    } else {
31104        factory(jQuery, global, global.document, global.Math);
31105    }
31106})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
31107    'use strict';
31108
31109    // keeping central set of classnames and selectors
31110    var WRAPPER =               'fullpage-wrapper';
31111    var WRAPPER_SEL =           '.' + WRAPPER;
31112
31113    // slimscroll
31114    var SCROLLABLE =            'fp-scrollable';
31115    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
31116
31117    // util
31118    var RESPONSIVE =            'fp-responsive';
31119    var NO_TRANSITION =         'fp-notransition';
31120    var DESTROYED =             'fp-destroyed';
31121    var ENABLED =               'fp-enabled';
31122    var VIEWING_PREFIX =        'fp-viewing';
31123    var ACTIVE =                'active';
31124    var ACTIVE_SEL =            '.' + ACTIVE;
31125    var COMPLETELY =            'fp-completely';
31126    var COMPLETELY_SEL =        '.' + COMPLETELY;
31127
31128    // section
31129    var SECTION_DEFAULT_SEL =   '.section';
31130    var SECTION =               'fp-section';
31131    var SECTION_SEL =           '.' + SECTION;
31132    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
31133    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
31134    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
31135    var TABLE_CELL =            'fp-tableCell';
31136    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
31137    var AUTO_HEIGHT =           'fp-auto-height';
31138    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
31139    var NORMAL_SCROLL =         'fp-normal-scroll';
31140    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
31141
31142    // section nav
31143    var SECTION_NAV =           'fp-nav';
31144    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
31145    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
31146    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
31147    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
31148
31149    // slide
31150    var SLIDE_DEFAULT_SEL =     '.slide';
31151    var SLIDE =                 'fp-slide';
31152    var SLIDE_SEL =             '.' + SLIDE;
31153    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
31154    var SLIDES_WRAPPER =        'fp-slides';
31155    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
31156    var SLIDES_CONTAINER =      'fp-slidesContainer';
31157    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
31158    var TABLE =                 'fp-table';
31159
31160    // slide nav
31161    var SLIDES_NAV =            'fp-slidesNav';
31162    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
31163    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
31164    var SLIDES_ARROW =          'fp-controlArrow';
31165    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
31166    var SLIDES_PREV =           'fp-prev';
31167    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
31168    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
31169    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
31170    var SLIDES_NEXT =           'fp-next';
31171    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
31172    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
31173    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
31174
31175    var $window = $(window);
31176    var $document = $(document);
31177
31178    // Default options for iScroll.js used when using scrollOverflow
31179    var iscrollOptions = {
31180        scrollbars: true,
31181        mouseWheel: true,
31182        hideScrollbars: false,
31183        fadeScrollbars: false,
31184        disableMouse: true,
31185        interactiveScrollbars: true,
31186        bounce: false,
31187    };
31188
31189    $.fn.fullpage = function(options) {
31190        //only once my friend!
31191        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
31192
31193        // common jQuery objects
31194        var $htmlBody = $('html, body');
31195        var $body = $('body');
31196
31197        var FP = $.fn.fullpage;
31198
31199        // Creating some defaults, extending them with any options that were provided
31200        options = $.extend({
31201            //navigation
31202            menu: false,
31203            anchors:[],
31204            lockAnchors: false,
31205            navigation: false,
31206            navigationPosition: 'right',
31207            navigationTooltips: [],
31208            showActiveTooltip: false,
31209            slidesNavigation: false,
31210            slidesNavPosition: 'bottom',
31211            scrollBar: false,
31212            hybrid: false,
31213
31214            //scrolling
31215            css3: true,
31216            scrollingSpeed: 700,
31217            autoScrolling: true,
31218            fitToSection: true,
31219            fitToSectionDelay: 1000,
31220            easing: 'easeInOutCubic',
31221            easingcss3: 'ease',
31222            loopBottom: false,
31223            loopTop: false,
31224            loopHorizontal: true,
31225            continuousVertical: false,
31226            continuousHorizontal: false,
31227            scrollHorizontally: false,
31228            interlockedSlides: false,
31229            dragAndMove: false,
31230            offsetSections: false,
31231            resetSliders: false,
31232            fadingEffect: false,
31233            normalScrollElements: null,
31234            scrollOverflow: false,
31235            scrollOverflowReset: false,
31236            scrollOverflowHandler: iscrollHandler,
31237            scrollOverflowOptions: null,
31238            touchSensitivity: 5,
31239            normalScrollElementTouchThreshold: 5,
31240            bigSectionsDestination: null,
31241
31242            //Accessibility
31243            keyboardScrolling: true,
31244            animateAnchor: true,
31245            recordHistory: true,
31246
31247            //design
31248            controlArrows: true,
31249            controlArrowColor: '#fff',
31250            verticalCentered: true,
31251            sectionsColor : [],
31252            paddingTop: 0,
31253            paddingBottom: 0,
31254            fixedElements: null,
31255            responsive: 0, //backwards compabitility with responsiveWiddth
31256            responsiveWidth: 0,
31257            responsiveHeight: 0,
31258            responsiveSlides: false,
31259            parallax: false,
31260            parallaxOptions: {
31261                type: 'reveal',
31262                percentage: 62,
31263                property: 'translate'
31264            },
31265
31266            //Custom selectors
31267            sectionSelector: SECTION_DEFAULT_SEL,
31268            slideSelector: SLIDE_DEFAULT_SEL,
31269
31270            //events
31271            afterLoad: null,
31272            onLeave: null,
31273            afterRender: null,
31274            afterResize: null,
31275            afterReBuild: null,
31276            afterSlideLoad: null,
31277            onSlideLeave: null,
31278            afterResponsive: null,
31279
31280            lazyLoading: true
31281        }, options);
31282
31283        //flag to avoid very fast sliding for landscape sliders
31284        var slideMoving = false;
31285
31286        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
31287        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
31288        var container = $(this);
31289        var windowsHeight = $window.height();
31290        var isResizing = false;
31291        var isWindowFocused = true;
31292        var lastScrolledDestiny;
31293        var lastScrolledSlide;
31294        var canScroll = true;
31295        var scrollings = [];
31296        var controlPressed;
31297        var startingSection;
31298        var isScrollAllowed = {};
31299        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
31300        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
31301        var MSPointer = getMSPointer();
31302        var events = {
31303            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
31304            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
31305        };
31306
31307        //cheks for passive event support
31308        //added by Uncode from new fullPage updates
31309        var g_supportsPassive = false;
31310        try {
31311          var opts = Object.defineProperty({}, 'passive', {
31312            get: function() {
31313              g_supportsPassive = true;
31314            }
31315          });
31316          window.addEventListener("testPassive", null, opts);
31317          window.removeEventListener("testPassive", null, opts);
31318        } catch (e) {}
31319
31320        //timeouts
31321        var resizeId;
31322        var afterSectionLoadsId;
31323        var afterSlideLoadsId;
31324        var scrollId;
31325        var scrollId2;
31326        var keydownId;
31327        var originals = $.extend(true, {}, options); //deep copy
31328
31329        //Uncode addition
31330        var $masthead = $('#masthead');
31331        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
31332        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
31333        var bodyBorder = UNCODE.bodyBorder;
31334        var adminBarHeight = UNCODE.adminBarHeight;
31335
31336        displayWarnings();
31337
31338        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
31339        iscrollOptions.click = isTouch; // see #2035
31340
31341        //extending iScroll options with the user custom ones
31342        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
31343
31344        //easeInOutCubic animation included in the plugin
31345        $.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;}});
31346
31347        /**
31348        * Sets the autoScroll option.
31349        * It changes the scroll bar visibility and the history of the site as a result.
31350        */
31351        function setAutoScrolling(value, type){
31352            //removing the transformation
31353            if(!value){
31354                silentScroll(0);
31355            }
31356
31357            setVariableState('autoScrolling', value, type);
31358
31359            var element = $(SECTION_ACTIVE_SEL);
31360
31361            if(options.autoScrolling && !options.scrollBar){
31362                $htmlBody.css({
31363                    'overflow' : 'hidden !important',
31364                    'height' : '100%'
31365                });
31366
31367                //Uncode addition
31368                //setRecordHistory(originals.recordHistory, 'internal');
31369
31370                //for IE touch devices
31371                container.css({
31372                    '-ms-touch-action': 'none',
31373                    'touch-action': 'none'
31374                });
31375
31376                if(element.length){
31377                    //moving the container up
31378                    silentScroll(element.position().top);
31379                }
31380
31381            }else{
31382                $htmlBody.css({
31383                    'overflow' : 'visible !important',
31384                    'height' : 'initial'
31385                });
31386
31387                //Uncode addition
31388                //setRecordHistory(false, 'internal');
31389
31390                //for IE touch devices
31391                container.css({
31392                    '-ms-touch-action': '',
31393                    'touch-action': ''
31394                });
31395
31396                //scrolling the page to the section with no animation
31397                if (element.length) {
31398                    $htmlBody.scrollTop(element.position().top);
31399                }
31400            }
31401        }
31402
31403        /**
31404        * Defines wheter to record the history for each hash change in the URL.
31405        */
31406        function setRecordHistory(value, type){
31407            setVariableState('recordHistory', value, type);
31408        }
31409
31410        /**
31411        * Defines the scrolling speed
31412        */
31413        function setScrollingSpeed(value, type){
31414            setVariableState('scrollingSpeed', value, type);
31415        }
31416
31417        /**
31418        * Sets fitToSection
31419        */
31420        function setFitToSection(value, type){
31421            setVariableState('fitToSection', value, type);
31422        }
31423
31424        /**
31425        * Sets lockAnchors
31426        */
31427        function setLockAnchors(value){
31428            options.lockAnchors = value;
31429        }
31430
31431        /**
31432        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
31433        */
31434        function setMouseWheelScrolling(value){
31435            if(value){
31436                addMouseWheelHandler();
31437                addMiddleWheelHandler();
31438            }else{
31439                removeMouseWheelHandler();
31440                removeMiddleWheelHandler();
31441            }
31442        }
31443
31444        /**
31445        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
31446        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
31447        *
31448        * @param directions string containing the direction or directions separated by comma.
31449        */
31450        function setAllowScrolling(value, directions){
31451            if(typeof directions !== 'undefined'){
31452                directions = directions.replace(/ /g,'').split(',');
31453
31454                $.each(directions, function (index, direction){
31455                    setIsScrollAllowed(value, direction, 'm');
31456                });
31457            }
31458            else if(value){
31459                setMouseWheelScrolling(true);
31460                addTouchHandler();
31461            }else{
31462                setMouseWheelScrolling(false);
31463                removeTouchHandler();
31464            }
31465        }
31466
31467        /**
31468        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
31469        */
31470        function setKeyboardScrolling(value, directions){
31471            if(typeof directions !== 'undefined'){
31472                directions = directions.replace(/ /g,'').split(',');
31473
31474                $.each(directions, function (index, direction){
31475                    setIsScrollAllowed(value, direction, 'k');
31476                });
31477            }else{
31478                options.keyboardScrolling = value;
31479            }
31480        }
31481
31482        /**
31483        * Moves the page up one section.
31484        */
31485        function moveSectionUp(){
31486            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
31487
31488            //looping to the bottom if there's no more sections above
31489            if (!prev.length && (options.loopTop || options.continuousVertical)) {
31490                prev = $(SECTION_SEL).last();
31491            }
31492
31493            if (prev.length) {
31494                scrollPage(prev, null, true);
31495            }
31496        }
31497
31498        /**
31499        * Moves the page down one section.
31500        */
31501        function moveSectionDown(){
31502            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
31503
31504            //looping to the top if there's no more sections below
31505            if(!next.length &&
31506                (options.loopBottom || options.continuousVertical)){
31507                next = $(SECTION_SEL).first();
31508            }
31509
31510            if(next.length){
31511                scrollPage(next, null, false);
31512            }
31513        }
31514
31515        /**
31516        * Moves the page to the given section and slide with no animation.
31517        * Anchors or index positions can be used as params.
31518        */
31519        function silentMoveTo(sectionAnchor, slideAnchor){
31520            setScrollingSpeed (0, 'internal');
31521            moveTo(sectionAnchor, slideAnchor);
31522            setScrollingSpeed (originals.scrollingSpeed, 'internal');
31523        }
31524
31525        /**
31526        * Moves the page to the given section and slide.
31527        * Anchors or index positions can be used as params.
31528        */
31529        function moveTo(sectionAnchor, slideAnchor){
31530            var destiny = getSectionByAnchor(sectionAnchor);
31531
31532            if (typeof slideAnchor !== 'undefined'){
31533                scrollPageAndSlide(sectionAnchor, slideAnchor);
31534            }else if(destiny.length > 0){
31535                scrollPage(destiny);
31536            }
31537        }
31538
31539        /**
31540        * Slides right the slider of the active section.
31541        * Optional `section` param.
31542        */
31543        function moveSlideRight(section){
31544            moveSlide('right', section);
31545        }
31546
31547        /**
31548        * Slides left the slider of the active section.
31549        * Optional `section` param.
31550        */
31551        function moveSlideLeft(section){
31552            moveSlide('left', section);
31553        }
31554
31555        /**
31556         * When resizing is finished, we adjust the slides sizes and positions
31557         */
31558        function reBuild(resizing){
31559            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
31560
31561            isResizing = true;
31562
31563            windowsHeight = $window.height();  //updating global var
31564
31565            $(SECTION_SEL).each(function(){
31566                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
31567                var slides = $(this).find(SLIDE_SEL);
31568
31569                //adjusting the height of the table-cell for IE and Firefox
31570                if(options.verticalCentered){
31571                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
31572                }
31573
31574                $(this).css('height', windowsHeight + 'px');
31575
31576                //resizing the scrolling divs
31577                if(options.scrollOverflow){
31578                    if(slides.length){
31579                        slides.each(function(){
31580                            createScrollBar($(this));
31581                        });
31582                    }else{
31583                        createScrollBar($(this));
31584                    }
31585                }
31586
31587                //adjusting the position fo the FULL WIDTH slides...
31588                if (slides.length > 1) {
31589                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
31590                }
31591            });
31592
31593            var activeSection = $(SECTION_ACTIVE_SEL);
31594            var sectionIndex = activeSection.index(SECTION_SEL);
31595
31596            //isn't it the first section?
31597            if(sectionIndex){
31598                //adjusting the position for the current section
31599                silentMoveTo(sectionIndex + 1);
31600            }
31601
31602            isResizing = false;
31603            // Uncode change
31604            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
31605            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
31606            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
31607        }
31608
31609        /**
31610        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
31611        * are smaller than the set limit values.
31612        */
31613        function setResponsive(active){
31614            var isResponsive = $body.hasClass(RESPONSIVE);
31615
31616            if(active){
31617                if(!isResponsive){
31618                    setAutoScrolling(false, 'internal');
31619                    setFitToSection(false, 'internal');
31620                    $(SECTION_NAV_SEL).hide();
31621                    $body.addClass(RESPONSIVE);
31622                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31623                }
31624            }
31625            else if(isResponsive){
31626                setAutoScrolling(originals.autoScrolling, 'internal');
31627                setFitToSection(originals.autoScrolling, 'internal');
31628                $(SECTION_NAV_SEL).show();
31629                $body.removeClass(RESPONSIVE);
31630                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31631            }
31632        }
31633
31634        if($(this).length){
31635            //public functions
31636            FP.setAutoScrolling = setAutoScrolling;
31637            FP.setRecordHistory = setRecordHistory;
31638            FP.setScrollingSpeed = setScrollingSpeed;
31639            FP.setFitToSection = setFitToSection;
31640            FP.setLockAnchors = setLockAnchors;
31641            FP.setMouseWheelScrolling = setMouseWheelScrolling;
31642            FP.setAllowScrolling = setAllowScrolling;
31643            FP.setKeyboardScrolling = setKeyboardScrolling;
31644            FP.moveSectionUp = moveSectionUp;
31645            FP.moveSectionDown = moveSectionDown;
31646            FP.silentMoveTo = silentMoveTo;
31647            FP.moveTo = moveTo;
31648            FP.moveSlideRight = moveSlideRight;
31649            FP.moveSlideLeft = moveSlideLeft;
31650            FP.fitToSection = fitToSection;
31651            FP.reBuild = reBuild;
31652            FP.setResponsive = setResponsive;
31653            FP.destroy = destroy;
31654
31655            init();
31656
31657            bindEvents();
31658        }
31659
31660        function init(){
31661            //if css3 is not supported, it will use jQuery animations
31662            if(options.css3){
31663                options.css3 = support3d();
31664            }
31665
31666            options.scrollBar = options.scrollBar || options.hybrid;
31667
31668            setOptionsFromDOM();
31669            prepareDom();
31670            setAllowScrolling(true);
31671            setAutoScrolling(options.autoScrolling, 'internal');
31672            responsive();
31673
31674            //setting the class for the body element
31675            setBodyClass();
31676
31677            //Uncode addition
31678            // if(document.readyState === 'complete'){
31679            //     scrollToAnchor();
31680            // }
31681            // $window.on('load', scrollToAnchor);
31682        }
31683
31684        function bindEvents(){
31685            $window
31686                //when scrolling...
31687                //.on('scroll', scrollHandler)
31688
31689                //detecting any change on the URL to scroll to the given anchor link
31690                //(a way to detect back history button as we play with the hashes on the URL)
31691                .on('hashchange', hashChangeHandler)
31692
31693                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
31694                .blur(blurHandler)
31695
31696                //when resizing the site, we adjust the heights of the sections, slimScroll...
31697                .resize(resizeHandler);
31698
31699            $document
31700                //Sliding with arrow keys, both, vertical and horizontal
31701                .keydown(keydownHandler)
31702
31703                //to prevent scrolling while zooming
31704                .keyup(keyUpHandler)
31705
31706                //Scrolls to the section when clicking the navigation bullet
31707                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
31708
31709                //Scrolls the slider to the given slide destination for the given section
31710                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
31711
31712                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
31713
31714            //Scrolling horizontally when clicking on the slider controls.
31715            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
31716
31717            /**
31718            * Applying normalScroll elements.
31719            * Ignoring the scrolls over the specified selectors.
31720            */
31721            if(options.normalScrollElements){
31722                $document.on('mouseenter', options.normalScrollElements, function () {
31723                    setMouseWheelScrolling(false);
31724                });
31725
31726                $document.on('mouseleave', options.normalScrollElements, function(){
31727                    setMouseWheelScrolling(true);
31728                });
31729            }
31730        }
31731
31732        /**
31733        * Setting options from DOM elements if they are not provided.
31734        */
31735        function setOptionsFromDOM(){
31736            var sections = container.find(options.sectionSelector);
31737
31738            //no anchors option? Checking for them in the DOM attributes
31739            if(!options.anchors.length){
31740                options.anchors = sections.filter('[data-anchor]').map(function(){
31741                    return $(this).data('anchor').toString();
31742                }).get();
31743            }
31744
31745            //no tooltips option? Checking for them in the DOM attributes
31746            if(!options.navigationTooltips.length){
31747                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
31748                    return $(this).data('tooltip').toString();
31749                }).get();
31750            }
31751        }
31752
31753        /**
31754        * Works over the DOM structure to set it up for the current fullpage options.
31755        */
31756        function prepareDom(){
31757            container.css({
31758                'height': '100%',
31759                'position': 'relative'
31760            });
31761
31762            //adding a class to recognize the container internally in the code
31763            container.addClass(WRAPPER);
31764            $('html').addClass(ENABLED);
31765
31766            windowsHeight = $window.height();
31767
31768            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
31769
31770            addInternalSelectors();
31771
31772             //styling the sections / slides / menu
31773            $(SECTION_SEL).each(function(index){
31774                var section = $(this);
31775                var slides = section.find(SLIDE_SEL);
31776                var numSlides = slides.length;
31777
31778                styleSection(section, index);
31779                styleMenu(section, index);
31780
31781                // if there's any slide
31782                if (numSlides > 0) {
31783                    styleSlides(section, slides, numSlides);
31784                }else{
31785                    if(options.verticalCentered){
31786                        addTableClass(section);
31787                    }
31788                }
31789            });
31790
31791            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31792            if(options.fixedElements && options.css3){
31793                $(options.fixedElements).appendTo($body);
31794            }
31795
31796            //vertical centered of the navigation + active bullet
31797            if(options.navigation){
31798                addVerticalNavigation();
31799            }
31800
31801            enableYoutubeAPI();
31802
31803            if(options.scrollOverflow){
31804                if(document.readyState === 'complete'){
31805                    createScrollBarHandler();
31806                }
31807                //after DOM and images are loaded
31808                $window.on('load', createScrollBarHandler);
31809            }else{
31810                afterRenderActions();
31811            }
31812        }
31813
31814        /**
31815        * Styles the horizontal slides for a section.
31816        */
31817        function styleSlides(section, slides, numSlides){
31818            var sliderWidth = numSlides * 100;
31819            var slideWidth = 100 / numSlides;
31820
31821            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31822            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31823
31824            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31825
31826            if(numSlides > 1){
31827                if(options.controlArrows){
31828                    createSlideArrows(section);
31829                }
31830
31831                if(options.slidesNavigation){
31832                    addSlidesNavigation(section, numSlides);
31833                }
31834            }
31835
31836            slides.each(function(index) {
31837                $(this).css('width', slideWidth + '%');
31838
31839                if(options.verticalCentered){
31840                    addTableClass($(this));
31841                }
31842            });
31843
31844            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31845
31846            //if the slide won't be an starting point, the default will be the first one
31847            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31847ide by default.
31848            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31849                silentLandscapeScroll(startingSlide, 'internal');
31850            }else{
31851                slides.eq(0).addClass(ACTIVE);
31852            }
31853        }
31854
31855        /**
31856        * Styling vertical sections
31857        */
31858        function styleSection(section, index){
31859            //if no active section is defined, the 1st one will be the default one
31860            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31861                section.addClass(ACTIVE);
31862            }
31863            startingSection = $(SECTION_ACTIVE_SEL);
31864
31865            section.css('height', windowsHeight + 'px');
31866
31867            if(options.paddingTop){
31868                section.css('padding-top', options.paddingTop);
31869            }
31870
31871            if(options.paddingBottom){
31872                section.css('padding-bottom', options.paddingBottom);
31873            }
31874
31875            if (typeof options.sectionsColor[index] !==  'undefined') {
31876                section.css('background-color', options.sectionsColor[index]);
31877            }
31878
31879            if (typeof options.anchors[index] !== 'undefined') {
31880                section.attr('data-anchor', options.anchors[index]);
31881            }
31882        }
31883
31884        /**
31885        * Sets the data-anchor attributes to the menu elements and activates the current one.
31886        */
31887        function styleMenu(section, index){
31888            if (typeof options.anchors[index] !== 'undefined') {
31889                //activating the menu / nav element on load
31890                if(section.hasClass(ACTIVE)){
31891                    activateMenuAndNav(options.anchors[index], index);
31892                }
31893            }
31894
31895            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31896            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31897                $(options.menu).appendTo($body);
31898            }
31899        }
31900
31901        /**
31902        * Adds internal classes to be able to provide customizable selectors
31903        * keeping the link with the style sheet.
31904        */
31905        function addInternalSelectors(){
31906            container.find(options.sectionSelector).addClass(SECTION);
31907            container.find(options.slideSelector).addClass(SLIDE);
31908        }
31909
31910        /**
31911        * Creates the control arrows for the given section
31912        */
31913        function createSlideArrows(section){
31914            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31915
31916            if(options.controlArrowColor!='#fff'){
31917                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31918                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31919            }
31920
31921            if(!options.loopHorizontal){
31922                section.find(SLIDES_ARROW_PREV_SEL).hide();
31923            }
31924        }
31925
31926        /**
31927        * Creates a vertical navigation bar.
31928        */
31929        function addVerticalNavigation(){
31930            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31931            var nav = $(SECTION_NAV_SEL);
31932
31933            nav.addClass(function() {
31934                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31935            });
31936
31937            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31938                var link = '';
31939                if (options.anchors.length) {
31940                    link = options.anchors[i];
31941                }
31942
31943                var li = '<li><a href="#' + link + '"><span></span></a>';
31944
31945                // Only add tooltip if needed (defined by user)
31946                var tooltip = options.navigationTooltips[i];
31947
31948                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31949                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31950                }
31951
31952                li += '</li>';
31953
31954                nav.find('ul').append(li);
31955            }
31956
31957            //centering it vertically
31958            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
31959
31960            //activating the current active section
31961            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
31962        }
31963
31964        /**
31965        * Creates the slim scroll scrollbar for the sections and slides inside them.
31966        */
31967        function createScrollBarHandler(){
31968            $(SECTION_SEL).each(function(){
31969                var slides = $(this).find(SLIDE_SEL);
31970
31971                if(slides.length){
31972                    slides.each(function(){
31973                        createScrollBar($(this));
31974                    });
31975                }else{
31976                    createScrollBar($(this));
31977                }
31978
31979            });
31980            afterRenderActions();
31981        }
31982
31983        /*
31984        * Enables the Youtube videos API so we can control their flow if necessary.
31985        */
31986        function enableYoutubeAPI(){
31987            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
31988                addURLParam($(this), 'enablejsapi=1');
31989            });
31990        }
31991
31992        /**
31993        * Adds a new parameter and its value to the `src` of a given element
31994        */
31995        function addURLParam(element, newParam){
31996            var originalSrc = element.attr('src');
31997            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
31998        }
31999
32000        /*
32001        * Returns the prefix sign to use for a new parameter in an existen URL.
32002        *
32003        * @return {String}  ? | &
32004        */
32005        function getUrlParamSign(url){
32006            return ( !/\?/.test( url ) ) ? '?' : '&';
32007        }
32008
32009        /**
32010        * Actions and callbacks to fire afterRender
32011        */
32012        function afterRenderActions(){
32013            var section = $(SECTION_ACTIVE_SEL);
32014
32015            section.addClass(COMPLETELY);
32016
32017            if(options.scrollOverflowHandler.afterRender){
32018                options.scrollOverflowHandler.afterRender(section);
32019            }
32020            lazyLoad(section);
32021            playMedia(section);
32022            options.scrollOverflowHandler.afterLoad();
32023
32024            if(isDestinyTheStartingSection()){
32025                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32026            }
32027
32028            // Uncode change
32029            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32030            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32031        }
32032
32033        /**
32034        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32035        */
32036        function isDestinyTheStartingSection(){
32037            var anchors =  window.location.hash.replace('#', '').split('/');
32038            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32039
32040            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32041        }
32042
32043
32044        var isScrolling = false;
32045        var lastScroll = 0;
32046
32047        //when scrolling...
32048        function scrollHandler(){
32049            var currentSection;
32050
32051            if(!options.autoScrolling || options.scrollBar){
32052                var currentScroll = $window.scrollTop();
32053                var scrollDirection = getScrollDirection(currentScroll);
32054                var visibleSectionIndex = 0;
32055                var screen_mid = currentScroll + ($window.height() / 2.0);
32056                var isAtBottom = $body.height() - $window.height() === currentScroll;
32057                var sections =  document.querySelectorAll(SECTION_SEL);
32058
32059                //when using `auto-height` for a small last section it won't be centered in the viewport
32060                if(isAtBottom){
32061                    visibleSectionIndex = sections.length - 1;
32062                }
32063                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32064                else if(!currentScroll){
32065                    visibleSectionIndex = 0;
32066                }
32067
32068                //taking the section which is showing more content in the viewport
32069                else{
32070                    for (var i = 0; i < sections.length; ++i) {
32071                        var section = sections[i];
32072
32073                        // Pick the the last section which passes the middle line of the screen.
32074                        if (section.offsetTop <= screen_mid)
32075                        {
32076                            visibleSectionIndex = i;
32077                        }
32078                    }
32079                }
32080
32081                if(isCompletelyInViewPort(scrollDirection)){
32082                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
32083                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32084                    }
32085                }
32086
32087                //geting the last one, the current one on the screen
32088                currentSection = $(sections).eq(visibleSectionIndex);
32089
32090                //setting the visible section as active when manually scrolling
32091                //executing only once the first time we reach the section
32092                if(!currentSection.hasClass(ACTIVE)){
32093                    isScrolling = true;
32094                    var leavingSection = $(SECTION_ACTIVE_SEL);
32095                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
32096                    var yMovement = getYmovement(currentSection);
32097                    var anchorLink  = currentSection.data('anchor');
32098                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
32099                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
32100                    var slideIndex;
32101                    var slideAnchorLink;
32102
32103                    if(activeSlide.length){
32104                        slideAnchorLink = activeSlide.data('anchor');
32105                        slideIndex = activeSlide.index();
32106                    }
32107
32108                    if(canScroll){
32109                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32110
32111                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
32112                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
32113
32114                        stopMedia(leavingSection);
32115                        lazyLoad(currentSection);
32116                        playMedia(currentSection);
32117
32118                        activateMenuAndNav(anchorLink, sectionIndex - 1);
32119
32120                        if(options.anchors.length){
32121                            //needed to enter in hashChange event when using the menu with anchor links
32122                            lastScrolledDestiny = anchorLink;
32123                        }
32124                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
32125                    }
32126
32127                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
32128                    clearTimeout(scrollId);
32129                    scrollId = setTimeout(function(){
32130                        isScrolling = false;
32131                    }, 100);
32132                }
32133
32134                if(options.fitToSection){
32135                    //for the auto adjust of the viewport to fit a whole section
32136                    clearTimeout(scrollId2);
32137
32138                    scrollId2 = setTimeout(function(){
32139                        //checking it again in case it changed during the delay
32140                        if(options.fitToSection){
32141                            fitToSection();
32142                        }
32143                    }, options.fitToSectionDelay);
32144                }
32145            }
32146        }
32147
32148        /**
32149        * Fits the site to the nearest active section
32150        */
32151        function fitToSection(){
32152            //checking fitToSection again in case it was set to false before the timeout delay
32153            if(canScroll){
32154                //allows to scroll to an active section and
32155                //if the section is already active, we prevent firing callbacks
32156                isResizing = true;
32157
32158                scrollPage($(SECTION_ACTIVE_SEL));
32159                isResizing = false;
32160            }
32161        }
32162
32163        /**
32164        * Determines whether the active section has seen in its whole or not.
32165        */
32166        function isCompletelyInViewPort(movement){
32167            var top = $(SECTION_ACTIVE_SEL).position().top;
32168            var bottom = top + $window.height();
32169
32170            if(movement == 'up'){
32171                return bottom >= ($window.scrollTop() + $window.height());
32172            }
32173            return top <= $window.scrollTop();
32174        }
32175
32176        /**
32177        * Gets the directon of the the scrolling fired by the scroll event.
32178        */
32179        function getScrollDirection(currentScroll){
32180            var direction = currentScroll > lastScroll ? 'down' : 'up';
32181
32182            lastScroll = currentScroll;
32183
32184            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
32185            previousDestTop = currentScroll;
32186
32187            return direction;
32188        }
32189
32190        /**
32191        * Determines the way of scrolling up or down:
32192        * by 'automatically' scrolling a section or by using the default and normal scrolling.
32193        */
32194        function scrolling(type, scrollable){
32195            if (!isScrollAllowed.m[type]){
32196                return;
32197            }
32198            var check = (type === 'down') ? 'bottom' : 'top';
32199            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
32200
32201            if(scrollable.length > 0 ){
32202                //is the scrollbar at the start/end of the scroll?
32203                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
32204                    scrollSection();
32205                }else{
32206                    return true;
32207                }
32208            }else{
32209                // moved up/down
32210                scrollSection();
32211            }
32212        }
32213
32214        /*
32215        * Preventing bouncing in iOS #2285
32216        */
32217        function preventBouncing(event){
32218            var e = event.originalEvent;
32219            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
32220                //preventing the easing on iOS devices
32221                event.preventDefault();
32222            }
32223        }
32224
32225        var touchStartY = 0;
32226        var touchStartX = 0;
32227        var touchEndY = 0;
32228        var touchEndX = 0;
32229
32230        /* Detecting touch events
32231
32232        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
32233        * This way, the touchstart and the touch moves shows an small difference between them which is the
32234        * used one to determine the direction.
32235        */
32236        function touchMoveHandler(event){
32237            var e = event.originalEvent;
32238            var activeSection = $(e.target).closest(SECTION_SEL);
32239
32240            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
32241            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
32242
32243                if(options.autoScrolling){
32244                    //preventing the easing on iOS devices
32245                    event.preventDefault();
32246                }
32247
32248                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32249                var touchEvents = getEventsPage(e);
32250
32251                touchEndY = touchEvents.y;
32252                touchEndX = touchEvents.x;
32253
32254                //if movement in the X axys is greater than in the Y and the currect section has slides...
32255                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
32256
32257                    //is the movement greater than the minimum resistance to scroll?
32258                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
32259                        if (touchStartX > touchEndX) {
32260                            if(isScrollAllowed.m.right){
32261                                moveSlideRight(activeSection); //next
32262                            }
32263                        } else {
32264                            if(isScrollAllowed.m.left){
32265                                moveSlideLeft(activeSection); //prev
32266                            }
32267                        }
32268                    }
32269                }
32270
32271                //vertical scrolling (only when autoScrolling is enabled)
32272                else if(options.autoScrolling && canScroll){
32273
32274                    //is the movement greater than the minimum resistance to scroll?
32275                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
32276                        if (touchStartY > touchEndY) {
32277                            scrolling('down', scrollable);
32278                        } else if (touchEndY > touchStartY) {
32279                            scrolling('up', scrollable);
32280                        }
32281                    }
32282                }
32283            }
32284        }
32285
32286        /**
32287         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
32288         * Currently works well for iOS - Android might need some testing
32289         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
32290         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
32291         * @return {boolean} true if there is a match to options.normalScrollElements
32292         */
32293        function checkParentForNormalScrollElement (el, hop) {
32294            hop = hop || 0;
32295            var parent = $(el).parent();
32296
32297            if (hop < options.normalScrollElementTouchThreshold &&
32298                parent.is(options.normalScrollElements) ) {
32299                return true;
32300            } else if (hop == options.normalScrollElementTouchThreshold) {
32301                return false;
32302            } else {
32303                return checkParentForNormalScrollElement(parent, ++hop);
32304            }
32305        }
32306
32307        /**
32308        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
32309        * this way we make sure that is really a touch event what IE is detecting.
32310        */
32311        function isReallyTouch(e){
32312            //if is not IE   ||  IE is detecting `touch` or `pen`
32313            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
32314        }
32315
32316        /**
32317        * Handler for the touch start event.
32318        */
32319        function touchStartHandler(event){
32320            var e = event.originalEvent;
32321
32322            //stopping the auto scroll to adjust to a section
32323            if(options.fitToSection){
32324                $htmlBody.stop();
32325            }
32326
32327            if(isReallyTouch(e)){
32328                var touchEvents = getEventsPage(e);
32329                touchStartY = touchEvents.y;
32330                touchStartX = touchEvents.x;
32331            }
32332        }
32333
32334        /**
32335        * Gets the average of the last `number` elements of the given array.
32336        */
32337        function getAverage(elements, number){
32338            var sum = 0;
32339
32340            //taking `number` elements from the end to make the average, if there are not enought, 1
32341            var lastElements = elements.slice(Math.max(elements.length - number, 1));
32342
32343            for(var i = 0; i < lastElements.length; i++){
32344                sum = sum + lastElements[i];
32345            }
32346
32347            return Math.ceil(sum/number);
32348        }
32349
32350        /**
32351         * Detecting mousewheel scrolling
32352         *
32353         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
32354         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
32355         */
32356        var prevTime = new Date().getTime();
32357
32358        function MouseWheelHandler(e) {
32359            var curTime = new Date().getTime();
32360            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
32361
32362            //autoscrolling and not zooming?
32363            if(options.autoScrolling && !controlPressed && !isNormalScroll){
32364                // cross-browser wheel delta
32365                e = e || window.event;
32366                var value = e.wheelDelta || -e.deltaY || -e.detail;
32367                var delta = Math.max(-1, Math.min(1, value));
32368
32369                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
32370                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
32371
32372                //Limiting the array to 150 (lets not waste memory!)
32373                if(scrollings.length > 149){
32374                    scrollings.shift();
32375                }
32376
32377                //keeping record of the previous scrollings
32378                scrollings.push(Math.abs(value));
32379
32380                //preventing to scroll the site on mouse wheel when scrollbar is present
32381                if(options.scrollBar){
32382                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
32383                }
32384
32385                var activeSection = $(SECTION_ACTIVE_SEL);
32386                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32387
32388                //time difference between the last scroll and the current one
32389                var timeDiff = curTime-prevTime;
32390                prevTime = curTime;
32391
32392                //haven't they scrolled in a while?
32393                //(enough to be consider a different scrolling action to scroll another section)
32394                if(timeDiff > 200){
32395                    //emptying the array, we dont care about old scrollings for our averages
32396                    scrollings = [];
32397                }
32398
32399                if(canScroll){
32400                    var averageEnd = getAverage(scrollings, 10);
32401                    var averageMiddle = getAverage(scrollings, 70);
32402                    var isAccelerating = averageEnd >= averageMiddle;
32403
32404                    //to avoid double swipes...
32405                    if(isAccelerating && isScrollingVertically){
32406                        //scrolling down?
32407                        if (delta < 0) {
32408                            scrolling('down', scrollable);
32409
32410                        //scrolling up?
32411                        }else {
32412                            scrolling('up', scrollable);
32413                        }
32414                    }
32415                }
32416
32417                return false;
32418            }
32419
32420            if(options.fitToSection){
32421                //stopping the auto scroll to adjust to a section
32422                $htmlBody.stop();
32423            }
32424        }
32425
32426        /**
32427        * Slides a slider to the given direction.
32428        * Optional `section` param.
32429        */
32430        function moveSlide(direction, section){
32431            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
32432            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
32433            var numSlides = slides.find(SLIDE_SEL).length;
32434
32435            // more than one slide needed and nothing should be sliding
32436            if (!slides.length || slideMoving || numSlides < 2) {
32437                return;
32438            }
32439
32440            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
32441            var destiny = null;
32442
32443            if(direction === 'left'){
32444                destiny = currentSlide.prev(SLIDE_SEL);
32445            }else{
32446                destiny = currentSlide.next(SLIDE_SEL);
32447            }
32448
32449            //isn't there a next slide in the secuence?
32450            if(!destiny.length){
32451                //respect loopHorizontal settin
32452                if (!options.loopHorizontal) return;
32453
32454                if(direction === 'left'){
32455                    destiny = currentSlide.siblings(':last');
32456                }else{
32457                    destiny = currentSlide.siblings(':first');
32458                }
32459            }
32460
32461            slideMoving = true;
32462
32463            landscapeScroll(slides, destiny, direction);
32464        }
32465
32466        /**
32467        * Maintains the active slides in the viewport
32468        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
32469        */
32470        function keepSlidesPosition(){
32471            $(SLIDE_ACTIVE_SEL).each(function(){
32472                silentLandscapeScroll($(this), 'internal');
32473            });
32474        }
32475
32476        var previousDestTop = 0;
32477        /**
32478        * Returns the destination Y position based on the scrolling direction and
32479        * the height of the section.
32480        */
32481        function getDestinationPosition(element){
32482            var elemPosition = element.position();
32483
32484            //top of the desination will be at the top of the viewport
32485            var position = elemPosition.top;
32486            var isScrollingDown =  elemPosition.top > previousDestTop;
32487            var sectionBottom = position - windowsHeight + element.outerHeight();
32488            var bigSectionsDestination = options.bigSectionsDestination;
32489
32490            //Uncode addition
32491            var containerH = container.outerHeight();
32492            var containerPosition = container.offset();
32493
32494            //########### Commented by Uncode - START ###########
32495            //is the destination element bigger than the viewport?
32496            // if(element.outerHeight() > windowsHeight){
32497            //     //scrolling up?
32498            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
32499            //         position = sectionBottom;
32500            //     }
32501            // }
32502
32503            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
32504            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
32505            //     //The bottom of the destination will be at the bottom of the viewport
32506            //     position = sectionBottom;
32507            // }
32508            //########### Commented by Uncode - END ###########
32509
32510            //Uncode addition
32511            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
32512                position += 18;
32513            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
32514                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
32515            }
32516
32517            /*
32518            Keeping record of the last scrolled position to determine the scrolling direction.
32519            No conventional methods can be used as the scroll bar might not be present
32520            AND the section might not be active if it is auto-height and didnt reach the middle
32521            of the viewport.
32522            */
32523            previousDestTop = position;
32524            return position;
32525        }
32526
32527        /**
32528        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
32529        */
32530        function scrollPage(element, callback, isMovementUp){
32531            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
32532
32533            var dtop = getDestinationPosition(element);
32534            var slideAnchorLink;
32535            var slideIndex;
32536
32537            //local variables
32538            var v = {
32539                element: element,
32540                callback: callback,
32541                isMovementUp: isMovementUp,
32542                dtop: dtop,
32543                yMovement: getYmovement(element),
32544                anchorLink: element.data('anchor'),
32545                sectionIndex: element.index(SECTION_SEL),
32546                activeSlide: element.find(SLIDE_ACTIVE_SEL),
32547                activeSection: $(SECTION_ACTIVE_SEL),
32548                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
32549
32550                //caching the value of isResizing at the momment the function is called
32551                //because it will be checked later inside a setTimeout and the value might change
32552                localIsResizing: isResizing
32553            };
32554
32555            //quiting when destination scroll is the same as the current one
32556            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
32557
32558            if(v.activeSlide.length){
32559                slideAnchorLink = v.activeSlide.data('anchor');
32560                slideIndex = v.activeSlide.index();
32561            }
32562
32563            // If continuousVertical && we need to wrap around
32564            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
32565                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
32566                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
32567
32568                v = createInfiniteSections(v);
32569            }
32570
32571            //callback (onLeave) if the site is not just resizing and readjusting the slides
32572            if($.isFunction(options.onLeave) && !v.localIsResizing){
32573                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
32574                    return;
32575                }
32576            }
32577
32578            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
32579            if(!v.localIsResizing){
32580                stopMedia(v.activeSection);
32581            }
32582
32583            options.scrollOverflowHandler.beforeLeave();
32584            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32585            lazyLoad(element);
32586            options.scrollOverflowHandler.onLeave();
32587
32588
32589            //preventing from activating the MouseWheelHandler event
32590            //more than once if the page is scrolling
32591            canScroll = false;
32592
32593            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
32594
32595            performMovement(v);
32596
32597            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
32598            lastScrolledDestiny = v.anchorLink;
32599
32600            //avoid firing it twice (as it does also on scroll)
32601            activateMenuAndNav(v.anchorLink, v.sectionIndex);
32602        }
32603
32604        /**
32605        * Performs the vertical movement (by CSS3 or by jQuery)
32606        */
32607        function performMovement(v){
32608            // using CSS3 translate functionality
32609            if (options.css3 && options.autoScrolling && !options.scrollBar) {
32610
32611                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32612                // that's why we round it to 0.
32613                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
32614                transformContainer(translate3d, true);
32615
32616                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
32617                //scrollingSpeed to change in case of using silentMoveTo();
32618                if(options.scrollingSpeed){
32619                    clearTimeout(afterSectionLoadsId);
32620                    afterSectionLoadsId = setTimeout(function () {
32621                        afterSectionLoads(v);
32622                    }, options.scrollingSpeed);
32623                }else{
32624                    afterSectionLoads(v);
32625                }
32626            }
32627
32628            // using jQuery animate
32629            else{
32630                var scrollSettings = getScrollSettings(v);
32631
32632                $(scrollSettings.element).animate(
32633                    scrollSettings.options,
32634                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
32635                    if(options.scrollBar){
32636
32637                        /* Hack!
32638                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
32639                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
32640
32641                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
32642                        */
32643                        setTimeout(function(){
32644                            afterSectionLoads(v);
32645                        },30);
32646                    }else{
32647                        afterSectionLoads(v);
32648                    }
32649                });
32650            }
32651        }
32652
32653        /**
32654        * Gets the scrolling settings depending on the plugin autoScrolling option
32655        */
32656        function getScrollSettings(v){
32657            var scroll = {};
32658
32659            if(options.autoScrolling && !options.scrollBar){
32660                scroll.options = { 'top': -v.dtop};
32661                scroll.element = WRAPPER_SEL;
32662            }else{
32663                scroll.options = { 'scrollTop': v.dtop};
32664                scroll.element = 'html, body';
32665            }
32666
32667            return scroll;
32668        }
32669
32670        /**
32671        * Adds sections before or after the current one to create the infinite effect.
32672        */
32673        function createInfiniteSections(v){
32674            // Scrolling down
32675            if (!v.isMovementUp) {
32676                // Move all previous sections to after the active section
32677                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
32678            }
32679            else { // Scrolling up
32680                // Move all next sections to before the active section
32681                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
32682            }
32683
32684            // Maintain the displayed position (now that we changed the element order)
32685            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32686
32687            // Maintain the active slides visible in the viewport
32688            keepSlidesPosition();
32689
32690            // save for later the elements that still need to be reordered
32691            v.wrapAroundElements = v.activeSection;
32692
32693            // Recalculate animation variables
32694            v.dtop = v.element.position().top;
32695            v.yMovement = getYmovement(v.element);
32696
32697            return v;
32698        }
32699
32700        /**
32701        * Fix section order after continuousVertical changes have been animated
32702        */
32703        function continuousVerticalFixSectionOrder (v) {
32704            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
32705            // finish moving the elements around so the direct navigation will function more simply
32706            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
32707                return;
32708            }
32709
32710            if (v.isMovementUp) {
32711                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
32712            }
32713            else {
32714                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
32715            }
32716
32717            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32718
32719            // Maintain the active slides visible in the viewport
32720            keepSlidesPosition();
32721        }
32722
32723
32724        /**
32725        * Actions to do once the section is loaded.
32726        */
32727        function afterSectionLoads (v){
32728            continuousVerticalFixSectionOrder(v);
32729
32730            //callback (afterLoad) if the site is not just resizing and readjusting the slides
32731            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
32732            options.scrollOverflowHandler.afterLoad();
32733
32734            if(!v.localIsResizing){
32735                playMedia(v.element);
32736            }
32737
32738            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32739
32740            canScroll = true;
32741
32742            $.isFunction(v.callback) && v.callback.call(this);
32743        }
32744
32745        /**
32746        * Sets the value for the given attribute from the `data-` attribute with the same suffix
32747        * ie: data-srcset ==> srcset  |  data-src ==> src
32748        */
32749        function setSrc(element, attribute){
32750            element
32751                .attr(attribute, element.data(attribute))
32752                .removeAttr('data-' + attribute);
32753        }
32754
32755        /**
32756        * Lazy loads image, video and audio elements.
32757        */
32758        function lazyLoad(destiny){
32759            if (!options.lazyLoading){
32760                return;
32761            }
32762
32763            var panel = getSlideOrSection(destiny);
32764            var element;
32765
32766            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
32767                element = $(this);
32768
32769                $.each(['src', 'srcset'], function(index, type){
32770                    var attribute = element.attr('data-' + type);
32771                    if(typeof attribute !== 'undefined' && attribute){
32772                        setSrc(element, type);
32773                    }
32774                });
32775
32776                if(element.is('source')){
32777                    element.closest('video').get(0).load();
32778                }
32779            });
32780        }
32781
32782        /**
32783        * Plays video and audio elements.
32784        */
32785        function playMedia(destiny){
32786            var panel = getSlideOrSection(destiny);
32787
32788            //playing HTML5 media elements
32789            panel.find('video, audio').each(function(){
32790                var element = $(this).get(0);
32791
32792                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32793                    element.play();
32794                }
32795            });
32796
32797            //youtube videos
32798            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32799                var element = $(this).get(0);
32800
32801                if ( element.hasAttribute('data-autoplay') ){
32802                    playYoutube(element);
32803                }
32804
32805                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32806                element.onload = function() {
32807                    if ( element.hasAttribute('data-autoplay') ){
32808                        playYoutube(element);
32809                    }
32810                };
32811            });
32812        }
32813
32814        /**
32815        * Plays a youtube video
32816        */
32817        function playYoutube(element){
32818            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32819        }
32820
32821        /**
32822        * Stops video and audio elements.
32823        */
32824        function stopMedia(destiny){
32825            var panel = getSlideOrSection(destiny);
32826
32827            //stopping HTML5 media elements
32828            panel.find('video, audio').each(function(){
32829                var element = $(this).get(0);
32830
32831                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32832                    element.pause();
32833                }
32834            });
32835
32836            //youtube videos
32837            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32838                var element = $(this).get(0);
32839
32840                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32841                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32842                }
32843            });
32844        }
32845
32846        /**
32847        * Gets the active slide (or section) for the given section
32848        */
32849        function getSlideOrSection(destiny){
32850            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32851            if( slide.length ) {
32852                destiny = $(slide);
32853            }
32854
32855            return destiny;
32856        }
32857
32858        /**
32859        * Scrolls to the anchor in the URL when loading the site
32860        */
32861        function scrollToAnchor(){
32862            //getting the anchor link in the URL and deleting the `#`
32863            var value =  window.location.hash.replace('#', '').split('/');
32864            var sectionAnchor = decodeURIComponent(value[0]);
32865            var slideAnchor = decodeURIComponent(value[1]);
32866
32867            if(sectionAnchor){  //if theres any #
32868                if(options.animateAnchor){
32869                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32870                }else{
32871                    silentMoveTo(sectionAnchor, slideAnchor);
32872                }
32873            }
32874        }
32875
32876        /**
32877        * Detecting any change on the URL to scroll to the given anchor link
32878        * (a way to detect back history button as we play with the hashes on the URL)
32879        */
32880        function hashChangeHandler(){
32881            if(!isScrolling && !options.lockAnchors){
32882                var value =  window.location.hash.replace('#', '').split('/');
32883                var sectionAnchor = decodeURIComponent(value[0]);
32884                var slideAnchor = decodeURIComponent(value[1]);
32885
32886                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32887                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32888                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32889
32890
32891                if(sectionAnchor.length){
32892                    /*in order to call scrollpage() only once for each destination at a time
32893                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32894                    event is fired on every scroll too.*/
32895                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32896                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32897                    }
32898                }
32899            }
32900        }
32901
32902        //Sliding with arrow keys, both, vertical and horizontal
32903        function keydownHandler(e) {
32904
32905            clearTimeout(keydownId);
32906
32907            var activeElement = $(':focus');
32908
32909            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32910                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32911                options.keyboardScrolling && options.autoScrolling){
32912                var keyCode = e.which;
32913
32914                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32915                var keyControls = [40, 38, 32, 33, 34];
32916                if($.inArray(keyCode, keyControls) > -1){
32917                    e.preventDefault();
32918                }
32919
32920                controlPressed = e.ctrlKey;
32921
32922                keydownId = setTimeout(function(){
32923                    onkeydown(e);
32924                },150);
32925            }
32926        }
32927
32928        function tooltipTextHandler(){
32929            $(this).prev().trigger('click');
32930        }
32931
32932        //to prevent scrolling while zooming
32933        function keyUpHandler(e){
32934            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32935                controlPressed = e.ctrlKey;
32936            }
32937        }
32938
32939        //binding the mousemove when the mouse's middle button is released
32940        function mouseDownHandler(e){
32941            //middle button
32942            if (e.which == 2){
32943                oldPageY = e.pageY;
32944                container.on('mousemove', mouseMoveHandler);
32945            }
32946        }
32947
32948        //unbinding the mousemove when the mouse's middle button is released
32949        function mouseUpHandler(e){
32950            //middle button
32951            if (e.which == 2){
32952                container.off('mousemove');
32953            }
32954        }
32955
32956        //Scrolling horizontally when clicking on the slider controls.
32957        function slideArrowHandler(){
32958            var section = $(this).closest(SECTION_SEL);
32959
32960            if ($(this).hasClass(SLIDES_PREV)) {
32961                if(isScrollAllowed.m.left){
32962                    moveSlideLeft(section);
32963                }
32964            } else {
32965                if(isScrollAllowed.m.right){
32966                    moveSlideRight(section);
32967                }
32968            }
32969        }
32970
32971        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32972        function blurHandler(){
32973            isWindowFocused = false;
32974            controlPressed = false;
32975        }
32976
32977        //Scrolls to the section when clicking the navigation bullet
32978        function sectionBulletHandler(e){
32979            e.preventDefault();
32980            var index = $(this).parent().index();
32981            scrollPage($(SECTION_SEL).eq(index));
32982        }
32983
32984        //Scrolls the slider to the given slide destination for the given section
32985        function slideBulletHandler(e){
32986            e.preventDefault();
32987            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
32988            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
32989
32990            landscapeScroll(slides, destiny);
32991        }
32992
32993        /**
32994        * Keydown event
32995        */
32996        function onkeydown(e){
32997            var shiftPressed = e.shiftKey;
32998
32999            //do nothing if we can not scroll or we are not using horizotnal key arrows.
33000            if(!canScroll && [37,39].indexOf(e.which) < 0){
33001                return;
33002            }
33003
33004            switch (e.which) {
33005                //up
33006                case 38:
33007                case 33:
33008                    if(isScrollAllowed.k.up){
33009                        moveSectionUp();
33010                    }
33011                    break;
33012
33013                //down
33014                case 32: //spacebar
33015                    if(shiftPressed && isScrollAllowed.k.up){
33016                        moveSectionUp();
33017                        break;
33018                    }
33019                /* falls through */
33020                case 40:
33021                case 34:
33022                    if(isScrollAllowed.k.down){
33023                        moveSectionDown();
33024                    }
33025                    break;
33026
33027                //Home
33028                case 36:
33029                    if(isScrollAllowed.k.up){
33030                        moveTo(1);
33031                    }
33032                    break;
33033
33034                //End
33035                case 35:
33036                     if(isScrollAllowed.k.down){
33037                        moveTo( $(SECTION_SEL).length );
33038                    }
33039                    break;
33040
33041                //left
33042                case 37:
33043                    if(isScrollAllowed.k.left){
33044                        moveSlideLeft();
33045                    }
33046                    break;
33047
33048                //right
33049                case 39:
33050                    if(isScrollAllowed.k.right){
33051                        moveSlideRight();
33052                    }
33053                    break;
33054
33055                default:
33056                    return; // exit this handler for other keys
33057            }
33058        }
33059
33060        /**
33061        * Detecting the direction of the mouse movement.
33062        * Used only for the middle button of the mouse.
33063        */
33064        var oldPageY = 0;
33065        function mouseMoveHandler(e){
33066            if(canScroll){
33067                // moving up
33068                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33069                    moveSectionUp();
33070                }
33071
33072                // moving down
33073                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
33074                    moveSectionDown();
33075                }
33076            }
33077            oldPageY = e.pageY;
33078        }
33079
33080        /**
33081        * Scrolls horizontal sliders.
33082        */
33083        function landscapeScroll(slides, destiny, direction){
33084            var section = slides.closest(SECTION_SEL);
33085            var v = {
33086                slides: slides,
33087                destiny: destiny,
33088                direction: direction,
33089                destinyPos: destiny.position(),
33090                slideIndex: destiny.index(),
33091                section: section,
33092                sectionIndex: section.index(SECTION_SEL),
33093                anchorLink: section.data('anchor'),
33094                slidesNav: section.find(SLIDES_NAV_SEL),
33095                slideAnchor:  getAnchor(destiny),
33096                prevSlide: section.find(SLIDE_ACTIVE_SEL),
33097                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
33098
33099                //caching the value of isResizing at the momment the function is called
33100                //because it will be checked later inside a setTimeout and the value might change
33101                localIsResizing: isResizing
33102            };
33103            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
33104            v.direction = v.direction ? v.direction : v.xMovement;
33105
33106            //important!! Only do it when not resizing
33107            if(!v.localIsResizing){
33108                //preventing from scrolling to the next/prev section when using scrollHorizontally
33109                canScroll = false;
33110            }
33111
33112            if(options.onSlideLeave){
33113
33114                //if the site is not just resizing and readjusting the slides
33115                if(!v.localIsResizing && v.xMovement!=='none'){
33116                    if($.isFunction( options.onSlideLeave )){
33117                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
33118                            slideMoving = false;
33119                            return;
33120                        }
33121                    }
33122                }
33123            }
33124
33125            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33126
33127            if(!v.localIsResizing){
33128                stopMedia(v.prevSlide);
33129                lazyLoad(destiny);
33130            }
33131
33132            if(!options.loopHorizontal && options.controlArrows){
33133                //hidding it for the fist slide, showing for the rest
33134                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
33135
33136                //hidding it for the last slide, showing for the rest
33137                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
33138            }
33139
33140            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
33141            if(section.hasClass(ACTIVE) && !v.localIsResizing){
33142                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
33143            }
33144
33145            performHorizontalMove(slides, v, true);
33146        }
33147
33148
33149        function afterSlideLoads(v){
33150            activeSlidesNavigation(v.slidesNav, v.slideIndex);
33151
33152            //if the site is not just resizing and readjusting the slides
33153            if(!v.localIsResizing){
33154                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
33155
33156                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
33157                //and to prevent double scroll right after a windows resize
33158                canScroll = true;
33159
33160                playMedia(v.destiny);
33161            }
33162
33163            //letting them slide again
33164            slideMoving = false;
33165        }
33166
33167        /**
33168        * Performs the horizontal movement. (CSS3 or jQuery)
33169        *
33170        * @param fireCallback {Bool} - determines whether or not to fire the callback
33171        */
33172        function performHorizontalMove(slides, v, fireCallback){
33173            var destinyPos = v.destinyPos;
33174
33175            if(options.css3){
33176                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
33177
33178                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
33179
33180                afterSlideLoadsId = setTimeout(function(){
33181                    fireCallback && afterSlideLoads(v);
33182                }, options.scrollingSpeed, options.easing);
33183            }else{
33184                slides.animate({
33185                    scrollLeft : Math.round(destinyPos.left)
33186                }, options.scrollingSpeed, options.easing, function() {
33187
33188                    fireCallback && afterSlideLoads(v);
33189                });
33190            }
33191        }
33192
33193        /**
33194        * Sets the state for the horizontal bullet navigations.
33195        */
33196        function activeSlidesNavigation(slidesNav, slideIndex){
33197            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
33198            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
33199        }
33200
33201        var previousHeight = windowsHeight;
33202
33203        //when resizing the site, we adjust the heights of the sections, slimScroll...
33204        function resizeHandler(){
33205            //checking if it needs to get responsive
33206            responsive();
33207
33208            // rebuild immediately on touch devices
33209            if (isTouchDevice) {
33210                var activeElement = $(document.activeElement);
33211
33212                //if the keyboard is NOT visible
33213                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
33214                    var currentHeight = $window.height();
33215
33216                    //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)
33217                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
33218                        reBuild(true);
33219                        previousHeight = currentHeight;
33220                    }
33221                }
33222            }else{
33223                //in order to call the functions only when the resize is finished
33224                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
33225                clearTimeout(resizeId);
33226
33227                resizeId = setTimeout(function(){
33228                    reBuild(true);
33229                }, 350);
33230            }
33231        }
33232
33233        /**
33234        * Checks if the site needs to get responsive and disables autoScrolling if so.
33235        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
33236        */
33237        function responsive(){
33238            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
33239            var heightLimit = options.responsiveHeight;
33240
33241            //only calculating what we need. Remember its called on the resize event.
33242            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
33243            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
33244
33245            if(widthLimit && heightLimit){
33246                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
33247            }
33248            else if(widthLimit){
33249                setResponsive(isBreakingPointWidth);
33250            }
33251            else if(heightLimit){
33252                setResponsive(isBreakingPointHeight);
33253            }
33254        }
33255
33256        /**
33257        * Adds transition animations for the given element
33258        */
33259        function addAnimation(container, element){
33260            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
33261
33262            container.removeClass(NO_TRANSITION);
33263            return container.css({
33264                '-webkit-transition': transition,
33265                'transition': transition
33266            });
33267        }
33268
33269        /**
33270        * Remove transition animations for the given element
33271        */
33272        function removeAnimation(element){
33273            return element.addClass(NO_TRANSITION);
33274        }
33275
33276        /**
33277        * Activating the vertical navigation bullets according to the given slide name.
33278        */
33279        function activateNavDots(name, sectionIndex){
33280            if(options.navigation){
33281                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
33282                if(name){
33283                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
33284                }else{
33285                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
33286                }
33287            }
33288        }
33289
33290        /**
33291        * Activating the website main menu elements according to the given slide name.
33292        */
33293        function activateMenuElement(name){
33294            if(options.menu){
33295                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
33296                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
33297            }
33298        }
33299
33300        /**
33301        * Sets to active the current menu and vertical nav items.
33302        */
33303        function activateMenuAndNav(anchor, index){
33304            activateMenuElement(anchor);
33305            activateNavDots(anchor, index);
33306        }
33307
33308        /**
33309        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
33310        * from the current section.
33311        */
33312        function getYmovement(destiny){
33313            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
33314            var toIndex = destiny.index(SECTION_SEL);
33315            if( fromIndex == toIndex){
33316                return 'none';
33317            }
33318            if(fromIndex > toIndex){
33319                return 'up';
33320            }
33321            return 'down';
33322        }
33323
33324        /**
33325        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
33326        * from the current slide.
33327        */
33328        function getXmovement(fromIndex, toIndex){
33329            if( fromIndex == toIndex){
33330                return 'none';
33331            }
33332            if(fromIndex > toIndex){
33333                return 'left';
33334            }
33335            return 'right';
33336        }
33337
33338        /**
33339        * Checks if the element needs scrollbar and if the user wants to apply it.
33340        * If so it creates it.
33341        *
33342        * @param {Object} element   jQuery object of the section or slide
33343        */
33344        function createScrollBar(element){
33345            //User doesn't want scrollbar here? Sayonara baby!
33346            if(element.hasClass('fp-noscroll')) return;
33347
33348            //needed to make `scrollHeight` work under Opera 12
33349            element.css('overflow', 'hidden');
33350
33351            var scrollOverflowHandler = options.scrollOverflowHandler;
33352            var wrap = scrollOverflowHandler.wrapContent();
33353            //in case element is a slide
33354            var section = element.closest(SECTION_SEL);
33355            var scrollable = scrollOverflowHandler.scrollable(element);
33356            var contentHeight;
33357
33358            //if there was scroll, the contentHeight will be the one in the scrollable section
33359            if(scrollable.length){
33360                contentHeight = scrollOverflowHandler.scrollHeight(element);
33361            }else{
33362                contentHeight = element.get(0).scrollHeight;
33363                if(options.verticalCentered){
33364                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
33365                }
33366            }
33367
33368            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
33369
33370            //needs scroll?
33371            if ( contentHeight > scrollHeight) {
33372                //did we already have an scrollbar ? Updating it
33373                if(scrollable.length){
33374                    scrollOverflowHandler.update(element, scrollHeight);
33375                }
33376                //creating the scrolling
33377                else{
33378                    if(options.verticalCentered){
33379                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
33380                    }else{
33381                        element.wrapInner(wrap);
33382                    }
33383                    scrollOverflowHandler.create(element, scrollHeight);
33384                }
33385            }
33386            //removing the scrolling when it is not necessary anymore
33387            else{
33388                scrollOverflowHandler.remove(element);
33389            }
33390
33391            //undo
33392            element.css('overflow', '');
33393        }
33394
33395        function addTableClass(element){
33396            //In case we are styling for the 2nd time as in with reponsiveSlides
33397            if(!element.hasClass(TABLE)){
33398                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
33399            }
33400        }
33401
33402        function getTableHeight(element){
33403            var sectionHeight = windowsHeight;
33404
33405            if(options.paddingTop || options.paddingBottom){
33406                var section = element;
33407                if(!section.hasClass(SECTION)){
33408                    section = element.closest(SECTION_SEL);
33409                }
33410
33411                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
33412                sectionHeight = (windowsHeight - paddings);
33413            }
33414
33415            return sectionHeight;
33416        }
33417
33418        /**
33419        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
33420        */
33421        function transformContainer(translate3d, animated){
33422            if(animated){
33423                addAnimation(container);
33424            }else{
33425                removeAnimation(container);
33426            }
33427
33428            container.css(getTransforms(translate3d));
33429
33430            //syncronously removing the class after the animation has been applied.
33431            setTimeout(function(){
33432                container.removeClass(NO_TRANSITION);
33433            },10);
33434        }
33435
33436        /**
33437        * Gets a section by its anchor / index
33438        */
33439        function getSectionByAnchor(sectionAnchor){
33440            if(!sectionAnchor) return [];
33441
33442            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
33443            if(!section.length){
33444                section = $(SECTION_SEL).eq( sectionAnchor -1);
33445            }
33446
33447            return section;
33448        }
33449
33450        /**
33451        * Gets a slide inside a given section by its anchor / index
33452        */
33453        function getSlideByAnchor(slideAnchor, section){
33454            var slides = section.find(SLIDES_WRAPPER_SEL);
33455            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
33456
33457            if(!slide.length){
33458                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
33459            }
33460
33461            return slide;
33462        }
33463
33464        /**
33465        * Scrolls to the given section and slide anchors
33466        */
33467        function scrollPageAndSlide(destiny, slide){
33468            var section = getSectionByAnchor(destiny);
33469
33470            //do nothing if there's no section with the given anchor name
33471            if(!section.length) return;
33472
33473            //default slide
33474            if (typeof slide === 'undefined') {
33475                slide = 0;
33476            }
33477
33478            //we need to scroll to the section and then to the slide
33479            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
33480                scrollPage(section, function(){
33481                    scrollSlider(section, slide);
33482                });
33483            }
33484            //if we were already in the section
33485            else{
33486                scrollSlider(section, slide);
33487            }
33488        }
33489
33490        /**
33491        * Scrolls the slider to the given slide destination for the given section
33492        */
33493        function scrollSlider(section, slideAnchor){
33494            if(typeof slideAnchor !== 'undefined'){
33495                var slides = section.find(SLIDES_WRAPPER_SEL);
33496                var destiny =  getSlideByAnchor(slideAnchor, section);
33497
33498                if(destiny.length){
33499                    landscapeScroll(slides, destiny);
33500                }
33501            }
33502        }
33503
33504        /**
33505        * Creates a landscape navigation bar with dots for horizontal sliders.
33506        */
33507        function addSlidesNavigation(section, numSlides){
33508            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
33509            var nav = section.find(SLIDES_NAV_SEL);
33510
33511            //top or bottom
33512            nav.addClass(options.slidesNavPosition);
33513
33514            for(var i=0; i< numSlides; i++){
33515                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
33516            }
33517
33518            //centering it
33519            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
33520
33521            nav.find('li').first().find('a').addClass(ACTIVE);
33522        }
33523
33524
33525        /**
33526        * Sets the state of the website depending on the active section/slide.
33527        * It changes the URL hash when needed and updates the body class.
33528        */
33529        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
33530            var sectionHash = '';
33531
33532            if(options.anchors.length && !options.lockAnchors){
33533
33534                //isn't it the first slide?
33535                if(slideIndex){
33536                    if(typeof anchorLink !== 'undefined'){
33537                        sectionHash = anchorLink;
33538                    }
33539
33540                    //slide without anchor link? We take the index instead.
33541                    if(typeof slideAnchor === 'undefined'){
33542                        slideAnchor = slideIndex;
33543                    }
33544
33545                    lastScrolledSlide = slideAnchor;
33546                    setUrlHash(sectionHash + '/' + slideAnchor);
33547
33548                //first slide won't have slide anchor, just the section one
33549                }else if(typeof slideIndex !== 'undefined'){
33550                    lastScrolledSlide = slideAnchor;
33551                    setUrlHash(anchorLink);
33552                }
33553
33554                //section without slides
33555                else{
33556                    setUrlHash(anchorLink);
33557                }
33558            }
33559
33560            setBodyClass();
33561        }
33562
33563        /**
33564        * Sets the URL hash.
33565        */
33566        function setUrlHash(url){
33567            //Uncode addition
33568            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
33569                return false;
33570
33571            if(options.recordHistory){
33572                location.hash = url;
33573            }else{
33574                //Uncode addition
33575                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
33576                // if(isTouchDevice || isTouch){
33577                //     window.history.replaceState(undefined, undefined, '#' + url);
33578                // }else{
33579                //     var baseUrl = window.location.href.split('#')[0];
33580                //     window.location.replace( baseUrl + '#' + url );
33581                // }
33582                return false;
33583            }
33584        }
33585
33586        /**
33587        * Gets the anchor for the given slide / section. Its index will be used if there's none.
33588        */
33589        function getAnchor(element){
33590            var anchor = element.data('anchor');
33591            var index = element.index();
33592
33593            //Slide without anchor link? We take the index instead.
33594            if(typeof anchor === 'undefined'){
33595                anchor = index;
33596            }
33597
33598            return anchor;
33599        }
33600
33601        /**
33602        * Sets a class for the body of the page depending on the active section / slide
33603        */
33604        function setBodyClass(){
33605            var section = $(SECTION_ACTIVE_SEL);
33606            var slide = section.find(SLIDE_ACTIVE_SEL);
33607
33608            var sectionAnchor = getAnchor(section);
33609            var slideAnchor = getAnchor(slide);
33610
33611            var text = String(sectionAnchor);
33612
33613            if(slide.length){
33614                text = text + '-' + slideAnchor;
33615            }
33616
33617            //changing slash for dash to make it a valid CSS style
33618            text = text.replace('/', '-').replace('#','');
33619
33620            //removing previous anchor classes
33621            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
33622            $body[0].className = $body[0].className.replace(classRe, '');
33623
33624            //adding the current anchor
33625            $body.addClass(VIEWING_PREFIX + '-' + text);
33626        }
33627
33628        /**
33629        * Checks for translate3d support
33630        * @return boolean
33631        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
33632        */
33633        function support3d() {
33634            var el = document.createElement('p'),
33635                has3d,
33636                transforms = {
33637                    'webkitTransform':'-webkit-transform',
33638                    'OTransform':'-o-transform',
33639                    'msTransform':'-ms-transform',
33640                    'MozTransform':'-moz-transform',
33641                    'transform':'transform'
33642                };
33643
33644            // Add it to the body to get the computed style.
33645            document.body.insertBefore(el, null);
33646
33647            for (var t in transforms) {
33648                if (el.style[t] !== undefined) {
33649                    el.style[t] = 'translate3d(1px,1px,1px)';
33650                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
33651                }
33652            }
33653
33654            document.body.removeChild(el);
33655
33656            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
33657        }
33658
33659        /**
33660        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
33661        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
33662        */
33663        function removeMouseWheelHandler(){
33664            if (document.addEventListener) {
33665                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
33666                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
33667                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
33668            } else {
33669                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
33670            }
33671        }
33672
33673        /**
33674        * Adds the auto scrolling action for the mouse wheel and trackpad.
33675        * After this function is called, the mousewheel and trackpad movements will scroll through sections
33676        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
33677        */
33678        function addMouseWheelHandler(){
33679            var prefix = '';
33680            var _addEventListener;
33681
33682            if (window.addEventListener){
33683                _addEventListener = "addEventListener";
33684            }else{
33685                _addEventListener = "attachEvent";
33686                prefix = 'on';
33687            }
33688
33689             // detect available wheel event
33690            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
33691                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
33692                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
33693            var passiveEvent = g_supportsPassive ? {passive: false }
33693: false;
33694
33695
33696            if(support == 'DOMMouseScroll'){
33697                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
33698            }
33699
33700            //handle MozMousePixelScroll in older Firefox
33701            else{
33702                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
33703            }
33704        }
33705
33706        /**
33707        * Binding the mousemove when the mouse's middle button is pressed
33708        */
33709        function addMiddleWheelHandler(){
33710            container
33711                .on('mousedown', mouseDownHandler)
33712                .on('mouseup', mouseUpHandler);
33713        }
33714
33715        /**
33716        * Unbinding the mousemove when the mouse's middle button is released
33717        */
33718        function removeMiddleWheelHandler(){
33719            container
33720                .off('mousedown', mouseDownHandler)
33721                .off('mouseup', mouseUpHandler);
33722        }
33723
33724        /**
33725        * Adds the possibility to auto scroll through sections on touch devices.
33726        */
33727        function addTouchHandler(){
33728            if(isTouchDevice || isTouch){
33729                if(options.autoScrolling){
33730                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
33731                }
33732
33733                $(WRAPPER_SEL)
33734                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
33735                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
33736            }
33737        }
33738
33739        /**
33740        * Removes the auto scrolling for touch devices.
33741        */
33742        function removeTouchHandler(){
33743            if(isTouchDevice || isTouch){
33744                $(WRAPPER_SEL)
33745                    .off(events.touchstart)
33746                    .off(events.touchmove);
33747            }
33748        }
33749
33750        /*
33751        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
33752        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
33753        */
33754        function getMSPointer(){
33755            var pointer;
33756
33757            //IE >= 11 & rest of browsers
33758            if(window.PointerEvent){
33759                pointer = { down: 'pointerdown', move: 'pointermove'};
33760            }
33761
33762            //IE < 11
33763            else{
33764                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
33765            }
33766
33767            return pointer;
33768        }
33769
33770        /**
33771        * Gets the pageX and pageY properties depending on the browser.
33772        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
33773        */
33774        function getEventsPage(e){
33775            var events = [];
33776
33777            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
33778            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33779
33780            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33781            if(isTouch && isReallyTouch(e) && options.scrollBar){
33782                events.y = e.touches[0].pageY;
33783                events.x = e.touches[0].pageX;
33784            }
33785
33786            return events;
33787        }
33788
33789        /**
33790        * Slides silently (with no animation) the active slider to the given slide.
33791        * @param noCallback {bool} true or defined -> no callbacks
33792        */
33793        function silentLandscapeScroll(activeSlide, noCallbacks){
33794            setScrollingSpeed (0, 'internal');
33795
33796            if(typeof noCallbacks !== 'undefined'){
33797                //preventing firing callbacks afterSlideLoad etc.
33798                isResizing = true;
33799            }
33800
33801            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33802
33803            if(typeof noCallbacks !== 'undefined'){
33804                isResizing = false;
33805            }
33806
33807            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33808        }
33809
33810        /**
33811        * Scrolls silently (with no animation) the page to the given Y position.
33812        */
33813        function silentScroll(top){
33814            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33815            // that's why we round it to 0.
33816            var roundedTop = Math.round(top);
33817
33818            if (options.css3 && options.autoScrolling && !options.scrollBar){
33819                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33820                transformContainer(translate3d, false);
33821            }
33822            else if(options.autoScrolling && !options.scrollBar){
33823                container.css('top', -roundedTop);
33824            }
33825            else{
33826                $htmlBody.scrollTop(roundedTop);
33827            }
33828        }
33829
33830        /**
33831        * Returns the cross-browser transform string.
33832        */
33833        function getTransforms(translate3d){
33834            return {
33835                '-webkit-transform': translate3d,
33836                '-moz-transform': translate3d,
33837                '-ms-transform':translate3d,
33838                'transform': translate3d
33839            };
33840        }
33841
33842        /**
33843        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33844        * @type  m (mouse) or k (keyboard)
33845        */
33846        function setIsScrollAllowed(value, direction, type){
33847            switch (direction){
33848                case 'up': isScrollAllowed[type].up = value; break;
33849                case 'down': isScrollAllowed[type].down = value; break;
33850                case 'left': isScrollAllowed[type].left = value; break;
33851                case 'right': isScrollAllowed[type].right = value; break;
33852                case 'all':
33853                    if(type == 'm'){
33854                        setAllowScrolling(value);
33855                    }else{
33856                        setKeyboardScrolling(value);
33857                    }
33858            }
33859        }
33860
33861        /*
33862        * Destroys fullpage.js plugin events and optinally its html markup and styles
33863        */
33864        function destroy(all){
33865            setAutoScrolling(false, 'internal');
33866            setAllowScrolling(false);
33867            setKeyboardScrolling(false);
33868            container.addClass(DESTROYED);
33869
33870            clearTimeout(afterSlideLoadsId);
33871            clearTimeout(afterSectionLoadsId);
33872            clearTimeout(resizeId);
33873            clearTimeout(scrollId);
33874            clearTimeout(scrollId2);
33875
33876            $window
33877                .off('scroll', scrollHandler)
33878                .off('hashchange', hashChangeHandler)
33879                .off('resize', resizeHandler);
33880
33881            $document
33882                .off('click touchstart', SECTION_NAV_SEL + ' a')
33883                .off('mouseenter', SECTION_NAV_SEL + ' li')
33884                .off('mouseleave', SECTION_NAV_SEL + ' li')
33885                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33886                .off('mouseover', options.normalScrollElements)
33887                .off('mouseout', options.normalScrollElements);
33888
33889            $(SECTION_SEL)
33890                .off('click touchstart', SLIDES_ARROW_SEL);
33891
33892            clearTimeout(afterSlideLoadsId);
33893            clearTimeout(afterSectionLoadsId);
33894
33895            //lets make a mess!
33896            if(all){
33897                destroyStructure();
33898            }
33899        }
33900
33901        /*
33902        * Removes inline styles added by fullpage.js
33903        */
33904        function destroyStructure(){
33905            //reseting the `top` or `translate` properties to 0
33906            silentScroll(0);
33907
33908            //loading all the lazy load content
33909            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33910                setSrc($(this), 'src');
33911            });
33912
33913            container.find('img[data-srcset]').each(function(){
33914                setSrc($(this), 'srcset');
33915            });
33916
33917            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33918
33919            //removing inline styles
33920            $(SECTION_SEL).css( {
33921                'height': '',
33922                'background-color' : '',
33923                'padding': ''
33924            });
33925
33926            $(SLIDE_SEL).css( {
33927                'width': ''
33928            });
33929
33930            container.css({
33931                'height': '',
33932                'position': '',
33933                '-ms-touch-action': '',
33934                'touch-action': ''
33935            });
33936
33937            $htmlBody.css({
33938                'overflow': '',
33939                'height': ''
33940            });
33941
33942            // remove .fp-enabled class
33943            $('html').removeClass(ENABLED);
33944
33945            // remove .fp-responsive class
33946            $body.removeClass(RESPONSIVE);
33947
33948            // remove all of the .fp-viewing- classes
33949            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33950                if (className.indexOf(VIEWING_PREFIX) === 0) {
33951                    $body.removeClass(className);
33952                }
33953            });
33954
33955            //removing added classes
33956            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
33957                options.scrollOverflowHandler.remove($(this));
33958                $(this).removeClass(TABLE + ' ' + ACTIVE);
33959            });
33960
33961            removeAnimation(container);
33962
33963            //Unwrapping content
33964            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
33965                //unwrap not being use in case there's no child element inside and its just text
33966                $(this).replaceWith(this.childNodes);
33967            });
33968
33969            //removing the applied transition from the fullpage wrapper
33970            container.css({
33971                '-webkit-transition': 'none',
33972                'transition': 'none'
33973            });
33974
33975            //scrolling the page to the top with no animation
33976            $htmlBody.scrollTop(0);
33977
33978            //removing selectors
33979            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
33980            $.each(usedSelectors, function(index, value){
33981                $('.' + value).removeClass(value);
33982            });
33983        }
33984
33985        /*
33986        * Sets the state for a variable with multiple states (original, and temporal)
33987        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
33988        * This function is used to keep track of both states, the original and the temporal one.
33989        * If type is not 'internal', then we assume the user is globally changing the variable.
33990        */
33991        function setVariableState(variable, value, type){
33992            options[variable] = value;
33993            if(type !== 'internal'){
33994                originals[variable] = value;
33995            }
33996        }
33997
33998        /**
33999        * Displays warnings
34000        */
34001        function displayWarnings(){
34002            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
34003            //UNCODE.addition
34004            // if($('html').hasClass(ENABLED)){
34005            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
34006            //     return;
34007            // }
34008
34009            // Disable mutually exclusive settings
34010            //UNCODE.addition
34011            // if (options.continuousVertical &&
34012            //     (options.loopTop || options.loopBottom)) {
34013            //     options.continuousVertical = false;
34014            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34015            // }
34016
34017            // if(options.scrollBar && options.scrollOverflow){
34018            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34019            // }
34020
34021            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34022            //     options.continuousVertical = false;
34023            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34024            // }
34025
34026            //using extensions? Wrong file!
34027            $.each(extensions, function(index, extension){
34028                //is the option set to true?
34029                if(options[extension]){
34030                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34031                }
34032            });
34033
34034            //anchors can not have the same value as any element ID or NAME
34035            $.each(options.anchors, function(index, name){
34036
34037                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34038                var nameAttr = $document.find('[name]').filter(function() {
34039                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34040                });
34041
34042                var idAttr = $document.find('[id]').filter(function() {
34043                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34044                });
34045
34046                if(idAttr.length || nameAttr.length ){
34047                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34048                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34049                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34050                }
34051            });
34052        }
34053
34054        /**
34055        * Shows a message in the console of the given type.
34056        */
34057        function showError(type, text){
34058            console && console[type] && console[type]('fullPage: ' + text);
34059        }
34060
34061    }; //end of $.fn.fullpage
34062
34063    if(typeof IScroll !== 'undefined'){
34064        /*
34065        * Turns iScroll `mousewheel` option off dynamically
34066        * https://github.com/cubiq/iscroll/issues/1036
34067        */
34068        IScroll.prototype.wheelOn = function () {
34069            this.wrapper.addEventListener('wheel', this);
34070            this.wrapper.addEventListener('mousewheel', this);
34071            this.wrapper.addEventListener('DOMMouseScroll', this);
34072        };
34073
34074        /*
34075        * Turns iScroll `mousewheel` option on dynamically
34076        * https://github.com/cubiq/iscroll/issues/1036
34077        */
34078        IScroll.prototype.wheelOff = function () {
34079            this.wrapper.removeEventListener('wheel', this);
34080            this.wrapper.removeEventListener('mousewheel', this);
34081            this.wrapper.removeEventListener('DOMMouseScroll', this);
34082        };
34083    }
34084
34085    /**
34086     * An object to handle overflow scrolling.
34087     * This uses jquery.slimScroll to accomplish overflow scrolling.
34088     * It is possible to pass in an alternate scrollOverflowHandler
34089     * to the fullpage.js option that implements the same functions
34090     * as this handler.
34091     *
34092     * @type {Object}
34093     */
34094    var iscrollHandler = {
34095        refreshId: null,
34096        iScrollInstances: [],
34097
34098        // Enables or disables the mouse wheel for the active section or all slides in it
34099        toggleWheel: function(value){
34100            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
34101            scrollable.each(function(){
34102                var iScrollInstance = $(this).data('iscrollInstance');
34103                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
34104                    if(value){
34105                        iScrollInstance.wheelOn();
34106                    }
34107                    else{
34108                        iScrollInstance.wheelOff();
34109                    }
34110                }
34111            });
34112        },
34113
34114        /**
34115        * Turns off iScroll for the destination section.
34116        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
34117        * scroll the destination section/slide before the sections animations ends.
34118        */
34119        onLeave: function(){
34120            iscrollHandler.toggleWheel(false);
34121        },
34122
34123        // Turns off iScroll for the leaving section
34124        beforeLeave: function(){
34125            iscrollHandler.onLeave()
34126        },
34127
34128        // Turns on iScroll on section load
34129        afterLoad: function(){
34130            iscrollHandler.toggleWheel(true);
34131        },
34132
34133        /**
34134         * Called when overflow scrolling is needed for a section.
34135         *
34136         * @param  {Object} element      jQuery object containing current section
34137         * @param  {Number} scrollHeight Current window height in pixels
34138         */
34139        create: function(element, scrollHeight) {
34140            var scrollable = element.find(SCROLLABLE_SEL);
34141
34142            scrollable.height(scrollHeight);
34143            scrollable.each(function() {
34144                var $this = $(this);
34145                var iScrollInstance = $this.data('iscrollInstance');
34146                if (iScrollInstance) {
34147                    $.each(iscrollHandler.iScrollInstances, function(){
34148                        $(this).destroy();
34149                    });
34150                }
34151
34152                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
34153                iscrollHandler.iScrollInstances.push(iScrollInstance);
34154
34155                //off by default until the section gets active
34156                iScrollInstance.wheelOff();
34157
34158                $this.data('iscrollInstance', iScrollInstance);
34159            });
34160        },
34161
34162        /**
34163         * Return a boolean depending on whether the scrollable element is a
34164         * the end or at the start of the scrolling depending on the given type.
34165         *
34166         * @param  {String}  type       Either 'top' or 'bottom'
34167         * @param  {Object}  scrollable jQuery object for the scrollable element
34168         * @return {Boolean}
34169         */
34170        isScrolled: function(type, scrollable) {
34171            var scroller = scrollable.data('iscrollInstance');
34172
34173            //no scroller?
34174            if (!scroller) {
34175                return true;
34176            }
34177
34178            //Uncode addition
34179            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
34180            //End Uncode addition
34181
34182            if (type === 'top') {
34183                return scroller.y >= 0 && !scrollable.scrollTop();
34184            } else if (type === 'bottom') {
34185                //Uncode change
34186                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34187                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34188                //End Uncode change
34189            }
34190        },
34191
34192        /**
34193         * Returns the scrollable element for the given section.
34194         * If there are landscape slides, will only return a scrollable element
34195         * if it is in the active slide.
34196         *
34197         * @param  {Object}  activeSection jQuery object containing current section
34198         * @return {Boolean}
34199         */
34200        scrollable: function(activeSection){
34201            // if there are landscape slides, we check if the scrolling bar is in the current one or not
34202            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
34203                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
34204            }
34205            return activeSection.find(SCROLLABLE_SEL);
34206        },
34207
34208        /**
34209         * Returns the scroll height of the wrapped content.
34210         * If this is larger than the window height minus section padding,
34211         * overflow scrolling is needed.
34212         *
34213         * @param  {Object} element jQuery object containing current section
34214         * @return {Number}
34215         */
34216        scrollHeight: function(element) {
34217            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
34218        },
34219
34220        /**
34221         * Called when overflow scrolling is no longer needed for a section.
34222         *
34223         * @param  {Object}
34223 element      jQuery object containing current section
34224         */
34225        remove: function(element) {
34226            var scrollable = element.find(SCROLLABLE_SEL);
34227            if (scrollable.length) {
34228                var iScrollInstance = scrollable.data('iscrollInstance');
34229                iScrollInstance.destroy();
34230
34231                scrollable.data('iscrollInstance', null);
34232            }
34233            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
34234        },
34235
34236        /**
34237         * Called when overflow scrolling has already been setup but the
34238         * window height has potentially changed.
34239         *
34240         * @param  {Object} element      jQuery object containing current section
34241         * @param  {Number} scrollHeight Current window height in pixels
34242         */
34243        update: function(element, scrollHeight) {
34244            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
34245            //short period of time.
34246            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
34247            clearTimeout(iscrollHandler.refreshId);
34248            iscrollHandler.refreshId = setTimeout(function(){
34249                $.each(iscrollHandler.iScrollInstances, function(){
34250                    $(this).get(0).refresh();
34251                });
34252            }, 150);
34253
34254            //updating the wrappers height
34255            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
34256        },
34257
34258        /**
34259         * Called to get any additional elements needed to wrap the section
34260         * content in order to facilitate overflow scrolling.
34261         *
34262         * @return {String|Object} Can be a string containing HTML,
34263         *                         a DOM element, or jQuery object.
34264         */
34265        wrapContent: function() {
34266            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
34267        }
34268    };
34269});
34270
34271(function (global, factory) {
34272	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
34273	typeof define === 'function' && define.amd ? define(['exports'], factory) :
34274	(global = global || self, factory(global.window = global.window || {}));
34275}(this, (function (exports) { 'use strict';
34276
34277	/*!
34278	 * ScrollTrigger 3.8.0
34279	 * https://greensock.com
34280	 *
34281	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
34282	 * Subject to the terms at https://greensock.com/standard-license or for
34283	 * Club GreenSock members, the agreement issued with that membership.
34284	 * @author: Jack Doyle, [email protected]
34285	*/
34286	var gsap,
34287	    _coreInitted,
34288	    _win,
34289	    _doc,
34290	    _docEl,
34291	    _body,
34292	    _root,
34293	    _resizeDelay,
34294	    _raf,
34295	    _request,
34296	    _toArray,
34297	    _clamp,
34298	    _time2,
34299	    _syncInterval,
34300	    _refreshing,
34301	    _pointerIsDown,
34302	    _transformProp,
34303	    _i,
34304	    _prevWidth,
34305	    _prevHeight,
34306	    _autoRefresh,
34307	    _sort,
34308	    _suppressOverwrites,
34309	    _ignoreResize,
34310	    _limitCallbacks,
34311	    _startup = 1,
34312	    _proxies = [],
34313	    _scrollers = [],
34314	    _getTime = Date.now,
34315	    _time1 = _getTime(),
34316	    _lastScrollTime = 0,
34317	    _enabled = 1,
34318	    _passThrough = function _passThrough(v) {
34319	  return v;
34320	},
34321	    _getTarget = function _getTarget(t) {
34322	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
34323	},
34324	    _round = function _round(value) {
34325	  return Math.round(value * 100000) / 100000 || 0;
34326	},
34327	    _windowExists = function _windowExists() {
34328	  return typeof window !== "undefined";
34329	},
34330	    _getGSAP = function _getGSAP() {
34331	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
34332	},
34333	    _isViewport = function _isViewport(e) {
34334	  return !!~_root.indexOf(e);
34335	},
34336	    _getProxyProp = function _getProxyProp(element, property) {
34337	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
34338	},
34339	    _getScrollFunc = function _getScrollFunc(element, _ref) {
34340	  var s = _ref.s,
34341	      sc = _ref.sc;
34342
34343	  var i = _scrollers.indexOf(element),
34344	      offset = sc === _vertical.sc ? 1 : 2;
34345
34346	  !~i && (i = _scrollers.push(element) - 1);
34347	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
34348	    return arguments.length ? element[s] = value : element[s];
34349	  }));
34350	},
34351	    _getBoundsFunc = function _getBoundsFunc(element) {
34352	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
34353	    _winOffsets.width = _win.innerWidth;
34354	    _winOffsets.height = _win.innerHeight;
34355	    return _winOffsets;
34356	  } : function () {
34357	    return _getBounds(element);
34358	  });
34359	},
34360	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
34361	  var d = _ref2.d,
34362	      d2 = _ref2.d2,
34363	      a = _ref2.a;
34364	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
34365	    return a()[d];
34366	  } : function () {
34367	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
34368	  };
34369	},
34370	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
34371	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
34372	    return _winOffsets;
34373	  };
34374	},
34375	    _maxScroll = function _maxScroll(element, _ref3) {
34376	  var s = _ref3.s,
34377	      d2 = _ref3.d2,
34378	      d = _ref3.d,
34379	      a = _ref3.a;
34380	  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];
34381	},
34382	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
34383	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 34384-34588
34384	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
34385	  }
34386	},
34387	    _isString = function _isString(value) {
34388	  return typeof value === "string";
34389	},
34390	    _isFunction = function _isFunction(value) {
34391	  return typeof value === "function";
34392	},
34393	    _isNumber = function _isNumber(value) {
34394	  return typeof value === "number";
34395	},
34396	    _isObject = function _isObject(value) {
34397	  return typeof value === "object";
34398	},
34399	    _callIfFunc = function _callIfFunc(value) {
34400	  return _isFunction(value) && value();
34401	},
34402	    _combineFunc = function _combineFunc(f1, f2) {
34403	  return function () {
34404	    var result1 = _callIfFunc(f1),
34405	        result2 = _callIfFunc(f2);
34406
34407	    return function () {
34408	      _callIfFunc(result1);
34409
34410	      _callIfFunc(result2);
34411	    };
34412	  };
34413	},
34414	    _endAnimation = function _endAnimation(animation, reversed, pause) {
34415	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
34416	},
34417	    _callback = function _callback(self, func) {
34418	  var result = func(self);
34419	  result && result.totalTime && (self.callbackAnimation = result);
34420	},
34421	    _abs = Math.abs,
34422	    _scrollLeft = "scrollLeft",
34423	    _scrollTop = "scrollTop",
34424	    _left = "left",
34425	    _top = "top",
34426	    _right = "right",
34427	    _bottom = "bottom",
34428	    _width = "width",
34429	    _height = "height",
34430	    _Right = "Right",
34431	    _Left = "Left",
34432	    _Top = "Top",
34433	    _Bottom = "Bottom",
34434	    _padding = "padding",
34435	    _margin = "margin",
34436	    _Width = "Width",
34437	    _Height = "Height",
34438	    _px = "px",
34439	    _horizontal = {
34440	  s: _scrollLeft,
34441	  p: _left,
34442	  p2: _Left,
34443	  os: _right,
34444	  os2: _Right,
34445	  d: _width,
34446	  d2: _Width,
34447	  a: "x",
34448	  sc: function sc(value) {
34449	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
34450	  }
34451	},
34452	    _vertical = {
34453	  s: _scrollTop,
34454	  p: _top,
34455	  p2: _Top,
34456	  os: _bottom,
34457	  os2: _Bottom,
34458	  d: _height,
34459	  d2: _Height,
34460	  a: "y",
34461	  op: _horizontal,
34462	  sc: function sc(value) {
34463	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
34464	  }
34465	},
34466	    _getComputedStyle = function _getComputedStyle(element) {
34467	  return _win.getComputedStyle(element);
34468	},
34469	    _makePositionable = function _makePositionable(element) {
34470	  var position = _getComputedStyle(element).position;
34471
34472	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
34473	},
34474	    _setDefaults = function _setDefaults(obj, defaults) {
34475	  for (var p in defaults) {
34476	    p in obj || (obj[p] = defaults[p]);
34477	  }
34478
34479	  return obj;
34480	},
34481	    _getBounds = function _getBounds(element, withoutTransforms) {
34482	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
34483	    x: 0,
34484	    y: 0,
34485	    xPercent: 0,
34486	    yPercent: 0,
34487	    rotation: 0,
34488	    rotationX: 0,
34489	    rotationY: 0,
34490	    scale: 1,
34491	    skewX: 0,
34492	    skewY: 0
34493	  }).progress(1),
34494	      bounds = element.getBoundingClientRect();
34495	  tween && tween.progress(0).kill();
34496	  return bounds;
34497	},
34498	    _getSize = function _getSize(element, _ref4) {
34499	  var d2 = _ref4.d2;
34500	  return element["offset" + d2] || element["client" + d2] || 0;
34501	},
34502	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
34503	  var a = [],
34504	      labels = timeline.labels,
34505	      duration = timeline.duration(),
34506	      p;
34507
34508	  for (p in labels) {
34509	    a.push(labels[p] / duration);
34510	  }
34511
34512	  return a;
34513	},
34514	    _getClosestLabel = function _getClosestLabel(animation) {
34515	  return function (value) {
34516	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
34517	  };
34518	},
34519	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
34520	  var snap = gsap.utils.snap(snapIncrementOrArray),
34521	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
34522	    return a - b;
34523	  });
34524	  return a ? function (value, direction) {
34525	    var i;
34526
34527	    if (!direction) {
34528	      return snap(value);
34529	    }
34530
34531	    if (direction > 0) {
34532	      value -= 1e-4;
34533
34534	      for (i = 0; i < a.length; i++) {
34535	        if (a[i] >= value) {
34536	          return a[i];
34537	        }
34538	      }
34539
34540	      return a[i - 1];
34541	    } else {
34542	      i = a.length;
34543	      value += 1e-4;
34544
34545	      while (i--) {
34546	        if (a[i] <= value) {
34547	          return a[i];
34548	        }
34549	      }
34550	    }
34551
34552	    return a[0];
34553	  } : function (value, direction) {
34554	    var snapped = snap(value);
34555	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
34556	  };
34557	},
34558	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
34559	  return function (value, st) {
34560	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
34561	  };
34562	},
34563	    _multiListener = function _multiListener(func, element, types, callback) {
34564	  return types.split(",").forEach(function (type) {
34565	    return func(element, type, callback);
34566	  });
34567	},
34568	    _addListener = function _addListener(element, type, func) {
34569	  return element.addEventListener(type, func, {
34570	    passive: true
34571	  });
34572	},
34573	    _removeListener = function _removeListener(element, type, func) {
34574	  return element.removeEventListener(type, func);
34575	},
34576	    _markerDefaults = {
34577	  startColor: "green",
34578	  endColor: "red",
34579	  indent: 0,
34580	  fontSize: "16px",
34581	  fontWeight: "normal"
34582	},
34583	    _defaults = {
34584	  toggleActions: "play",
34585	  anticipatePin: 0
34586	},
34587	    _keywords = {
34588	  top: 0,
34589	  left: 0,
34590	  center: 0.5,
34591	  bottom: 1,
34592	  right: 1
34593	},
34594	    _offsetToPx = function _offsetToPx(value, size) {
34595	  if (_isString(value)) {
34596	    var eqIndex = value.indexOf("="),
34597	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
34598
34599	    if (~eqIndex) {
34600	      value.indexOf("%") > eqIndex && (relative *= size / 100);
34601	      value = value.substr(0, eqIndex - 1);
34602	    }
34603
34604	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
34605	  }
34606
34607	  return value;
34608	},
34609	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
34610	  var startColor = _ref5.startColor,
34611	      endColor = _ref5.endColor,
34612	      fontSize = _ref5.fontSize,
34613	      indent = _ref5.indent,
34614	      fontWeight = _ref5.fontWeight;
34615
34616	  var e = _doc.createElement("div"),
34617	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
34618	      isScroller = type.indexOf("scroller") !== -1,
34619	      parent = useFixedPosition ? _body : container,
34620	      isStart = type.indexOf("start") !== -1,
34621	      color = isStart ? startColor : endColor,
34622	      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;";
34623
34624	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
34625	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
34626	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
34627	  e._isStart = isStart;
34628	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
34629	  e.style.cssText = css;
34630	  e.innerText = name || name === 0 ? type + "-" + name : type;
34631	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
34632	  e._offset = e["offset" + direction.op.d2];
34633
34634	  _positionMarker(e, 0, direction, isStart);
34635
34636	  return e;
34637	},
34638	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
34639	  var vars = {
34640	    display: "block"
34641	  },
34642	      side = direction[flipped ? "os2" : "p2"],
34643	      oppositeSide = direction[flipped ? "p2" : "os2"];
34644	  marker._isFlipped = flipped;
34645	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
34646	  vars[direction.a] = flipped ? "1px" : 0;
34647	  vars["border" + side + _Width] = 1;
34648	  vars["border" + oppositeSide + _Width] = 0;
34649	  vars[direction.p] = start + "px";
34650	  gsap.set(marker, vars);
34651	},
34652	    _triggers = [],
34653	    _ids = {},
34654	    _sync = function _sync() {
34655	  return _getTime() - _lastScrollTime > 20 && _updateAll();
34656	},
34657	    _onScroll = function _onScroll() {
34658	  var time = _getTime();
34659
34660	  if (_lastScrollTime !== time) {
34661	    _updateAll();
34662
34663	    _lastScrollTime || _dispatch("scrollStart");
34664	    _lastScrollTime = time;
34665	  } else if (!_request) {
34666	    _request = _raf(_updateAll);
34667	  }
34668	},
34669	    _onResize = function _onResize() {
34670	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
34671	},
34672	    _listeners = {},
34673	    _emptyArray = [],
34674	    _media = [],
34675	    _creatingMedia,
34676	    _lastMediaTick,
34677	    _onMediaChange = function _onMediaChange(e) {
34678	  var tick = gsap.ticker.frame,
34679	      matches = [],
34680	      i = 0,
34681	      index;
34682
34683	  if (_lastMediaTick !== tick || _startup) {
34684	    _revertAll();
34685
34686	    for (; i < _media.length; i += 4) {
34687	      index = _win.matchMedia(_media[i]).matches;
34688
34689	      if (index !== _media[i + 3]) {
34690	        _media[i + 3] = index;
34691	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
34692	      }
34693	    }
34694
34695	    _revertRecorded();
34696
34697	    for (i = 0; i < matches.length; i++) {
34698	      index = matches[i];
34699	      _creatingMedia = _media[index];
34700	      _media[index + 2] = _media[index + 1](e);
34701	    }
34702
34703	    _creatingMedia = 0;
34704	    _coreInitted && _refreshAll(0, 1);
34705	    _lastMediaTick = tick;
34706
34707	    _dispatch("matchMedia");
34708	  }
34709	},
34710	    _softRefresh = function _softRefresh() {
34711	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
34712	},
34713	    _dispatch = function _dispatch(type) {
34714	  return _listeners[type] && _listeners[type].map(function (f) {
34715	    return f();
34716	  }) || _emptyArray;
34717	},
34718	    _savedStyles = [],
34719	    _revertRecorded = function _revertRecorded(media) {
34720	  for (var i = 0; i < _savedStyles.length; i += 5) {
34721	    if (!media || _savedStyles[i + 4] === media) {
34722	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
34723	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
34724	      _savedStyles[i + 3].uncache = 1;
34725	    }
34726	  }
34727	},
34728	    _revertAll = function _revertAll(kill, media) {
34729	  var trigger;
34730
34731	  for (_i = 0; _i < _triggers.length; _i++) {
34732	    trigger = _triggers[_i];
34733
34734	    if (!media || trigger.media === media) {
34735	      if (kill) {
34736	        trigger.kill(1);
34737	      } else {
34738	        trigger.revert();
34739	      }
34740	    }
34741	  }
34742
34743	  media && _revertRecorded(media);
34744	  media || _dispatch("revert");
34745	},
34746	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 34747-35081
34747	  return _scrollers.forEach(function (obj) {
34748	    return typeof obj === "function" && (obj.rec = 0);
34749	  });
34750	},
34751	    _refreshingAll,
34752	    _refreshAll = function _refreshAll(force, skipRevert) {
34753	  if (_lastScrollTime && !force) {
34754	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34755
34756	    return;
34757	  }
34758
34759	  _refreshingAll = true;
34760
34761	  var refreshInits = _dispatch("refreshInit");
34762
34763	  _sort && ScrollTrigger.sort();
34764	  skipRevert || _revertAll();
34765
34766	  _triggers.forEach(function (t) {
34767	    return t.refresh();
34768	  });
34769
34770	  refreshInits.forEach(function (result) {
34771	    return result && result.render && result.render(-1);
34772	  });
34773
34774	  _clearScrollMemory();
34775
34776	  _resizeDelay.pause();
34777
34778	  _refreshingAll = false;
34779
34780	  _dispatch("refresh");
34781	},
34782	    _lastScroll = 0,
34783	    _direction = 1,
34784	    _updateAll = function _updateAll() {
34785	  if (!_refreshingAll) {
34786	    var l = _triggers.length,
34787	        time = _getTime(),
34788	        recordVelocity = time - _time1 >= 50,
34789	        scroll = l && _triggers[0].scroll();
34790
34791	    _direction = _lastScroll > scroll ? -1 : 1;
34792	    _lastScroll = scroll;
34793
34794	    if (recordVelocity) {
34795	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34796	        _lastScrollTime = 0;
34797
34798	        _dispatch("scrollEnd");
34799	      }
34800
34801	      _time2 = _time1;
34802	      _time1 = time;
34803	    }
34804
34805	    if (_direction < 0) {
34806	      _i = l;
34807
34808	      while (_i-- > 0) {
34809	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34810	      }
34811
34812	      _direction = 1;
34813	    } else {
34814	      for (_i = 0; _i < l; _i++) {
34815	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34816	      }
34817	    }
34818
34819	    _request = 0;
34820	  }
34821	},
34822	    _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"],
34823	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34824	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34825	  _setState(state);
34826
34827	  var cache = pin._gsap;
34828
34829	  if (cache.spacerIsNative) {
34830	    _setState(cache.spacerState);
34831	  } else if (pin.parentNode === spacer) {
34832	    var parent = spacer.parentNode;
34833
34834	    if (parent) {
34835	      parent.insertBefore(pin, spacer);
34836	      parent.removeChild(spacer);
34837	    }
34838	  }
34839	},
34840	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34841	  if (pin.parentNode !== spacer) {
34842	    var i = _propNamesToCopy.length,
34843	        spacerStyle = spacer.style,
34844	        pinStyle = pin.style,
34845	        p;
34846
34847	    while (i--) {
34848	      p = _propNamesToCopy[i];
34849	      spacerStyle[p] = cs[p];
34850	    }
34851
34852	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34853	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34854	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34855	    spacerStyle.overflow = "visible";
34856	    spacerStyle.boxSizing = "border-box";
34857	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34858	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34859	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34860
34861	    _setState(spacerState);
34862
34863	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34864	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34865	    pinStyle[_padding] = cs[_padding];
34866	    pin.parentNode.insertBefore(spacer, pin);
34867	    spacer.appendChild(pin);
34868	  }
34869	},
34870	    _capsExp = /([A-Z])/g,
34871	    _setState = function _setState(state) {
34872	  if (state) {
34873	    var style = state.t.style,
34874	        l = state.length,
34875	        i = 0,
34876	        p,
34877	        value;
34878	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34879
34880	    for (; i < l; i += 2) {
34881	      value = state[i + 1];
34882	      p = state[i];
34883
34884	      if (value) {
34885	        style[p] = value;
34886	      } else if (style[p]) {
34887	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34888	      }
34889	    }
34890	  }
34891	},
34892	    _getState = function _getState(element) {
34893	  var l = _stateProps.length,
34894	      style = element.style,
34895	      state = [],
34896	      i = 0;
34897
34898	  for (; i < l; i++) {
34899	    state.push(_stateProps[i], style[_stateProps[i]]);
34900	  }
34901
34902	  state.t = element;
34903	  return state;
34904	},
34905	    _copyState = function _copyState(state, override, omitOffsets) {
34906	  var result = [],
34907	      l = state.length,
34908	      i = omitOffsets ? 8 : 0,
34909	      p;
34910
34911	  for (; i < l; i += 2) {
34912	    p = state[i];
34913	    result.push(p, p in override ? override[p] : state[i + 1]);
34914	  }
34915
34916	  result.t = state.t;
34917	  return result;
34918	},
34919	    _winOffsets = {
34920	  left: 0,
34921	  top: 0
34922	},
34923	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34924	  _isFunction(value) && (value = value(self));
34925
34926	  if (_isString(value) && value.substr(0, 3) === "max") {
34927	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34928	  }
34929
34930	  var time = containerAnimation ? containerAnimation.time() : 0,
34931	      p1,
34932	      p2,
34933	      element;
34934	  containerAnimation && containerAnimation.seek(0);
34935
34936	  if (!_isNumber(value)) {
34937	    _isFunction(trigger) && (trigger = trigger(self));
34938	    var offsets = value.split(" "),
34939	        bounds,
34940	        localOffset,
34941	        globalOffset,
34942	        display;
34943	    element = _getTarget(trigger) || _body;
34944	    bounds = _getBounds(element) || {};
34945
34946	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34947	      display = element.style.display;
34948	      element.style.display = "block";
34949	      bounds = _getBounds(element);
34950	      display ? element.style.display = display : element.style.removeProperty("display");
34951	    }
34952
34953	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
34954	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
34955	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
34956	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
34957	    scrollerSize -= scrollerSize - globalOffset;
34958	  } else if (markerScroller) {
34959	    _positionMarker(markerScroller, scrollerSize, direction, true);
34960	  }
34961
34962	  if (marker) {
34963	    var position = value + scrollerSize,
34964	        isStart = marker._isStart;
34965	    p1 = "scroll" + direction.d2;
34966
34967	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
34968
34969	    if (useFixedPosition) {
34970	      scrollerBounds = _getBounds(markerScroller);
34971	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
34972	    }
34973	  }
34974
34975	  if (containerAnimation && element) {
34976	    p1 = _getBounds(element);
34977	    containerAnimation.seek(scrollerMax);
34978	    p2 = _getBounds(element);
34979	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
34980	    value = value / containerAnimation._caScrollDist * scrollerMax;
34981	  }
34982
34983	  containerAnimation && containerAnimation.seek(time);
34984	  return containerAnimation ? value : Math.round(value);
34985	},
34986	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
34987	    _reparent = function _reparent(element, parent, top, left) {
34988	  if (element.parentNode !== parent) {
34989	    var style = element.style,
34990	        p,
34991	        cs;
34992
34993	    if (parent === _body) {
34994	      element._stOrig = style.cssText;
34995	      cs = _getComputedStyle(element);
34996
34997	      for (p in cs) {
34998	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
34999	          style[p] = cs[p];
35000	        }
35001	      }
35002
35003	      style.top = top;
35004	      style.left = left;
35005	    } else {
35006	      style.cssText = element._stOrig;
35007	    }
35008
35009	    gsap.core.getCache(element).uncache = 1;
35010	    parent.appendChild(element);
35011	  }
35012	},
35013	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
35014	  var getScroll = _getScrollFunc(scroller, direction),
35015	      prop = "_scroll" + direction.p2,
35016	      lastScroll1,
35017	      lastScroll2,
35018	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
35019	    var tween = getTween.tween,
35020	        onComplete = vars.onComplete,
35021	        modifiers = {};
35022	    tween && tween.kill();
35023	    lastScroll1 = Math.round(initialValue);
35024	    vars[prop] = scrollTo;
35025	    vars.modifiers = modifiers;
35026
35027	    modifiers[prop] = function (value) {
35028	      value = _round(getScroll());
35029
35030	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
35031	        tween.kill();
35032	        getTween.tween = 0;
35033	      } else {
35034	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
35035	      }
35036
35037	      lastScroll2 = lastScroll1;
35038	      return lastScroll1 = _round(value);
35039	    };
35040
35041	    vars.onComplete = function () {
35042	      getTween.tween = 0;
35043	      onComplete && onComplete.call(tween);
35044	    };
35045
35046	    tween = getTween.tween = gsap.to(scroller, vars);
35047	    return tween;
35048	  };
35049
35050	  scroller[prop] = getScroll;
35051	  scroller.addEventListener("wheel", function () {
35052	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
35053	  }, {
35054	    passive: true
35055	  });
35056	  return getTween;
35057	};
35058
35059	_horizontal.op = _vertical;
35060	var ScrollTrigger = function () {
35061	  function ScrollTrigger(vars, animation) {
35062	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
35063	    this.init(vars, animation);
35064	  }
35065
35066	  var _proto = ScrollTrigger.prototype;
35067
35068	  _proto.init = function init(vars, animation) {
35069	    this.progress = this.start = 0;
35070	    this.vars && this.kill(1);
35071
35072	    if (!_enabled) {
35073	      this.update = this.refresh = this.kill = _passThrough;
35074	      return;
35075	    }
35076
35077	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
35078	      trigger: vars
35079	    } : vars, _defaults);
35080
35081	    var _vars = vars,
35082	        onUpdate = _vars.onUpdate,
35083	        toggleClass = _vars.toggleClass,
35084	        id = _vars.id,
35085	        onToggle = _vars.onToggle,
35086	        onRefresh = _vars.onRefresh,
35087	        scrub = _vars.scrub,
35088	        trigger = _vars.trigger,
35089	        pin = _vars.pin,
35090	        pinSpacing = _vars.pinSpacing,
35091	        invalidateOnRefresh = _vars.invalidateOnRefresh,
35092	        anticipatePin = _vars.anticipatePin,
35093	        onScrubComplete = _vars.onScrubComplete,
35094	        onSnapComplete = _vars.onSnapComplete,
35095	        once = _vars.once,
35096	        snap = _vars.snap,
35097	        pinReparent = _vars.pinReparent,
35098	        pinSpacer = _vars.pinSpacer,
35099	        containerAnimation = _vars.containerAnimation,
35100	        fastScrollEnd = _vars.fastScrollEnd,
35101	        preventOverlaps = _vars.preventOverlaps,
35102	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
35103	        isToggle = !scrub && scrub !== 0,
35104	        scroller = _getTarget(vars.scroller || _win),
35105	        scrollerCache = gsap.core.getCache(scroller),
35106	        isViewport = _isViewport(scroller),
35107	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
35108	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
35109	        toggleActions = isToggle && vars.toggleActions.split(" "),
35110	        markers = "markers" in vars ? vars.markers : _defaults.markers,
35111	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
35112	        self = this,
35113	        onRefreshInit = vars.onRefreshInit && function () {
35114	      return vars.onRefreshInit(self);
35115	    },
35116	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
35117	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
35118	        lastSnap = 0,
35119	        scrollFunc = _getScrollFunc(scroller, direction),
35120	        tweenTo,
35121	        pinCache,
35122	        snapFunc,
35123	        scroll1,
35124	        scroll2,
35125	        start,
35126	        end,
35127	        markerStart,
35128	        markerEnd,
35129	        markerStartTrigger,
35130	        markerEndTrigger,
35131	        markerVars,
35132	        change,
35133	        pinOriginalState,
35134	        pinActiveState,
35135	        pinState,
35136	        spacer,
35137	        offset,
35138	        pinGetter,
35139	        pinSetter,
35140	        pinStart,
35141	        pinChange,
35142	        spacingStart,
35143	        spacerState,
35144	        markerStartSetter,
35145	        markerEndSetter,
35146	        cs,
35147	        snap1,
35148	        snap2,
35149	        scrubTween,
35150	        scrubSmooth,
35151	        snapDurClamp,
35152	        snapDelayedCall,
35153	        prevProgress,
35154	        prevScroll,
35155	        prevAnimProgress,
35156	        caMarkerSetter;
35157
35158	    self.media = _creatingMedia;
35159	    anticipatePin *= 45;
35160	    self.scroller = scroller;
35161	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
35162	    scroll1 = scrollFunc();
35163	    self.vars = vars;
35164	    animation = animation || vars.animation;
35165	    "refreshPriority" in vars && (_sort = 1);
35166	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
35167	      top: _getTweenCreator(scroller, _vertical),
35168	      left: _getTweenCreator(scroller, _horizontal)
35169	    };
35170	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
35171
35172	    if (animation) {
35173	      animation.vars.lazy = false;
35174	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
35175	      self.animation = animation.pause();
35176	      animation.scrollTrigger = self;
35177	      scrubSmooth = _isNumber(scrub) && scrub;
35178	      scrubSmooth && (scrubTween = gsap.to(animation, {
35179	        ease: "power3",
35180	        duration: scrubSmooth,
35181	        onComplete: function onComplete() {
35182	          return onScrubComplete && onScrubComplete(self);
35183	        }
35184	      }));
35185	      snap1 = 0;
35186	      id || (id = animation.vars.id);
35187	    }
35188
35189	    _triggers.push(self);
35190
35191	    if (snap) {
35192	      if (!_isObject(snap) || snap.push) {
35193	        snap = {
35194	          snapTo: snap
35195	        };
35196	      }
35197
35198	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
35199	        scrollBehavior: "auto"
35200	      });
35201	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
35202	        return _snapDirectional(snap.snapTo)(value, st.direction);
35203	      } : gsap.utils.snap(snap.snapTo);
35204	      snapDurClamp = snap.duration || {
35205	        min: 0.1,
35206	        max: 2
35207	      };
35208	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
35209	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
35210	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
35211	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
35212	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
35213	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
35214	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
35215	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
35216	              scroll = scrollFunc(),
35217	              endScroll = Math.round(start + endValue * change),
35218	              _snap = snap,
35219	              onStart = _snap.onStart,
35220	              _onInterrupt = _snap.onInterrupt,
35221	              _onComplete = _snap.onComplete,
35222	              tween = tweenTo.tween;
35223
35224	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
35225	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
35226	              return;
35227	            }
35228
35229	            if (snap.inertia === false) {
35230	              change1 = endValue - self.progress;
35231	            }
35232
35233	            tweenTo(endScroll, {
35234	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
35235	              ease: snap.ease || "power3",
35236	              data: _abs(endScroll - scroll),
35237	              onInterrupt: function onInterrupt() {
35238	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
35239	              },
35240	              onComplete: function onComplete() {
35241	                lastSnap = scrollFunc();
35242	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
35243	                onSnapComplete && onSnapComplete(self);
35244	                _onComplete && _onComplete(self);
35245	              }
35246	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
35247	            onStart && onStart(self, tweenTo.tween);
35248	          }
35249	        } else if (self.isActive) {
35250	          snapDelayedCall.restart(true);
35251	        }
35252	      }).pause();
35253	    }
35254
35255	    id && (_ids[id] = self);
35256	    trigger = self.trigger = _getTarget(trigger || pin);
35257	    pin = pin === true ? trigger : _getTarget(pin);
35258	    _isString(toggleClass) && (toggleClass = {
35259	      targets: trigger,
35260	      className: toggleClass
35261	    });
35262
35263	    if (pin) {
35264	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
35265	      self.pin = pin;
35266	      vars.force3D !== false && gsap.set(pin, {
35267	        force3D: true
35268	      });
35269	      pinCache = gsap.core.getCache(pin);
35270
35271	      if (!pinCache.spacer) {
35272	        if (pinSpacer) {
35273	          pinSpacer = _getTarget(pinSpacer);
35274	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
35275	          pinCache.spacerIsNative = !!pinSpacer;
35276	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
35277	        }
35278
35279	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
35280	        spacer.classList.add("pin-spacer");
35281	        id && spacer.classList.add("pin-spacer-" + id);
35282	        pinCache.pinState = pinOriginalState = _getState(pin);
35283	      } else {
35284	        pinOriginalState = pinCache.pinState;
35285	      }
35286
35287	      self.spacer = spacer = pinCache.spacer;
35288	      cs = _getComputedStyle(pin);
35289	      spacingStart = cs[pinSpacing + direction.os2];
35290	      pinGetter = gsap.getProperty(pin);
35291	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
35292
35293	      _swapPinIn(pin, spacer, cs);
35294
35295	      pinState = _getState(pin);
35296	    }
35297
35298	    if (markers) {
35299	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
35300	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
35301	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
35302	      offset = markerStartTrigger["offset" + direction.op.d2];
35303	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35304	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35305	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
35306
35307	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
35308	        _makePositionable(isViewport ? _body : scroller);
35309
35310	        gsap.set([markerStartTrigger, markerEndTrigger], {
35311	          force3D: true
35312	        });
35313	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
35314	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
35315	      }
35316	    }
35317
35318	    if (containerAnimation) {
35319	      var oldOnUpdate = containerAnimation.vars.onUpdate,
35320	          oldParams = containerAnimation.vars.onUpdateParams;
35321	      containerAnimation.eventCallback("onUpdate", function () {
35322	        self.update(0, 0, 1);
35323	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
35324	      });
35325	    }
35326
35327	    self.previous = function () {
35328	      return _triggers[_triggers.indexOf(self) - 1];
35329	    };
35330
35331	    self.next = function () {
35332	      return _triggers[_triggers.indexOf(self) + 1];
35333	    };
35334
35335	    self.revert = function (revert) {
35336	      var r = revert !== false || !self.enabled,
35337	          prevRefreshing = _refreshing;
35338
35339	      if (r !== self.isReverted) {
35340	        if (r) {
35341	          self.scroll.rec || (self.scroll.rec = scrollFunc());
35342	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
35343	          prevProgress = self.progress;
35344	          prevAnimProgress = animation && animation.progress();
35345	        }
35346
35347	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35348	          return m.style.display = r ? "none" : "block";
35349	        });
35350	        r && (_refreshing = 1);
35351	        self.update(r);
35352	        _refreshing = prevRefreshing;
35353	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
35354	        self.isReverted = r;
35355	      }
35356	    };
35357
35358	    self.refresh = function (soft, force) {
35359	      if ((_refreshing || !self.enabled) && !force) {
35360	        return;
35361	      }
35362
35363	      if (pin && soft && _lastScrollTime) {
35364	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
35365
35366	        return;
35367	      }
35368
35369	      _refreshing = 1;
35370	      scrubTween && scrubTween.pause();
35371	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
35372	      self.isReverted || self.revert();
35373
35374	      var size = getScrollerSize(),
35375	          scrollerBounds = getScrollerOffsets(),
35376	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
35377	          offset = 0,
35378	          otherPinOffset = 0,
35379	          parsedEnd = vars.end,
35380	          parsedEndTrigger = vars.endTrigger || trigger,
35381	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
35382	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
35383	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
35384	          i = triggerIndex,
35385	          cs,
35386	          bounds,
35387	          scroll,
35388	          isVertical,
35389	          override,
35390	          curTrigger,
35391	          curPin,
35392	          oppositeScroll,
35393	          initted,
35394	          revertedPins;
35395
35396	      while (i--) {
35397	        curTrigger = _triggers[i];
35398	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
35399	        curPin = curTrigger.pin;
35400
35401	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
35402	          revertedPins || (revertedPins = []);
35403	          revertedPins.unshift(curTrigger);
35404	          curTrigger.revert();
35405	        }
35406	      }
35407
35408	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
35409	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
35410	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
35411
35412	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
35413	        if (~parsedEnd.indexOf(" ")) {
35414	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
35415	        } else {
35416	          offset = _offsetToPx(parsedEnd.substr(2), size);
35417	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
35418	          parsedEndTrigger = trigger;
35419	        }
35420	      }
35421
35422	      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;
35423	      change = end - start || (start -= 0.01) && 0.001;
35424	      offset = 0;
35425	      i = triggerIndex;
35426
35427	      while (i--) {
35428	        curTrigger = _triggers[i];
35429	        curPin = curTrigger.pin;
35430
35431	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
35432	          cs = curTrigger.end - curTrigger.start;
35433	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
35434	          curPin === pin && (otherPinOffset += cs);
35435	        }
35436	      }
35437
35438	      start += offset;
35439	      end += offset;
35440	      self._pinPush = otherPinOffset;
35441
35442	      if (markerStart && offset) {
35443	        cs = {};
35444	        cs[direction.a] = "+=" + offset;
35445	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
35446	        gsap.set([markerStart, markerEnd], cs);
35447	      }
35448
35449	      if (pin) {
35450	        cs = _getComputedStyle(pin);
35451	        isVertical = direction === _vertical;
35452	        scroll = scrollFunc();
35453	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
35454	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
35455
35456	        _swapPinIn(pin, spacer, cs);
35457
35458	        pinState = _getState(pin);
35459	        bounds = _getBounds(pin, true);
35460	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
35461
35462	        if (pinSpacing) {
35463	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
35464	          spacerState.t = spacer;
35465	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
35466	          i && spacerState.push(direction.d, i + _px);
35467
35468	          _setState(spacerState);
35469
35470	          useFixedPosition && scrollFunc(prevScroll);
35471	        }
35472
35473	        if (useFixedPosition) {
35474	          override = {
35475	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
35476	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
35477	            boxSizing: "border-box",
35478	            position: "fixed"
35479	          };
35480	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
35481	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
35482	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
35483	          override[_padding] = cs[_padding];
35484	          override[_padding + _Top] = cs[_padding + _Top];
35485	          override[_padding + _Right] = cs[_padding + _Right];
35486	          override[_padding + _Bottom] = cs[_padding + _Bottom];
35487	          override[_padding + _Left] = cs[_padding + _Left];
35488	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
35489	        }
35490
35491	        if (animation) {
35492	          initted = animation._initted;
35493
35494	          _suppressOverwrites(1);
35495
35496	          animation.render(animation.duration(), true, true);
35497	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
35498	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
35499	          animation.render(0, true, true);
35500	          initted || animation.invalidate();
35501
35502	          _suppressOverwrites(0);
35503	        } else {
35504	          pinChange = change;
35505	        }
35506	      } else if (trigger && scrollFunc() && !containerAnimation) {
35507	        bounds = trigger.parentNode;
35508
35509	        while (bounds && bounds !== _body) {
35510	          if (bounds._pinOffset) {
35511	            start -= bounds._pinOffset;
35512	            end -= bounds._pinOffset;
35513	          }
35514
35515	          bounds = bounds.parentNode;
35516	        }
35517	      }
35518
35519	      revertedPins && revertedPins.forEach(function (t) {
35520	        return t.revert(false);
35521	      });
35522	      self.start = start;
35523	      self.end = end;
35524	      scroll1 = scroll2 = scrollFunc();
35525
35526	      if (!containerAnimation) {
35527	        scroll1 < prevScroll && scrollFunc(prevScroll);
35528	        self.scroll.rec = 0;
35529	      }
35530
35531	      self.revert(false);
35532	      _refreshing = 0;
35533	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
35534
35535	      if (prevProgress !== self.progress) {
35536	        animation && !isToggle && animation.totalProgress(prevProgress, true);
35537	        self.progress = prevProgress;
35538	        self.update(0, 0, 1);
35539	      }
35540
35541	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
35542	      onRefresh && onRefresh(self);
35543	    };
35544
35545	    self.getVelocity = function () {
35546	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
35547	    };
35548
35549	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 35550-35788
35550	      _endAnimation(self.callbackAnimation);
35551
35552	      if (animation) {
35553	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
35554	      }
35555	    };
35556
35557	    self.getTrailing = function (name) {
35558	      var i = _triggers.indexOf(self),
35559	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
35560
35561	      return _isString(name) ? a.filter(function (t) {
35562	        return t.vars.preventOverlaps === name;
35563	      }) : a;
35564	    };
35565
35566	    self.update = function (reset, recordVelocity, forceFake) {
35567	      if (containerAnimation && !forceFake && !reset) {
35568	        return;
35569	      }
35570
35571	      var scroll = self.scroll(),
35572	          p = reset ? 0 : (scroll - start) / change,
35573	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
35574	          prevProgress = self.progress,
35575	          isActive,
35576	          wasActive,
35577	          toggleState,
35578	          action,
35579	          stateChanged,
35580	          toggled,
35581	          isAtMax,
35582	          isTakingAction;
35583
35584	      if (recordVelocity) {
35585	        scroll2 = scroll1;
35586	        scroll1 = containerAnimation ? scrollFunc() : scroll;
35587
35588	        if (snap) {
35589	          snap2 = snap1;
35590	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
35591	        }
35592	      }
35593
35594	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
35595
35596	      if (clipped !== prevProgress && self.enabled) {
35597	        isActive = self.isActive = !!clipped && clipped < 1;
35598	        wasActive = !!prevProgress && prevProgress < 1;
35599	        toggled = isActive !== wasActive;
35600	        stateChanged = toggled || !!clipped !== !!prevProgress;
35601	        self.direction = clipped > prevProgress ? 1 : -1;
35602	        self.progress = clipped;
35603
35604	        if (stateChanged && !_refreshing) {
35605	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
35606
35607	          if (isToggle) {
35608	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
35609	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
35610	          }
35611	        }
35612
35613	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
35614	          return t.endAnimation();
35615	        }));
35616
35617	        if (!isToggle) {
35618	          if (scrubTween && !_refreshing && !_startup) {
35619	            scrubTween.vars.totalProgress = clipped;
35620	            scrubTween.invalidate().restart();
35621	          } else if (animation) {
35622	            animation.totalProgress(clipped, !!_refreshing);
35623	          }
35624	        }
35625
35626	        if (pin) {
35627	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
35628
35629	          if (!useFixedPosition) {
35630	            pinSetter(pinStart + pinChange * clipped);
35631	          } else if (stateChanged) {
35632	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
35633
35634	            if (pinReparent) {
35635	              if (!reset && (isActive || isAtMax)) {
35636	                var bounds = _getBounds(pin, true),
35637	                    _offset = scroll - start;
35638
35639	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
35640	              } else {
35641	                _reparent(pin, spacer);
35642	              }
35643	            }
35644
35645	            _setState(isActive || isAtMax ? pinActiveState : pinState);
35646
35647	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
35648	          }
35649	        }
35650
35651	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
35652	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
35653	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
35654	        });
35655	        onUpdate && !isToggle && !reset && onUpdate(self);
35656
35657	        if (stateChanged && !_refreshing) {
35658	          if (isToggle) {
35659	            if (isTakingAction) {
35660	              if (action === "complete") {
35661	                animation.pause().totalProgress(1);
35662	              } else if (action === "reset") {
35663	                animation.restart(true).pause();
35664	              } else if (action === "restart") {
35665	                animation.restart(true);
35666	              } else {
35667	                animation[action]();
35668	              }
35669	            }
35670
35671	            onUpdate && onUpdate(self);
35672	          }
35673
35674	          if (toggled || !_limitCallbacks) {
35675	            onToggle && toggled && _callback(self, onToggle);
35676	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35677	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
35678
35679	            if (!toggled) {
35680	              toggleState = clipped === 1 ? 1 : 3;
35681	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35682	            }
35683	          }
35684
35685	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
35686	            _endAnimation(self.callbackAnimation);
35687
35688	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
35689	          }
35690	        } else if (isToggle && onUpdate && !_refreshing) {
35691	          onUpdate(self);
35692	        }
35693	      }
35694
35695	      if (markerEndSetter) {
35696	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
35697	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
35698	        markerEndSetter(n);
35699	      }
35700
35701	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
35702	    };
35703
35704	    self.enable = function (reset, refresh) {
35705	      if (!self.enabled) {
35706	        self.enabled = true;
35707
35708	        _addListener(scroller, "resize", _onResize);
35709
35710	        _addListener(scroller, "scroll", _onScroll);
35711
35712	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
35713
35714	        if (reset !== false) {
35715	          self.progress = prevProgress = 0;
35716	          scroll1 = scroll2 = lastSnap = scrollFunc();
35717	        }
35718
35719	        refresh !== false && self.refresh();
35720	      }
35721	    };
35722
35723	    self.getTween = function (snap) {
35724	      return snap && tweenTo ? tweenTo.tween : scrubTween;
35725	    };
35726
35727	    self.disable = function (reset, allowAnimation) {
35728	      if (self.enabled) {
35729	        reset !== false && self.revert();
35730	        self.enabled = self.isActive = false;
35731	        allowAnimation || scrubTween && scrubTween.pause();
35732	        prevScroll = 0;
35733	        pinCache && (pinCache.uncache = 1);
35734	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
35735
35736	        if (snapDelayedCall) {
35737	          snapDelayedCall.pause();
35738	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
35739	        }
35740
35741	        if (!isViewport) {
35742	          var i = _triggers.length;
35743
35744	          while (i--) {
35745	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
35746	              return;
35747	            }
35748	          }
35749
35750	          _removeListener(scroller, "resize", _onResize);
35751
35752	          _removeListener(scroller, "scroll", _onScroll);
35753	        }
35754	      }
35755	    };
35756
35757	    self.kill = function (revert, allowAnimation) {
35758	      self.disable(revert, allowAnimation);
35759	      scrubTween && scrubTween.kill();
35760	      id && delete _ids[id];
35761
35762	      var i = _triggers.indexOf(self);
35763
35764	      _triggers.splice(i, 1);
35765
35766	      i === _i && _direction > 0 && _i--;
35767	      i = 0;
35768
35769	      _triggers.forEach(function (t) {
35770	        return t.scroller === self.scroller && (i = 1);
35771	      });
35772
35773	      i || (self.scroll.rec = 0);
35774
35775	      if (animation) {
35776	        animation.scrollTrigger = null;
35777	        revert && animation.render(-1);
35778	        allowAnimation || animation.kill();
35779	      }
35780
35781	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35782	        return m.parentNode && m.parentNode.removeChild(m);
35783	      });
35784
35785	      if (pin) {
35786	        pinCache && (pinCache.uncache = 1);
35787	        i = 0;
35788
35789	        _triggers.forEach(function (t) {
35790	          return t.pin === pin && i++;
35791	        });
35792
35793	        i || (pinCache.spacer = 0);
35794	      }
35795	    };
35796
35797	    self.enable(false, false);
35798	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35799	      return start || end || self.refresh();
35800	    }) && (change = 0.01) && (start = end = 0);
35801	  };
35802
35803	  ScrollTrigger.register = function register(core) {
35804	    if (!_coreInitted) {
35805	      gsap = core || _getGSAP();
35806
35807	      if (_windowExists() && window.document) {
35808	        _win = window;
35809	        _doc = document;
35810	        _docEl = _doc.documentElement;
35811	        _body = _doc.body;
35812	      }
35813
35814	      if (gsap) {
35815	        _toArray = gsap.utils.toArray;
35816	        _clamp = gsap.utils.clamp;
35817	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35818	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35819
35820	        if (_body) {
35821	          _raf = _win.requestAnimationFrame || function (f) {
35822	            return setTimeout(f, 16);
35823	          };
35824
35825	          _addListener(_win, "wheel", _onScroll);
35826
35827	          _root = [_win, _doc, _docEl, _body];
35828
35829	          _addListener(_doc, "scroll", _onScroll);
35830
35831	          var bodyStyle = _body.style,
35832	              border = bodyStyle.borderTopStyle,
35833	              bounds;
35834	          bodyStyle.borderTopStyle = "solid";
35835	          bounds = _getBounds(_body);
35836	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35837	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35838	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35839	          _syncInterval = setInterval(_sync, 200);
35840	          gsap.delayedCall(0.5, function () {
35841	            return _startup = 0;
35842	          });
35843
35844	          _addListener(_doc, "touchcancel", _passThrough);
35845
35846	          _addListener(_body, "touchstart", _passThrough);
35847
35848	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35849	            return _pointerIsDown = 1;
35850	          });
35851
35852	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35853	            return _pointerIsDown = 0;
35854	          });
35855
35856	          _transformProp = gsap.utils.checkPrefix("transform");
35857
35858	          _stateProps.push(_transformProp);
35859
35860	          _coreInitted = _getTime();
35861	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35862	          _autoRefresh = [_doc, "visibilitychange", function () {
35863	            var w = _win.innerWidth,
35864	                h = _win.innerHeight;
35865
35866	            if (_doc.hidden) {
35867	              _prevWidth = w;
35868	              _prevHeight = h;
35869	            } else if (_prevWidth !== w || _prevHeight !== h) {
35870	              _onResize();
35871	            }
35872	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35873	            return _lastScrollTime || _refreshAll();
35874	          }, _win, "resize", _onResize];
35875
35876	          _iterateAutoRefresh(_addListener);
35877	        }
35878	      }
35879	    }
35880
35881	    return _coreInitted;
35882	  };
35883
35884	  ScrollTrigger.defaults = function defaults(config) {
35885	    for (var p in config) {
35886	      _defaults[p] = config[p];
35887	    }
35888	  };
35889
35890	  ScrollTrigger.kill = function kill() {
35891	    _enabled = 0;
35892
35893	    _triggers.slice(0).forEach(function (trigger) {
35894	      return trigger.kill(1);
35895	    });
35896	  };
35897
35898	  ScrollTrigger.config = function config(vars) {
35899	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35900	    var ms = vars.syncInterval;
35901	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35902
35903	    if ("autoRefreshEvents" in vars) {
35904	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35905	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35906	    }
35907	  };
35908
35909	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35910	    var t = _getTarget(target),
35911	        i = _scrollers.indexOf(t),
35912	        isViewport = _isViewport(t);
35913
35914	    if (~i) {
35915	      _scrollers.splice(i, isViewport ? 6 : 2);
35916	    }
35917
35918	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35919	  };
35920
35921	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35922	    var mq, p, i, func, result;
35923
35924	    for (p in vars) {
35925	      i = _media.indexOf(p);
35926	      func = vars[p];
35927	      _creatingMedia = p;
35928
35929	      if (p === "all") {
35930	        func();
35931	      } else {
35932	        mq = _win.matchMedia(p);
35933
35934	        if (mq) {
35935	          mq.matches && (result = func());
35936
35937	          if (~i) {
35938	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35939	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35940	          } else {
35941	            i = _media.length;
35942
35943	            _media.push(p, func, result);
35944
35945	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35946	          }
35947
35948	          _media[i + 3] = mq.matches;
35949	        }
35950	      }
35951
35952	      _creatingMedia = 0;
35953	    }
35954
35955	    return _media;
35956	  };
35957
35958	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
35959	    query || (_media.length = 0);
35960	    query = _media.indexOf(query);
35961	    query >= 0 && _media.splice(query, 4);
35962	  };
35963
35964	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
35965	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
35966	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
35967	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
35968	  };
35969
35970	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
35971	    _isString(element) && (element = _getTarget(element));
35972	    var bounds = element.getBoundingClientRect(),
35973	        size = bounds[horizontal ? _width : _height],
35974	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
35975	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
35976	  };
35977
35978	  return ScrollTrigger;
35979	}();
35980	ScrollTrigger.version = "3.8.0";
35981
35982	ScrollTrigger.saveStyles = function (targets) {
35983	  return targets ? _toArray(targets).forEach(function (target) {
35984	    if (target && target.style) {
35985	      var i = _savedStyles.indexOf(target);
35986
35987	      i >= 0 && _savedStyles.splice(i, 5);
35988
35989	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
35990	    }
35991	  }) : _savedStyles;
35992	};
35993
35994	ScrollTrigger.revert = function (soft, media) {
35995	  return _revertAll(!soft, media);
35996	};
35997
35998	ScrollTrigger.create = function (vars, animation) {
35999	  return new ScrollTrigger(vars, animation);
36000	};
36001
36002	ScrollTrigger.refresh = function (safe) {
36003	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
36004	};
36005
36006	ScrollTrigger.update = _updateAll;
36007	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
36008
36009	ScrollTrigger.maxScroll = function (element, horizontal) {
36010	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
36011	};
36012
36013	ScrollTrigger.getScrollFunc = function (element, horizontal) {
36014	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
36015	};
36016
36017	ScrollTrigger.getById = function (id) {
36018	  return _ids[id];
36019	};
36020
36021	ScrollTrigger.getAll = function () {
36022	  return _triggers.slice(0);
36023	};
36024
36025	ScrollTrigger.isScrolling = function () {
36026	  return !!_lastScrollTime;
36027	};
36028
36029	ScrollTrigger.snapDirectional = _snapDirectional;
36030
36031	ScrollTrigger.addEventListener = function (type, callback) {
36032	  var a = _listeners[type] || (_listeners[type] = []);
36033	  ~a.indexOf(callback) || a.push(callback);
36034	};
36035
36036	ScrollTrigger.removeEventListener = function (type, callback) {
36037	  var a = _listeners[type],
36038	      i = a && a.indexOf(callback);
36039	  i >= 0 && a.splice(i, 1);
36040	};
36041
36042	ScrollTrigger.batch = function (targets, vars) {
36043	  var result = [],
36044	      varsCopy = {},
36045	      interval = vars.interval || 0.016,
36046	      batchMax = vars.batchMax || 1e9,
36047	      proxyCallback = function proxyCallback(type, callback) {
36048	    var elements = [],
36049	        triggers = [],
36050	        delay = gsap.delayedCall(interval, function () {
36051	      callback(elements, triggers);
36052	      elements = [];
36053	      triggers = [];
36054	    }).pause();
36055	    return function (self) {
36056	      elements.length || delay.restart(true);
36057	      elements.push(self.trigger);
36058	      triggers.push(self);
36059	      batchMax <= elements.length && delay.progress(1);
36060	    };
36061	  },
36062	      p;
36063
36064	  for (p in vars) {
36065	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
36066	  }
36067
36068	  if (_isFunction(batchMax)) {
36069	    batchMax = batchMax();
36070
36071	    _addListener(ScrollTrigger, "refresh", function () {
36072	      return batchMax = vars.batchMax();
36073	    });
36074	  }
36075
36076	  _toArray(targets).forEach(function (target) {
36077	    var config = {};
36078
36079	    for (p in varsCopy) {
36080	      config[p] = varsCopy[p];
36081	    }
36082
36083	    config.trigger = target;
36084	    result.push(ScrollTrigger.create(config));
36085	  });
36086
36087	  return result;
36088	};
36089
36090	ScrollTrigger.sort = function (func) {
36091	  return _triggers.sort(func || function (a, b) {
36092	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
36093	  });
36094	};
36095
36096	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
36097
36098	exports.ScrollTrigger = ScrollTrigger;
36099	exports.default = ScrollTrigger;
36100
36101	Object.defineProperty(exports, '__esModule', { value: true });
36102
36103})));
36104
36105/* ========================================================================
36106 * Bootstrap: collapse.js v3.1.1
36107 * http://getbootstrap.com/javascript/#collapse
36108 * ========================================================================
36109 * Copyright 2011-2014 Twitter, Inc.
36110 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36111 * ======================================================================== */
36112
36113
36114+function ($) {
36115	'use strict';
36116
36117	// COLLAPSE PUBLIC CLASS DEFINITION
36118	// ================================
36119
36120	var Collapse = function (element, options) {
36121		this.$element      = $(element)
36122		this.options       = $.extend({}, Collapse.DEFAULTS, options)
36123		this.transitioning = null
36124
36125		if (this.options.parent) this.$parent = $(this.options.parent)
36126		if (this.options.toggle) this.toggle()
36127	}
36128
36129	Collapse.DEFAULTS = {
36130		toggle: true
36131	}
36132
36133	Collapse.prototype.dimension = function () {
36134		var hasWidth = this.$element.hasClass('width')
36135		return hasWidth ? 'width' : 'height'
36136	}
36137
36138	Collapse.prototype.show = function () {
36139		if (this.transitioning || this.$element.hasClass('in')) return
36140
36141		var startEvent = $.Event('show.bs.collapse')
36142		this.$element.trigger(startEvent)
36143		if (startEvent.isDefaultPrevented()) return
36144
36145		var actives = this.$parent && this.$parent.find('> .panel > .in')
36146
36147		if (actives && actives.length) {
36148			var hasData = actives.data('bs.collapse')
36149			if (hasData && hasData.transitioning) return
36150			//START UNCODE EDIT
36151			var parentNoToggle = this.$parent.data('no-toggle')
36152			if (!parentNoToggle) {
36153				actives.collapse('hide')
36154			}
36155			//END UNCODE EDIT
36156			hasData || actives.data('bs.collapse', null)
36157		}
36158
36159		var dimension = this.dimension()
36160
36161		this.$element
36162			.removeClass('collapse')
36163			.addClass('collapsing')[dimension](0)
36164
36165		this.transitioning = 1
36166
36167		var complete = function (e) {
36168			if (e && e.target != this.$element[0]) return
36169			this.$element
36170				.removeClass('collapsing')
36171				.addClass('collapse in')[dimension]('auto')
36172			this.transitioning = 0
36173			this.$element.trigger('shown.bs.collapse')
36174		}
36175
36176		if (!$.support.transition) return complete.call(this)
36177
36178		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
36179
36180		this.$element
36181			.one($.support.transition.end, $.proxy(complete, this))
36182			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
36183	}
36184
36185	Collapse.prototype.hide = function () {
36186		if (this.transitioning || !this.$element.hasClass('in')) return
36187
36188		var startEvent = $.Event('hide.bs.collapse')
36189		this.$element.trigger(startEvent)
36190		if (startEvent.isDefaultPrevented()) return
36191
36192		var dimension = this.dimension()
36193
36194		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
36195
36196		this.$element
36197			.addClass('collapsing')
36198			.removeClass('collapse')
36199			.removeClass('in')
36200
36201		this.transitioning = 1
36202
36203		var complete = function (e) {
36204			if (e && e.target != this.$element[0]) return
36205			this.transitioning = 0
36206			this.$element
36207				.trigger('hidden.bs.collapse')
36208				.removeClass('collapsing')
36209				.addClass('collapse')
36210		}
36211
36212		if (!$.support.transition) return complete.call(this)
36213
36214		this.$element
36215			[dimension](0)
36216			.one($.support.transition.end, $.proxy(complete, this))
36217			.emulateTransitionEnd(350)
36218	}
36219
36220	Collapse.prototype.toggle = function () {
36221		this[this.$element.hasClass('in') ? 'hide' : 'show']()
36222	}
36223
36224
36225	// COLLAPSE PLUGIN DEFINITION
36226	// ==========================
36227
36228	var old = $.fn.collapse
36229
36230	$.fn.collapse = function (option) {
36231		return this.each(function () {
36232			var $this   = $(this)
36233			var data    = $this.data('bs.collapse')
36234			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
36235
36236			if (!data && options.toggle && option == 'show') option = !option
36237			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
36238			if (typeof option == 'string') data[option]()
36239		})
36240	}
36241
36242	$.fn.collapse.Constructor = Collapse
36243
36244
36245	// COLLAPSE NO CONFLICT
36246	// ====================
36247
36248	$.fn.collapse.noConflict = function () {
36249		$.fn.collapse = old
36250		return this
36251	}
36252
36253
36254	// COLLAPSE DATA-API
36255	// =================
36256
36257	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
36258		var $this   = $(this), href
36259		var target  = $this.attr('data-target')
36260				|| e.preventDefault()
36261				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
36262		//Edited by Uncode to replace ID in panel [START]
36263		var _target = href.replace(/^#/, "");
36264		if ( $('[data-id="' + _target + '"]').length ) {
36265			var $target = $('[data-id="' + _target + '"]')
36266		} else {
36267			var $target = $(target)
36268		}
36269		//Edited by Uncode to replace ID in panel [END]
36270		var data    = $target.data('bs.collapse')
36271		var option  = data ? 'toggle' : $this.data()
36272		var parent  = $this.attr('data-parent')
36273		var $parent = parent && $(parent)
36274
36275		if (!data || !data.transitioning) {
36276			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
36277			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
36278		}
36279
36280		$target.collapse(option)
36281	})
36282
36283}(jQuery);
36284
36285/* ========================================================================
36286 * Bootstrap: tab.js v3.1.1
36287 * http://getbootstrap.com/javascript/#tabs
36288 * ========================================================================
36289 * Copyright 2011-2014 Twitter, Inc.
36290 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36291 * ======================================================================== */
36292
36293
36294+function ($) {
36295  'use strict';
36296
36297  // TAB CLASS DEFINITION
36298  // ====================
36299
36300  var Tab = function (element) {
36301    this.element = $(element)
36302  }
36303
36304  Tab.prototype.show = function () {
36305    var $this    = this.element
36306    var $ul      = $this.closest('ul:not(.dropdown-menu)')
36307    var selector = $this.data('target')
36308
36309    if (!selector) {
36310      selector = $this.attr('href')
36311      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
36312    }
36313
36314    if ($this.parent('li').hasClass('active')) return
36315
36316    var previous = $ul.find('.active:last a')[0]
36317    var e        = $.Event('show.bs.tab', {
36318      relatedTarget: previous
36319    })
36320
36321    $this.trigger(e)
36322
36323    if (e.isDefaultPrevented()) return
36324
36325    //Edited by Uncode to replace ID in panel [START]
36326    var _target = selector.replace(/^#/, "");
36327    if ( $('[data-id="' + _target + '"]').length )
36328      var $target = $('[data-id="' + _target + '"]')
36329    else
36330      var $target = $(selector)
36331    //Edited by Uncode to replace ID in panel [END]
36332
36333    this.activate($this.parent('li'), $ul)
36334    this.activate($target, $target.parent(), function () {
36335      $this.trigger({
36336        type: 'shown.bs.tab',
36337        relatedTarget: previous
36338      })
36339    })
36340  }
36341
36342  Tab.prototype.activate = function (element, container, callback) {
36343    var $active    = container.find('> .active').add(container.find('> .active > .active'))
36344    var transition = callback
36345      && $.support.transition
36346      && $active.hasClass('fade')
36347
36348    function next() {
36349      $active
36350        .removeClass('active')
36351        .find('> .dropdown-menu > .active')
36352        .removeClass('active')
36353
36354      $active
36355        .find('.tab-excerpt').slideUp();
36356
36357      element.addClass('active')
36358      $('.tab-excerpt', element).slideDown();
36359
36360      //if (transition) {
36361        element[0].offsetWidth // reflow for transition
36362        element.add($active).addClass('in')
36363      /*} else {
36364        element.removeClass('fade')
36365      }*/
36366
36367      if (element.parent('.dropdown-menu')) {
36368        element.closest('li.dropdown').addClass('active')
36369      }
36370
36371      callback && callback()
36372    }
36373
36374    transition ?
36375      $active
36376        .one($.support.transition.end, next)
36377        .emulateTransitionEnd(150) :
36378      next()
36379
36380    $active.removeClass('in')
36381  }
36382
36383
36384  // TAB PLUGIN DEFINITION
36385  // =====================
36386
36387  var old = $.fn.tab
36388
36389  $.fn.tab = function ( option ) {
36390    return this.each(function () {
36391      var $this = $(this)
36392      var data  = $this.data('bs.tab')
36393
36394      if (!data) $this.data('bs.tab', (data = new Tab(this)))
36395      if (typeof option == 'string') data[option]()
36396    })
36397  }
36398
36399  $.fn.tab.Constructor = Tab
36400
36401
36402  // TAB NO CONFLICT
36403  // ===============
36404
36405  $.fn.tab.noConflict = function () {
36406    $.fn.tab = old
36407    return this
36408  }
36409
36410
36411  // TAB DATA-API
36412  // ============
36413
36414  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
36415    e.preventDefault()
36416    $(this).tab('show')
36417  })
36418
36419}(jQuery);
36420
36421/* ========================================================================
36422 * Bootstrap: tooltip.js v3.1.1
36423 * http://getbootstrap.com/javascript/#tooltip
36424 * Inspired by the original jQuery.tipsy by Jason Frame
36425 * ========================================================================
36426 * Copyright 2011-2014 Twitter, Inc.
36427 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36428 * ======================================================================== */
36429
36430
36431+function ($) {
36432  'use strict';
36433
36434  // TOOLTIP PUBLIC CLASS DEFINITION
36435  // ===============================
36436
36437  var Tooltip = function (element, options) {
36438    this.type       =
36439    this.options    =
36440    this.enabled    =
36441    this.timeout    =
36442    this.hoverState =
36443    this.$element   = null
36444
36445    this.init('tooltip', element, options)
36446  }
36447
36448  Tooltip.DEFAULTS = {
36449    animation: true,
36450    placement: 'top',
36451    selector: false,
36452    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
36453    trigger: 'hover focus',
36454    title: '',
36455    delay: 0,
36456    html: false,
36457    container: false,
36458    viewport: {
36459      selector: 'body',
36460      padding: 0
36461    }
36462  }
36463
36464  Tooltip.prototype.init = function (type, element, options) {
36465    this.enabled   = true
36466    this.type      = type
36467    this.$element  = $(element)
36468    this.options   = this.getOptions(options)
36469    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
36470
36471    var triggers = this.options.trigger.split(' ')
36472
36473    for (var i = triggers.length; i--;) {
36474      var trigger = triggers[i]
36475
36476      if (trigger == 'click') {
36477        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
36478      } else if (trigger != 'manual') {
36479        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
36480        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
36481
36482        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
36483        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
36484      }
36485    }
36486
36487    this.options.selector ?
36488      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
36489      this.fixTitle()
36490  }
36491
36492  Tooltip.prototype.getDefaults = function () {
36493    return Tooltip.DEFAULTS
36494  }
36495
36496  Tooltip.prototype.getOptions = function (options) {
36497    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
36498
36499    if (options.delay && typeof options.delay == 'number') {
36500      options.delay = {
36501        show: options.delay,
36502        hide: options.delay
36503      }
36504    }
36505
36506    return options
36507  }
36508
36509  Tooltip.prototype.getDelegateOptions = function () {
36510    var options  = {}
36511    var defaults = this.getDefaults()
36512
36513    this._options && $.each(this._options, function (key, value) {
36514      if (defaults[key] != value) options[key] = value
36515    })
36516
36517    return options
36518  }
36519
36520  Tooltip.prototype.enter = function (obj) {
36521    var self = obj instanceof this.constructor ?
36522      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36523
36524    clearTimeout(self.timeout)
36525
36526    self.hoverState = 'in'
36527
36528    if (!self.options.delay || !self.options.delay.show) return self.show()
36529
36530    self.timeout = setTimeout(function () {
36531      if (self.hoverState == 'in') self.show()
36532    }, self.options.delay.show)
36533  }
36534
36535  Tooltip.prototype.leave = function (obj) {
36536    var self = obj instanceof this.constructor ?
36537      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36538
36539    clearTimeout(self.timeout)
36540
36541    self.hoverState = 'out'
36542
36543    if (!self.options.delay || !self.options.delay.hide) return self.hide()
36544
36545    self.timeout = setTimeout(function () {
36546      if (self.hoverState == 'out') self.hide()
36547    }, self.options.delay.hide)
36548  }
36549
36550  Tooltip.prototype.show = function () {
36551    var e = $.Event('show.bs.' + this.type)
36552
36553    if (this.hasContent() && this.enabled) {
36554      this.$element.trigger(e)
36555
36556      if (e.isDefaultPrevented()) return
36557      var that = this;
36558
36559      var $tip = this.tip()
36560
36561      this.setContent()
36562
36563      if (this.options.animation) $tip.addClass('fade')
36564
36565      var placement = typeof this.options.placement == 'function' ?
36566        this.options.placement.call(this, $tip[0], this.$element[0]) :
36567        this.options.placement
36568
36569      var autoToken = /\s?auto?\s?/i
36570      var autoPlace = autoToken.test(placement)
36571      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
36572
36573      $tip
36574        .detach()
36575        .cs
36575s({ top: 0, left: 0, display: 'block' })
36576        .addClass(placement)
36577
36578      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
36579
36580      var pos          = this.getPosition()
36581      var actualWidth  = $tip[0].offsetWidth
36582      var actualHeight = $tip[0].offsetHeight
36583
36584      if (autoPlace) {
36585        var orgPlacement = placement
36586        var $parent      = this.$element.parent()
36587        var parentDim    = this.getPosition($parent)
36588
36589        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
36590                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
36591                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
36592                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
36593                    placement
36594
36595        $tip
36596          .removeClass(orgPlacement)
36597          .addClass(placement)
36598      }
36599
36600      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
36601
36602      this.applyPlacement(calculatedOffset, placement)
36603      this.hoverState = null
36604
36605      var complete = function() {
36606        that.$element.trigger('shown.bs.' + that.type)
36607      }
36608
36609      $.support.transition && this.$tip.hasClass('fade') ?
36610        $tip
36611          .one($.support.transition.end, complete)
36612          .emulateTransitionEnd(150) :
36613        complete()
36614    }
36615  }
36616
36617  Tooltip.prototype.applyPlacement = function (offset, placement) {
36618    var $tip   = this.tip()
36619    var width  = $tip[0].offsetWidth
36620    var height = $tip[0].offsetHeight
36621
36622    // manually read margins because getBoundingClientRect includes difference
36623    var marginTop = parseInt($tip.css('margin-top'), 10)
36624    var marginLeft = parseInt($tip.css('margin-left'), 10)
36625
36626    // we must check for NaN for ie 8/9
36627    if (isNaN(marginTop))  marginTop  = 0
36628    if (isNaN(marginLeft)) marginLeft = 0
36629
36630    offset.top  = offset.top  + marginTop
36631    offset.left = offset.left + marginLeft
36632
36633    // $.fn.offset doesn't round pixel values
36634    // so we use setOffset directly with our own function B-0
36635    $.offset.setOffset($tip[0], $.extend({
36636      using: function (props) {
36637        $tip.css({
36638          top: Math.round(props.top),
36639          left: Math.round(props.left)
36640        })
36641      }
36642    }, offset), 0)
36643
36644    $tip.addClass('in')
36645
36646    // check to see if placing tip in new offset caused the tip to resize itself
36647    var actualWidth  = $tip[0].offsetWidth
36648    var actualHeight = $tip[0].offsetHeight
36649
36650    if (placement == 'top' && actualHeight != height) {
36651      offset.top = offset.top + height - actualHeight
36652    }
36653
36654    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
36655
36656    if (delta.left) offset.left += delta.left
36657    else offset.top += delta.top
36658
36659    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
36660    var arrowPosition       = delta.left ? 'left'        : 'top'
36661    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
36662
36663    $tip.offset(offset)
36664    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
36665  }
36666
36667  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
36668    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
36669  }
36670
36671  Tooltip.prototype.setContent = function () {
36672    var $tip  = this.tip()
36673    var title = this.getTitle()
36674
36675    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
36676    $tip.removeClass('fade in top bottom left right')
36677  }
36678
36679  Tooltip.prototype.hide = function () {
36680    var that = this
36681    var $tip = this.tip()
36682    var e    = $.Event('hide.bs.' + this.type)
36683
36684    function complete() {
36685      if (that.hoverState != 'in') $tip.detach()
36686      that.$element.trigger('hidden.bs.' + that.type)
36687    }
36688
36689    this.$element.trigger(e)
36690
36691    if (e.isDefaultPrevented()) return
36692
36693    $tip.removeClass('in')
36694
36695    $.support.transition && this.$tip.hasClass('fade') ?
36696      $tip
36697        .one($.support.transition.end, complete)
36698        .emulateTransitionEnd(150) :
36699      complete()
36700
36701    this.hoverState = null
36702
36703    return this
36704  }
36705
36706  Tooltip.prototype.fixTitle = function () {
36707    var $e = this.$element
36708    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
36709      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
36710    }
36711  }
36712
36713  Tooltip.prototype.hasContent = function () {
36714    return this.getTitle()
36715  }
36716
36717  Tooltip.prototype.getPosition = function ($element) {
36718    $element   = $element || this.$element
36719    var el     = $element[0]
36720    var isBody = el.tagName == 'BODY'
36721    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
36722      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
36723      width:  isBody ? $(window).width()  : $element.outerWidth(),
36724      height: isBody ? $(window).height() : $element.outerHeight()
36725    }, isBody ? {top: 0, left: 0} : $element.offset())
36726  }
36727
36728  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
36729    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
36730           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
36731           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
36732        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
36733
36734  }
36735
36736  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
36737    var delta = { top: 0, left: 0 }
36738    if (!this.$viewport) return delta
36739
36740    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
36741    var viewportDimensions = this.getPosition(this.$viewport)
36742
36743    if (/right|left/.test(placement)) {
36744      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
36745      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
36746      if (topEdgeOffset < viewportDimensions.top) { // top overflow
36747        delta.top = viewportDimensions.top - topEdgeOffset
36748      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
36749        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
36749EdgeOffset
36750      }
36751    } else {
36752      var leftEdgeOffset  = pos.left - viewportPadding
36753      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
36754      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
36755        delta.left = viewportDimensions.left - leftEdgeOffset
36756      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
36757        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
36758      }
36759    }
36760
36761    return delta
36762  }
36763
36764  Tooltip.prototype.getTitle = function () {
36765    var title
36766    var $e = this.$element
36767    var o  = this.options
36768
36769    title = $e.attr('data-original-title')
36770      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
36771
36772    return title
36773  }
36774
36775  Tooltip.prototype.tip = function () {
36776    return this.$tip = this.$tip || $(this.options.template)
36777  }
36778
36779  Tooltip.prototype.arrow = function () {
36780    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
36781  }
36782
36783  Tooltip.prototype.validate = function () {
36784    if (!this.$element[0].parentNode) {
36785      this.hide()
36786      this.$element = null
36787      this.options  = null
36788    }
36789  }
36790
36791  Tooltip.prototype.enable = function () {
36792    this.enabled = true
36793  }
36794
36795  Tooltip.prototype.disable = function () {
36796    this.enabled = false
36797  }
36798
36799  Tooltip.prototype.toggleEnabled = function () {
36800    this.enabled = !this.enabled
36801  }
36802
36803  Tooltip.prototype.toggle = function (e) {
36804    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36805    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36806  }
36807
36808  Tooltip.prototype.destroy = function () {
36809    clearTimeout(this.timeout)
36810    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36811  }
36812
36813
36814  // TOOLTIP PLUGIN DEFINITION
36815  // =========================
36816
36817  var old = $.fn.tooltip
36818
36819  $.fn.tooltip = function (option) {
36820    return this.each(function () {
36821      var $this   = $(this)
36822      var data    = $this.data('bs.tooltip')
36823      var options = typeof option == 'object' && option
36824
36825      if (!data && option == 'destroy') return
36826      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36827      if (typeof option == 'string') data[option]()
36828    })
36829  }
36830
36831  $.fn.tooltip.Constructor = Tooltip
36832
36833
36834  // TOOLTIP NO CONFLICT
36835  // ===================
36836
36837  $.fn.tooltip.noConflict = function () {
36838    $.fn.tooltip = old
36839    return this
36840  }
36841
36842}(jQuery);
36843
36844/* ========================================================================
36845 * Bootstrap: transition.js v3.1.1
36846 * http://getbootstrap.com/javascript/#transitions
36847 * ========================================================================
36848 * Copyright 2011-2014 Twitter, Inc.
36849 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36850 * ======================================================================== */
36851
36852
36853+function ($) {
36854  'use strict';
36855
36856  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36857  // ============================================================
36858
36859  function transitionEnd() {
36860    var el = document.createElement('bootstrap')
36861
36862    var transEndEventNames = {
36863      WebkitTransition : 'webkitTransitionEnd',
36864      MozTransition    : 'transitionend',
36865      OTransition      : 'oTransitionEnd otransitionend',
36866      transition       : 'transitionend'
36867    }
36868
36869    for (var name in transEndEventNames) {
36870      if (el.style[name] !== undefined) {
36871        return { end: transEndEventNames[name] }
36872      }
36873    }
36874
36875    return false // explicit for ie8 (  ._.)
36876  }
36877
36878  // http://blog.alexmaccaw.com/css-transitions
36879  $.fn.emulateTransitionEnd = function (duration) {
36880    var called = false, $el = this
36881    $(this).one($.support.transition.end, function () { called = true })
36882    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36883    setTimeout(callback, duration)
36884    return this
36885  }
36886
36887  $(function () {
36888    $.support.transition = transitionEnd()
36889  })
36890
36891}(jQuery);
36892
36893
36894// ------------------------------------------
36895// Rellax.js
36896// Buttery smooth parallax library
36897// Copyright (c) 2016 Moe Amaya (@moeamaya)
36898// MIT license
36899//
36900// Thanks to Paraxify.js and Jaime Cabllero
36901// for parallax concepts
36902// ------------------------------------------
36903
36904(function (root, factory) {
36905	if (typeof define === 'function' && define.amd) {
36906		// AMD. Register as an anonymous module.
36907		define([], factory);
36908	} else if (typeof module === 'object' && module.exports) {
36909		// Node. Does not work with strict CommonJS, but
36910		// only CommonJS-like environments that support module.exports,
36911		// like Node.
36912		module.exports = factory();
36913	} else {
36914		// Browser globals (root is window)
36915		root.Rellax = factory();
36916	}
36917}(typeof window !== "undefined" ? window : global, function () {
36918	var Rellax = function(el, options){
36919		"use strict";
36920
36921		var self = Object.create(Rellax.prototype);
36922
36923		var posY = 0;
36924		var screenY = 0;
36925		var posX = 0;
36926		var screenX = 0;
36927		var blocks = [];
36928		var pause = true;
36929
36930		// check what requestAnimationFrame to use, and if
36931		// it's not supported, use the onscroll event
36932		var loop = window.requestAnimationFrame ||
36933			window.webkitRequestAnimationFrame ||
36934			window.mozRequestAnimationFrame ||
36935			window.msRequestAnimationFrame ||
36936			window.oRequestAnimationFrame ||
36937			function(callback){ return setTimeout(callback, 1000 / 60); };
36938
36939		// store the id for later use
36940		var loopId = null;
36941
36942		// Test via a getter in the options object to see if the passive property is accessed
36943		var supportsPassive = false;
vendor: 10,724 bytes, lines 36944-37245
36944		try {
36945			var opts = Object.defineProperty({}, 'passive', {
36946				get: function() {
36947					supportsPassive = true;
36948				}
36949			});
36950			window.addEventListener("testPassive", null, opts);
36951			window.removeEventListener("testPassive", null, opts);
36952		} catch (e) {}
36953
36954		// check what cancelAnimation method to use
36955		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
36956
36957		// check which transform property to use
36958		var transformProp = window.transformProp || (function(){
36959				var testEl = document.createElement('div');
36960				if (testEl.style.transform === null) {
36961					var vendors = ['Webkit', 'Moz', 'ms'];
36962					for (var vendor in vendors) {
36963						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
36964							return vendors[vendor] + 'Transform';
36965						}
36966					}
36967				}
36968				return 'transform';
36969			})();
36970
36971		// Default Settings
36972		self.options = {
36973			speed: -2,
36974			verticalSpeed: null,
36975			horizontalSpeed: null,
36976			breakpoints: [576, 768, 1201],
36977			center: false,
36978			wrapper: null,
36979			relativeToWrapper: false,
36980			round: true,
36981			vertical: true,
36982			horizontal: false,
36983			verticalScrollAxis: "y",
36984			horizontalScrollAxis: "x",
36985			callback: function() {},
36986		};
36987
36988		// User defined options (might have more in the future)
36989		if (options){
36990			Object.keys(options).forEach(function(key){
36991				self.options[key] = options[key];
36992			});
36993		}
36994
36995		function validateCustomBreakpoints () {
36996			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
36997				var isAscending = true;
36998				var isNumerical = true;
36999				var lastVal;
37000				self.options.breakpoints.forEach(function (i) {
37001					if (typeof i !== 'number') isNumerical = false;
37002					if (lastVal !== null) {
37003						if (i < lastVal) isAscending = false;
37004					}
37005					lastVal = i;
37006				});
37007				if (isAscending && isNumerical) return;
37008			}
37009			// revert defaults if set incorrectly
37010			self.options.breakpoints = [576, 768, 1201];
37011			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
37012		}
37013
37014		if (options && options.breakpoints) {
37015			validateCustomBreakpoints();
37016		}
37017
37018		// By default, rellax class
37019		if (!el) {
37020			el = '.rellax';
37021		}
37022
37023		// check if el is a className or a node
37024		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
37025
37026		// Now query selector
37027		if (elements.length > 0) {
37028			self.elems = elements;
37029		}
37030
37031		// The elements don't exist
37032		else {
37033			console.warn("Rellax: The elements you're trying to select don't exist.");
37034			return;
37035		}
37036
37037		// Has a wrapper and it exists
37038		if (self.options.wrapper) {
37039			if (!self.options.wrapper.nodeType) {
37040				var wrapper = document.querySelector(self.options.wrapper);
37041
37042				if (wrapper) {
37043					self.options.wrapper = wrapper;
37044				} else {
37045					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
37046					return;
37047				}
37048			}
37049		}
37050
37051		// set a placeholder for the current breakpoint
37052		var currentBreakpoint;
37053
37054		// helper to determine current breakpoint
37055		var getCurrentBreakpoint = function (w) {
37056			var bp = self.options.breakpoints;
37057			if (w < bp[0]) return 'xs';
37058			if (w >= bp[0] && w < bp[1]) return 'sm';
37059			if (w >= bp[1] && w < bp[2]) return 'md';
37060			return 'lg';
37061		};
37062
37063		// Get and cache initial position of all elements
37064		var cacheBlocks = function() {
37065			for (var i = 0; i < self.elems.length; i++){
37066				var block = createBlock(self.elems[i]);
37067				blocks.push(block);
37068			}
37069		};
37070
37071
37072		// Let's kick this script off
37073		// Build array for cached element values
37074		var init = function() {
37075			for (var i = 0; i < blocks.length; i++){
37076				self.elems[i].style.cssText = blocks[i].style;
37077			}
37078
37079			blocks = [];
37080
37081			screenY = window.innerHeight;
37082			screenX = window.innerWidth;
37083			currentBreakpoint = getCurrentBreakpoint(screenX);
37084
37085			setPosition();
37086
37087			cacheBlocks();
37088
37089			animate();
37090
37091			// If paused, unpause and set listener for window resizing events
37092			if (pause) {
37093				window.addEventListener('resize', init);
37094				pause = false;
37095				// Start the loop
37096				update();
37097			}
37098		};
37099
37100		// We want to cache the parallax blocks'
37101		// values: base, top, height, speed
37102		// el: is dom object, return: el cache values
37103		var createBlock = function(el) {
37104			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
37105			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
37106			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
37107			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
37108			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
37109			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
37110			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
37111			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
37112			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
37113			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
37114			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
37115			var dataMin = el.getAttribute( 'data-rellax-min' );
37116			var dataMax = el.getAttribute( 'data-rellax-max' );
37117			var dataMinX = el.getAttribute('data-rellax-min-x');
37118			var dataMaxX = el.getAttribute('data-rellax-max-x');
37119			var dataMinY = el.getAttribute('data-rellax-min-y');
37120			var dataMaxY = el.getAttribute('data-rellax-max-y');
37121			var mapBreakpoints;
37122			var breakpoints = true;
37123
37124			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
37125				breakpoints = false;
37126			} else {
37127				mapBreakpoints = {
37128					'xs': dataXsSpeed,
37129					'sm': dataMobileSpeed,
37130					'md': dataTabletSpeed,
37131					'lg': dataDesktopSpeed
37132				};
37133			}
37134
37135			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
37136			// ensures elements are positioned based on HTML layout.
37137			//
37138			// If the element has the percentage attribute, the posY and posX needs to be
37139			// the current scroll position's value, so that the elements are still positioned based on HTML layout
37140			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37141			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
37142			if (self.options.relativeToWrapper) {
37143				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37144				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
37145			}
37146			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
37147			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;
37148
37149			var blockTop = posY + el.getBoundingClientRect().top;
37150			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
37151
37152			var blockLeft = posX + el.getBoundingClientRect().left;
37153			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
37154
37155			// apparently parallax equation everyone uses
37156			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
37157			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
37158			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
37159
37160			// Optional individual block speed as data attr, otherwise global speed
37161			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
37162			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
37163			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
37164
37165			// Optional individual block movement axis direction as data attr, otherwise global movement direction
37166			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
37167			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
37168
37169			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
37170
37171			// ~~Store non-translate3d transforms~~
37172			// Store inline styles and extract transforms
37173			var style = el.style.cssText;
37174			var transform = '';
37175
37176			// Check if there's an inline styled transform
37177			var searchResult = /transform\s*:/i.exec(style);
37178			if (searchResult) {
37179				// Get the index of the transform
37180				var index = searchResult.index;
37181
37182				// Trim the style to the transform point and get the following semi-colon index
37183				var trimmedStyle = style.slice(index);
37184				var delimiter = trimmedStyle.indexOf(';');
37185
37186				// Remove "transform" string and save the attribute
37187				if (delimiter) {
37188					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
37189				} else {
37190					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
37191				}
37192			}
37193
37194			return {
37195				baseX: bases.x,
37196				baseY: bases.y,
37197				top: blockTop,
37198				left: blockLeft,
37199				height: blockHeight,
37200				width: blockWidth,
37201				speed: speed,
37202				verticalSpeed: verticalSpeed,
37203				horizontalSpeed: horizontalSpeed,
37204				verticalScrollAxis: verticalScrollAxis,
37205				horizontalScrollAxis: horizontalScrollAxis,
37206				style: style,
37207				transform: transform,
37208				zindex: dataZindex,
37209				min: dataMin,
37210				max: dataMax,
37211				minX: dataMinX,
37212				maxX: dataMaxX,
37213				minY: dataMinY,
37214				maxY: dataMaxY
37215			};
37216		};
37217
37218		// set scroll position (posY, posX)
37219		// side effect method is not ideal, but okay for now
37220		// returns true if the scroll changed, false if nothing happened
37221		var setPosition = function() {
37222			var oldY = posY;
37223			var oldX = posX;
37224
37225			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37226			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
37227			// If option relativeToWrapper is true, use relative wrapper value instead.
37228			if (self.options.relativeToWrapper) {
37229				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37230				posY = scrollPosY - self.options.wrapper.offsetTop;
37231			}
37232
37233
37234			if (oldY != posY && self.options.vertical) {
37235				// scroll changed, return true
37236				return true;
37237			}
37238
37239			if (oldX != posX && self.options.horizontal) {
37240				// scroll changed, return true
37241				return true;
37242			}
37243
37244			// scroll did not change
37245			return false;
37246		};
37247
37248		// Ahh a pure function, gets new transform value
37249		// based on scrollPosition and speed
37250		// Allow for decimal pixel values
37251		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
37252			var result = {};
37253			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
37254			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
37255
37256			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
37257			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
37258
37259			return result;
37260		};
37261
37262		// Remove event listeners and loop again
37263		var deferredUpdate = function() {
37264			window.removeEventListener('resize', deferredUpdate);
37265			window.removeEventListener('orientationchange', deferredUpdate);
37266			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
37267			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
37268
37269			// loop again
37270			loopId = loop(update);
37271		};
37272
37273		// Loop
37274		var update = function() {
37275			if (setPosition() && pause === false) {
37276				animate();
37277
37278				// loop again
37279				loopId = loop(update);
37280			} else {
37281				loopId = null;
37282
37283				// Don't animate until we get a position updating event
37284				window.addEventListener('resize', deferredUpdate);
37285				window.addEventListener('orientationchange', deferredUpdate);
37286				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
37287				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
37288			}
37289		};
37290
37291		// Transform3d on parallax element
37292		var animate = function() {
37293			var positions;
37294			for (var i = 0; i < self.elems.length; i++){
37295				// Determine relevant movement directions
37296				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
37297				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
37298				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
37299				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
37300				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
37301				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
37302
37303				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
37304				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
37305
37306				// Subtracting initialize value, so element stays in same spot as HTML
37307				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
37308				var positionY = positions.y - blocks[i].baseY;
37309				var positionX = positions.x - blocks[i].baseX;
37310
37311				// The next two "if" blocks go like this:
37312				// Check if a limit is defined (first "min", then "max");
37313				// Check if we need to change the Y or the X
37314				// (Currently working only if just one of the axes is enabled)
37315				// Then, check if the new position is inside the allowed limit
37316				// If so, use new position. If not, set position to limit.
37317
37318				// Check if a min limit is defined
37319				if (blocks[i].min !== null) {
37320					if (self.options.vertical && !self.options.horizontal) {
37321						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
37322					}
37323					if (self.options.horizontal && !self.options.vertical) {
37324						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
37325					}
37326				}
37327
37328				// Check if directional min limits are defined
37329				if (blocks[i].minY != null) {
37330						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
37331				}
37332				if (blocks[i].minX != null) {
37333						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
37334				}
37335
37336				// Check if a max limit is defined
37337				if (blocks[i].max !== null) {
37338					if (self.options.vertical && !self.options.horizontal) {
37339						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
37340					}
37341					if (self.options.horizontal && !self.options.vertical) {
37342						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
37343					}
37344				}
37345
37346				// Check if directional max limits are defined
37347				if (blocks[i].maxY != null) {
37348						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
37349				}
37350				if (blocks[i].maxX != null) {
37351						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
37352				}
37353
37354				var zindex = blocks[i].zindex;
37355
37356				// Move that element
37357				// (Set the new translation and append initial inline transforms.)
37358				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
37359				self.elems[i].style[transformProp] = translate;
37360			}
37361			self.options.callback(positions);
37362		};
37363
37364		self.destroy = function() {
37365			for (var i = 0; i < self.elems.length; i++){
37366				self.elems[i].style.cssText = blocks[i].style;
37367			}
37368
37369			// Remove resize event listener if not pause, and pause
37370			if (!pause) {
37371				window.removeEventListener('resize', init);
37372				pause = true;
37373			}
37374
37375			// Clear the animation loop to prevent possible memory leak
37376			clearLoop(loopId);
37377			loopId = null;
37378		};
37379
37380		// Init
37381		init();
37382
37383		// Allow to recalculate the initial values whenever we want
37384		self.refresh = init;
37385
37386		return self;
37387	};
37388	return Rellax;
37389}));
37390
37391/*
37392 * OKVideo by OKFocus v2.3.2
37393 * http://okfoc.us
37394 *
37395 * Copyright 2014, OKFocus
37396 * Licensed under the MIT license.
37397 *
37398 */
37399var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
37400// youtube player ready
37401function onYouTubeIframeAPIReady() {
37402	YTplayers = new Array();
37403	jQuery('.uncode-video-container.video').each(function() {
37404		var playerY;
37405		if (jQuery(this).attr('data-provider') == 'youtube') {
37406			var id = jQuery(this).attr('data-id'),
37407				start = jQuery(this).attr('data-start'),
37408				end = jQuery(this).attr('data-end');
37409			start = typeof start && start !== null ? start : 0;
37410			end = typeof end && end !== null ? end : 0;
37411			options = jQuery(window).data('okoptions-' + id);
37412			if ( typeof options === 'undefined' ) {
37413				return true;
37414			}
37415			options.time = jQuery(this).attr('data-t');
37416			playerY = new YT.Player('okplayer-' + id, {
37417				videoId: options.video ? options.video.id : null,
37418				playerVars: {
37419					'autohide': 1,
37420					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
37421					'disablekb': 1,
37422					'cc_load_policy': options.captions,
37423					'controls': 0,
37424					'enablejsapi': 1,
37425					'fs': 0,
37426					'modestbranding': 1,
37427					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
37428					'iv_load_policy': options.annotations,
37429					'loop': options.loop,
37430					'showinfo': 0,
37431					'rel': 0,
37432					'wmode': 'opaque',
37433					'hd': options.hd,
37434					'mute': 1,
37435					'start': start,
37436					'end': end
37437				},
37438				events: {
37439					'onReady': OKEvents.yt.ready,
37440					'onStateChange': OKEvents.yt.onStateChange,
37441					'onError': OKEvents.yt.error
37442				}
37443			});
37444			YTplayers[id] = playerY;
37445			playerY.videoId = id;
37446		}
37447
37448	});
37449}
37450// vimeo player ready
37451function vimeoPlayerReady(id) {
37452	options = jQuery(window).data('okoptions-' + id);
37453	if ( typeof options === 'undefined' ) {
37454		return true;
37455	}
37456	var jIframe = options.jobject,
37457		iframe = jIframe[0];
37458
37459	jIframe.attr('src', jIframe.data('src'));
37460	var playerV = new Vimeo.Player(iframe);
37461	// hide player until Vimeo hides controls...
37462	playerV.on('loaded', function(e) {
37463		OKEvents.v.onReady(iframe);
37464		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
37465		if (carouselContainer.length) {
37466			UNCODE.owlPlayVideo(carouselContainer);
37467		}
37468		// "Do not try to add listeners or call functions before receiving this event."
37469		if (OKEvents.utils.isMobile()) {
37470			// mobile devices cannot listen for play event
37471			OKEvents.v.onPlay(playerV);
37472		} else {
37473			playerV.on('play', function(){
37474				OKEvents.v.onPlay(playerV);
37475				jQuery(window).trigger('okevents.v.play', [playerV]);
37476			});
37477			playerV.on('pause', function(){
37478				OKEvents.v.onPause;
37479				jQuery(window).trigger('okevents.v.pause', [playerV]);
37480			});
37481			playerV.on('ended', function(){
37482				OKEvents.v.onFinish
37483				jQuery(window).trigger('okevents.v.ended', [playerV]);
37484			});
37485		}
37486		if (options.time != null) {
37487			var optsTimeStr = (options.time).replace('t=', ''),
37488				timeV = '';
37489
37490			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
37491				var timeArr = optsTimeStr.split(/([^\d.-])/);
37492				for ( var i = 0; i < timeArr.length; i++ ) {
37493					if ( timeArr[i] === 'h' ) {
37494						timeV += parseFloat(timeArr[i-1]) * 3600;
37495					} else if ( timeArr[i] === 'm' ) {
37496						timeV += parseFloat(timeArr[i-1]) * 60;
37497					} else if ( timeArr[i] === 's' ) {
37498						timeV += parseFloat(timeArr[i-1]);
37499					}
37500				}
37501			} else {
37502				timeV = optsTimeStr;
37503			}
37504
37505			playerV.setCurrentTime(timeV);
37506		}
37507
37508		playerV.setVolume(0);
37509		playerV.play();
37510		jQuery(iframe).css({
37511			visibility: 'visible',
37512			opacity: 1
37513		});
37514		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37515		jQuery(iframe).closest('#page-header').addClass('video-started');
37516		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37517
37518		jQuery(window).trigger('okevents.v.loaded', [playerV]);
37519	});
37520}
37521OKEvents = {
37522	yt: {
37523		ready: function(event) {
37524			var id = event.target.videoId,
37525				$video = jQuery('#okplayer-' + id),
37526				options = jQuery(window).data('okoptions-' + id);
37527			if ( typeof options === 'undefined' ) {
37528				return true;
37529			}
37530			youtubePlayers[id] = event.target;
37531			event.target.setVolume(options.volume);
37532			if (options.autoplay === 1) {
37533				if (options.playlist.list) {
37534					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
37535				} else {
37536					var inCarousel = $video.closest('.owl-item');
37537					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
37538						if (options.time != null) {
37539							event.target.seekTo(parseInt(options.time));
37540						}
37541						event.target.playVideo();
37542					} else {
37543						event.target.pauseVideo();
37544					}
37545				}
37546			}
37547			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
37548
37549			$video.closest('[data-provider]').on('uncode-resume', function(){
37550				if (options.time != null) {
37551					event.target.seekTo(parseInt(options.time)).playVideo();
37552				} else {
37553					event.target.seekTo(0).playVideo();
37554				}
37555			});
37556
37557			$video.closest('[data-provider]').on('uncode-pause', function(){
37558				if (options.time != null) {
37559					event.target.seekTo(parseInt(options.time)).pauseVideo();
37560				} else {
37561					event.target.seekTo(0).pauseVideo();
37562				}
37563			});
37564			jQuery(window).trigger('okevents.y.loaded', [event]);
37565		},
37566		onStateChange: function(event) {
37567			var id = event.target.videoId,
37568				$video = jQuery('#okplayer-' + id),
37569				options = jQuery(window).data('okoptions-' + id);
37570			if ( typeof options === 'undefined' ) {
37571				return true;
37572			}
37573			youtubePlayers[id] = event.target;
37574			event.target.setVolume(options.volume);
37575			var $fluid = $video.closest('.fluid-object'),
37576				$tmb = $video.closest('.tmb'),
37577				setTime;
37578			switch (event.data) {
37579				case -1:
37580					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
37581					break;
37582				case 0:
37583					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
37584					options.loop && event.target.playVideo();
37585					break;
37586				case 1:
37587					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37588					setTimeout(function() {
37589						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
37590						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37591						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
37592						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37593					}, 300);
37594				break;
37595				case 2:
37596					OKEvents.utils.isFunction(options.onPause) && options.onPause();
37597					break;
37598				case 3:
37599					OKEvents.utils.isFunction(options.buffering) && options.buffering();
37600					break;
37601				case 5:
37602					OKEvents.utils.isFunction(options.cued) && options.cued();
37603					break;
37604				default:
37605					throw "OKVideo: received invalid data from YT player.";
37606			}
37607
37608			jQuery(window).trigger('okevents.y.change', [event]);
37609		},
37610		error: function(event) {
37611			throw event;
37612		}
37613	},
37614	v: {
37615		onReady: function(target) {
37616			if ( typeof options === 'undefined' ) {
37617				return true;
37618			}
37619			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
37620		},
37621		onPlay: function(player) {
37622			if ( typeof options === 'undefined' ) {
37623				return true;
37624			}
37625			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
37626			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37627			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37628			jQuery(player.element).closest('#page-header').addClass('video-started');
37629			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37630		},
37631		onPause: function() {
37632			if ( typeof options === 'undefined' ) {
37633				return true;
37634			}
37635			OKEvents.utils.isFunction(options.onPause) && options.onPause();
37636		},
37637		onFinish: function() {
37638			if ( typeof options === 'undefined' ) {
37639				return true;
37640			}
37641			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
37642		}
37643	},
37644	utils: {
37645		isFunction: function(func) {
37646			if (typeof func === 'function') {
37647				return true;
37648			} else {
37649				return false;
37650			}
37651		},
37652		isMobile: function() {
37653			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
37654				return true;
37655			} else {
37656				return false;
37657			}
37658		}
37659	}
37660};
37661
37662/**
37663 * vivus - JavaScript library to make drawing animation on SVG
37664 * @version v0.4.4
37665 * @link https://github.com/maxwellito/vivus
37666 * @license MIT
37667 */
37668
37669'use strict';
37670
37671(function () {
37672
37673  'use strict';
37674
37675/**
37676 * Pathformer
37677 * Beta version
37678 *
37679 * Take any SVG version 1.1 and transform
37680 * child elements to 'path' elements
37681 *
37682 * This code is purely forked from
37683 * https://github.com/Waest/SVGPathConverter
37684 */
37685
37686/**
37687 * Class constructor
37688 *
37689 * @param {DOM|String} element Dom element of the SVG or id of it
37690 */
37691function Pathformer(element) {
37692  // Test params
37693  if (typeof element === 'undefined') {
37694	throw new Error('Pathformer [constructor]: "element" parameter is required');
37695  }
37696
37697  // Set the element
37698  if (element.constructor === String) {
37699	element = document.getElementById(element);
37700	if (!element) {
37701	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
37702	}
37703  }
37704  if (element instanceof window.SVGElement ||
37705	  element instanceof window.SVGGElement ||
37706	  /^svg$/i.test(element.nodeName)) {
37707	this.el = element;
37708  } else {
37709	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
37710  }
37711
37712  // Start
37713  this.scan(element);
37714}
37715
37716/**
37717 * List of tags which can be transformed
37718 * to path elements
37719 *
37720 * @type {Array}
37721 */
37722Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
37723
37724/**
37725 * List of attribute names which contain
37726 * data. This array list them to check if
37727 * they contain bad values, like percentage.
37728 *
37729 * @type {Array}
37730 */
37731Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 37731-38529
37731y1', 'y2'];
37732
37733/**
37734 * Finds the elements compatible for transform
37735 * and apply the liked method
37736 *
37737 * @param  {object} options Object from the constructor
37738 */
37739Pathformer.prototype.scan = function (svg) {
37740  var fn, element, pathData, pathDom,
37741	  elements = svg.querySelectorAll(this.TYPES.join(','));
37742
37743  for (var i = 0; i < elements.length; i++) {
37744	element = elements[i];
37745	fn = this[element.tagName.toLowerCase() + 'ToPath'];
37746	pathData = fn(this.parseAttr(element.attributes));
37747	pathDom = this.pathMaker(element, pathData);
37748	element.parentNode.replaceChild(pathDom, element);
37749  }
37750};
37751
37752
37753/**
37754 * Read `line` element to extract and transform
37755 * data, to make it ready for a `path` object.
37756 *
37757 * @param  {DOMelement} element Line element to transform
37758 * @return {object}			 Data for a `path` element
37759 */
37760Pathformer.prototype.lineToPath = function (element) {
37761  var newElement = {},
37762	  x1 = element.x1 || 0,
37763	  y1 = element.y1 || 0,
37764	  x2 = element.x2 || 0,
37765	  y2 = element.y2 || 0;
37766
37767  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
37768  return newElement;
37769};
37770
37771/**
37772 * Read `rect` element to extract and transform
37773 * data, to make it ready for a `path` object.
37774 * The radius-border is not taken in charge yet.
37775 * (your help is more than welcomed)
37776 *
37777 * @param  {DOMelement} element Rect element to transform
37778 * @return {object}             Data for a `path` element
37779 */
37780Pathformer.prototype.rectToPath = function (element) {
37781  var newElement = {},
37782      x      = parseFloat(element.x)      || 0,
37783      y      = parseFloat(element.y)      || 0,
37784      width  = parseFloat(element.width)  || 0,
37785      height = parseFloat(element.height) || 0;
37786
37787  if (element.rx || element.ry) {
37788    var rx = parseInt(element.rx, 10) || -1,
37789        ry = parseInt(element.ry, 10) || -1;
37790    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
37791    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
37792
37793    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
37794                   'L ' + (x + width - rx) + ',' + y + ' ' +
37795                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
37796                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
37797                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
37798                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
37799                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
37800                   'L ' + x + ',' + (y + ry) + ' ' +
37801                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
37802  }
37803  else {
37804    newElement.d = 'M' + x + ' ' + y + ' ' +
37805                   'L' + (x + width) + ' ' + y + ' ' +
37806                   'L' + (x + width) + ' ' + (y + height) + ' ' +
37807                   'L' + x + ' ' + (y + height) + ' Z';
37808  }
37809  return newElement;
37810};
37811
37812/**
37813 * Read `polyline` element to extract and transform
37814 * data, to make it ready for a `path` object.
37815 *
37816 * @param  {DOMelement} element Polyline element to transform
37817 * @return {object}             Data for a `path` element
37818 */
37819Pathformer.prototype.polylineToPath = function (element) {
37820  var newElement = {},
37821      points = element.points.trim().split(' '),
37822      i, path;
37823
37824  // Reformatting if points are defined without commas
37825  if (element.points.indexOf(',') === -1) {
37826    var formattedPoints = [];
37827    for (i = 0; i < points.length; i+=2) {
37828      formattedPoints.push(points[i] + ',' + points[i+1]);
37829    }
37830    points = formattedPoints;
37831  }
37832
37833  // Generate the path.d value
37834  path = 'M' + points[0];
37835  for(i = 1; i < points.length; i++) {
37836    if (points[i].indexOf(',') !== -1) {
37837      path += 'L' + points[i];
37838    }
37839  }
37840  newElement.d = path;
37841  return newElement;
37842};
37843
37844/**
37845 * Read `polygon` element to extract and transform
37846 * data, to make it ready for a `path` object.
37847 * This method rely on polylineToPath, because the
37848 * logic is similar. The path created is just closed,
37849 * so it needs an 'Z' at the end.
37850 *
37851 * @param  {DOMelement} element Polygon element to transform
37852 * @return {object}             Data for a `path` element
37853 */
37854Pathformer.prototype.polygonToPath = function (element) {
37855  var newElement = Pathformer.prototype.polylineToPath(element);
37856
37857  newElement.d += 'Z';
37858  return newElement;
37859};
37860
37861/**
37862 * Read `ellipse` element to extract and transform
37863 * data, to make it ready for a `path` object.
37864 *
37865 * @param  {DOMelement} element ellipse element to transform
37866 * @return {object}             Data for a `path` element
37867 */
37868Pathformer.prototype.ellipseToPath = function (element) {
37869  var newElement = {},
37870      rx = parseFloat(element.rx) || 0,
37871      ry = parseFloat(element.ry) || 0,
37872      cx = parseFloat(element.cx) || 0,
37873      cy = parseFloat(element.cy) || 0,
37874      startX = cx - rx,
37875      startY = cy,
37876      endX = parseFloat(cx) + parseFloat(rx),
37877      endY = cy;
37878
37879  newElement.d = 'M' + startX + ',' + startY +
37880                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37881                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37882  return newElement;
37883};
37884
37885/**
37886 * Read `circle` element to extract and transform
37887 * data, to make it ready for a `path` object.
37888 *
37889 * @param  {DOMelement} element Circle element to transform
37890 * @return {object}             Data for a `path` element
37891 */
37892Pathformer.prototype.circleToPath = function (element) {
37893  var newElement = {},
37894      r  = parseFloat(element.r)  || 0,
37895      cx = parseFloat(element.cx) || 0,
37896      cy = parseFloat(element.cy) || 0,
37897      startX = cx - r,
37898      startY = cy,
37899      endX = parseFloat(cx) + parseFloat(r),
37900      endY = cy;
37901
37902  newElement.d =  'M' + startX + ',' + startY +
37903                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37904                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37905  return newElement;
37906};
37907
37908/**
37909 * Create `path` elements form original element
37910 * and prepared objects
37911 *
37912 * @param  {DOMelement} element  Original element to transform
37913 * @param  {object} pathData     Path data (from `toPath` methods)
37914 * @return {DOMelement}          Path element
37915 */
37916Pathformer.prototype.pathMaker = function (element, pathData) {
37917  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37918  for(i = 0; i < element.attributes.length; i++) {
37919    attr = element.attributes[i];
37920    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37921      pathTag.setAttribute(attr.name, attr.value);
37922    }
37923  }
37924  for(i in pathData) {
37925    pathTag.setAttribute(i, pathData[i]);
37926  }
37927  return pathTag;
37928};
37929
37930/**
37931 * Parse attributes of a DOM element to
37932 * get an object of attribute => value
37933 *
37934 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37935 * @return {object}                  Object of attributes
37936 */
37937Pathformer.prototype.parseAttr = function (element) {
37938  var attr, output = {};
37939  for (var i = 0; i < element.length; i++) {
37940    attr = element[i];
37941    // Check if no data attribute contains '%', or the transformation is impossible
37942    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37943      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37944    }
37945    output[attr.name] = attr.value;
37946  }
37947  return output;
37948};
37949
37950  'use strict';
37951
37952var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37953
37954/**
37955 * Vivus
37956 * Beta version
37957 *
37958 * Take any SVG and make the animation
37959 * to give give the impression of live drawing
37960 *
37961 * This in more than just inspired from codrops
37962 * At that point, it's a pure fork.
37963 */
37964
37965/**
37966 * Class constructor
37967 * option structure
37968 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
37969 *   duration: <int> (in frames)
37970 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
37971 *   delay: <int> (delay between the drawing of first and last path)
37972 *   dashGap <integer> whitespace extra margin between dashes
37973 *   pathTimingFunction <function> timing animation function for each path element of the SVG
37974 *   animTimingFunction <function> timing animation function for the complete SVG
37975 *   forceRender <boolean> force the browser to re-render all updated path items
37976 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
37977 *
37978 * The attribute 'type' is by default on 'delayed'.
37979 *  - 'delayed'
37980 *    all paths are draw at the same time but with a
37981 *    little delay between them before start
37982 *  - 'sync'
37983 *    all path are start and finish at the same time
37984 *  - 'oneByOne'
37985 *    only one path is draw at the time
37986 *    the end of the first one will trigger the draw
37987 *    of the next one
37988 *
37989 * All these values can be overwritten individually
37990 * for each path item in the SVG
37991 * The value of frames will always take the advantage of
37992 * the duration value.
37993 * If you fail somewhere, an error will be thrown.
37994 * Good luck.
37995 *
37996 * @constructor
37997 * @this {Vivus}
37998 * @param {DOM|String}   element  Dom element of the SVG or id of it
37999 * @param {Object}       options  Options about the animation
38000 * @param {Function}     callback Callback for the end of the animation
38001 */
38002function Vivus (element, options, callback) {
38003
38004  setupEnv();
38005
38006  // Setup
38007  this.isReady = false;
38008  this.setElement(element, options);
38009  this.setOptions(options);
38010  this.setCallback(callback);
38011
38012  if (this.isReady) {
38013    this.init();
38014  }
38015}
38016
38017/**
38018 * Timing functions
38019 **************************************
38020 *
38021 * Default functions to help developers.
38022 * It always take a number as parameter (between 0 to 1) then
38023 * return a number (between 0 and 1)
38024 */
38025Vivus.LINEAR          = function (x) {return x;};
38026Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
38027Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
38028Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
38029Vivus.EASE_OUT_BOUNCE = function (x) {
38030  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
38031    rate = Math.pow(base,1.5),
38032    rateR = Math.pow(1 - x, 2),
38033    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
38034  return (1- rateR) + (progress * rateR);
38035};
38036
38037
38038/**
38039 * Setters
38040 **************************************
38041 */
38042
38043/**
38044 * Check and set the element in the instance
38045 * The method will not return anything, but will throw an
38046 * error if the parameter is invalid
38047 *
38048 * @param {DOM|String}   element  SVG Dom element or id of it
38049 */
38050Vivus.prototype.setElement = function (element, options) {
38051  var onLoad, self;
38052
38053  // Basic check
38054  if (typeof element === 'undefined') {
38055    throw new Error('Vivus [constructor]: "element" parameter is required');
38056  }
38057
38058  // Set the element
38059  if (element.constructor === String) {
38060    element = document.getElementById(element);
38061    if (!element) {
38062      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
38063    }
38064  }
38065  this.parentEl = element;
38066
38067  // Load the SVG with XMLHttpRequest and extract the SVG
38068  if (options && options.file) {
38069    var self = this;
38070    onLoad = function (e) {
38071      var domSandbox = document.createElement('div');
38072      domSandbox.innerHTML = this.responseText;
38073
38074      var svgTag = domSandbox.querySelector('svg');
38075      if (!svgTag) {
38076        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
38077      }
38078
38079      self.el = svgTag
38080      self.el.setAttribute('width', '100%');
38081      self.el.setAttribute('height', '100%');
38082      self.parentEl.appendChild(self.el)
38083      self.isReady = true;
38084      self.init();
38085      self = null;
38086    }
38087
38088    var oReq = new window.XMLHttpRequest();
38089    oReq.addEventListener('load', onLoad);
38090    oReq.open('GET', options.file);
38091    oReq.send();
38092    return;
38093  }
38094
38095  switch (element.constructor) {
38096  case window.SVGSVGElement:
38097  case window.SVGElement:
38098  case window.SVGGElement:
38099    this.el = element;
38100    this.isReady = true;
38101    break;
38102
38103  case window.HTMLObjectElement:
38104    self = this;
38105    onLoad = function (e) {
38106      if (self.isReady) {
38107        return;
38108      }
38109      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
38110      if (!self.el && e) {
38111        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
38112      }
38113      else if (self.el) {
38114        if (element.getAttribute('built-by-vivus')) {
38115          self.parentEl.insertBefore(self.el, element);
38116          self.parentEl.removeChild(element);
38117          self.el.setAttribute('width', '100%');
38118          self.el.setAttribute('height', '100%');
38119        }
38120        self.isReady = true;
38121        self.init();
38122        self = null;
38123      }
38124    };
38125
38126    if (!onLoad()) {
38127      element.addEventListener('load', onLoad);
38128    }
38129    break;
38130
38131  default:
38132    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
38133  }
38134};
38135
38136/**
38137 * Set up user option to the instance
38138 * The method will not return anything, but will throw an
38139 * error if the parameter is invalid
38140 *
38141 * @param  {object} options Object from the constructor
38142 */
38143Vivus.prototype.setOptions = function (options) {
38144  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
38145  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
38146
38147  // Basic check
38148  if (options !== undefined && options.constructor !== Object) {
38149    throw new Error('Vivus [constructor]: "options" parameter must be an object');
38150  }
38151  else {
38152    options = options || {};
38153  }
38154
38155  // Set the animation type
38156  if (options.type && allowedTypes.indexOf(options.type) === -1) {
38157    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
38158  }
38159  else {
38160    this.type = options.type || allowedTypes[0];
38161  }
38162
38163  // Set the start type
38164  if (options.start && allowedStarts.indexOf(options.start) === -1) {
38165    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
38166  }
38167  else {
38168    this.start = options.start || allowedStarts[0];
38169  }
38170
38171  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
38172  this.duration     = parsePositiveInt(options.duration, 120);
38173  this.delay        = parsePositiveInt(options.delay, null);
38174  //Uncode addition
38175  this.delayStart   = parsePositiveInt(options.delayStart, null);
38176  //#END
38177  this.dashGap      = parsePositiveInt(options.dashGap, 1);
38178  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
38179  this.reverseStack = !!options.reverseStack;
38180  this.selfDestroy  = !!options.selfDestroy;
38181  this.onReady      = options.onReady;
38182  this.map          = [];
38183  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
38184
38185  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
38186
38187  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
38188  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
38189
38190  if (this.delay >= this.duration) {
38191    throw new Error('Vivus [constructor]: delay must be shorter than duration');
38192  }
38193};
38194
38195/**
38196 * Set up callback to the instance
38197 * The method will not return enything, but will throw an
38198 * error if the parameter is invalid
38199 *
38200 * @param  {Function} callback Callback for the animation end
38201 */
38202Vivus.prototype.setCallback = function (callback) {
38203  // Basic check
38204  if (!!callback && callback.constructor !== Function) {
38205    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
38206  }
38207  this.callback = callback || function () {};
38208};
38209
38210
38211/**
38212 * Core
38213 **************************************
38214 */
38215
38216/**
38217 * Map the svg, path by path.
38218 * The method return nothing, it just fill the
38219 * `map` array. Each item in this array represent
38220 * a path element from the SVG, with informations for
38221 * the animation.
38222 *
38223 * ```
38224 * [
38225 *   {
38226 *     el: <DOMobj> the path element
38227 *     length: <number> length of the path line
38228 *     startAt: <number> time start of the path animation (in frames)
38229 *     duration: <number> path animation duration (in frames)
38230 *   },
38231 *   ...
38232 * ]
38233 * ```
38234 *
38235 */
38236Vivus.prototype.mapping = function () {
38237  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
38238  timePoint = totalLength = lengthMeter = 0;
38239  paths = this.el.querySelectorAll('path');
38240
38241  for (i = 0; i < paths.length; i++) {
38242    path = paths[i];
38243    if (this.isInvisible(path)) {
38244      continue;
38245    }
38246    pathObj = {
38247      el: path,
38248      length: Math.ceil(path.getTotalLength())
38249    };
38250    // Test if the path length is correct
38251    if (isNaN(pathObj.length)) {
38252      if (window.console && console.warn) {
38253        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
38254      }
38255      continue;
38256    }
38257    this.map.push(pathObj);
38258    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
38259    path.style.strokeDashoffset = pathObj.length + this.dashGap;
38260    pathObj.length += this.dashGap;
38261    totalLength += pathObj.length;
38262
38263    this.renderPath(i);
38264  }
38265
38266  totalLength = totalLength === 0 ? 1 : totalLength;
38267  this.delay = this.delay === null ? this.duration / 3 : this.delay;
38268  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
38269
38270  // Reverse stack if asked
38271  if (this.reverseStack) {
38272    this.map.reverse();
38273  }
38274
38275  for (i = 0; i < this.map.length; i++) {
38276    pathObj = this.map[i];
38277
38278    switch (this.type) {
38279    case 'delayed':
38280      pathObj.startAt = this.delayUnit * i;
38281      pathObj.duration = this.duration - this.delay;
38282      break;
38283
38284    case 'oneByOne':
38285      pathObj.startAt = lengthMeter / totalLength * this.duration;
38286      pathObj.duration = pathObj.length / totalLength * this.duration;
38287      break;
38288
38289    case 'sync':
38290    case 'async':
38291    case 'nsync':
38292      pathObj.startAt = 0;
38293      pathObj.duration = this.duration;
38294      break;
38295
38296    case 'scenario-sync':
38297      path = pathObj.el;
38298      pAttrs = this.parseAttr(path);
38299      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
38300      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38301      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
38302      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38303      break;
38304
38305    case 'scenario':
38306      path = pathObj.el;
38307      pAttrs = this.parseAttr(path);
38308      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
38309      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38310      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38311      break;
38312    }
38313    lengthMeter += pathObj.length;
38314    this.frameLength = this.frameLength || this.duration;
38315  }
38316};
38317
38318/**
38319 * Interval method to draw the SVG from current
38320 * position of the animation. It update the value of
38321 * `currentFrame` and re-trace the SVG.
38322 *
38323 * It use this.handle to store the requestAnimationFrame
38324 * and clear it one the animation is stopped. So this
38325 * attribute can be used to know if the animation is
38326 * playing.
38327 *
38328 * Once the animation at the end, this method will
38329 * trigger the Vivus callback.
38330 *
38331 */
38332Vivus.prototype.drawer = function () {
38333  var self = this;
38334  this.currentFrame += this.speed;
38335
38336  if (this.currentFrame <= 0) {
38337    this.stop();
38338    this.reset();
38339  } else if (this.currentFrame >= this.frameLength) {
38340    this.stop();
38341    this.currentFrame = this.frameLength;
38342    this.trace();
38343    if (this.selfDestroy) {
38344      this.destroy();
38345    }
38346  } else {
38347    this.trace();
38348    this.handle = requestAnimFrame(function () {
38349      self.drawer();
38350    });
38351    return;
38352  }
38353
38354  this.callback(this);
38355  if (this.instanceCallback) {
38356    this.instanceCallback(this);
38357    this.instanceCallback = null;
38358  }
38359};
38360
38361/**
38362 * Draw the SVG at the current instant from the
38363 * `currentFrame` value. Here is where most of the magic is.
38364 * The trick is to use the `strokeDashoffset` style property.
38365 *
38366 * For optimisation reasons, a new property called `progress`
38367 * is added in each item of `map`. This one contain the current
38368 * progress of the path element. Only if the new value is different
38369 * the new value will be applied to the DOM element. This
38370 * method save a lot of resources to re-render the SVG. And could
38371 * be improved if the animation couldn't be played forward.
38372 *
38373 */
38374Vivus.prototype.trace = function () {
38375  var i, progress, path, currentFrame;
38376  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
38377  for (i = 0; i < this.map.length; i++) {
38378    path = this.map[i];
38379    progress = (currentFrame - path.startAt) / path.duration;
38380    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
38381    if (path.progress !== progress) {
38382      path.progress = progress;
38383      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
38384      this.renderPath(i);
38385    }
38386  }
38387};
38388
38389/**
38390 * Method forcing the browser to re-render a path element
38391 * from it's index in the map. Depending on the `forceRender`
38392 * value.
38393 * The trick is to replace the path element by it's clone.
38394 * This practice is not recommended because it's asking more
38395 * ressources, too much DOM manupulation..
38396 * but it's the only way to let the magic happen on IE.
38397 * By default, this fallback is only applied on IE.
38398 *
38399 * @param  {Number} index Path index
38400 */
38401Vivus.prototype.renderPath = function (index) {
38402  if (this.forceRender && this.map && this.map[index]) {
38403    var pathObj = this.map[index],
38404        newPath = pathObj.el.cloneNode(true);
38405    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
38406    pathObj.el = newPath;
38407  }
38408};
38409
38410/**
38411 * When the SVG object is loaded and ready,
38412 * this method will continue the initialisation.
38413 *
38414 * This this mainly due to the case of passing an
38415 * object tag in the constructor. It will wait
38416 * the end of the loading to initialise.
38417 *
38418 */
38419Vivus.prototype.init = function () {
38420  // Set object variables
38421  this.frameLength = 0;
38422  this.currentFrame = 0;
38423  this.map = [];
38424
38425  // Start
38426  new Pathformer(this.el);
38427  this.mapping();
38428  this.starter();
38429
38430  if (this.onReady) {
38431    this.onReady(this);
38432  }
38433};
38434
38435/**
38436 * Trigger to start of the animation.
38437 * Depending on the `start` value, a different script
38438 * will be applied.
38439 *
38440 * If the `start` value is not valid, an error will be thrown.
38441 * Even if technically, this is impossible.
38442 *
38443 */
38444Vivus.prototype.starter = function () {
38445  switch (this.start) {
38446  case 'manual':
38447    return;
38448
38449  case 'autostart':
38450    this.play();
38451    break;
38452
38453  case 'inViewport':
38454    var self = this,
38455    listener = function () {
38456      if (self.isInViewport(self.parentEl, 1)) {
38457        self.play();
38458        window.removeEventListener('scroll', listener);
38459        //Uncode addition
38460        window.removeEventListener('fp-slide-changed', listener);
38461        window.removeEventListener('fp-slide-scroll', listener);
38462        //#END
38463      }
38464    };
38465    window.addEventListener('scroll', listener);
38466    //Uncode addition
38467    window.addEventListener('fp-slide-changed', listener);
38468    window.addEventListener('fp-slide-scroll', listener);
38469    //#END
38470    listener();
38471    break;
38472  }
38473};
38474
38475
38476/**
38477 * Controls
38478 **************************************
38479 */
38480
38481/**
38482 * Get the current status of the animation between
38483 * three different states: 'start', 'progress', 'end'.
38484 * @return {string} Instance status
38485 */
38486Vivus.prototype.getStatus = function () {
38487  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
38488};
38489
38490/**
38491 * Reset the instance to the initial state : undraw
38492 * Be careful, it just reset the animation, if you're
38493 * playing the animation, this won't stop it. But just
38494 * make it start from start.
38495 *
38496 */
38497Vivus.prototype.reset = function () {
38498  return this.setFrameProgress(0);
38499};
38500
38501/**
38502 * Set the instance to the final state : drawn
38503 * Be careful, it just set the animation, if you're
38504 * playing the animation on rewind, this won't stop it.
38505 * But just make it start from the end.
38506 *
38507 */
38508Vivus.prototype.finish = function () {
38509  return this.setFrameProgress(1);
38510};
38511
38512/**
38513 * Set the level of progress of the drawing.
38514 *
38515 * @param {number} progress Level of progress to set
38516 */
38517Vivus.prototype.setFrameProgress = function (progress) {
38518  progress = Math.min(1, Math.max(0, progress));
38519  this.currentFrame = Math.round(this.frameLength * progress);
38520  this.trace();
38521  return this;
38522};
38523
38524/**
38525 * Play the animation at the desired speed.
38526 * Speed must be a valid number (no zero).
38527 * By default, the speed value is 1.
38528 * But a negative value is accepted to go forward.
38529 *
38530 * And works with float too.
38531 * But don't forget we are in JavaScript, se be nice
38532 * with him and give him a 1/2^x value.
38533 *
38534 * @param  {number} speed Animation speed [optional]
38535 */
38536Vivus.prototype.play = function (speed, callback) {
38537  this.instanceCallback = null;
38538
38539  if (speed && typeof speed === 'function') {
38540    this.instanceCallback = speed; // first parameter is actually the callback function
38541    speed = null;
38542  }
38543  else if (speed && typeof speed !== 'number') {
38544    throw new Error('Vivus [play]: invalid speed');
38545  }
38546  // if the first parameter wasn't the callback, check if the seconds was
38547  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
38548    this.instanceCallback = callback;
38549  }
38550
38551
38552  this.speed = speed || 1;
38553  //Uncode addition
38554  if (!this.handle) {
38555    var $this = this,
38556    delay = (this.delayStart != null) ? this.delayStart : 0;
38557    setTimeout(function() {
38558      $this.drawer();
38559    }, delay);
38560  }
38561  //#END
38562  return this;
38563};
38564
38565/**
38566 * Stop the current animation, if on progress.
38567 * Should not trigger any error.
38568 *
38569 */
38570Vivus.prototype.stop = function () {
38571  if (this.handle) {
38572    cancelAnimFrame(this.handle);
38573    this.handle = null;
38574  }
38575  return this;
38576};
38577
38578/**
38579 * Destroy the instance.
38580 * Remove all bad styling attributes on all
38581 * path tags
38582 *
38583 */
38584Vivus.prototype.destroy = function () {
38585  this.stop();
38586  var i, path;
38587  for (i = 0; i < this.map.length; i++) {
38588    path = this.map[i];
38589    path.el.style.strokeDashoffset = null;
38590    path.el.style.strokeDasharray = null;
38591    this.renderPath(i);
38592  }
38593};
38594
38595
38596/**
38597 * Utils methods
38598 * include methods from Codrops
38599 **************************************
38600 */
38601
38602/**
38603 * Method to best guess if a path should added into
38604 * the animation or not.
38605 *
38606 * 1. Use the `data-vivus-ignore` attribute if set
38607 * 2. Check if the instance must ignore invisible paths
38608 * 3. Check if the path is visible
38609 *
38610 * For now the visibility checking is unstable.
38611 * It will be used for a beta phase.
38612 *
38613 * Other improvments are planned. Like detecting
38614 * is the path got a stroke or a valid opacity.
38615 */
38616Vivus.prototype.isInvisible = function (el) {
38617  var rect,
38618    ignoreAttr = el.getAttribute('data-ignore');
38619
38620  if (ignoreAttr !== null) {
38621    return ignoreAttr !== 'false';
38622  }
38623
38624  if (this.ignoreInvisible) {
38625    rect = el.getBoundingClientRect();
38626    return !rect.width && !rect.height;
38627  }
38628  else {
38629    return false;
38630  }
38631};
38632
38633/**
38634 * Parse attributes of a DOM element to
38635 * get an object of {attributeName => attributeValue}
38636 *
38637 * @param  {object} element DOM element to parse
38638 * @return {object}         Object of attributes
38639 */
38640Vivus.prototype.parseAttr = function (element) {
38641  var attr, output = {};
38642  if (element && element.attributes) {
38643    for (var i = 0; i < element.attributes.length; i++) {
38644      attr = element.attributes[i];
38645      output[attr.name] = attr.value;
38646    }
38647  }
38648  return output;
38649};
38650
38651/**
38652 * Reply if an element is in the page viewport
38653 *
38654 * @param  {object} el Element to observe
38655 * @param  {number} h  Percentage of height
38656 * @return {boolean}
38657 */
38658Vivus.prototype.isInViewport = function (el, h) {
38659  var scrolled   = this.scrollY(),
38660    viewed       = scrolled + this.getViewportH(),
38661    elBCR        = el.getBoundingClientRect(),
38662    elHeight     = elBCR.height,
38663    elTop        = scrolled + elBCR.top,
38664    elBottom     = elTop + elHeight;
38665
38666  // if 0, the element is considered in the viewport as soon as it enters.
38667  // if 1, the element is considered in the viewport only when it's fully inside
38668  // value in percentage (1 >= h >= 0)
38669  h = h || 0;
38670
38671  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
38672};
38673
38674
38675/**
38676 * Get the viewport height in pixels
38677 *
38678 * @return {integer} Viewport height
38679 */
38680Vivus.prototype.getViewportH = function () {
38681  var client = this.docElem.clientHeight,
38682    inner = window.innerHeight;
38683
38684  if (client < inner) {
38685    return inner;
38686  }
38687  else {
38688    return client;
38689  }
38690};
38691
38692/**
38693 * Get the page Y offset
38694 *
38695 * @return {integer} Page Y offset
38696 */
38697Vivus.prototype.scrollY = function () {
38698  return window.pageYOffset || this.docElem.scrollTop;
38699};
38700
38701setupEnv = function () {
38702
38703  if (Vivus.prototype.docElem) {
38704    return;
38705  }
38706
38707  /**
38708   * Alias for document element
38709   *
38710   * @type {DOMelement}
38711   */
38712  Vivus.prototype.docElem = window.document.documentElement;
38713
38714  /**
38715   * Alias for `requestAnimationFrame` or
38716   * `setTimeout` function for deprecated browsers.
38717   *
38718   */
38719  requestAnimFrame = (function () {
38720    return (
38721      window.requestAnimationFrame       ||
38722      window.webkitRequestAnimationFrame ||
38723      window.mozRequestAnimationFrame    ||
38724      window.oRequestAnimationFrame      ||
38725      window.msRequestAnimationFrame     ||
38726      function(/* function */ callback){
38727        return window.setTimeout(callback, 1000 / 60);
38728      }
38729    );
38730  })();
38731
38732  /**
38733   * Alias for `cancelAnimationFrame` or
38734   * `cancelTimeout` function for deprecated browsers.
38735   *
38736   */
38737  cancelAnimFrame = (function () {
38738    return (
38739      window.cancelAnimationFrame       ||
38740      window.webkitCancelAnimationFrame ||
38741      window.mozCancelAnimationFrame    ||
38742      window.oCancelAnimationFrame      ||
38743      window.msCancelAnimationFrame     ||
38744      function(id){
38745        return window.clearTimeout(id);
38746      }
38747    );
38748  })();
38749};
38750
38751/**
38752 * Parse string to integer.
38753 * If the number is not positive or null
38754 * the method will return the default value
38755 * or 0 if undefined
38756 *
38757 * @param {string} value String to parse
38758 * @param {*}
38758 defaultValue Value to return if the result parsed is invalid
38759 * @return {number}
38760 *
38761 */
38762parsePositiveInt = function (value, defaultValue) {
38763  var output = parseInt(value, 10);
38764  return (output >= 0) ? output : defaultValue;
38765};
38766
38767
38768  if (typeof define === 'function' && define.amd) {
38769    // AMD. Register as an anonymous module.
38770    define([], function() {
38771      return Vivus;
38772    });
38773  } else if (typeof exports === 'object') {
38774    // Node. Does not work with strict CommonJS, but
38775    // only CommonJS-like environments that support module.exports,
38776    // like Node.
38777    module.exports = Vivus;
38778  } else {
38779    // Browser globals
38780    window.Vivus = Vivus;
38781  }
38782
38783}());

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.