PageSourceSearch

https://www.ceds.it/wp-content/themes/uncode/library/js/plugins.js?ver=208717116

js ceds.it collected 2026-10-10 00:36:20 UTC 1,288,538 bytes, 38,781 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						this.menuHide(this.visibleSubMenus[i]);
12905					}
12906				}
12907				// hide root if it's popup
12908				if (this.opts.isPopup) {
12909					this.$root.stop(true, true);
12910					if (this.$root.is(':visible')) {
12911						if (this.opts.hideFunction) {
12912							this.opts.hideFunction.call(this, this.$root);
12913						} else {
12914							this.$root.hide(this.opts.hideDuration);
12915						}
12916						// remove IE iframe shim
12917						if (this.$root.dataSM('ie-shim')) {
12918							this.$root.dataSM('ie-shim').remove();
12919						}
12920					}
12921				}
12922				this.activatedItems = [];
12923				this.visibleSubMenus = [];
12924				this.clickActivated = false;
12925				// reset z-index increment
12926				this.zIndexInc = 0;
12927			},
12928			menuIframeShim: function($ul) {
12929				// create iframe shim for the menu
12930				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
12931					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
12932						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
12933					);
12934				}
12935			},
12936			menuInit: function($ul) {
12937				if (!$ul.dataSM('in-mega')) {
12938					this.subMenus.push($ul);
12939					// mark UL's in mega drop downs (if any) so we can neglect them
12940					if ($ul.hasClass('mega-menu')) {
12941						$ul.find('ul').dataSM('in-mega', true);
12942					}
12943					// get level (much faster than, for example, using parentsUntil)
12944					var level = 2,
12945						par = $ul[0];
12946					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
12947						level++;
12948					}
12949					// cache stuff
12950					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
12951						.dataSM('level', level)
12952						.parent().dataSM('sub', $ul);
12953					// add sub indicator to parent item
12954					if (this.opts.subIndicators) {
12955						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
12956					}
12957				}
12958			},
12959			menuPosition: function($sub) {
12960				var fixIE = $('html.ie').length;
12961				// if (fixIE) {
12962				// 	var $rowParent = $($sub).closest('.main-menu-container');
12963				// 	$rowParent.height($rowParent.height());
12964				// }
12965				var $a = $sub.dataSM('parent-a'),
12966					$li = $sub.parent(),
12967					$ul = $sub.parent().parent(),
12968					// $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'),
12969					$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'),
12970					level = $sub.dataSM('level'),
12971					subW = this.getWidth($sub),
12972					subH = this.getHeight($sub),
12973					itemOffset = $a.offset(),
12974					itemX = itemOffset.left,
12975					itemY = itemOffset.top,
12976					itemW = this.getWidth($a),
12977					itemH = this.getHeight($a),
12978					$win = $(window),
12979					winX = $win.scrollLeft(),
12980					winY = $win.scrollTop(),
12981					winW = $win.width(),
12982					winH = $win.height(),
12983					containerW = $container.width(),
12984					containerOffsetX = containerW + ((winW - containerW) / 2),
12985					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
12986					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
12987					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
12988					x, y, leftPos;
12989
12990				if (horizontalParent) {
12991					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
12992					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
12993				} else {
12994					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
12995					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
12996				}
12997				if (this.opts.keepInViewport && !this.isCollapsible()) {
12998					if (this.isFixed()) {
12999						itemX -= winX;
13000						itemY -= winY;
13001						winX = winY = 0;
13002					}
13003					var absX = itemX + x,
13004						absY = itemY + y;
13005					if (this.opts.rightToLeftSubMenus && absX < winX) {
13006						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
13007					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
13008						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
13009					}
13010					if (!horizontalParent) {
13011						if (subH < winH && absY + subH > winY + winH) {
13012							y += winY + winH - subH - absY;
13013						} else if (subH >= winH || absY < winY) {
13014							y += winY - absY;
13015						}
13016					}
13017					// do we need scrolling?
13018					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
13019					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
13020						var self = this;
13021						if (!$sub.dataSM('scroll-arrows')) {
13022							$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]])
13023								.bind({
13024									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
13025									mouseleave: function(e) {
13026										self.menuScrollStop($sub);
13027										self.menuScrollOut($sub, e);
13028									},
13029									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
13030								})
13031								.insertAfter($sub)
13032							);
13033						}
13034						// bind events to show/hide arrows on hover and save scrolling data for this sub
13035						var vportY = winY - (itemY + itemH);
13036						$sub.dataSM('scroll', {
13037								vportY: vportY,
13038								subH: subH,
13039								winH: winH,
13040								step: 1
13041							})
13042							.bind({
13043								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
13044								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
13045								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
13046							})
13047							.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
13047StartZIndex() + this.zIndexInc })
13048							.eq(0).css('margin-top', vportY).end()
13049							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
13050							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
13051					}
13052				}
13053				if ( !$sub.closest('.menu-accordion').length ) {
13054					var rightPos = 'auto';
13055					if ( $sub.closest('.grid-filters').length ) {
13056						if ( $sub.closest('.text-right').length ) {
13057							leftPos = '0px';
13058							rightPos = 'auto';
13059						} else {
13060							leftPos = 'auto';
13061							rightPos = '0px';
13062						}
13063						x = 0;
13064					} else {
13065						if ( $sub.hasClass('mega-menu-inner') ) {
13066							$sub.css({ width: containerW});
13067							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
13068							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
13069								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
13070							}
13071							x = 0;
13072						} else {
13073							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
13074							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
13075						}
13076					}
13077				}
13078
13079				// $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) });
13080				$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) });
13081				// IE iframe shim
13082				this.menuIframeShim($sub);
13083				if ($sub.dataSM('ie-shim')) {
13084					$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) });
13085				}
13086			},
13087			menuScroll: function($sub, up, wheel) {
13088				var y = parseFloat($sub.css('margin-top')),
13089					scroll = $sub.dataSM('scroll'),
13090					end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH),
13091					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
13092				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
13093				y = parseFloat($sub.css('margin-top'));
13094				// show opposite arrow if appropriate
13095				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
13096					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
13097				}
13098				// accelerate when not using mousewheel to scroll
13099				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
13100					$sub.dataSM('scroll').step += 0.5;
13101				}
13102				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
13103				if (Math.abs(y - end) < 1) {
13104					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
13105					$sub.dataSM('scroll').step = 1;
13106				} else if (!wheel) {
13107					var self = this;
13108					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
13109				}
13110			},
13111			menuScrollMousewheel: function($sub, e) {
13112				var $closestSub = $(e.target).closest('ul');
13113				while ($closestSub.dataSM('in-mega')) {
13114					$closestSub = $closestSub.parent().closest('ul');
13115				}
13116				if ($closestSub[0] == $sub[0]) {
13117					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
13118					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
13119						this.menuScroll($sub, up, true);
13120					}
13121				}
13122				e.preventDefault();
13123			},
13124			menuScrollOut: function($sub, e) {
13125				var reClass = /^scroll-(up|down)/,
13126					$closestSub = $(e.relatedTarget).closest('ul');
13127				while ($closestSub.dataSM('in-mega')) {
13128					$closestSub = $closestSub.parent().closest('ul');
13129				}
13130				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
13131					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
13132				}
13133			},
13134			menuScrollOver: function($sub, e) {
13135				var reClass = /^scroll-(up|down)/,
13136					$closestSub = $(e.target).closest('ul');
13137				while ($closestSub.dataSM('in-mega')) {
13138					$closestSub = $closestSub.parent().closest('ul');
13139				}
13140				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
13141					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
13142				}
13143			},
13144			menuScrollStop: function($sub) {
13145				if (this.scrollTimeout) {
13146					clearTimeout(this.scrollTimeout);
13147					this.scrollTimeout = 0;
13148					$sub.dataSM('scroll').step = 1;
13149				}
13150			},
13151			menuShow: function($sub) {
13152				if (!$sub.dataSM('beforefirstshowfired')) {
13153					$sub.dataSM('beforefirstshowfired', true);
13154					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
13155						return;
13156					}
13157				}
13158				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
13159					return;
13160				}
13161				this.menuFixLayout($sub);
13162				$sub.stop(true, true);
13163				if (!$sub.is(':visible')) {
13164					$sub.css({
13165						'visibility': 'visible',
13166						'pointer-events': 'auto',
13167					});
13168					// set z-index - for IE < 9 set it to the parent LI
13169					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
13170					if (IElt9) {
13171						$sub.parent().css('z-index', zIndex);
13172					} else {
13173						$sub.css('z-index', zIndex);
13174					}
13175					// highlight parent item
13176					if (this.opts.keepHighlighted || this.isCollapsible()) {
13177						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
13178							$sub.dataSM('parent-a').addClass('highlighted');
13179					}
13180					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
13181					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
13182						if (!IElt8) {
13183							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13184							if (this.opts.subMenusMinWidth) {
13185							 	$sub.css('min-width', this.opts.subMenusMinWidth);
13186							}
13187							if (this.opts.subMenusMaxWidth) {
13188							 	var noMaxWidth = this.getWidth($sub);
13189							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13190								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13191							 	}
13192								if (noMaxWidth > this.getWidth($sub)) {
13193									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13194								}
13195							}
13196						// IE6,7
13197 						} else {
13198							$sub.children().css('styleFloat', 'none');
13199							if (IE6) {
13200								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
13201									.children().children('a').css('white-space', 'nowrap');
13202							} else { // IE7
13203								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13204								if (this.opts.subMenusMinWidth) {
13205									$sub.css('min-width', this.opts.subMenusMinWidth);
13206								}
13207							}
13208							if (this.opts.subMenusMaxWidth) {
13209								var noMaxWidth = $sub.width();
13210								if (IE6) {
13211							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
13212									if (noMaxWidth > maxWidth) {
13213										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
13214									} else {
13215										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
13216									}
13217								} else { // IE7
13218								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13219									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13220								 	}
13221									if (noMaxWidth > $sub.width()) {
13222										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13223									} else {
13224										$sub.width(noMaxWidth);
13225									}
13226								}
13227							} else {
13228							 	$sub.width($sub.width());
13229							}
13230							$sub.children().css('styleFloat', 'left');
13231						}
13232					}
13233					this.menuPosition($sub);
13234					// insert IE iframe shim
13235					if ($sub.dataSM('ie-shim')) {
13236						$sub.dataSM('ie-shim').insertBefore($sub);
13237					}
13238					var complete = function() {
13239						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
13240						$sub.css('overflow', '');
13241					};
13242					// if sub is collapsible (mobile view)
13243					if (this.isCollapsible()) {
13244						if (this.opts.collapsibleShowFunction) {
13245							this.opts.collapsibleShowFunction.call(this, $sub, complete);
13246						} else {
13247							$sub.show(this.opts.collapsibleShowDuration, complete);
13248						}
13249					} else {
13250						if (this.opts.showFunction) {
13251							this.opts.showFunction.call(this, $sub, complete);
13252						} else {
13253							$sub.show(this.opts.showDuration, complete);
13254						}
13255					}
13256					// save new sub menu for this level
13257					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
13258					this.$root.triggerHandler('show.smapi', $sub[0]);
13259				}
13260			},
13261			popupHide: function(noHideTimeout) {
13262				if (this.hideTimeout) {
13263					clearTimeout(this.hideTimeout);
13264					this.hideTimeout = 0;
13265				}
13266				var self = this;
13267				this.hideTimeout = setTimeout(function() {
13268					self.menuHideAll();
13269				}, noHideTimeout ? 1 : this.opts.hideTimeout);
13270			},
13271			popupShow: function(left, top) {
13272				if (!this.opts.isPopup) {
13273					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
13274					return;
13275				}
13276				if (this.hideTimeout) {
13277					clearTimeout(this.hideTimeout);
13278					this.hideTimeout = 0;
13279				}
13280				this.menuFixLayout(this.$root);
13281				this.$root.stop(true, true);
13282				if (!this.$root.is(':visible')) {
13283					this.$root.css({ left: left, top: top });
13284					// IE iframe shim
13285					this.menuIframeShim(this.$root);
13286					if (this.$root.dataSM('ie-shim')) {
13287						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
13287: left, top: top }).insertBefore(this.$root);
13288					}
13289					// show menu
13290					if (this.opts.showFunction) {
13291						this.opts.showFunction.call(this, this.$root);
13292					} else {
13293						this.$root.show(this.opts.showDuration);
13294					}
13295					this.visibleSubMenus[0] = this.$root;
13296				}
13297			},
13298			refresh: function() {
13299				this.menuHideAll();
13300				this.$root.find('ul').each(function() {
13301						var $this = $(this);
13302						if ($this.dataSM('scroll-arrows')) {
13303							$this.dataSM('scroll-arrows').remove();
13304						}
13305					})
13306					.removeDataSM('in-mega')
13307					.removeDataSM('shown-before')
13308					.removeDataSM('ie-shim')
13309					.removeDataSM('scroll-arrows')
13310					.removeDataSM('parent-a')
13311					.removeDataSM('level')
13312					.removeDataSM('beforefirstshowfired');
13313				this.$root.find('a.has-submenu').removeClass('has-submenu')
13314					.parent().removeDataSM('sub');
13315				if (this.opts.subIndicators) {
13316					this.$root.find('span.sub-arrow').remove();
13317				}
13318				if (this.opts.markCurrentItem) {
13319					this.$root.find('a.current').removeClass('current');
13320				}
13321				this.subMenus = [];
13322				this.init(true);
13323			},
13324			rootOut: function(e) {
13325				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13326					return;
13327				}
13328				if (this.hideTimeout) {
13329					clearTimeout(this.hideTimeout);
13330					this.hideTimeout = 0;
13331				}
13332				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
13333					var self = this;
13334					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
13335				}
13336			},
13337			rootOver: function(e) {
13338				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13339					return;
13340				}
13341				if (this.hideTimeout) {
13342					clearTimeout(this.hideTimeout);
13343					this.hideTimeout = 0;
13344				}
13345			},
13346			winResize: function(e) {
13347				if (!this.handleEvents()) {
13348					// we still need to resize the disable overlay if it's visible
13349					if (this.$disableOverlay) {
13350						var pos = this.$root.offset();
13351	 					this.$disableOverlay.css({
13352							top: pos.top,
13353							left: pos.left,
13354							width: this.$root.outerWidth(),
13355							height: this.$root.outerHeight()
13356						});
13357					}
13358					return;
13359				}
13360				// hide sub menus on resize - on mobile do it only on orientation change
13361				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
13362					if (this.activatedItems.length) {
13363						this.activatedItems[this.activatedItems.length - 1][0].blur();
13364					}
13365					this.menuHideAll();
13366				}
13367			}
13368		}
13369	});
13370
13371	$.fn.dataSM = function(key, val) {
13372		if (val) {
13373			return this.data(key + '_smartmenus', val);
13374		}
13375		return this.data(key + '_smartmenus');
13376	}
13377
13378	$.fn.removeDataSM = function(key) {
13379		return this.removeData(key + '_smartmenus');
13380	}
13381
13382	$.fn.smartmenus = function(options) {
13383		if (typeof options == 'string') {
13384			var args = arguments,
13385				method = options;
13386			Array.prototype.shift.call(args);
13387			return this.each(function() {
13388				var smartmenus = $(this).data('smartmenus');
13389				if (smartmenus && smartmenus[method]) {
13390					smartmenus[method].apply(smartmenus, args);
13391				}
13392			});
13393		}
13394		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
13395		return this.each(function() {
13396			new $.SmartMenus(this, opts);
13397		});
13398	}
13399
13400	// default settings
13401	$.fn.smartmenus.defaults = {
13402		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
13403		mainMenuSubOffsetX:	0,		// pixels offset from default position
13404		mainMenuSubOffsetY:	0,		// pixels offset from default position
13405		subMenusSubOffsetX:	0,		// pixels offset from default position
13406		subMenusSubOffsetY:	0,		// pixels offset from default position
13407		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13408		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13409		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
13410		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
13411		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
13412		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
13413		scrollInterval:		30,		// interval between each scrolling step
13414		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
13415		showTimeout:		250,		// timeout before showing the sub menus
13416		hideTimeout:		500,		// timeout before hiding the sub menus
13417		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
13418		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
13419							// don't forget to call complete() at the end of whatever you do
13420							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
13421		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
13422		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
13423							// don't forget to call complete() at the end of whatever you do
13424							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
13425		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
13426		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
13427							// (i.e. when mobile styles are used to make the sub menus collapsible)
13428		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
13429		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
13430							// (i.e. when mobile styles are used to make the sub menus collapsible)
13431		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
13432		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
13433		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
13434		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
13435		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
13436		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
13437		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
13438		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
13439		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
13440	};
13441
13442})(jQuery);
13443/*
13444 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
13445 * Open source under the BSD License.
13446 * Copyright © 2008 George McGinley Smith
13447 * All rights reserved.
13448 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
13449*/
13450
13451/* globals jQuery, define, module, require */
13452(function (factory) {
13453	if (typeof define === "function" && define.amd) {
13454		define(['jquery'], function ($) {
13455			return factory($);
13456		});
13457	} else if (typeof module === "object" && typeof module.exports === "object") {
13458		module.exports = factory(require('jquery'));
13459	} else {
13460		factory(jQuery);
13461	}
13462})(function($){
13463
13464	// Preserve the original jQuery "swing" easing as "jswing"
13465	if (typeof $.easing !== 'undefined') {
13466		$.easing['jswing'] = $.easing['swing'];
13467	}
13468
13469	var pow = Math.pow,
13470		sqrt = Math.sqrt,
13471		sin = Math.sin,
13472		cos = Math.cos,
13473		PI = Math.PI,
13474		c1 = 1.70158,
13475		c2 = c1 * 1.525,
13476		c3 = c1 + 1,
13477		c4 = ( 2 * PI ) / 3,
13478		c5 = ( 2 * PI ) / 4.5;
13479
13480	// x is the fraction of animation progress, in the range 0..1
13481	function bounceOut(x) {
13482		var n1 = 7.5625,
13483			d1 = 2.75;
13484		if ( x < 1/d1 ) {
13485			return n1*x*x;
13486		} else if ( x < 2/d1 ) {
13487			return n1*(x-=(1.5/d1))*x + .75;
13488		} else if ( x < 2.5/d1 ) {
13489			return n1*(x-=(2.25/d1))*x + .9375;
13490		} else {
13491			return n1*(x-=(2.625/d1))*x + .984375;
13492		}
13493	}
13494
13495	$.extend( $.easing, {
13496		def: 'easeOutQuad',
13497		swing: function (x) {
13498			return $.easing[$.easing.def](x);
13499		},
13500		easeInQuad: function (x) {
13501			return x * x;
13502		},
13503		easeOutQuad: function (x) {
13504			return 1 - ( 1 - x ) * ( 1 - x );
13505		},
13506		easeInOutQuad: function (x) {
13507			return x < 0.5 ?
13508				2 * x * x :
13509				1 - pow( -2 * x + 2, 2 ) / 2;
13510		},
13511		easeInCubic: function (x) {
13512			return x * x * x;
13513		},
13514		easeOutCubic: function (x) {
13515			return 1 - pow( 1 - x, 3 );
13516		},
13517		easeInOutCubic: function (x) {
13518			return x < 0.5 ?
13519				4 * x * x * x :
13520				1 - pow( -2 * x + 2, 3 ) / 2;
13521		},
13522		easeInQuart: function (x) {
13523			return x * x * x * x;
13524		},
13525		easeOutQuart: function (x) {
13526			return 1 - pow( 1 - x, 4 );
13527		},
13528		easeInOutQuart: function (x) {
13529			return x < 0.5 ?
13530				8 * x * x * x * x :
13531				1 - pow( -2 * x + 2, 4 ) / 2;
13532		},
13533		easeInQuint: function (x) {
13534			return x * x * x * x * x;
13535		},
13536		easeOutQuint: function (x) {
13537			return 1 - pow( 1 - x, 5 );
13538		},
13539		easeInOutQuint: function (x) {
13540			return x < 0.5 ?
13541				16 * x * x * x * x * x :
13542				1 - pow( -2 * x + 2, 5 ) / 2;
13543		},
13544		easeInSine: function (x) {
13545			return 1 - cos( x * PI/2 );
13546		},
13547		easeOutSine: function (x) {
13548			return sin( x * PI/2 );
13549		},
13550		easeInOutSine: function (x) {
13551			return -( cos( PI * x ) - 1 ) / 2;
13552		},
13553		easeInExpo: function (x) {
13554			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
13555		},
13556		easeOutExpo: function (x) {
13557			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
13558		},
13559		easeInOutExpo: function (x) {
13560			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13561				pow( 2, 20 * x - 10 ) / 2 :
13562				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
13563		},
13564		easeInCirc: function (x) {
13565			return 1 - sqrt( 1 - pow( x, 2 ) );
13566		},
13567		easeOutCirc: function (x) {
13568			return sqrt( 1 - pow( x - 1, 2 ) );
13569		},
13570		easeInOutCirc: function (x) {
13571			return x < 0.5 ?
13572				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
13573				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
13574		},
13575		easeInElastic: function (x) {
13576			return x === 0 ? 0 : x === 1 ? 1 :
13577				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
13578		},
13579		easeOutElastic: function (x) {
13580			return x === 0 ? 0 : x === 1 ? 1 :
13581				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
13582		},
13583		easeInOutElastic: function (x) {
13584			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13585				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
13586				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
13587		},
13588		easeInBack: function (x) {
13589			return c3 * x * x * x - c1 * x * x;
13590		},
13591		easeOutBack: function (x) {
13592			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
13593		},
13594		easeInOutBack: function (x) {
13595			return x < 0.5 ?
13596				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
13597				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
13598		},
13599		easeInBounce: function (x) {
13600			return 1 - bounceOut( 1 - x );
13601		},
13602		easeOutBounce: bounceOut,
13603		easeInOutBounce: function (x) {
13604			return x < 0.5 ?
13605				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
13606				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
13607		}
13608	});
13609	return $;
13610});
13611
13612/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
13613 * Licensed under the MIT License (LICENSE.txt).
13614 *
13615 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
13616 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
13617 * Thanks to: Seamus Leahy for adding deltaX and deltaY
13618 *
13619 * Version: 3.0.6
13620 *
13621 * Requires: 1.2.2+
13622 */
13623(function($) {
13624    var types = ['DOMMouseScroll', 'mousewheel'];
13625    if ($.event.fixHooks) {
13626        for (var i = types.length; i;) {
13627            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
13628        }
13629    }
13630    $.event.special.mousewheel = {
13631        setup: function() {
13632            if (this.addEventListener) {
13633                for (var i = types.length; i;) {
13634                    this.addEventListener(types[--i], handler, false);
13635                }
13636            } else {
13637                this.onmousewheel = handler;
13638            }
13639        },
13640        teardown: function() {
13641            if (this.removeEventListener) {
13642                for (var i = types.length; i;) {
13643                    this.removeEventListener(types[--i], handler, false);
13644                }
13645            } else {
13646                this.onmousewheel = null;
13647            }
13648        }
13649    };
13650    $.fn.extend({
13651        mousewheel: function(fn) {
13652            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
13653        },
13654        unmousewheel: function(fn) {
13655            return this.unbind("mousewheel", fn);
13656        }
13657    });
13658
13659    function handler(event) {
13660        var orgEvent = event || window.event,
13661            args = [].slice.call(arguments, 1),
13662            delta = 0,
13663            returnValue = true,
13664            deltaX = 0,
13665            deltaY = 0;
13666        event = $.event.fix(orgEvent);
13667        event.type = "mousewheel";
13668        // Old school scrollwheel delta
13669        if (orgEvent.wheelDelta) {
13670            delta = orgEvent.wheelDelta / 120;
13671        }
13672        if (orgEvent.detail) {
13673            delta = -orgEvent.detail / 3;
13674        }
13675        // New school multidimensional scroll (touchpads) deltas
13676        deltaY = delta;
13677        // Gecko
13678        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
13679            deltaY = 0;
13680            deltaX = -1 * delta;
13681        }
13682        // Webkit
13683        if (orgEvent.wheelDeltaY !== undefined) {
13684            deltaY = orgEvent.wheelDeltaY / 120;
13685        }
13686        if (orgEvent.wheelDeltaX !== undefined) {
13687            deltaX = -1 * orgEvent.wheelDeltaX / 120;
13688        }
13689        // Add event and delta to the front of the arguments
13690        args.unshift(event, delta, deltaX, deltaY);
13691        return ($.event.dispatch || $.event.handle).apply(this, args);
13692    }
13693})(jQuery);
13694/**
13695 * jQuery iLightBox - Revolutionary Lightbox Plugin
13696 * http://www.ilightbox.net/
13697 *
13698 * @version: 2.2.4 - October 14, 2017
13699 *
13700 * @author: iProDev (Hemn Chawroka)
13701 *          http://www.iprodev.com/
13702 *
13703 */
13704(function($, window, undefined) {
13705
13706	var extensions = {
13707			flash: ['swf'],
13708			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
13709			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
13710			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
13711		},
13712
13713		// Global DOM elements
13714		$win = $(window),
13715		$doc = $(document),
13716
13717		// Support indicators
13718		browser,
13719		transform,
13720		gpuAcceleration,
13721		fullScreenApi = '',
13722		userAgent = navigator.userAgent || navigator.vendor || window.opera,
13723        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
13724        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
13725        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)),
13726
13727		// Events
13728		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
13729		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
13730		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
13731		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
13732
13733		// Math shorthands
13734		abs = Math.abs,
13735		sqrt = Math.sqrt,
13736		round = Math.round,
13737		max = Math.max,
13738		min = Math.min,
13739		floor = Math.floor,
13740		random = Math.random,
13741
13742		pluginspages = {
13743			quicktime: 'http://www.apple.com/quicktime/download',
13744			flash: 'http://www.adobe.com/go/getflash'
13745		},
13746
13747		iLightBox = function(el, options, items, instant) {
13748			var iL = this;
13749
13750			iL.options = options,
13751				iL.selector = options.selector || el,
13752				iL.context = document,
13753				iL.instant = instant;
13754
13755			if (items.length < 1) iL.attachItems();
13756			else iL.items = items;
13757
13758			iL.vars = {
13759				total: iL.items.length,
13760				start: 0,
13761				current: null,
13762				next: null,
13763				prev: null,
13764				BODY: $('body'),
13765				loadRequests: 0,
13766				overlay: $('<div class="ilightbox-overlay"></div>'),
13767				loader: $('<div class="ilightbox-loader"><div></div></div>'),
13768				toolbar: $('<div class="ilightbox-toolbar"></div>'),
13769				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
13770				title: $('<div class="ilightbox-title"></div>'),
13771				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
13772				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
13773				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
13774				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
13775				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
13776				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13777				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13778				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13779				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
13780				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13781				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>'),
13782				thumbs: false,
13783				nextLock: false,
13784				prevLock: false,
13785				hashLock: false,
13786				isMobile: false,
13787				mobileMaxWidth: 980,
13788				isInFullScreen: false,
13789				isSwipe: false,
13790				mouseID: 0,
13791				cycleID: 0,
13792				isPaused: 0,
13793				captionHeight: 39,
13794			};
13795
13796			// Hideable elements with mousemove event
13797			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
13798
13799			iL.normalizeItems();
13800
13801			//Check necessary plugins
13802			iL.availPlugins();
13803
13804			//Set startFrom
13805			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
13806
13807			//If randomStart
13808			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
13809			iL.vars.start = iL.options.startFrom;
13810
13811			if (instant) iL.instantCall();
13812			else iL.patchItemsEvents();
13813
13814			if (iL.options.linkId) {
13815				iL.hashChangeHandler();
13816				$win.iLightBoxHashChange(function() {
13817					iL.hashChangeHandler();
13818				});
13819			}
13820
13821			if (supportTouch) {
13822				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
13823					replace = "itap";
13824				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
13825					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
13826					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
13827					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
13828			}
13829
13830			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
13831				$.extend(iL.options.styles, {
13832					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13833					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13834					nextOpacity: 0,
13835					prevOpacity: 0
13836				});
13837			}
13838		};
13839
13840	//iLightBox helpers
13841	iLightBox.prototype = {
13842		showLoader: function() {
13843			var iL = this;
13844			iL.vars.loadRequests += 1;
13845			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
13846				//top: '-30px'
13847				opacity: '1'
13848			}, iL.options.show.speed, 'easeOutCirc');
13849			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
13850				//left: '-30px'
13851				opacity: '1'
13852			}, iL.options.show.speed, 'easeOutCirc');
13853		},
13854
13855		hideLoader: function() {
13856			var iL = this;
13857			iL.vars.loadRequests -= 1;
13858			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
13859			if (iL.options.path.toLowerCase() == "horizontal") {
13860				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13861					//top: '-192px'
13862					opacity: '0'
13863				}, iL.options.show.speed, 'easeInCirc');
13864			} else {
13865				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13866					//left: '-192px'
13867					opacity: '0'
13868				}, iL.options.show.speed, 'easeInCirc');
13869			}
13870		},
13871
13872		createUI: function() {
13873			var iL = this;
13874
13875			iL.ui = {
13876				currentElement: iL.vars.holder,
13877				nextElement: iL.vars.nextPhoto,
13878				prevElement: iL.vars.prevPhoto,
13879				currentItem: iL.vars.current,
13880				nextItem: iL.vars.next,
13881				prevItem: iL.vars.prev,
13882				hide: function() {
13883					iL.closeAction();
13884				},
13885				refresh: function() {
13886					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13887				},
13888				fullscreen: function() {
13889					iL.fullScreenAction();
13890				}
13891			};
13892		},
13893
13894		attachItems: function() {
13895			var iL = this,
13896				itemsObject = new Array(),
13897				items = new Array();
13898
13899			$(iL.selector, iL.context).each(function() {
13900				var t = $(this),
13901					URL = t.attr(iL.options.attr) || null,
13902					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
13903					caption = t.data('caption'),
13904					title = t.data('title'),
13905					type = t.data('type') || getTypeByExtension(URL),
13906					clone = t.data('lbox-clone') || false;
13907
13908				//Uncode addition ##START##
13909				if (type === false) {
13910					return;
13911				}
13912				//Uncode addition ##END##
13913
13914				if (t.data('lbox-clone') != undefined) return;
13915
13916				//Uncode addition ##START##
13917				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
13918					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
13919						URL_i,
13920						URLS_LENGHT = ALBUM_URLS.length;
13921
13922					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
13923						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
13924							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
13925							item_opts = item_opts && eval("({" + item_opts + "})") || {},
13926							items.push({
13927								URL: ALBUM_URLS[URL_i].url,
13928								caption: ALBUM_URLS[URL_i].caption,
13929								title: ALBUM_URLS[URL_i].title,
13930								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
13931								options: item_opts,
13932								clone: clone
13933							});
13934							var newT = t;
13935							newT.attr('href',ALBUM_URLS[URL_i].url);
13936							if (!iL.instant) itemsObject.push(newT);
13937						}
13938					}
13939				} else {
13940				//Uncode addition ##END##
13941					items.push({
13942						URL: URL,
13943						caption: caption,
13944						title: title,
13945						type: type,
13946						options: options,
13947						clone: clone
13948					});
13949				}
13950
13951
13952				if (iL.vars != undefined) iL.vars.total = items.length;
13953
13954				if (!iL.instant) itemsObject.push(t);
13955			});
13956
13957			iL.items = items,
13958				iL.itemsObject = itemsObject;
13959
13960		},
13961
13962		normalizeItems: function() {
13963			var iL = this,
13964				newItems = new Array();
13965
13966			$.each(iL.items, function(key, val) {
13967
13968				if (typeof val == "string") val = {
13969					url: val
13970				};
13971
13972				var URL = val.url || val.URL || null,
13973					options = val.options || {},
13974					caption = val.caption || null,
13975					title = val.title || null,
13976					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
13977					ext = (typeof URL != 'object') ? getExtension(URL) : '';
13978
13979				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
13980				options.videoType = options.videoType || null,
13981				options.skin = options.skin || iL.options.skin,
13982				options.width = options.width || null,
13983				options.height = options.height || null,
13984				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
13985				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
13986				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
13987
13988				if (type == "video") {
13989					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
13990
13991					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
13992					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
13993					options.html5video.preload = options.html5video.preload || "metadata";
13994					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
13995					//UNCODE addition
13996					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
13997				}
13998
13999				if (!options.width || !options.height) {
14000					if (type == "video") options.width = 1280, options.height = 720;
14001					else if (type == "iframe") options.width = '100%', options.height = '90%';
14002					else if (type == "flash") options.width = 1280, options.height = 720;
14003				}
14004
14005				delete val.url;
14006				val.index = key;
14007				val.URL = URL;
14008				val.caption = caption;
14009				val.title = title;
14010				val.type = type;
14011				val.options = options;
14012				val.ext = ext;
14013
14014				newItems.push(val);
14015			});
14016
14017			iL.items = newItems;
14018		},
14019
14020		instantCall: function() {
14021			var iL = this,
14022				key = iL.vars.start;
14023
14024			iL.vars.current = key;
14025			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
14026			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
14027
14028			iL.addContents();
14029			iL.patchEvents();
14030		},
14031
14032		addContents: function() {
14033			var iL = this,
14034				vars = iL.vars,
14035				opts = iL.options,
14036				viewport = getViewport(),
14037				path = opts.path.toLowerCase(),
14038				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
14039					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
14040				}),
14041				needRecognition = recognizingItems.length > 0;
14042
14043			if (opts.mobileOptimizer && !opts.innerToolbar)
14044				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14045
14046			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
14047
14048			if (opts.linkId)
14049				vars.overlay[0].setAttribute('linkid', opts.linkId);
14050
14051			//Add Toolbar Buttons
14052			if (opts.controls.toolbar) {
14053				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
14054				if (opts.controls.fullscreen)
14055					vars.toolbar.append(vars.fullScreenButton);
14056				if (opts.controls.slideshow)
14057					vars.toolbar.append(vars.innerPlayButton);
14058				if (vars.total > 1)
14059					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
14060			}
14061
14062			//Append elements to body
14063			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
14064
14065			if (!opts.innerToolbar)
14066				vars.BODY.append(vars.toolbar);
14067			if (opts.controls.arrows)
14068				vars.BODY.append(vars.nextButton).append(vars.prevButton);
14069
14070			if (opts.controls.thumbnail && vars.total > 1) {
14071				vars.BODY.append(vars.thumbnails);
14072				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
14073				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
14074				vars.thumbs = true;
14075			}
14076
14077			//Configure loader and arrows
14078			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
14079				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
14080			} : {
14081				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
14082			};
14083			vars.loader.addClass(opts.skin).css(loaderCss);
14084			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
14085			if (path == "horizontal")
14086				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
14087
14088			// Configure arrow buttons
14089			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14090
14091			if (!opts.infinite) {
14092				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14093
14094				if (vars.current == 0)
14095					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14096				if (vars.current >= vars.total - 1)
14097					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14098			}
14099
14100			if (opts.show.effect) {
14101				vars.overlay.stop().fadeIn(opts.show.speed);
14102				vars.toolbar.stop().fadeIn(opts.show.speed);
14103			} else {
14104				vars.overlay.show();
14105				vars.toolbar.show();
14106			}
14107
14108			var length = recognizingItems.length;
14109			if (needRecognition) {
14110				iL.showLoader();
14111
14112				$.each(recognizingItems, function(key, val) {
14113					var resultFnc = function(result) {
14114							var key = -1,
14115								filter = iL.items.filter(function(e, i, arr) {
14116									if (e.URL == result.url)
14117										key = i;
14118
14119									return e.URL == result.url;
14120								}),
14121								self = iL.items[key];
14122
14123							if (result)
14124								$.extend(true, self, {
14125									URL: result.source,
14126									type: result.type,
14127									recognized: true,
14128									options: {
14129										html5video: result.html5video,
14130										width: (result.type == "image") ? 0 : (result.width || self.width),
14131										height: (result.type == "image") ? 0 : (result.height || self.height),
14132										thumbnail: self.options.thumbnail || result.thumbnail
14133									}
14134								});
14135
14136							length--;
14137
14138							if (length == 0) {
14139								iL.hideLoader();
14140
14141								vars.dontGenerateThumbs = false;
14142								iL.generateThumbnails();
14143
14144								if (opts.show.effect)
14145									setTimeout(function() {
14146										iL.generateBoxes();
14147									}, opts.show.speed);
14148								else
14149									iL.generateBoxes();
14150							}
14151						};
14152
14153					iL.ogpRecognition(this, resultFnc);
14154				});
14155			}
14156			else {
14157				if (opts.show.effect)
14158					setTimeout(function() {
14159						iL.generateBoxes();
14160					}, opts.show.speed);
14161				else
14162					iL.generateBoxes();
14163			}
14164
14165			iL.createUI();
14166
14167			window.iLightBox = {
14168				close: function() {
14169					iL.closeAction();
14170				},
14171				fullscreen: function() {
14172					iL.fullScreenAction();
14173				},
14174				moveNext: function() {
14175					iL.moveTo('next');
14176				},
14177				movePrev: function() {
14178					iL.moveTo('prev');
14179				},
14180				goTo: function(index) {
14181					iL.goTo(index);
14182				},
14183				refresh: function() {
14184					iL.refresh();
14185				},
14186				reposition: function() {
14187					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
14188				},
14189				setOption: function(options) {
14190					iL.setOption(options);
14191				},
14192				destroy: function() {
14193					iL.closeAction();
14194					iL.dispatchItemsEvents();
14195				}
14196			};
14197
14198			if (opts.linkId) {
14199				vars.hashLock = true;
14200				window.location.hash = opts.linkId + '/' + vars.current;
14201				setTimeout(function() {
14202					vars.hashLock = false;
14203				}, 55);
14204			}
14205
14206			if (!opts.slideshow.startPaused) {
14207				iL.resume();
14208				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
14209			}
14210
14211			//Trigger the onOpen callback
14212			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
14213		},
14214
14215		loadContent: function(obj, opt, speed) {
14216			var iL = this,
14217				holder, item;
14218
14219			iL.createUI();
14220
14221			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
14222
14223			if (opt == 'current') {
14224				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
14225				else iL.vars.lockWheel = false;
14226
14227				if (!obj.options.swipe) iL.vars.lockSwipe = true;
14228				else iL.vars.lockSwipe = false;
14229			}
14230
14231			switch (opt) {
14232				case 'current':
14233					holder = iL.vars.holder, item = iL.vars.current;
14234					break;
14235				case 'next':
14236					holder = iL.vars.nextPhoto, item = iL.vars.next;
14237					break;
14238				case 'prev':
14239					holder = iL.vars.prevPhoto, item = iL.vars.prev;
14240					break;
14241			}
14242
14243			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
14244			$('div.ilightbox-inner-toolbar', holder).remove();
14245
14246			if (obj.title || iL.options.innerToolbar) {
14247				var innerToolbar = iL.vars.innerToolbar.clone();
14248				if (obj.title && iL.options.show.title) {
14249					var title = iL.vars.title.clone();
14250					title.empty().html(obj.title);
14251					innerToolbar.append(title);
14252				}
14253				if (iL.options.innerToolbar) {
14254					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
14255				}
14256				holder.prepend(innerToolbar);
14257			}
14258
14259			//console.warn('loadContent', arguments);
14260
14261			iL.loadSwitcher(obj, holder, item, opt);
14262		},
14263
14264		loadSwitcher: function(obj, holder, item, opt) {
14265			var iL = this,
14266				opts = iL.options,
14267				api = {
14268					element: holder,
14269					position: item
14270				};
14271
14272			switch (obj.type) {
14273				case 'image':
14274					//Trigger the onBeforeLoad callback
14275					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14276					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14277
14278					iL.loadImage(obj.URL, function(img) {
14279						//Trigger the onAfterLoad callback
14280						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14281						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14282
14283						var width = (img) ? img.width : 400,
14284							height = (img) ? img.height : 200;
14285
14286						holder.data({
14287							naturalWidth: width,
14288							naturalHeight: height
14289						});
14290
14291						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
14292
14293						//Trigger the onRender callback
14294						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14295						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14296
14297						iL.configureHolder(obj, opt, holder);
14298					});
14299
14300					break;
14301
14302				case 'video':
14303					holder.data({
14304						naturalWidth: obj.options.width,
14305						naturalHeight: obj.options.height
14306					});
14307
14308					if (opt === 'current') {
14309						iL.addContent(holder, obj);
14310
14311						//Trigger the onRender callback
14312						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14313						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14314					} else {
14315						$('div.ilightbox-container', holder).empty();
14316					}
14317
14318					iL.configureHolder(obj, opt, holder);
14319
14320					break;
14321
14322				case 'iframe':
14323					//iL.showLoader();
14324					holder.data({
14325						naturalWidth: obj.options.width,
14326						naturalHeight: obj.options.height
14327					});
14328
14329					iL.configureHolder(obj, opt, holder);
14330
14331					if (opt === 'current') {
14332						var el = iL.addContent(holder, obj);
14333
14334						//Trigger the onRender callback
14335						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14336						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14337
14338						//Trigger the onBeforeLoad callback
14339						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14340						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14341
14342						el.bind('load', function() {
14343							//Trigger the onAfterLoad callback
14344							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14345							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14346
14347							//iL.hideLoader();
14348							el.unbind('load');
14349						});
14350					} else {
14351						$('div.ilightbox-container', holder).empty();
14352					}
14353
14354					break;
14355
14356				case 'inline':
14357					var el = $(obj.URL),
14358						content = iL.addContent(holder, obj),
14359						images = findImageInElement(holder);
14360
14361					holder.data({
14362						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14363						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14364					});
14365					content.children().eq(0).show();
14366
14367					//Trigger the onRender callback
14368					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14369					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14370
14371					//Trigger the onBeforeLoad callback
14372					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14373					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14374
14375					iL.loadImage(images, function() {
14376						//Trigger the onAfterLoad callback
14377						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14378						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14379
14380						iL.configureHolder(obj, opt, holder);
14381					});
14382
14383					break;
14384
14385				case 'flash':
14386					var el = iL.addContent(holder, obj);
14387
14388					holder.data({
14389						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14390						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14391					});
14392
14393					//Trigger the onRender callback
14394					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14395					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14396
14397					iL.configureHolder(obj, opt, holder);
14398
14399					break;
14400
14401				case 'ajax':
14402					var ajax = obj.options.ajax || {};
14403					//Trigger the onBeforeLoad callback
14404					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14405					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14406
14407					iL.showLoader();
14408					$.ajax({
14409						url: obj.URL || opts.ajaxSetup.url,
14410						data: ajax.data || null,
14411						dataType: ajax.dataType || "html",
14412						type: ajax.type || opts.ajaxSetup.type,
14413						cache: ajax.cache || opts.ajaxSetup.cache,
14414						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
14415						global: ajax.global || opts.ajaxSetup.global,
14416						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
14417						username: ajax.username || opts.ajaxSetup.username,
14418						password: ajax.password || opts.ajaxSetup.password,
14419						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
14420						complete: ajax.complete || opts.ajaxSetup.complete,
14421						success: function(data, textStatus, jqXHR) {
14422							iL.hideLoader();
14423
14424							var el = $(data),
14425								container = $('div.ilightbox-container', holder),
14426								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
14427								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
14428								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
14429									'overflow': 'hidden'
14430								} : {};
14431
14432							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
14433							holder.show().data({
14434								naturalWidth: (elWidth || container.outerWidth()),
14435								naturalHeight: (elHeight || container.outerHeight())
14436							}).hide();
14437
14438							//Trigger the onRender callback
14439							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14440							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14441
14442							var images = findImageInElement(holder);
14443							iL.loadImage(images, function() {
14444								//Trigger the onAfterLoad callback
14445								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14446								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14447
14448								iL.configureHolder(obj, opt, holder);
14449							});
14450
14451							opts.ajaxSetup.success(data, textStatus, jqXHR);
14452							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
14453						},
14454						error: function(jqXHR, textStatus, errorThrown) {
14455							//Trigger the onAfterLoad callback
14456							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14457							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14458
14459							iL.hideLoader();
14460							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
14461							iL.configureHolder(obj, opt, holder);
14462
14463							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
14464							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
14465						}
14466					});
14467
14468					break;
14469
14470				case 'html':
14471					var object = obj.URL,
14472						el
14473					container = $('div.ilightbox-container', holder);
14474
14475					if (object[0].nodeName) el = object.clone();
14476					else {
14477						var dom = $(object);
14478						if (dom.selector) el = $('<div>' + dom + '</div>');
14479						else el = dom;
14480					}
14481
14482					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
14483						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
14484
14485					iL.addContent(holder, obj);
14486
14487					el.appendTo(document.documentElement).hide();
14488
14489					//Trigger the onRender callback
14490					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14491					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14492
14493					var images = findImageInElement(holder);
14494
14495					//Trigger the onBeforeLoad callback
14496					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14497					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14498
14499					iL.loadImage(images, function() {
14500						//Trigger the onAfterLoad callback
14501						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14502						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14503
14504						holder.show().data({
14505							naturalWidth: (elWidth || container.outerWidth()),
14506							naturalHeight: (elHeight || container.outerHeight())
14507						}).hide();
14508						el.remove();
14509
14510						iL.configureHolder(obj, opt, holder);
14511					});
14512
14513					break;
14514			}
14515		},
14516
14517		configureHolder: function(obj, opt, holder) {
14518			var iL = this,
14519				vars = iL.vars,
14520				opts = iL.options;
14521
14522			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
14523
14524			if (opt == "current")
14525				var item = vars.current;
14526			else if (opt == "next")
14527				var opacity = opts.styles.nextOpacity,
14528					item = vars.next;
14529			else
14530				var opacity = opts.styles.prevOpacity,
14531					item = vars.prev;
14532
14533			var api = {
14534				element: holder,
14535				position: item
14536			};
14537
14538			iL.items[item].options.width = iL.items[item].options.width || 0,
14539			iL.items[item].options.height = iL.items[item].options.height || 0;
14540
14541			if (opt == "current") {
14542				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
14543					holder.css(transform, '');
14544					if (obj.caption) {
14545						iL.setCaption(obj, holder);
14546						var caption = $('div.ilightbox-caption', holder),
14547							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
14548						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
14548Speed);
14549					}
14550
14551					var social = obj.options.social;
14552					if (social) {
14553						iL.setSocial(social, obj.URL, holder);
14554						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
14555					}
14556
14557					//Generate thumbnails
14558					iL.generateThumbnails();
14559
14560					//Trigger the onShow callback
14561					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14562					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14563				});
14564				else {
14565					holder.show();
14566
14567					//Generate thumbnails
14568					iL.generateThumbnails();
14569
14570					//Trigger the onShow callback
14571					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14572					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14573				}
14574			} else {
14575				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
14576					if (opt == "next") vars.nextLock = false;
14577					else vars.prevLock = false;
14578
14579					//Generate thumbnails
14580					iL.generateThumbnails();
14581
14582					//Trigger the onShow callback
14583					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14584					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14585				});
14586				else {
14587					holder.css({
14588						opacity: opacity
14589					}).show();
14590					if (opt == "next") vars.nextLock = false;
14591					else vars.prevLock = false;
14592
14593					//Generate thumbnails
14594					iL.generateThumbnails();
14595
14596					//Trigger the onShow callback
14597					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14598					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14599				}
14600			}
14601
14602			setTimeout(function() {
14603				iL.repositionPhoto();
14604			}, 0);
14605		},
14606
14607		generateBoxes: function() {
14608			var iL = this,
14609				vars = iL.vars,
14610				opts = iL.options;
14611
14612			if (opts.infinite && vars.total >= 3) {
14613				if (vars.current == vars.total - 1) vars.next = 0;
14614				if (vars.current == 0) vars.prev = vars.total - 1;
14615			} else opts.infinite = false;
14616
14617			//UNCODE addition
14618			if ( typeof iL.items[vars.current] == 'undefined' )
14619				vars.current = 0;
14620
14621			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
14622
14623			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
14624			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
14625		},
14626
14627		generateThumbnails: function() {
14628			var iL = this,
14629				vars = iL.vars,
14630				opts = iL.options,
14631				timeOut = null;
14632
14633			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
14634				var thumbnails = vars.thumbnails,
14635					container = $('div.ilightbox-thumbnails-container', thumbnails),
14636					grid = $('div.ilightbox-thumbnails-grid', container),
14637					i = 0;
14638
14639				grid.removeAttr('style').empty();
14640
14641				$.each(iL.items, function(key, val) {
14642					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
14643						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
14644						thumb = val.options.thumbnail,
14645						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
14646						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
14647
14648					thumbnail.css({
14649						opacity: 0
14650					}).addClass(isActive);
14651
14652					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
14653						icon.addClass('ilightbox-thumbnail-video');
14654						thumbnail.append(icon);
14655					} else if (val.options.icon) {
14656						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
14657						thumbnail.append(icon);
14658					}
14659
14660					if (thumb) iL.loadImage(thumb, function(img) {
14661						i++;
14662						if (img) thumbnail.data({
14663							naturalWidth: img.width,
14664							naturalHeight: img.height
14665						}).append('<img src="' + thumb + '" border="0" />');
14666						else thumbnail.data({
14667							naturalWidth: opts.thumbnails.maxWidth,
14668							naturalHeight: opts.thumbnails.maxHeight
14669						});
14670
14671						clearTimeout(timeOut);
14672						timeOut = setTimeout(function() {
14673							iL.positionThumbnails(thumbnails, container, grid);
14674						}, 20);
14675						setTimeout(function() {
14676							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
14677						}, i * 20);
14678					});
14679
14680					grid.append(thumbnail);
14681				});
14682				iL.vars.dontGenerateThumbs = true;
14683			}
14684		},
14685
14686		positionThumbnails: function(thumbnails, container, grid) {
14687			var iL = this,
14688				vars = iL.vars,
14689				opts = iL.options,
14690				viewport = getViewport(),
14691				path = opts.path.toLowerCase();
14692
14693			if (!thumbnails) thumbnails = vars.thumbnails;
14694			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
14695			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
14696
14697			var thumbs = $('.ilightbox-thumbnail', grid),
14698				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
14699				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
14700				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
14701				gridHeight = (path == 'horizontal') ? heightAvail : 0,
14702				active = $('.ilightbox-active', grid),
14703				gridCss = {},
14704				css = {};
14705
14706			if (arguments.length < 3) {
14707				thumbs.css({
14708					opacity: opts.thumbnails.normalOpacity
14709				});
14710				active.css({
14711					opacity: opts.thumbnails.activeOpacity
14712				});
14713			}
14714
14715			thumbs.each(function(i) {
14716				var t = $(this),
14717					data = t.data(),
14718					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
14719				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
14720				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
14721
14722				t.css({
14723					width: dims.width,
14724					height: dims.height
14725				});
14726				if (path == 'horizontal') t.css({
14727					'float': 'left'
14728				});
14729
14730				(path == 'horizontal') ? (
14731					gridWidth += t.outerWidth()
14732				) : (
14733					gridHeight += t.outerHeight()
14734				);
14735			});
14736
14737			gridCss = {
14738				width: gridWidth,
14739				height: gridHeight
14740			};
14741
14742			grid.css(gridCss);
14743
14744			gridCss = {};
14745
14746			var gridOffset = grid.offset(),
14747				activeOffset = (active.length) ? active.offset() : {
14748					top: parseInt(heightAvail / 2),
14749					left: parseInt(widthAvail / 2)
14750				};
14751
14752			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
14753				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
14754				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
14755				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
14756
14757			(path == 'horizontal') ? (
14758				gridCss.top = 0,
14759				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
14760			) : (
14761				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
14762				gridCss.left = 0
14763			);
14764
14765			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
14766			else grid.css(gridCss);
14767		},
14768
14769		loadImage: function(image, callback) {
14770			if (!$.isArray(image)) image = [image];
14771
14772			var iL = this,
14773				length = image.length;
14774
14775			if (length > 0) {
14776				iL.showLoader();
14777				$.each(image, function(index, value) {
14778					var img = new Image();
14779					img.onload = function() {
14780						length -= 1;
14781						if (length == 0) {
14782							iL.hideLoader();
14783							callback(img);
14784						}
14785					};
14786					img.onerror = img.onabort = function() {
14787						length -= 1;
14788						if (length == 0) {
14789							iL.hideLoader();
14790							callback(false);
14791						}
14792					};
14793					img.src = image[index];
14794				});
14795			} else callback(false);
14796		},
14797
14798		patchItemsEvents: function() {
14799			var iL = this,
14800				vars = iL.vars,
14801				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
14802				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
14803
14804			if (iL.context && iL.selector) {
14805				var $items = $(iL.selector, iL.context);
14806
14807				$(iL.context).on(clickEvent, iL.selector, function() {
14808					var $this = $(this),
14809						//UNCODE addition
14810						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
14811					if (UNCODE.isMobile) {
14812						var isCarousel = $this.closest('.owl-carousel');
14813						if (isCarousel.length) {
14814							if (isCarousel.hasClass('owl-translating')) return false;
14815						}
14816					}
14817
14818					vars.current = key;
14819					vars.next = iL.items[key + 1] ? key + 1 : null;
14820					vars.prev = iL.items[key - 1] ? key - 1 : null;
14821
14822					//UNCODE addition
14823					if ( vars.BODY.hasClass('fp-slide-scrolling') )
14824						return false;
14825
14826					iL.addContents();
14827					iL.patchEvents();
14828
14829					return false;
14830				}).on(vEvent, iL.selector, function() {
14831					return false;
14832				});
14833			} else
14834				$.each(iL.itemsObject, function(key, val) {
14835					val.on(clickEvent, function() {
14836						vars.current = key;
14837						vars.next = iL.items[key + 1] ? key + 1 : null;
14838						vars.prev = iL.items[key - 1] ? key - 1 : null;
14839
14840						iL.addContents();
14841						iL.patchEvents();
14842
14843						return false;
14844					}).on(vEvent, function() {
14845						return false;
14846					});
14847				});
14848		},
14849
14850		dispatchItemsEvents: function() {
14851			var iL = this,
14852				vars = iL.vars,
14853				opts = iL.options;
14854
14855			if (iL.context && iL.selector)
14856				$(iL.context).off('.iL', iL.selector);
14857			else
14858				$.each(iL.itemsObject, function(key, val) {
14859					val.off('.iL');
14860				});
14861		},
14862
14863		refresh: function() {
14864			var iL = this;
14865
14866			iL.dispatchItemsEvents();
14867			iL.attachItems();
14868			iL.normalizeItems();
14869			iL.patchItemsEvents();
14870		},
14871
14872		patchEvents: function() {
14873			var iL = this,
14874				vars = iL.vars,
14875				opts = iL.options,
14876				path = opts.path.toLowerCase(),
14877				holders = $('.ilightbox-holder'),
14878				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
14879				durationThreshold = 1000,
14880				horizontalDistanceThreshold =
14881				verticalDistanceThreshold = 100,
14882				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
14883
14884			$win.bind('resize.iLightBox', function() {
14885				var viewport = getViewport();
14886
14887				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14888				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14889
14890				iL.repositionPhoto(null);
14891				if (supportTouch) {
14892					clearTimeout(vars.setTime);
14893					vars.setTime = setTimeout(function() {
14894						var scrollTop = getScrollXY().y;
14895						window.scrollTo(0, scrollTop - 30);
14896						window.scrollTo(0, scrollTop + 30);
14897						window.scrollTo(0, scrollTop);
14898					}, 2000);
14899				}
14900				if (vars.thumbs) iL.positionThumbnails();
14901			}).bind('keydown.iLightBox', function(event) {
14902				if (opts.controls.keyboard) {
14903					switch (event.keyCode) {
14904						case 13:
14905							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
14906							break;
14907						case 27:
14908							if (opts.keyboard.esc) iL.closeAction();
14909							break;
14910						case 37:
14911							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
14912							break;
14913						case 38:
14914							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
14915							break;
14916						case 39:
14917							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
14918							break;
14919						case 40:
14920							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
14921							break;
14922					}
14923				}
14924			});
14925
14926			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
14927				iL.doFullscreen();
14928			});
14929
14930			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
14931					return arr.lastIndexOf(e) === i;
14932				}),
14933				holderEvents = "";
14934
14935			$.each(holderEventsArr, function(key, val) {
14936				if (key != 0) holderEvents += ' ';
14937				holderEvents += val;
14938			});
14939
14940			$doc.on(clickEvent, '.ilightbox-overlay', function() {
14941				if (opts.overlay.blur) iL.closeAction();
14942			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
14943				iL.moveTo('next');
14944			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
14945				iL.moveTo('prev');
14946			}).on(clickEvent, '.ilightbox-thumbnail', function() {
14947				var t = $(this),
14948					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
14949					index = thumbs.index(t);
14950
14951				if (index != vars.current) iL.goTo(index);
14952			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14953				var caption = $('div.ilightbox-caption', vars.holder),
14954					social = $('div.ilightbox-social', vars.holder),
14955					fadeSpeed = opts.effects.fadeSpeed;
14956
14957				if (vars.nextLock || vars.prevLock) {
14958					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
14959					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
14960
14961					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
14962					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
14963				} else {
14964					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
14965					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
14966
14967					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
14968					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
14969				}
14970			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
14971				if (e.type == 'mouseenter') vars.lockWheel = true;
14972				else vars.lockWheel = false;
14973			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
14974				var t = $(this);
14975
14976				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
14977				else if (t.hasClass('ilightbox-play')) {
14978					iL.resume();
14979					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
14980				} else if (t.hasClass('ilightbox-pause')) {
14981					iL.pause();
14982					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
14983				} else iL.closeAction();
14984			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
14985				// prevent scrolling
14986				e.preventDefault();
14987			});
14988
14989			function mouseMoveHandler(e) {
14990				if (!vars.isMobile) {
14991					if (!vars.mouseID) {
14992						vars.hideableElements.show();
14993					}
14994
14995					vars.mouseID = clearTimeout(vars.mouseID);
14996
14997					if (buttonsArray.indexOf(e.target) === -1)
14998						vars.mouseID = setTimeout(function() {
14999							vars.hideableElements.hide();
15000							vars.mouseID = clearTimeout(vars.mouseID);
15001						}, 3000);
15002				}
15003			}
15004
15005			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
15006
15007			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15008				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
15009				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
15010			});
15011
15012			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
15013				delay = false;
15014
15015			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
15016				event.preventDefault();
15017				if (delay) return;
15018				delay = true;
15019				if (!vars.lockWheel) {
15020					event.preventDefault();
15021					if (delta < 0) {
15022						iL.moveTo('next');
15023					} else if (delta > 0) {
15024						iL.moveTo('prev');
15025					}
15026				}
15027				setTimeout(function(){
15028					delay = false;
15029				}, 2000);
15030			});
15031
15032			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
15033				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
15034
15035				vars.BODY.addClass('ilightbox-closedhand');
15036
15037				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
15038					scrollTop = $doc.scrollTop(),
15039					scrollLeft = $doc.scrollLeft(),
15040					offsets = [
15041						holders.eq(0).offset(),
15042						holders.eq(1).offset(),
15043						holders.eq(2).offset()
15044					],
15045					offSet = [{
15046						top: offsets[0].top - scrollTop,
15047						left: offsets[0].left - scrollLeft
15048					}, {
15049						top: offsets[1].top - scrollTop,
15050						left: offsets[1].left - scrollLeft
15051					}, {
15052						top: offsets[2].top - scrollTop,
15053						left: offsets[2].left - scrollLeft
15054					}],
15055					start = {
15056						time: (new Date()).getTime(),
15057						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15058					},
15059					stop;
15060
15061				function moveEachHandler(i) {
15062					var t = $(this),
15063						offset = offSet[i],
15064						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
15065
15066					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
15067				}
15068
15069				function moveHandler(event) {
15070
15071					if (!start) return;
15072
15073					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
15074
15075					stop = {
15076						time: (new Date()).getTime(),
15077						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15078					};
15079
15080					holders.each(moveEachHandler);
15081
15082					// prevent scrolling
15083					event.preventDefault();
15084				}
15085
15086				function repositionHolders() {
15087					holders.each(function() {
15088						var t = $(this),
15089							offset = t.data('offset') || {
15090								top: t.offset().top - scrollTop,
15091								left: t.offset().left - scrollLeft
15092							},
15093							top = offset.top,
15094							left = offset.left;
15095
15096						t.css(transform, gpuAcceleration).stop().animate({
15097							top: top,
15098							left: left
15099						}, 500, 'easeOutCirc', function() {
15100							t.css(transform, '');
15101						});
15102					});
15103				}
15104
15105				holders.bind(touchMoveEvent, moveHandler);
15106				$doc.one(touchStopEvent, function(event) {
15107					holders.unbind(touchMoveEvent, moveHandler);
15108
15109					vars.BODY.removeClass('ilightbox-closedhand');
15110
15111					if (start && stop) {
15112						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
15113							if (start.coords[0] > stop.coords[0]) {
15114								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15115								else {
15116									vars.isSwipe = true;
15117									iL.moveTo('next');
15118								}
15119							} else {
15120								if (vars.current == 0 && !opts.infinite) repositionHolders();
15121								else {
15122									vars.isSwipe = true;
15123									iL.moveTo('prev');
15124								}
15125							}
15126						} 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) {
15127							if (start.coords[1] > stop.coords[1]) {
15128								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15129								else {
15130									vars.isSwipe = true;
15131									iL.moveTo('next');
15132								}
15133							} else {
15134								if (vars.current == 0 && !opts.infinite) repositionHolders();
15135								else {
15136									vars.isSwipe = true;
15137									iL.moveTo('prev');
15138								}
15139							}
15140						} else repositionHolders();
15141					}
15142					start = stop = undefined;
15143				});
15144			});
15145
15146		},
15147
15148		goTo: function(index) {
15149			var iL = this,
15150				vars = iL.vars,
15151				opts = iL.options,
15152				diff = (index - vars.current);
15153
15154			if (opts.infinite) {
15155				if (index == vars.total - 1 && vars.current == 0) diff = -1;
15156				if (vars.current == vars.total - 1 && index == 0) diff = 1;
15157			}
15158
15159			if (diff == 1) iL.moveTo('next');
15160			else if (diff == -1) iL.moveTo('prev');
15161			else {
15162
15163				if (vars.nextLock || vars.prevLock) return false;
15164
15165				//Trigger the onBeforeChange callback
15166				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
15167
15168				if (opts.linkId) {
15169					vars.hashLock = true;
15170					window.location.hash = opts.linkId + '/' + index;
15171				}
15172
15173				if (iL.items[index]) {
15174					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
15175					else iL.vars.lockWheel = false;
15176
15177					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
15178					else vars.lockSwipe = false;
15179				}
15180
15181				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
15182					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
15183				});
15184
15185				vars.current = index;
15186				vars.next = index + 1;
15187				vars.prev = index - 1;
15188
15189				iL.createUI();
15190
15191				setTimeout(function() {
15192					iL.generateBoxes();
15193				}, opts.effects.loadedFadeSpeed + 50);
15194
15195				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
15196				iL.positionThumbnails();
15197
15198				if (opts.linkId) setTimeout(function() {
15199					vars.hashLock = false;
15200				}, 55);
15201
15202				// Configure arrow buttons
15203				if (!opts.infinite) {
15204					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15205
15206					if (vars.current == 0) {
15207						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15208					}
15209					if (vars.current >= vars.total - 1) {
15210						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15211					}
15212				}
15213
15214				// Reset next cycle timeout
15215				iL.resetCycle();
15216
15217				//Trigger the onAfterChange callback
15218				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
15219			}
15220		},
15221
15222		moveTo: function(side) {
15223			var iL = this,
15224				vars = iL.vars,
15225				opts = iL.options,
15226				path = opts.path.toLowerCase(),
15227				viewport = getViewport(),
15228				switchSpeed = opts.effects.switchSpeed;
15229
15230			if (vars.nextLock || vars.prevLock) return false;
15231			else {
15232
15233				var item = (side == "next") ? vars.next : vars.prev;
15234
15235				if (opts.linkId) {
15236					vars.hashLock = true;
15237					window.location.hash = opts.linkId + '/' + item;
15238				}
15239
15240				if (side == "next") {
15241					if (!iL.items[item]) return false;
15242					var firstHolder = vars.nextPhoto,
15243						secondHolder = vars.holder,
15244						lastHolder = vars.prevPhoto,
15245						firstClass = 'ilightbox-prev',
15246						secondClass = 'ilightbox-next';
15247				} else if (side == "prev") {
15248					if (!iL.items[item]) return false;
15249					var firstHolder = vars.prevPhoto,
15250						secondHolder = vars.holder,
15251						lastHolder = vars.nextPhoto,
15252						firstClass = 'ilightbox-next',
15253						secondClass = 'ilightbox-prev';
15254				}
15255
15256				//Trigger the onBeforeChange callback
15257				if (typeof opts.callback.onBeforeChange == 'function')
15258					opts.callback.onBeforeChange.call(iL, iL.ui);
15259
15260				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
15261
15262				var captionFirst = $('div.ilightbox-caption', secondHolder),
15263					socialFirst = $('div.ilightbox-social', secondHolder);
15264
15265				if (captionFirst.length)
15266					captionFirst.stop().fadeOut(switchSpeed, function() {
15267						$(this).remove();
15268					});
15269				if (socialFirst.length)
15270					socialFirst.stop().fadeOut(switchSpeed, function() {
15271						$(this).remove();
15272					});
15273
15274				if (iL.items[item].caption) {
15275					iL.setCaption(iL.items[item], firstHolder);
15276					var caption = $('div.ilightbox-caption', firstHolder),
15277						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
15278					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
15279				}
15280
15281				var social = iL.items[item].options.social;
15282				if (social) {
15283					iL.setSocial(social, iL.items[item].URL, firstHolder);
15284					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
15285				}
15286
15287				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
15288					val.removeClass('ilightbox-next ilightbox-prev');
15289				});
15290
15291				var firstOffset = firstHolder.data('offset'),
15292					winW = (viewport.width - (opts.styles.pageOffsetX)),
15293					winH = (viewport.height - (opts.styles.pageOffsetY)),
15294					width = firstOffset.newDims.width,
15295					height = firstOffset.newDims.height,
15296					thumbsOffset = firstOffset.thumbsOffset,
15297					diff = firstOffset.diff,
15298					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
15299					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15300
15301				var secondOffset = secondHolder.data('offset'),
15302					object = secondOffset.object;
15303
15304				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15305					var objRatio = width / height;
15306					height = height - vars.captionHeight;
15307					width = height * objRatio;
15308					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
15309					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15310				}*/
15311
15312				firstHolder.show().css(transform, gpuAcceleration).animate({
15313					top: top,
15314					left: left,
15315					opacity: 1
15316				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15317					firstHolder.css(transform, '');
15318				});
15319
15320				$('div.ilightbox-container', firstHolder).animate({
15321					width: width,
15322					height: height
15323				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15324
15325				diff = secondOffset.diff;
15326
15327				width = secondOffset.newDims.width,
15328					height = secondOffset.newDims.height;
15329
15330				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15331					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15332					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
15333
15334				if (side == 'prev')
15335					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
15336				else {
15337					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
15338					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
15339				}
15340
15341				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15342					var objRatio = width / height;
15343					height = height - vars.captionHeight;
15344					width = height * objRatio;
15345					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
15346				}*/
15347
15348				$('div.ilightbox-container', secondHolder).animate({
15349					width: width,
15350					height: height
15351				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15352
15353				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
15354					top: top,
15355					left: left,
15356					opacity: opts.styles.prevOpacity,
15357				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15358					secondHolder.css(transform, '');
15359
15360					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
15361					iL.positionThumbnails();
15362
15363					if (iL.items[item]) {
15364						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
15365						else vars.lockWheel = false;
15366
15367						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
15368						else vars.lockSwipe = false;
15369					}
15370
15371					vars.isSwipe = false;
15372
15373					// Remove iframe & video from previous slide
15374					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15375						$('div.ilightbox-container', secondHolder).empty();
15376					}
15377
15378					if (side == "next") {
15379						vars.nextPhoto = lastHolder,
15380							vars.prevPhoto = secondHolder,
15381							vars.holder = firstHolder;
15382
15383						vars.nextPhoto.hide();
15384
15385						vars.next = vars.next + 1,
15386							vars.prev = vars.current,
15387							vars.current = vars.current + 1;
15388
15389						if (opts.infinite) {
15390							if (vars.current > vars.total - 1) vars.current = 0;
15391							if (vars.current == vars.total - 1) vars.next = 0;
15392							if (vars.current == 0) vars.prev = vars.total - 1;
15393						}
15394
15395						iL.createUI();
15396
15397						if (!iL.items[vars.next])
15398							vars.nextLock = false;
15399						else
15400							iL.loadContent(iL.items[vars.next], 'next');
15401					} else {
15402						vars.prevPhoto = lastHolder;
15403						vars.nextPhoto = secondHolder;
15404						vars.holder = firstHolder;
15405
15406						vars.prevPhoto.hide();
15407
15408						vars.next = vars.current;
15409						vars.current = vars.prev;
15410						vars.prev = vars.current - 1;
15411
15412						if (opts.infinite) {
15413							if (vars.current == vars.total - 1) vars.next = 0;
15414							if (vars.current == 0) vars.prev = vars.total - 1;
15415						}
15416
15417						iL.createUI();
15418
15419						if (!iL.items[vars.prev])
15420							vars.prevLock = false;
15421						else
15422							iL.loadContent(iL.items[vars.prev], 'prev');
15423					}
15424
15425					// Add iframe & video content for current slide
15426					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15427						iL.loadContent(iL.items[vars.current], 'current');
15428					}
15429
15430					if (opts.linkId) setTimeout(function() {
15431						vars.hashLock = false;
15432					}, 55);
15433
15434					// Configure arrow buttons
15435					if (!opts.infinite) {
15436						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15437
15438						if (vars.current == 0)
15439							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15440						if (vars.current >= vars.total - 1)
15441							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15442					}
15443
15444					iL.repositionPhoto();
15445
15446					// Reset next cycle timeout
15447					iL.resetCycle();
15448
15449					//Trigger the onAfterChange callback
15450					if (typeof opts.callback.onAfterChange == 'function')
15451						opts.callback.onAfterChange.call(iL, iL.ui);
15452				});
15453
15454				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
15455					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
15456
15457				lastHolder.css(transform, gpuAcceleration).animate({
15458					top: top,
15459					left: left,
15460					opacity: opts.styles.nextOpacity
15461				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15462					lastHolder.css(transform, '');
15463				}).addClass(secondClass);
15464			}
15465		},
15466
15467		setCaption: function(obj, target) {
15468			var iL = this,
15469				caption = $('<div class="ilightbox-caption"></div>');
15470
15471			if (obj.caption) {
15472				caption.html(obj.caption);
15473				$('div.ilightbox-container', target).append(caption);
15474			}
15475		},
15476
15477		normalizeSocial: function(obj, url) {
15478			var iL = this,
15479				vars = iL.vars,
15480				opts = iL.options,
15481				baseURL = window.location.href;
15482
15483			$.each(obj, function(key, value) {
15484				if (!value)
15485					return true;
15486
15487				var item = key.toLowerCase(),
15488					source, text;
15489
15490				switch (item) {
15491					case 'facebook':
15492						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
15493							text = "Share on Facebook";
15494						break;
15495					case 'twitter':
15496						source = "http://twitter.com/home?status={URL}",
15497							text = "Share on Twitter";
15498						break;
15499					case 'digg':
15500						source = "http://digg.com/submit?phase=2&url={URL}",
15501							text = "Share on Digg";
15502						break;
15503					case 'reddit':
15504						source = "http://reddit.com/submit?url={URL}",
15505							text = "Share on reddit";
15506						break;
15507				}
15508
15509				obj[key] = {
15510					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
15511					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
15512					text: value.text || text || "Share on " + key,
15513					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
15514					height: value.height || 360
15515				};
15516
15517			});
15518
15519			return obj;
15520		},
15521
15522		setSocial: function(obj, url, target) {
15523			var iL = this,
15524				socialBar = $('<div class="ilightbox-social"></div>'),
15525				buttons = '<ul>';
15526
15527			obj = iL.normalizeSocial(obj, url);
15528
15529			$.each(obj, function(key, value) {
15530				var item = key.toLowerCase(),
15531					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, '+'));
15532				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>';
15533			});
15534
15535			buttons += '</ul>';
15536
15537			socialBar.html(buttons);
15538			$('div.ilightbox-container', target).append(socialBar);
15539		},
15540
15541		fullScreenAction: function() {
15542			var iL = this,
15543				vars = iL.vars;
15544
15545			if (fullScreenApi.supportsFullScreen) {
15546				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
15547				else fullScreenApi.requestFullScreen(document.documentElement);
15548			} else {
15549				iL.doFullscreen();
15550			}
15551		},
15552
15553		doFullscreen: function() {
15554			var iL = this,
15555				vars = iL.vars,
15556				viewport = getViewport(),
15557				opts = iL.options;
15558
15559			if (opts.fullAlone) {
15560				var currentHolder = vars.holder,
15561					current = iL.items[vars.current],
15562					windowWidth = viewport.width,
15563					windowHeight = viewport.height,
15564					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
15565					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15566
15567				if (!vars.isInFullScreen) {
15568					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
15569					vars.overlay.css({
15570						opacity: 1
15571					});
15572
15573					$.each(hideElements, function(i, element) {
15574						element.hide();
15575					});
15576
15577					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
15578
15579					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
15580						naturalWidthOld: currentHolder.data('naturalWidth'),
15581						naturalHeightOld: currentHolder.data('naturalHeight'),
15582						naturalWidth: windowWidth,
15583						naturalHeight: windowHeight
15584					});
15585					else {
15586						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
15587							newWidth = windowWidth,
15588							newHeight = windowHeight,
15589							width = currentHolder.data('naturalWidth'),
15590							height = currentHolder.data('naturalHeight');
15591
15592						if (viewport.toLowerCase() == 'fill') {
15593							newHeight = (newWidth / width) * height;
15594
15595							if (newHeight < windowHeight) {
15596								newWidth = (windowHeight / height) * width,
15597									newHeight = windowHeight;
15598							}
15599						} else if (viewport.toLowerCase() == 'fit') {
15600							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
15601
15602							newWidth = dims.width,
15603								newHeight = dims.height;
15604						} else if (viewport.toLowerCase() == 'stretch') {
15605							newWidth = newWidth,
15606								newHeight = newHeight;
15607						} else {
15608							var scale = (width > newWidth || height > newHeight) ? true : false,
15609								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
15610							newWidth = dims.width,
15611								newHeight = dims.height;
15612						}
15613
15614						currentHolder.data({
15615							naturalWidthOld: currentHolder.data('naturalWidth'),
15616							naturalHeightOld: currentHolder.data('naturalHeight'),
15617							naturalWidth: newWidth,
15618							naturalHeight: newHeight
15619						});
15620					}
15621
15622					$.each(elements, function(key, val) {
15623						val.addClass('ilightbox-fullscreen');
15624					});
15625
15626					//Trigger the onEnterFullScreen callback
15627					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
15628				} else {
15629					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
15630					vars.overlay.css({
15631						opacity: iL.options.overlay.opacity
15632					});
15633
15634					$.each(hideElements, function(i, element) {
15635						element.show();
15636					});
15637
15638					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
15639
15640					currentHolder.data({
15641						naturalWidth: currentHolder.data('naturalWidthOld'),
15642						naturalHeight: currentHolder.data('naturalHeightOld'),
15643						naturalWidthOld: null,
15644						naturalHeightOld: null
15645					});
15646
15647					$.each(elements, function(key, val) {
15648						val.removeClass('ilightbox-fullscreen');
15649					});
15650
15651					//Trigger the onExitFullScreen callback
15652					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
15653				}
15654			} else {
15655				if (!vars.isInFullScreen) vars.isInFullScreen = true;
15656				else vars.isInFullScreen = false;
15657			}
15658			iL.repositionPhoto(true);
15659		},
15660
15661		closeAction: function() {
15662			var iL = this,
15663				vars = iL.vars,
15664				opts = iL.options;
15665
15666			$win.unbind('.iLightBox');
15667			$doc.off('.iLightBox');
15668
15669			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
15670
15671			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
15672
15673			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
15674				vars.overlay.remove();
15675				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15676			});
15677			else {
15678				vars.overlay.remove();
15679				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15680			}
15681
15682			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15683
15684			$.each(fadeOuts, function(i, element) {
15685				element.removeAttr('style').remove();
15686			});
15687
15688			vars.dontGenerateThumbs = vars.isInFullScreen = false;
15689
15690			window.iLightBox = null;
15691
15692			if (opts.linkId) {
15693				vars.hashLock = true;
15694				removeHash();
15695				setTimeout(function() {
15696					vars.hashLock = false;
15697				}, 55);
15698			}
15699
15700			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15701
15702			//Trigger the onHide callback
15703			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
15704		},
15705
15706		repositionPhoto: function() {
15707			var iL = this,
15708				vars = iL.vars,
15709				opts = iL.options,
15710				path = opts.path.toLowerCase(),
15711				viewport = getViewport(),
15712				winWidth = viewport.width,
15713				winHeight = viewport.height;
15714
15715			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
15716
15717			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
15718				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
15719				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
15720				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
15721				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,
15722				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)));
15723
15724			var elObject = {
15725				type: 'current',
15726				width: width,
15727				height: height,
15728				item: iL.items[vars.current],
15729				offsetW: offsetW,
15730				offsetH: offsetH,
15731				thumbsOffsetW: thumbsOffsetW,
15732				thumbsOffsetH: thumbsOffsetH,
15733				animate: arguments.length,
15734				holder: vars.holder
15735			};
15736
15737			iL.repositionEl(elObject);
15738
15739			if (iL.items[vars.next]) {
15740				elObject = $.extend(elObject, {
15741					type: 'next',
15742					item: iL.items[vars.next],
15743					offsetX: opts.styles.nextOffsetX,
15744					offsetY: opts.styles.nextOffsetY,
15745					holder: vars.nextPhoto
15746				});
15747
15748				iL.repositionEl(elObject);
15749			}
15750
15751			if (iL.items[vars.prev]) {
15752				elObject = $.extend(elObject, {
15753					type: 'prev',
15754					item: iL.items[vars.prev],
15755					offsetX: opts.styles.nextOffsetX,
15756					offsetY: opts.styles.prevOffsetY,
15757					holder: vars.prevPhoto
15758				});
15759
15760				iL.repositionEl(elObject);
15761			}
15762
15763			var loaderCss = (path == "horizontal") ? {
15764				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
15765			} : {
15766				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
15767			};
15768			vars.loader.css(loaderCss);
15769		},
15770
15771		repositionEl: function(obj) {
15772			var iL = this,
15773				vars = iL.vars,
15774				opts = iL.options,
15775				path = opts.path.toLowerCase(),
15776				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
15777				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
15778				itemParent = obj.item,
15779				item = obj.item.options,
15780				holder = obj.holder,
15781				offsetX = obj.offsetX || 0,
15782				offsetY = obj.offsetY || 0,
15783				//Uncode change ##START##
15784				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
15785				//Uncode change ##END##
15786				thumbsOffsetW = obj.thumbsOffsetW,
15787				thumbsOffsetH = obj.thumbsOffsetH;
15788
15789			if (obj.type == 'current') {
15790				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);
15791				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);
15792			} else {
15793				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
15794				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
15795			}
15796
15797
15798			//Uncode change ##START##
15799			heightAvail = parseInt(heightAvail - toolbarHeight);
15800			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
15801			//Uncode change ##END##
15802
15803			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
15804				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
15805
15806			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
15807					width: width,
15808					height: height
15809				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
15810				newDims = $.extend({}, dims, {});
15811
15812			if (obj.type == 'prev' || obj.type == 'next')
15813				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
15814				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
15815			else
15816				width = dims.width,
15817				height = dims.height;
15818
15819			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
15820				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);
15821
15822			switch (obj.type) {
15823				case 'current':
15824					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
15825						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15826					break;
15827
15828				case 'next':
15829					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
15830						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
15831					break;
15832
15833				case 'prev':
15834					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
15835						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15836					break;
15837			}
15838
15839			holder.data('offset', {
15840				top: top,
15841				left: left,
15842				newDims: newDims,
15843				diff: {
15844					W: widthDiff,
15845					H: heightDiff
15846				},
15847				thumbsOffset: {
15848					W: thumbsOffsetW,
15849					H: thumbsOffsetH
15850				},
15851				object: obj
15852			});
15853
15854			var opacityMobile;
15855			if ( isMobile ) {
15856				opacityMobile = {
15857					opacity: 1,
15858					top: top,
15859					left: left
15860				};
15861			} else {
15862				opacityMobile = {
15863					top: top,
15864					left: left
15865				};
15866			}
15867
15868			if (obj.animate > 0 && opts.effects.reposition) {
15869				holder.css(transform, gpuAcceleration).stop().animate(
15870					opacityMobile,
15871					opts.effects.repositionSpeed, 'easeOutCirc', function() {
15872					holder.css(transform, '');
15873				});
15874				$('div.ilightbox-container', holder).stop().animate({
15875					width: width,
15876					height: height
15877				}, opts.effects.repositionSpeed, 'easeOutCirc');
15878				$('div.ilightbox-inner-toolbar', holder).stop().animate({
15879					width: width
15880				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
15881					$(this).css('overflow', 'visible');
15882				});
15883			} else {
15884				holder.css(opacityMobile);
15885				$('div.ilightbox-container', holder).css({
15886					width: width,
15887					height: height
15888				});
15889				$('div.ilightbox-inner-toolbar', holder).css({
15890					width: width
15891				});
15892			}
15893		},
15894
15895
15896		resume: function(priority) {
15897			var iL = this,
15898				vars = iL.vars,
15899				opts = iL.options;
15900
15901			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
15902				return;
15903			}
15904
15905			vars.isPaused = 0;
15906
15907			if (vars.cycleID) {
15908				vars.cycleID = clearTimeout(vars.cycleID);
15909			}
15910
15911			vars.cycleID = setTimeout(function() {
15912				if (vars.current == vars.total - 1) iL.goTo(0);
15913				else iL.moveTo('next');
15914			}, opts.slideshow.pauseTime);
15915		},
15916
15917		pause: function(priority) {
15918			var iL = this,
15919				vars = iL.vars,
15920				opts = iL.options;
15921
15922			if (priority < vars.isPaused) {
15923				return;
15924			}
15925
15926			vars.isPaused = priority || 100;
15927
15928			if (vars.cycleID) {
15929				vars.cycleID = clearTimeout(vars.cycleID);
15930			}
15931		},
15932
15933		resetCycle: function() {
15934			var iL = this,
15935				vars = iL.vars,
15936				opts = iL.options;
15937
15938			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
15939				iL.resume();
15940			}
15941		},
15942
15943		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
15944			var iL = this;
15945
15946			if (!width) factor = height / height_old;
15947			else if (!height) factor = width / width_old;
15948			else factor = min(width / width_old, height / height_old);
15949
15950			if (!thumb) {
15951				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
15952				else if (factor < iL.options.minScale) factor = iL.options.minScale;
15953			}
15954
15955			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
15956				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
15957
15958			return {
15959				width: final_width,
15960				height: final_height,
15961				ratio: factor
15962			};
15963		},
15964
15965		setOption: function(options) {
15966			var iL = this;
15967
15968			iL.options = $.extend(true, iL.options, options || {});
15969			iL.refresh();
15970		},
15971
15972		availPlugins: function() {
15973			var iL = this,
15974				testEl = document.createElement("video");
15975
15976			iL.plugins = {
15977				flash: !isMobile,
15978				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
15979				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
15980				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
15981				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
15982				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
15983			};
15984		},
15985
15986		addContent: function(element, obj) {
15987			var iL = this,
15988				el;
15989
15990			switch (obj.type) {
15991				case 'video':
15992					var HTML5 = false,
15993						videoType = obj.videoType,
15994						html5video = obj.options.html5video;
15995
15996					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
15997						obj.ext = 'mp4',
15998						obj.URL = html5video.h264 || obj.URL;
15999					else if (html5video.webm && iL.plugins.html5WebM)
16000						obj.ext = 'webm',
16001						obj.URL = html5video.webm || obj.URL;
16002					else if (html5video.ogg && iL.plugins.html5Vorbis)
16003						obj.ext = 'ogv',
16004						obj.URL = html5video.ogg || obj.URL;
16005
16006					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
16007					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
16008					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
16009					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
16010
16011					if (HTML5) {
16012						el = $('<video />
16012', {
16013							"width": "100%",
16014							"height": "100%",
16015							"preload": html5video.preload,
16016							"autoplay": html5video.autoplay,
16017							"loop": html5video.loop,
16018							"poster": html5video.poster,
16019							"controls": html5video.controls,
16020							"controlslist": "nodownload"
16021						}).append($('<source />', {
16022							"src": obj.URL,
16023							"type": videoType
16024						}));
16025					} else {
16026						if (!iL.plugins.quicktime) el = $('<span />', {
16027							"class": "ilightbox-alert",
16028							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
16029						});
16030						else {
16031
16032							el = $('<object />', {
16033								"type": "video/quicktime",
16034								"pluginspage": pluginspages.quicktime
16035							}).attr({
16036								"data": obj.URL,
16037								"width": "100%",
16038								"height": "100%"
16039							}).append($('<param />', {
16040								"name": "src",
16041								"value": obj.URL
16042							})).append($('<param />', {
16043								"name": "autoplay",
16044								"value": "false"
16045							})).append($('<param />', {
16046								"name": "loop",
16047								"value": "false"
16048							})).append($('<param />', {
16049								"name": "scale",
16050								"value": "tofit"
16051							}));
16052
16053							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
16054						}
16055					}
16056
16057					break;
16058
16059				case 'flash':
16060					if (!iL.plugins.flash) el = $('<span />', {
16061						"class": "ilightbox-alert",
16062						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
16063					});
16064					else {
16065						var flashvars = "",
16066							i = 0;
16067
16068						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
16069							if (i != 0) flashvars += "&";
16070							flashvars += k + "=" + encodeURIComponent(v);
16071							i++;
16072						});
16073						else flashvars = null;
16074
16075						el = $('<embed />').attr({
16076							"type": "application/x-shockwave-flash",
16077							"src": obj.URL,
16078							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16079							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16080							"quality": "high",
16081							"bgcolor": "#000000",
16082							"play": "true",
16083							"loop": "true",
16084							"menu": "true",
16085							"wmode": "transparent",
16086							"scale": "showall",
16087							"allowScriptAccess": "always",
16088							"allowFullScreen": "true",
16089							"flashvars": flashvars,
16090							"fullscreen": "yes"
16091						});
16092					}
16093
16094					break;
16095
16096				case 'iframe':
16097					el = $('<iframe />').attr({
16098						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16099						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16100						src: obj.URL,
16101						frameborder: 0,
16102						'hspace': 0,
16103						'vspace': 0,
16104						'scrolling': supportTouch ? 'auto' : 'scroll',
16105						'webkitAllowFullScreen': '',
16106						'mozallowfullscreen': '',
16107						'allowFullScreen': ''
16108					});
16109
16110					break;
16111
16112				case 'inline':
16113					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
16114
16115					break;
16116
16117				case 'html':
16118					var object = obj.URL,
16119						el;
16120
16121					if (object[0].nodeName) {
16122						el = $('<div class="ilightbox-wrapper"></div>').html(object);
16123					} else {
16124						var dom = $(obj.URL),
16125							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
16126						el = $('<div class="ilightbox-wrapper"></div>').html(html);
16127					}
16128
16129					break;
16130			}
16131
16132			$('div.ilightbox-container', element).empty().html(el);
16133
16134			// For fixing Chrome about just playing the video for first time
16135			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
16136				var src = el[0].currentSrc + '?' + floor(random() * 30000);
16137				el[0].currentSrc = src;
16138				el[0].src = src;
16139			});
16140
16141			return el;
16142		},
16143
16144		ogpRecognition: function(obj, callback) {
16145			var iL = this,
16146				url = obj.URL;
16147
16148			iL.showLoader();
16149			doAjax(url, function(data) {
16150				iL.hideLoader();
16151				if (data) {
16152					var object = new Object();
16153
16154					object.length = false,
16155					object.url = data.url;
16156
16157					if (data.status == 200) {
16158						var result = data.results,
16159							type = result.type,
16160							source = result.source;
16161
16162						object.source = source.src,
16163						object.width = source.width && parseInt(source.width) || 0,
16164						object.height = source.height && parseInt(source.height) || 0,
16165						object.type = type,
16166						object.thumbnail = source.thumbnail || result.images && result.images[0],
16167						object.html5video = result.html5video || {},
16168						object.length = true;
16169
16170						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
16171						else if (source.type.indexOf("video/") != -1) object.type = "video";
16172						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
16173						else if (source.type.indexOf("image/") != -1) object.type = "image";
16174
16175					} else if (typeof data.response != 'undefined')
16176						throw data.response;
16177
16178					callback.call(this, object.length ? object : false);
16179				}
16180			});
16181		},
16182
16183		hashChangeHandler: function(url) {
16184			var iL = this,
16185				vars = iL.vars,
16186				opts = iL.options,
16187				URL = url || window.location.href,
16188				hash = parseURI(URL).hash,
16189				split = hash.split('/'),
16190				index = split[1];
16191
16192			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
16193
16194			if (index) {
16195				var target = split[1] || 0;
16196				if (iL.items[target]) {
16197					var overlay = $('.ilightbox-overlay');
16198					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
16199						iL.goTo(target);
16200					} else {
16201						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
16202						//iL.goTo(target);
16203					}
16204				} else {
16205					var overlay = $('.ilightbox-overlay');
16206					if (overlay.length) iL.closeAction();
16207				}
16208			} else {
16209				var overlay = $('.ilightbox-overlay');
16210				if (overlay.length) iL.closeAction();
16211			}
16212		}
16213	};
16214
16215	/**
16216	 * Parse style to pixels.
16217	 *
16218	 * @param {Object}   $element   jQuery object with element.
16219	 * @param {Property} property   CSS property to get the pixels from.
16220	 *
16221	 * @return {Int}
16222	 */
16223	function getPixel($element, property) {
16224		return parseInt($element.css(property), 10) || 0;
16225	}
16226
16227	/**
16228	 * Make sure that number is within the limits.
16229	 *
16230	 * @param {Number} number
16231	 * @param {Number} min
16232	 * @param {Number} max
16233	 *
16234	 * @return {Number}
16235	 */
16236	function within(number, min, max) {
16237		return number < min ? min : number > max ? max : number;
16238	}
16239
16240	/**
16241	 * Get viewport/window size (width and height).
16242	 *
16243	 * @return {Object}
16244	 */
16245	function getViewport() {
16246		var e = window,
16247			a = 'inner';
16248		if (!('innerWidth' in window)) {
16249			a = 'client';
16250			e = document.documentElement || document.body;
16251		}
16252		return {
16253			width: e[a + 'Width'],
16254			height: e[a + 'Height']
16255		}
16256	}
16257
16258	/**
16259	 * Remove hash tag from the URL
16260	 *
16261	 * @return {Void}
16262	 */
16263	function removeHash() {
16264		var scroll = getScrollXY();
16265
16266		//UNCODE change
16267		// window.location.hash = "";
16268		// history.pushState("", document.title, window.location.pathname + window.location.search);
16269		history.replaceState({}, document.title, window.location.pathname + window.location.search);
16270
16271		// Restore the scroll offset, should be flicker free
16272		window.scrollTo(scroll.x, scroll.y);
16273	}
16274
16275	/**
16276	 * Do the ajax requests with callback.
16277	 *
16278	 * @param {String}   url
16279	 * @param {Function} callback
16280	 *
16281	 * @return {Void}
16282	 */
16283	function doAjax(url, callback) {
16284		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');
16285		$.ajax({
16286			url: url,
16287			dataType: 'jsonp'
16288		});
16289
16290		iLCallback = function(data) {
16291			callback.call(this, data);
16292		};
16293	}
16294
16295	/**
16296	 * Find image from DOM elements
16297	 *
16298	 * @param {Element} element
16299	 *
16300	 * @return {Void}
16301	 */
16302	function findImageInElement(element) {
16303		var elements = $('*', element),
16304			imagesArr = new Array();
16305
16306		elements.each(function() {
16307			var url = "",
16308				element = this;
16309
16310			if ($(element).css("background-image") != "none") {
16311				url = $(element).css("background-image");
16312			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
16313				url = $(element).attr("src");
16314			}
16315
16316			if (url.indexOf("gradient") == -1) {
16317				url = url.replace(/url\(\"/g, "");
16318				url = url.replace(/url\(/g, "");
16319				url = url.replace(/\"\)/g, "");
16320				url = url.replace(/\)/g, "");
16321
16322				var urls = url.split(",");
16323
16324				for (var i = 0; i < urls.length; i++) {
16325					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
16326						var extra = "";
16327						if (browser.msie && browser.version < 9) {
16328							extra = "?" + floor(random() * 3000);
16329						}
16330						imagesArr.push(urls[i] + extra);
16331					}
16332				}
16333			}
16334		});
16335
16336		return imagesArr;
16337	}
16338
16339	/**
16340	 * Get file extension.
16341	 *
16342	 * @param {String} URL
16343	 *
16344	 * @return {String}
16345	 */
16346	function getExtension(URL) {
16347		if (URL !== null) {
16348			//UNCODE: fix issue to detect media type with query strings
16349			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
16350			ext = ext.split('.').pop().toLowerCase();
16351
16352			return ext;
16353		}
16354	}
16355
16356	/**
16357	 * Get type via extension.
16358	 *
16359	 * @param {String} URL
16360	 *
16361	 * @return {String}
16362	 */
16363	function getTypeByExtension(URL) {
16364		var type,
16365			ext = getExtension(URL);
16366
16367		//Uncode addition ##START##
16368		if (URL == undefined) {
16369			return false;
16370		}
16371		//Uncode addition ##END##
16372
16373		if (extensions.image.indexOf(ext) !== -1) type = 'image';
16374		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
16375		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
16376		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
16377		else type = 'iframe';
16378
16379		return type;
16380	}
16381
16382	/**
16383	 * Return value from percent of a number.
16384	 *
16385	 * @param {Number} percent
16386	 * @param {Number} total
16387	 *
16388	 * @return {Number}
16389	 */
16390	function percentToValue(percent, total) {
16391		return parseInt((total / 100) * percent);
16392	}
16393
16394	/**
16395	 * A JavaScript equivalent of PHP’s parse_url.
16396	 *
16397	 * @param {String} url           The URL to parse.
16398	 *
16399	 * @return {Mixed}
16400	 */
16401	function parseURI(url) {
16402		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
16403		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
16404		return (m ? {
16405			href: m[0] || '',
16406			protocol: m[1] || '',
16407			authority: m[2] || '',
16408			host: m[3] || '',
16409			hostname: m[4] || '',
16410			port: m[5] || '',
16411			pathname: m[6] || '',
16412			search: m[7] || '',
16413			hash: m[8] || ''
16414		} : null);
16415	}
16416
16417	/**
16418	 * Gets the absolute URI.
16419	 *
16420	 * @param {String} href     The relative URL.
16421	 * @param {String} base     The base URL.
16422	 *
16423	 * @return {String}         The absolute URL.
16424	 */
16425	function absolutizeURI(base, href) { // RFC 3986
16426		var iL = this;
16427
16428		function removeDotSegments(input) {
16429			var output = [];
16430			input.replace(/^(\.\.?(\/|$))+/, '')
16431				.replace(/\/(\.(\/|$))+/g, '/')
16432				.replace(/\/\.\.$/, '/../')
16433				.replace(/\/?[^\/]*/g, function(p) {
16434					if (p === '/..') {
16435						output.pop();
16436					} else {
16437						output.push(p);
16438					}
16439				});
16440			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
16441		}
16442
16443		href = parseURI(href || '');
16444		base = parseURI(base || '');
16445
16446		return !href || !base ? null : (href.protocol || base.protocol) +
16447			(href.protocol || href.authority ? href.authority : base.authority) +
16448			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)) +
16449			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
16450			href.hash;
16451	}
16452
16453	/**
16454	 * A JavaScript equivalent of PHP’s version_compare.
16455	 *
16456	 * @param {String} v1
16457	 * @param {String} v2
16458	 * @param {String} operator
16459	 *
16460	 * @return {Boolean}
16461	 */
16462	function version_compare(v1, v2, operator) {
16463		this.php_js = this.php_js || {};
16464		this.php_js.ENV = this.php_js.ENV || {};
16465		var i = 0,
16466			x = 0,
16467			compare = 0,
16468			vm = {
16469				'dev': -6,
16470				'alpha': -5,
16471				'a': -5,
16472				'beta': -4,
16473				'b': -4,
16474				'RC': -3,
16475				'rc': -3,
16476				'#': -2,
16477				'p': 1,
16478				'pl': 1
16479			},
16480			prepVersion = function(v) {
16481				v = ('' + v).replace(/[_\-+]/g, '.');
16482				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
16483				return (!v.length ? [-8] : v.split('.'));
16484			},
16485			numVersion = function(v) {
16486				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
16487			};
16488		v1 = prepVersion(v1);
16489		v2 = prepVersion(v2);
16490		x = max(v1.length, v2.length);
16491		for (i = 0; i < x; i++) {
16492			if (v1[i] == v2[i]) {
16493				continue;
16494			}
16495			v1[i] = numVersion(v1[i]);
16496			v2[i] = numVersion(v2[i]);
16497			if (v1[i] < v2[i]) {
16498				compare = -1;
16499				break;
16500			} else if (v1[i] > v2[i]) {
16501				compare = 1;
16502				break;
16503			}
16504		}
16505		if (!operator) {
16506			return compare;
16507		}
16508
16509		switch (operator) {
16510			case '>':
16511			case 'gt':
16512				return (compare > 0);
16513			case '>=':
16514			case 'ge':
16515				return (compare >= 0);
16516			case '<=':
16517			case 'le':
16518				return (compare <= 0);
16519			case '==':
16520			case '=':
16521			case 'eq':
16522				return (compare === 0);
16523			case '<>':
16524			case '!=':
16525			case 'ne':
16526				return (compare !== 0);
16527			case '':
16528			case '<':
16529			case 'lt':
16530				return (compare < 0);
16531			default:
16532				return null;
16533		}
16534	}
16535
16536
16537	// Begin the iLightBox plugin
16538	$.fn.iLightBox = function() {
16539
16540		var args = arguments,
16541			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
16542			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
16543
16544		if (!opt) opt = {};
16545
16546		// Default options. Play carefully.
16547		var options = $.extend(true, {
16548			attr: 'href',
16549			path: 'vertical',
16550			skin: 'dark',
16551			linkId: false,
16552			infinite: false,
16553			startFrom: 0,
16554			randomStart: false,
16555			keepAspectRatio: true,
16556			maxScale: 1,
16557			minScale: .2,
16558			innerToolbar: false,
16559			smartRecognition: false,
16560			mobileOptimizer: true,
16561			fullAlone: true,
16562			fullViewPort: null,
16563			fullStretchTypes: 'flash, video',
16564			overlay: {
16565				blur: true,
16566				opacity: .85
16567			},
16568			controls: {
16569				arrows: false,
16570				slideshow: false,
16571				toolbar: true,
16572				fullscreen: true,
16573				thumbnail: true,
16574				keyboard: true,
16575				mousewheel: true,
16576				swipe: true
16577			},
16578			keyboard: {
16579				left: true, // previous
16580				right: true, // next
16581				up: true, // previous
16582				down: true, // next
16583				esc: true, // close
16584				shift_enter: true // fullscreen
16585			},
16586			show: {
16587				effect: true,
16588				speed: 300,
16589				title: true
16590			},
16591			hide: {
16592				effect: true,
16593				speed: 300
16594			},
16595			caption: {
16596				start: true,
16597				show: 'mouseenter',
16598				hide: 'mouseleave'
16599			},
16600			social: {
16601				start: true,
16602				show: 'mouseenter',
16603				hide: 'mouseleave',
16604				buttons: false
16605			},
16606			styles: {
16607				pageOffsetX: 0,
16608				pageOffsetY: 0,
16609				nextOffsetX: 45,
16610				nextOffsetY: 0,
16611				nextOpacity: 1,
16612				nextScale: 1,
16613				prevOffsetX: 45,
16614				prevOffsetY: 0,
16615				prevOpacity: 1,
16616				prevScale: 1
16617			},
16618			thumbnails: {
16619				maxWidth: 120,
16620				maxHeight: 80,
16621				normalOpacity: 1,
16622				activeOpacity: .6
16623			},
16624			effects: {
16625				reposition: true,
16626				repositionSpeed: 200,
16627				switchSpeed: 500,
16628				loadedFadeSpeed: 180,
16629				fadeSpeed: 200
16630			},
16631			slideshow: {
16632				pauseTime: 5000,
16633				pauseOnHover: false,
16634				startPaused: true
16635			},
16636			text: {
16637				close: "Press Esc to close",
16638				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
16639				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
16640				slideShow: "Slideshow",
16641				next: "Next",
16642				previous: "Previous"
16643			},
16644			errors: {
16645				loadImage: "An error occurred when trying to load photo.",
16646				loadContents: "An error occurred when trying to load contents.",
16647				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
16648			},
16649			ajaxSetup: {
16650				url: '',
16651				beforeSend: function(jqXHR, settings) {},
16652				cache: false,
16653				complete: function(jqXHR, textStatus) {},
16654				crossDomain: false,
16655				error: function(jqXHR, textStatus, errorThrown) {},
16656				success: function(data, textStatus, jqXHR) {},
16657				global: true,
16658				ifModified: false,
16659				username: null,
16660				password: null,
16661				type: 'GET'
16662			},
16663			callback: {}
16664		}, opt);
16665
16666		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
16667
16668		items = $.isArray(items) ? items : new Array();
16669
16670		if (typeof args[0] == 'string') items[0] = args[0];
16671
16672		if (version_compare($.fn.jquery, '1.8', '>=')) {
16673			var iLB = new iLightBox($(this), options, items, instant);
16674			return {
16675				close: function() {
16676					iLB.closeAction();
16677				},
16678				fullscreen: function() {
16679					iLB.fullScreenAction();
16680				},
16681				moveNext: function() {
16682					iLB.moveTo('next');
16683				},
16684				movePrev: function() {
16685					iLB.moveTo('prev');
16686				},
16687				goTo: function(index) {
16688					iLB.goTo(index);
16689				},
16690				refresh: function() {
16691					iLB.refresh();
16692				},
16693				reposition: function() {
16694					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
16695				},
16696				setOption: function(options) {
16697					iLB.setOption(options);
16698				},
16699				destroy: function() {
16700					iLB.closeAction();
16701					iLB.dispatchItemsEvents();
16702				}
16703			};
16704		} else {
16705			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
16706		}
16707
16708	};
16709
16710
16711	$.iLightBox = function() {
16712		return $.fn.iLightBox(arguments[0], arguments[1]);
16713	};
16714
16715	function getScrollXY() {
16716		var scrOfX = 0,
16717			scrOfY = 0;
16718		if (typeof(window.pageYOffset) == 'number') {
16719			//Netscape compliant
16720			scrOfY = window.pageYOffset;
16721			scrOfX = window.pageXOffset;
16722		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
16723			//DOM compliant
16724			scrOfY = document.body.scrollTop;
16725			scrOfX = document.body.scrollLeft;
16726		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
16727			//IE6 standards compliant mode
16728			scrOfY = document.documentElement.scrollTop;
16729			scrOfX = document.documentElement.scrollLeft;
16730		}
16731		return {
16732			x: scrOfX,
16733			y: scrOfY
16734		};
16735	}
16736
16737	(function() {
16738		// add new event shortcuts
16739		$.each(("touchstart touchmove touchend " +
16740			"tap taphold " +
16741			"swipe swipeleft swiperight " +
16742			"scrollstart scrollstop").split(" "), function(i, name) {
16743
16744			$.fn[name] = function(fn) {
16745				return fn ? this.bind(name, fn) : this.trigger(name);
16746			};
16747
16748			// jQuery < 1.8
16749			// if ($.attrFn) {
16750			// 	$.attrFn[name] = true;
16751			// }
16752		});
16753
16754		var tapSettings = {
16755			startEvent: 'touchstart.iTap',
16756			endEvent: 'touchend.iTap'
16757		};
16758
16759		// tap Event:
16760		$.event.special.itap = {
16761			setup: function() {
16762
16763				var self = this,
16764					$self = $(this),
16765					start, stop;
16766
16767				$self.bind(tapSettings.startEvent, function(event) {
16768					start = getScrollXY();
16769
16770					$self.one(tapSettings.endEvent, function(event) {
16771						stop = getScrollXY();
16772
16773						var orgEvent = event || window.event;
16774						event = $.event.fix(orgEvent);
16775						event.type = "itap";
16776
16777						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
16778
16779						start = stop = undefined;
16780					});
16781				});
16782			},
16783
16784			teardown: function() {
16785				$(this).unbind(tapSettings.startEvent);
16786			}
16787		};
16788	}());
16789
16790
16791	//Fullscreen API
16792	(function() {
16793		fullScreenApi = {
16794				supportsFullScreen: false,
16795				isFullScreen: function() {
16796					return false;
16797				},
16798				requestFullScreen: function() {},
16799				cancelFullScreen: function() {},
16800				fullScreenEventName: '',
16801				prefix: ''
16802			},
16803			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
16804
16805		// check for native support
16806		if (typeof document.cancelFullScreen != 'undefined') {
16807			fullScreenApi.supportsFullScreen = true;
16808		} else {
16809			// check for fullscreen support by vendor prefix
16810			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
16811				fullScreenApi.prefix = browserPrefixes[i];
16812
16813				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
16814					fullScreenApi.supportsFullScreen = true;
16815
16816					break;
16817				}
16818			}
16819		}
16820
16821		// update methods to do something useful
16822		if (fullScreenApi.supportsFullScreen) {
16823			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
16824
16825			fullScreenApi.isFullScreen = function() {
16826				switch (this.prefix) {
16827					case '':
16828						return document.fullScreen;
16829					case 'webkit':
16830						return document.webkitIsFullScreen;
16831					default:
16832						return document[this.prefix + 'FullScreen'];
16833				}
16834			}
16835			fullScreenApi.requestFullScreen = function(el) {
16836				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
16837			}
16838			fullScreenApi.cancelFullScreen = function(el) {
16839				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
16840			}
16841		}
16842	}());
16843
16844	// Browser detect
16845	(function() {
16846		function uaMatch(ua) {
16847			ua = ua.toLowerCase();
16848
16849			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
16850				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
16851				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
16852				/(msie) ([\w.]+)/.exec(ua) ||
16853				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
16854
16855			return {
16856				browser: match[1] || "",
16857				version: match[2] || "0"
16858			};
16859		}
16860
16861		var matched = uaMatch(navigator.userAgent);
16862		browser = {};
16863
16864		if (matched.browser) {
16865			browser[matched.browser] = true;
16866			browser.version = matched.version;
16867		}
16868
16869		// Chrome is Webkit, but Webkit is also Safari.
16870		if (browser.chrome) {
16871			browser.webkit = true;
16872		} else if (browser.webkit) {
16873			browser.safari = true;
16874		}
16875	}());
16876
16877	// Feature detects
16878	(function() {
16879		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
16880		var el = document.createElement('div');
16881
16882		function testProp(prop) {
16883			for (var p = 0, pl = prefixes.length; p < pl; p++) {
16884				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
16885				if (el.style[prefixedProp] !== undefined) {
16886					return prefixedProp;
16887				}
16888			}
16889		}
16890
16891		// Global support indicators
16892		transform = testProp('transform') || '';
16893		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
16894	}());
16895
16896
16897	/*
16898		PluginDetect v0.7.9
16899		www.pinlady.net/PluginDetect/license/
16900		[ getVersion onWindowLoaded BetterIE ]
16901		[ Flash QuickTime Shockwave ]
16902	*/
16903	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;
16903d++){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);
16903d.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)}
16903c.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;
16903if(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();
16904
16905	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)};
16906
16907
16908	/*
16909		jQuery hashchange event v1.3
16910		https://github.com/cowboy/jquery-hashchange
16911		Copyright (c) 2010 "Cowboy" Ben Alman
16912		Dual licensed under the MIT and GPL licenses.
16913	*/
16914	(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=
16915	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||
16916	"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;
16916a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
16917
16918	if (!Array.prototype.filter) {
16919		Array.prototype.filter = function(fun /*, thisp */ ) {
16920			"use strict";
16921
16922			if (this == null)
16923				throw new TypeError();
16924
16925			var t = Object(this);
16926			var len = t.length >>> 0;
16927			if (typeof fun != "function")
16928				throw new TypeError();
16929
16930			var res = [];
16931			var thisp = arguments[1];
16932			for (var i = 0; i < len; i++) {
16933				if (i in t) {
16934					var val = t[i]; // in case fun mutates this
16935					if (fun.call(thisp, val, i, t))
16936						res.push(val);
16937				}
16938			}
16939
16940			return res;
16941		};
16942	}
16943
16944	if (!Array.prototype.indexOf) {
16945		Array.prototype.indexOf = function(searchElement, fromIndex) {
16946			var k;
16947
16948			if (this == null) {
16949				throw new TypeError('"this" is null or not defined');
16950			}
16951
16952			var O = Object(this);
16953
16954			var len = O.length >>> 0;
16955
16956			if (len === 0) {
16957				return -1;
16958			}
16959
16960			var n = +fromIndex || 0;
16961
16962			if (abs(n) === Infinity) {
16963				n = 0;
16964			}
16965
16966			if (n >= len) {
16967				return -1;
16968			}
16969
16970			k = max(n >= 0 ? n : len - abs(n), 0);
16971
16972			while (k < len) {
16973				var kValue;
16974				if (k in O && O[k] === searchElement) {
16975					return k;
16976				}
16977				k++;
16978			}
16979			return -1;
16980		};
16981	}
16982
16983	if (!Array.prototype.lastIndexOf) {
16984		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
16985			"use strict";
16986
16987			if (this == null)
16988				throw new TypeError();
16989
16990			var t = Object(this);
16991			var len = t.length >>> 0;
16992			if (len === 0)
16993				return -1;
16994
16995			var n = len;
16996			if (arguments.length > 1) {
16997				n = Number(arguments[1]);
16998				if (n != n)
16999					n = 0;
17000				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
17001					n = (n > 0 || -1) * floor(abs(n));
17002			}
17003
17004			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
17005
17006			for (; k >= 0; k--) {
17007				if (k in t && t[k] === searchElement)
17008					return k;
17009			}
17010			return -1;
17011		};
17012	}
17013})(jQuery, this);
17014
17015/*!
17016 * lightgallery | 2.5.0 | June 13th 2022
17017 * http://www.lightgalleryjs.com/
17018 * Copyright (c) 2020 Sachin Neravath;
17019 * @license GPLv3
17020 */
17021
17022(function (global, factory) {
17023	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
17024	typeof define === 'function' && define.amd ? define(factory) :
17025	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
17026}(this, (function () { 'use strict';
17027
17028	/*! *****************************************************************************
17029	Copyright (c) Microsoft Corporation.
17030
17031	Permission to use, copy, modify, and/or distribute this software for any
17032	purpose with or without fee is hereby granted.
17033
17034	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17035	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17036	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17037	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17038	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17039	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17040	PERFORMANCE OF THIS SOFTWARE.
17041	***************************************************************************** */
17042
17043	var __assign = function() {
17044		__assign = Object.assign || function __assign(t) {
17045			for (var s, i = 1, n = arguments.length; i < n; i++) {
17046				s = arguments[i];
17047				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
17048			}
17049			return t;
17050		};
17051		return __assign.apply(this, arguments);
17052	};
17053
17054	function __spreadArrays() {
17055		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
17056		for (var r = Array(s), k = 0, i = 0; i < il; i++)
17057			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
17058				r[k] = a[j];
17059		return r;
17060	}
17061
17062	/**
17063	 * List of lightGallery events
17064	 * All events should be documented here
17065	 * Below interfaces are used to build the website documentations
17066	 * */
17067	var lGEvents = {
17068		afterAppendSlide: 'lgAfterAppendSlide',
17069		init: 'lgInit',
17070		hasVideo: 'lgHasVideo',
17071		containerResize: 'lgContainerResize',
17072		updateSlides: 'lgUpdateSlides',
17073		afterAppendSubHtml: 'lgAfterAppendSubHtml',
17074		beforeOpen: 'lgBeforeOpen',
17075		afterOpen: 'lgAfterOpen',
17076		slideItemLoad: 'lgSlideItemLoad',
17077		beforeSlide: 'lgBeforeSlide',
17078		afterSlide: 'lgAfterSlide',
17079		posterClick: 'lgPosterClick',
17080		dragStart: 'lgDragStart',
17081		dragMove: 'lgDragMove',
17082		dragEnd: 'lgDragEnd',
17083		beforeNextSlide: 'lgBeforeNextSlide',
17084		beforePrevSlide: 'lgBeforePrevSlide',
17085		beforeClose: 'lgBeforeClose',
17086		afterClose: 'lgAfterClose',
17087		rotateLeft: 'lgRotateLeft',
17088		rotateRight: 'lgRotateRight',
17089		flipHorizontal: 'lgFlipHorizontal',
17090		flipVertical: 'lgFlipVertical',
17091		autoplay: 'lgAutoplay',
17092		autoplayStart: 'lgAutoplayStart',
17093		autoplayStop: 'lgAutoplayStop',
17094	};
17095
17096	var lightGalleryCoreSettings = {
17097		mode: 'lg-slide',
17098		easing: 'ease',
17099		speed: 400,
17100		licenseKey: '0000-0000-000-0000',
17101		height: '100%',
17102		width: '100%',
17103		addClass: '',
17104		startClass: 'lg-start-zoom',
17105		backdropDuration: 300,
17106		container: '',
17107		startAnimationDuration: 400,
17108		zoomFromOrigin: true,
17109		hideBarsDelay: 0,
17110		showBarsAfter: 10000,
17111		slideDelay: 0,
17112		supportLegacyBrowser: true,
17113		allowMediaOverlap: false,
17114		videoMaxSize: '1280-720',
17115		loadYouTubePoster: true,
17116		defaultCaptionHeight: 0,
17117		ariaLabelledby: '',
17118		ariaDescribedby: '',
17119		resetScrollPosition: true,
17120		hideScrollbar: false,
17121		closable: true,
17122		swipeToClose: true,
17123		closeOnTap: true,
17124		showCloseIcon: true,
17125		showMaximizeIcon: false,
17126		loop: true,
17127		escKey: true,
17128		keyPress: true,
17129		trapFocus: true,
17130		controls: true,
17131		slideEndAnimation: true,
17132		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 17133-17680
17133		mousewheel: false,
17134		getCaptionFromTitleOrAlt: true,
17135		appendSubHtmlTo: '.lg-sub-html',
17136		subHtmlSelectorRelative: false,
17137		preload: 2,
17138		numberOfSlideItemsInDom: 10,
17139		selector: '',
17140		selectWithin: '',
17141		nextHtml: '',
17142		prevHtml: '',
17143		index: 0,
17144		iframeWidth: '100%',
17145		iframeHeight: '100%',
17146		iframeMaxWidth: '100%',
17147		iframeMaxHeight: '100%',
17148		download: true,
17149		counter: true,
17150		appendCounterTo: '.lg-toolbar',
17151		swipeThreshold: 50,
17152		enableSwipe: true,
17153		enableDrag: true,
17154		dynamic: false,
17155		dynamicEl: [],
17156		extraProps: [],
17157		exThumbImage: '',
17158		isMobile: undefined,
17159		mobileSettings: {
17160			controls: false,
17161			showCloseIcon: false,
17162			download: false,
17163		},
17164		plugins: [],
17165		strings: {
17166			closeGallery: 'Close gallery',
17167			toggleMaximize: 'Toggle maximize',
17168			previousSlide: 'Previous slide',
17169			nextSlide: 'Next slide',
17170			download: 'Download',
17171			playVideo: 'Play video',
17172		},
17173	};
17174
17175	function initLgPolyfills() {
17176		(function () {
17177			if (typeof window.CustomEvent === 'function')
17178				return false;
17179			function CustomEvent(event, params) {
17180				params = params || {
17181					bubbles: false,
17182					cancelable: false,
17183					detail: null,
17184				};
17185				var evt = document.createEvent('CustomEvent');
17186				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
17187				return evt;
17188			}
17189			window.CustomEvent = CustomEvent;
17190		})();
17191		(function () {
17192			if (!Element.prototype.matches) {
17193				Element.prototype.matches =
17194					Element.prototype.msMatchesSelector ||
17195						Element.prototype.webkitMatchesSelector;
17196			}
17197		})();
17198	}
17199	var lgQuery = /** @class */ (function () {
17200		function lgQuery(selector) {
17201			this.cssVenderPrefixes = [
17202				'TransitionDuration',
17203				'TransitionTimingFunction',
17204				'Transform',
17205				'Transition',
17206			];
17207			this.selector = this._getSelector(selector);
17208			this.firstElement = this._getFirstEl();
17209			return this;
17210		}
17211		lgQuery.generateUUID = function () {
17212			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
17213				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
17214				return v.toString(16);
17215			});
17216		};
17217		lgQuery.prototype._getSelector = function (selector, context) {
17218			if (context === void 0) { context = document; }
17219			if (typeof selector !== 'string') {
17220				return selector;
17221			}
17222			context = context || document;
17223			var fl = selector.substring(0, 1);
17224			if (fl === '#') {
17225				return context.querySelector(selector);
17226			}
17227			else {
17228				return context.querySelectorAll(selector);
17229			}
17230		};
17231		lgQuery.prototype._each = function (func) {
17232			if (!this.selector) {
17233				return this;
17234			}
17235			if (this.selector.length !== undefined) {
17236				[].forEach.call(this.selector, func);
17237			}
17238			else {
17239				func(this.selector, 0);
17240			}
17241			return this;
17242		};
17243		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
17244			// prettier-ignore
17245			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
17246				return group1.toUpperCase();
17247			});
17248			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
17249				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
17250				el.style['webkit' + property] = value;
17251				el.style['moz' + property] = value;
17252				el.style['ms' + property] = value;
17253				el.style['o' + property] = value;
17254			}
17255			else {
17256				el.style[property] = value;
17257			}
17258		};
17259		lgQuery.prototype._getFirstEl = function () {
17260			if (this.selector && this.selector.length !== undefined) {
17261				return this.selector[0];
17262			}
17263			else {
17264				return this.selector;
17265			}
17266		};
17267		lgQuery.prototype.isEventMatched = function (event, eventName) {
17268			var eventNamespace = eventName.split('.');
17269			return event
17270				.split('.')
17271				.filter(function (e) { return e; })
17272				.every(function (e) {
17273				return eventNamespace.indexOf(e) !== -1;
17274			});
17275		};
17276		lgQuery.prototype.attr = function (attr, value) {
17277			if (value === undefined) {
17278				if (!this.firstElement) {
17279					return '';
17280				}
17281				return this.firstElement.getAttribute(attr);
17282			}
17283			this._each(function (el) {
17284				el.setAttribute(attr, value);
17285			});
17286			return this;
17287		};
17288		lgQuery.prototype.find = function (selector) {
17289			return $LG(this._getSelector(selector, this.selector));
17290		};
17291		lgQuery.prototype.first = function () {
17292			if (this.selector && this.selector.length !== undefined) {
17293				return $LG(this.selector[0]);
17294			}
17295			else {
17296				return $LG(this.selector);
17297			}
17298		};
17299		lgQuery.prototype.eq = function (index) {
17300			return $LG(this.selector[index]);
17301		};
17302		lgQuery.prototype.parent = function () {
17303			return $LG(this.selector.parentElement);
17304		};
17305		lgQuery.prototype.get = function () {
17306			return this._getFirstEl();
17307		};
17308		lgQuery.prototype.removeAttr = function (attributes) {
17309			var attrs = attributes.split(' ');
17310			this._each(function (el) {
17311				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
17312			});
17313			return this;
17314		};
17315		lgQuery.prototype.wrap = function (className) {
17316			if (!this.firstElement) {
17317				return this;
17318			}
17319			var wrapper = document.createElement('div');
17320			wrapper.className = className;
17321			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
17322			this.firstElement.parentNode.removeChild(this.firstElement);
17323			wrapper.appendChild(this.firstElement);
17324			return this;
17325		};
17326		lgQuery.prototype.addClass = function (classNames) {
17327			if (classNames === void 0) { classNames = ''; }
17328			this._each(function (el) {
17329				// IE doesn't support multiple arguments
17330				classNames.split(' ').forEach(function (className) {
17331					if (className) {
17332						el.classList.add(className);
17333					}
17334				});
17335			});
17336			return this;
17337		};
17338		lgQuery.prototype.removeClass = function (classNames) {
17339			this._each(function (el) {
17340				// IE doesn't support multiple arguments
17341				classNames.split(' ').forEach(function (className) {
17342					if (className) {
17343						el.classList.remove(className);
17344					}
17345				});
17346			});
17347			return this;
17348		};
17349		lgQuery.prototype.hasClass = function (className) {
17350			if (!this.firstElement) {
17351				return false;
17352			}
17353			return this.firstElement.classList.contains(className);
17354		};
17355		lgQuery.prototype.hasAttribute = function (attribute) {
17356			if (!this.firstElement) {
17357				return false;
17358			}
17359			return this.firstElement.hasAttribute(attribute);
17360		};
17361		lgQuery.prototype.toggleClass = function (className) {
17362			if (!this.firstElement) {
17363				return this;
17364			}
17365			if (this.hasClass(className)) {
17366				this.removeClass(className);
17367			}
17368			else {
17369				this.addClass(className);
17370			}
17371			return this;
17372		};
17373		lgQuery.prototype.css = function (property, value) {
17374			var _this = this;
17375			this._each(function (el) {
17376				_this._setCssVendorPrefix(el, property, value);
17377			});
17378			return this;
17379		};
17380		// Need to pass separate namespaces for separate elements
17381		lgQuery.prototype.on = function (events, listener) {
17382			var _this = this;
17383			if (!this.selector) {
17384				return this;
17385			}
17386			events.split(' ').forEach(function (event) {
17387				if (!Array.isArray(lgQuery.eventListeners[event])) {
17388					lgQuery.eventListeners[event] = [];
17389				}
17390				lgQuery.eventListeners[event].push(listener);
17391				_this.selector.addEventListener(event.split('.')[0], listener);
17392			});
17393			return this;
17394		};
17395		// @todo - test this
17396		lgQuery.prototype.once = function (event, listener) {
17397			var _this = this;
17398			this.on(event, function () {
17399				_this.off(event);
17400				listener(event);
17401			});
17402			return this;
17403		};
17404		lgQuery.prototype.off = function (event) {
17405			var _this = this;
17406			if (!this.selector) {
17407				return this;
17408			}
17409			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
17410				if (_this.isEventMatched(event, eventName)) {
17411					lgQuery.eventListeners[eventName].forEach(function (listener) {
17412						_this.selector.removeEventListener(eventName.split('.')[0], listener);
17413					});
17414					lgQuery.eventListeners[eventName] = [];
17415				}
17416			});
17417			return this;
17418		};
17419		lgQuery.prototype.trigger = function (event, detail) {
17420			if (!this.firstElement) {
17421				return this;
17422			}
17423			var customEvent = new CustomEvent(event.split('.')[0], {
17424				detail: detail || null,
17425			});
17426			this.firstElement.dispatchEvent(customEvent);
17427			return this;
17428		};
17429		// Does not support IE
17430		lgQuery.prototype.load = function (url) {
17431			var _this = this;
17432			fetch(url)
17433				.then(function (res) { return res.text(); })
17434				.then(function (html) {
17435				_this.selector.innerHTML = html;
17436			});
17437			return this;
17438		};
17439		lgQuery.prototype.html = function (html) {
17440			if (html === undefined) {
17441				if (!this.firstElement) {
17442					return '';
17443				}
17444				return this.firstElement.innerHTML;
17445			}
17446			this._each(function (el) {
17447				el.innerHTML = html;
17448			});
17449			return this;
17450		};
17451		lgQuery.prototype.append = function (html) {
17452			this._each(function (el) {
17453				if (typeof html === 'string') {
17454					el.insertAdjacentHTML('beforeend', html);
17455				}
17456				else {
17457					el.appendChild(html);
17458				}
17459			});
17460			return this;
17461		};
17462		lgQuery.prototype.prepend = function (html) {
17463			this._each(function (el) {
17464				el.insertAdjacentHTML('afterbegin', html);
17465			});
17466			return this;
17467		};
17468		lgQuery.prototype.remove = function () {
17469			this._each(function (el) {
17470				el.parentNode.removeChild(el);
17471			});
17472			return this;
17473		};
17474		lgQuery.prototype.empty = function () {
17475			this._each(function (el) {
17476				el.innerHTML = '';
17477			});
17478			return this;
17479		};
17480		lgQuery.prototype.scrollTop = function (scrollTop) {
17481			if (scrollTop !== undefined) {
17482				document.body.scrollTop = scrollTop;
17483				document.documentElement.scrollTop = scrollTop;
17484				return this;
17485			}
17486			else {
17487				return (window.pageYOffset ||
17488					document.documentElement.scrollTop ||
17489					document.body.scrollTop ||
17490					0);
17491			}
17492		};
17493		lgQuery.prototype.scrollLeft = function (scrollLeft) {
17494			if (scrollLeft !== undefined) {
17495				document.body.scrollLeft = scrollLeft;
17496				document.documentElement.scrollLeft = scrollLeft;
17497				return this;
17498			}
17499			else {
17500				return (window.pageXOffset ||
17501					document.documentElement.scrollLeft ||
17502					document.body.scrollLeft ||
17503					0);
17504			}
17505		};
17506		lgQuery.prototype.offset = function () {
17507			if (!this.firstElement) {
17508				return {
17509					left: 0,
17510					top: 0,
17511				};
17512			}
17513			var rect = this.firstElement.getBoundingClientRect();
17514			var bodyMarginLeft = $LG('body').style().marginLeft;
17515			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
17516			return {
17517				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
17518				top: rect.top + this.scrollTop(),
17519			};
17520		};
17521		lgQuery.prototype.style = function () {
17522			if (!this.firstElement) {
17523				return {};
17524			}
17525			return (this.firstElement.currentStyle ||
17526				window.getComputedStyle(this.firstElement));
17527		};
17528		// Width without padding and border even if box-sizing is used.
17529		lgQuery.prototype.width = function () {
17530			var style = this.style();
17531			return (this.firstElement.clientWidth -
17532				parseFloat(style.paddingLeft) -
17533				parseFloat(style.paddingRight));
17534		};
17535		// Height without padding and border even if box-sizing is used.
17536		lgQuery.prototype.height = function () {
17537			var style = this.style();
17538			return (this.firstElement.clientHeight -
17539				parseFloat(style.paddingTop) -
17540				parseFloat(style.paddingBottom));
17541		};
17542		lgQuery.eventListeners = {};
17543		return lgQuery;
17544	}());
17545	function $LG(selector) {
17546		initLgPolyfills();
17547		return new lgQuery(selector);
17548	}
17549
17550	var defaultDynamicOptions = [
17551		'src',
17552		'sources',
17553		'subHtml',
17554		'subHtmlUrl',
17555		'html',
17556		'video',
17557		'poster',
17558		'slideName',
17559		'responsive',
17560		'srcset',
17561		'sizes',
17562		'iframe',
17563		'downloadUrl',
17564		'download',
17565		'width',
17566		'facebookShareUrl',
17567		'tweetText',
17568		'iframeTitle',
17569		'twitterShareUrl',
17570		'pinterestShareUrl',
17571		'pinterestText',
17572		'fbHtml',
17573		'disqusIdentifier',
17574		'disqusUrl',
17575	];
17576	// Convert html data-attribute to camalcase
17577	function convertToData(attr) {
17578		// FInd a way for lgsize
17579		if (attr === 'href') {
17580			return 'src';
17581		}
17582		attr = attr.replace('data-', '');
17583		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
17584		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
17585		return attr;
17586	}
17587	var utils = {
17588		/**
17589		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
17590		 */
17591		//Uncode edit ##START##
17592		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
17593		// getSize: function (el, container, spacing, defaultLgSize) {
17594		//Uncode edit ##END##
17595			if (spacing === void 0) { spacing = 0; }
17596			var LGel = $LG(el);
17597			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
17598			//Uncode edit ##START##
17599			if ( typeof galleryItem.size && galleryItem.size != null ) {
17600				lgSize = galleryItem.size;
17601			}
17602			//Uncode edit ##END##
17603			if (!lgSize) {
17604				return;
17605			}
17606			var isResponsiveSizes = lgSize.split(',');
17607			// if at-least two viewport sizes are available
17608			if (isResponsiveSizes[1]) {
17609				var wWidth = window.innerWidth;
17610				for (var i = 0; i < isResponsiveSizes.length; i++) {
17611					var size_1 = isResponsiveSizes[i];
17612					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
17613					if (responsiveWidth > wWidth) {
17614						lgSize = size_1;
17615						break;
17616					}
17617					// take last item as last option
17618					if (i === isResponsiveSizes.length - 1) {
17619						lgSize = size_1;
17620					}
17621				}
17622			}
17623			var size = lgSize.split('-');
17624			var width = parseInt(size[0], 10);
17625			var height = parseInt(size[1], 10);
17626			var cWidth = container.width();
17627			var cHeight = container.height() - spacing;
17628			var maxWidth = Math.min(cWidth, width);
17629			var maxHeight = Math.min(cHeight, height);
17630			var ratio = Math.min(maxWidth / width, maxHeight / height);
17631			return { width: width * ratio, height: height * ratio };
17632		},
17633		/**
17634		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
17635		 * @param {jQuery Element}
17636		 * @returns {String} Transform CSS string
17637		 */
17638		getTransform: function (el, container, top, bottom, imageSize) {
17639			if (!imageSize) {
17640				return;
17641			}
17642			var LGel = $LG(el).find('img').first();
17643			if (!LGel.get()) {
17644				return;
17645			}
17646			var containerRect = container.get().getBoundingClientRect();
17647			var wWidth = containerRect.width;
17648			// using innerWidth to include mobile safari bottom bar
17649			var wHeight = container.height() - (top + bottom);
17650			var elWidth = LGel.width();
17651			var elHeight = LGel.height();
17652			var elStyle = LGel.style();
17653			var x = (wWidth - elWidth) / 2 -
17654				LGel.offset().left +
17655				(parseFloat(elStyle.paddingLeft) || 0) +
17656				(parseFloat(elStyle.borderLeft) || 0) +
17657				$LG(window).scrollLeft() +
17658				containerRect.left;
17659			var y = (wHeight - elHeight) / 2 -
17660				LGel.offset().top +
17661				(parseFloat(elStyle.paddingTop) || 0) +
17662				(parseFloat(elStyle.borderTop) || 0) +
17663				$LG(window).scrollTop() +
17664				top;
17665			var scX = elWidth / imageSize.width;
17666			var scY = elHeight / imageSize.height;
17667			var transform = 'translate3d(' +
17668				(x *= -1) +
17669				'px, ' +
17670				(y *= -1) +
17671				'px, 0) scale3d(' +
17672				scX +
17673				', ' +
17674				scY +
17675				', 1)';
17676			return transform;
17677		},
17678		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
17679			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
17680			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 17680-17752
17680+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
17681		},
17682		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
17683			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
17684			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17685			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17686			var sourceTag = '';
17687			if (sources) {
17688				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17689				sourceTag = sourceObj.map(function (source) {
17690					var attrs = '';
17691					Object.keys(source).forEach(function (key) {
17692						// Do not remove the first space as it is required to separate the attributes
17693						attrs += " " + key + "=\"" + source[key] + "\"";
17694					});
17695					return "<source " + attrs + "></source>";
17696				});
17697			}
17698			return "" + sourceTag + imgMarkup;
17699		},
17700		// Get src from responsive src
17701		getResponsiveSrc: function (srcItms) {
17702			var rsWidth = [];
17703			var rsSrc = [];
17704			var src = '';
17705			for (var i = 0; i < srcItms.length; i++) {
17706				var _src = srcItms[i].split(' ');
17707				// Manage empty space
17708				if (_src[0] === '') {
17709					_src.splice(0, 1);
17710				}
17711				rsSrc.push(_src[0]);
17712				rsWidth.push(_src[1]);
17713			}
17714			var wWidth = window.innerWidth;
17715			for (var j = 0; j < rsWidth.length; j++) {
17716				if (parseInt(rsWidth[j], 10) > wWidth) {
17717					src = rsSrc[j];
17718					break;
17719				}
17720			}
17721			return src;
17722		},
17723		isImageLoaded: function (img) {
17724			if (!img)
17725				return false;
17726			// During the onload event, IE correctly identifies any images that
17727			// weren’t downloaded as not complete. Others should too. Gecko-based
17728			// browsers act like NS4 in that they report this incorrectly.
17729			if (!img.complete) {
17730				return false;
17731			}
17732			// However, they do have two very useful properties: naturalWidth and
17733			// naturalHeight. These give the true size of the image. If it failed
17734			// to load, either of these should be zero.
17735			if (img.naturalWidth === 0) {
17736				return false;
17737			}
17738			// No other way of checking: assume it’s ok.
17739			return true;
17740		},
17741		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17742			var videoClass = '';
17743			if (_isVideo && _isVideo.youtube) {
17744				videoClass = 'lg-has-youtube';
17745			}
17746			else if (_isVideo && _isVideo.vimeo) {
17747				videoClass = 'lg-has-vimeo';
17748			}
17749			else {
17750				videoClass = 'lg-has-html5';
17751			}
17752			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
vendor: 5,030 bytes, lines 17752-17863
17752\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>";
17753		},
17754		getFocusableElements: function (container) {
17755			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])');
17756			var visibleElements = [].filter.call(elements, function (element) {
17757				var style = window.getComputedStyle(element);
17758				return style.display !== 'none' && style.visibility !== 'hidden';
17759			});
17760			return visibleElements;
17761		},
17762		/**
17763		 * @desc Create dynamic elements array from gallery items when dynamic option is false
17764		 * It helps to avoid frequent DOM interaction
17765		 * and avoid multiple checks for dynamic elments
17766		 *
17767		 * @returns {Array} dynamicEl
17768		 */
17769		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17770			var dynamicElements = [];
17771			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17772			[].forEach.call(items, function (item) {
17773				var dynamicEl = {};
17774				for (var i = 0; i < item.attributes.length; i++) {
17775					var attr = item.attributes[i];
17776					if (attr.specified) {
17777						var dynamicAttr = convertToData(attr.name);
17778						var label = '';
17779						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17780							label = dynamicAttr;
17781						}
17782						if (label) {
17783							dynamicEl[label] = attr.value;
17784						}
17785					}
17786				}
17787				var currentItem = $LG(item);
17788				var alt = currentItem.find('img').first().attr('alt');
17789				var title = currentItem.attr('title');
17790				//Uncode edit ##START##
17791				// var thumb = exThumbImage
17792				var thumb = exThumbImage && currentItem.attr(exThumbImage)
17793				//Uncode edit ##END##
17794					? currentItem.attr(exThumbImage)
17795					: currentItem.find('img').first().attr('src');
17796				dynamicEl.thumb = thumb;
17797				//Uncode edit ##START##
17798				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17799					// dynamicEl.subHtml = title || alt || '';
17800					dynamicEl.subHtml = title || '';
17801				}
17802				// dynamicEl.alt = alt || title || '';
17803				dynamicEl.alt = title || '';
17804				var inlineType = currentItem.attr('data-type');
17805				dynamicEl.type = inlineType;
17806				//Uncode edit ##END##
17807				dynamicElements.push(dynamicEl);
17808			});
17809			return dynamicElements;
17810		},
17811		isMobile: function () {
17812			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17813		},
17814		/**
17815		 * @desc Check the given src is video
17816		 * @param {String} src
17817		 * @return {Object} video type
17818		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17819		 *
17820		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
17821		 */
17822		isVideo: function (src, isHTML5VIdeo, index) {
17823			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
17824				if (isHTML5VIdeo) {
17825					return {
17826						html5: true,
17827					};
17828				}
17829				else {
17830					console.warn('lightGallery :- data-src is not provided on slide item ' +
17831						(index + 1) +
17832						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17833					return;
17834				}
17835			}
17836			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17837			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17838			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17839			if (youtube) {
17840				return {
17841					youtube: youtube,
17842				};
17843			}
17844			else if (vimeo) {
17845				return {
17846					vimeo: vimeo,
17847				};
17848			}
17849			else if (wistia) {
17850				return {
17851					wistia: wistia,
17852				};
17853			}
17854		},
17855	};
17856
17857	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17858	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17859	// Unique id for each gallery
17860	var lgId = 0;
17861	var LightGallery = /** @class */ (function () {
17862		function LightGallery(element, options) {
17863			this.lgOpened = false;
vendor: 4,563 bytes, lines 17864-17998
17864			this.index = 0;
17865			// lightGallery modules
17866			this.plugins = [];
17867			// false when lightGallery load first slide content;
17868			this.lGalleryOn = false;
17869			// True when a slide animation is in progress
17870			this.lgBusy = false;
17871			this.currentItemsInDom = [];
17872			// Scroll top value before lightGallery is opened
17873			this.prevScrollTop = 0;
17874			this.bodyPaddingRight = 0;
17875			this.isDummyImageRemoved = false;
17876			this.dragOrSwipeEnabled = false;
17877			this.mediaContainerPosition = {
17878				top: 0,
17879				bottom: 0,
17880			};
17881			if (!element) {
17882				return this;
17883			}
17884			lgId++;
17885			this.lgId = lgId;
17886			this.el = element;
17887			this.LGel = $LG(element);
17888			this.generateSettings(options);
17889			this.buildModules();
17890			// When using dynamic mode, ensure dynamicEl is an array
17891			if (this.settings.dynamic &&
17892				this.settings.dynamicEl !== undefined &&
17893				!Array.isArray(this.settings.dynamicEl)) {
17894				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17895			}
17896			this.galleryItems = this.getItems();
17897			this.normalizeSettings();
17898			// Gallery items
17899			this.init();
17900			//Uncode edit ##START##
17901			// this.validateLicense();
17902			//Uncode edit ##END##
17903			return this;
17904		}
17905		LightGallery.prototype.generateSettings = function (options) {
17906			// lightGallery settings
17907			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17908			if (this.settings.isMobile &&
17909				typeof this.settings.isMobile === 'function'
17910				? this.settings.isMobile()
17911				: utils.isMobile()) {
17912				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17913				this.settings = __assign(__assign({}, this.settings), mobileSettings);
17914			}
17915		};
17916		LightGallery.prototype.normalizeSettings = function () {
17917			if (this.settings.slideEndAnimation) {
17918				this.settings.hideControlOnEnd = false;
17919			}
17920			if (!this.settings.closable) {
17921				this.settings.swipeToClose = false;
17922			}
17923			// And reset it on close to get the correct value next time
17924			this.zoomFromOrigin = this.settings.zoomFromOrigin;
17925			// At the moment, Zoom from image doesn't support dynamic options
17926			// @todo add zoomFromOrigin support for dynamic images
17927			if (this.settings.dynamic) {
17928				this.zoomFromOrigin = false;
17929			}
17930			if (!this.settings.container) {
17931				this.settings.container = document.body;
17932			}
17933			// settings.preload should not be grater than $item.length
17934			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17935		};
17936		LightGallery.prototype.init = function () {
17937			var _this = this;
17938			this.addSlideVideoInfo(this.galleryItems);
17939			this.buildStructure();
17940			this.LGel.trigger(lGEvents.init, {
17941				instance: this,
17942			});
17943			if (this.settings.keyPress) {
17944				this.keyPress();
17945			}
17946			setTimeout(function () {
17947				_this.enableDrag();
17948				_this.enableSwipe();
17949				_this.triggerPosterClick();
17950			}, 50);
17951			this.arrow();
17952			if (this.settings.mousewheel) {
17953				this.mousewheel();
17954			}
17955			if (!this.settings.dynamic) {
17956				this.openGalleryOnItemClick();
17957			}
17958		};
17959		LightGallery.prototype.openGalleryOnItemClick = function () {
17960			var _this = this;
17961			var _loop_1 = function (index) {
17962				var element = this_1.items[index];
17963				var $element = $LG(element);
17964				// Using different namespace for click because click event should not unbind if selector is same object('this')
17965				// @todo manage all event listners - should have namespace that represent element
17966				var uuid = lgQuery.generateUUID();
17967				$element
17968					.attr('data-lg-id', uuid)
17969					.on("click.lgcustom-item-" + uuid, function (e) {
17970					e.preventDefault();
17971					var currentItemIndex = _this.settings.index || index;
17972					_this.openGallery(currentItemIndex, element);
17973				});
17974			};
17975			var this_1 = this;
17976			// Using for loop instead of using bubbling as the items can be any html element.
17977			for (var index = 0; index < this.items.length; index++) {
17978				_loop_1(index);
17979			}
17980		};
17981		/**
17982		 * Module constructor
17983		 * Modules are build incrementally.
17984		 * Gallery should be opened only once all the modules are initialized.
17985		 * use moduleBuildTimeout to make sure this
17986		 */
17987		LightGallery.prototype.buildModules = function () {
17988			var _this = this;
17989			this.settings.plugins.forEach(function (plugin) {
17990				_this.plugins.push(new plugin(_this, $LG));
17991			});
17992		};
17993		LightGallery.prototype.validateLicense = function () {
17994			if (!this.settings.licenseKey) {
17995				console.warn('Please provide a valid license key');
17996			}
17997			else if (this.settings.licenseKey === '0000-0000-000-0000') {
17998				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 17998-18412
17998id for production use");
17999			}
18000		};
18001		LightGallery.prototype.getSlideItem = function (index) {
18002			return $LG(this.getSlideItemId(index));
18003		};
18004		LightGallery.prototype.getSlideItemId = function (index) {
18005			return "#lg-item-" + this.lgId + "-" + index;
18006		};
18007		LightGallery.prototype.getIdName = function (id) {
18008			return id + "-" + this.lgId;
18009		};
18010		LightGallery.prototype.getElementById = function (id) {
18011			return $LG("#" + this.getIdName(id));
18012		};
18013		LightGallery.prototype.manageSingleSlideClassName = function () {
18014			if (this.galleryItems.length < 2) {
18015				this.outer.addClass('lg-single-item');
18016			}
18017			else {
18018				this.outer.removeClass('lg-single-item');
18019			}
18020		};
18021		LightGallery.prototype.buildStructure = function () {
18022			var _this = this;
18023			var container = this.$container && this.$container.get();
18024			if (container) {
18025				return;
18026			}
18027			var controls = '';
18028			var subHtmlCont = '';
18029			// Create controls
18030			if (this.settings.controls) {
18031				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>";
18032			}
18033			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18034				subHtmlCont =
18035					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
18036			}
18037			var addClasses = '';
18038			if (this.settings.allowMediaOverlap) {
18039				// Do not remove space before last single quote
18040				addClasses += 'lg-media-overlap ';
18041			}
18042			var ariaLabelledby = this.settings.ariaLabelledby
18043				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
18044				: '';
18045			var ariaDescribedby = this.settings.ariaDescribedby
18046				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
18047				: '';
18048			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
18049			var closeIcon = this.settings.closable && this.settings.showCloseIcon
18050				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
18051				: '';
18052			var maximizeIcon = this.settings.showMaximizeIcon
18053				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
18054				: '';
18055			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'
18056				? subHtmlCont
18057				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
18058				? subHtmlCont
18059				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
18060			$LG(this.settings.container).append(template);
18061			if (document.body !== this.settings.container) {
18062				$LG(this.settings.container).css('position', 'relative');
18063			}
18064			this.outer = this.getElementById('lg-outer');
18065			this.$lgComponents = this.getElementById('lg-components');
18066			this.$backdrop = this.getElementById('lg-backdrop');
18067			this.$container = this.getElementById('lg-container');
18068			this.$inner = this.getElementById('lg-inner');
18069			this.$content = this.getElementById('lg-content');
18070			this.$toolbar = this.getElementById('lg-toolbar');
18071			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
18072			var outerClassNames = this.settings.mode + " ";
18073			this.manageSingleSlideClassName();
18074			if (this.settings.enableDrag) {
18075				outerClassNames += 'lg-grab ';
18076			}
18077			this.outer.addClass(outerClassNames);
18078			this.$inner.css('transition-timing-function', this.settings.easing);
18079			this.$inner.css('transition-duration', this.settings.speed + 'ms');
18080			if (this.settings.download) {
18081				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>");
18082			}
18083			this.counter();
18084			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
18085				_this.refreshOnResize();
18086			});
18087			this.hideBars();
18088			this.manageCloseGallery();
18089			this.toggleMaximize();
18090			this.initModules();
18091		};
18092		LightGallery.prototype.refreshOnResize = function () {
18093			if (this.lgOpened) {
18094				var currentGalleryItem = this.galleryItems[this.index];
18095				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
18096				this.mediaContainerPosition = this.getMediaContainerPosition();
18097				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
18098				//Uncode edit ##START##
18099				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18100				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18101				//Uncode edit ##END##
18102				if (__slideVideoInfo) {
18103					this.resizeVideoSlide(this.index, this.currentImageSize);
18104				}
18105				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
18106					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18107					this.outer
18108						.find('.lg-current .lg-dummy-img')
18109						.first()
18110						.attr('style', imgStyle);
18111				}
18112				this.LGel.trigger(lGEvents.containerResize);
18113			}
18114		};
18115		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
18116			var lgVideoStyle = this.getVideoContStyle(imageSize);
18117			var currentSlide = this.getSlideItem(index);
18118			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
18119		};
18120		/**
18121		 * Update slides dynamically.
18122		 * Add, edit or delete slides dynamically when lightGallery is opened.
18123		 * Modify the current gallery items and pass it via updateSlides method
18124		 * @note
18125		 * - Do not mutate existing lightGallery items directly.
18126		 * - Always pass new list of gallery items
18127		 * - You need to take care of thumbnails outside the gallery if any
18128		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
18129		 * @param items Gallery items
18130		 * @param index After the update operation, which slide gallery should navigate to
18131		 * @category lGPublicMethods
18132		 * @example
18133		 * const plugin = lightGallery();
18134		 *
18135		 * // Adding slides dynamically
18136		 * let galleryItems = [
18137		 * // Access existing lightGallery items
18138		 * // galleryItems are automatically generated internally from the gallery HTML markup
18139		 * // or directly from galleryItems when dynamic gallery is used
18140		 *   ...plugin.galleryItems,
18141		 *     ...[
18142		 *       {
18143		 *         src: 'img/img-1.png',
18144		 *           thumb: 'img/thumb1.png',
18145		 *         },
18146		 *     ],
18147		 *   ];
18148		 *   plugin.updateSlides(
18149		 *     galleryItems,
18150		 *     plugin.index,
18151		 *   );
18152		 *
18153		 *
18154		 * // Remove slides dynamically
18155		 * galleryItems = JSON.parse(
18156		 *   JSON.stringify(updateSlideInstance.galleryItems),
18157		 * );
18158		 * galleryItems.shift();
18159		 * updateSlideInstance.updateSlides(galleryItems, 1);
18160		 * @see <a href="/demos/update-slides/">Demo</a>
18161		 */
18162		LightGallery.prototype.updateSlides = function (items, index) {
18163			if (this.index > items.length - 1) {
18164				this.index = items.length - 1;
18165			}
18166			if (items.length === 1) {
18167				this.index = 0;
18168			}
18169			if (!items.length) {
18170				this.closeGallery();
18171				return;
18172			}
18173			var currentSrc = this.galleryItems[index].src;
18174			this.galleryItems = items;
18175			this.updateControls();
18176			this.$inner.empty();
18177			this.currentItemsInDom = [];
18178			var _index = 0;
18179			// Find the current index based on source value of the slide
18180			this.galleryItems.some(function (galleryItem, itemIndex) {
18181				if (galleryItem.src === currentSrc) {
18182					_index = itemIndex;
18183					return true;
18184				}
18185				return false;
18186			});
18187			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
18188			this.loadContent(_index, true);
18189			this.getSlideItem(_index).addClass('lg-current');
18190			this.index = _index;
18191			this.updateCurrentCounter(_index);
18192			this.LGel.trigger(lGEvents.updateSlides);
18193		};
18194		// Get gallery items based on multiple conditions
18195		LightGallery.prototype.getItems = function () {
18196			// Gallery items
18197			this.items = [];
18198			if (!this.settings.dynamic) {
18199				if (this.settings.selector === 'this') {
18200					this.items.push(this.el);
18201				}
18202				else if (this.settings.selector) {
18203					if (typeof this.settings.selector === 'string') {
18204						if (this.settings.selectWithin) {
18205							var selectWithin = $LG(this.settings.selectWithin);
18206							this.items = selectWithin
18207								.find(this.settings.selector)
18208								.get();
18209						}
18210						else {
18211							this.items = this.el.querySelectorAll(this.settings.selector);
18212						}
18213					}
18214					else {
18215						this.items = this.settings.selector;
18216					}
18217				}
18218				else {
18219					this.items = this.el.children;
18220				}
18221				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
18222			}
18223			else {
18224				return this.settings.dynamicEl || [];
18225			}
18226		};
18227		LightGallery.prototype.shouldHideScrollbar = function () {
18228			return (this.settings.hideScrollbar &&
18229				document.body === this.settings.container);
18230		};
18231		LightGallery.prototype.hideScrollbar = function () {
18232			if (!this.shouldHideScrollbar()) {
18233				return;
18234			}
18235			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
18236			var bodyRect = document.documentElement.getBoundingClientRect();
18237			var scrollbarWidth = window.innerWidth - bodyRect.width;
18238			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
18239			$LG(document.body).addClass('lg-overlay-open');
18240		};
18241		LightGallery.prototype.resetScrollBar = function () {
18242			if (!this.shouldHideScrollbar()) {
18243				return;
18244			}
18245			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
18246			$LG(document.body).removeClass('lg-overlay-open');
18247		};
18248		/**
18249		 * Open lightGallery.
18250		 * Open gallery with specific slide by passing index of the slide as parameter.
18251		 * @category lGPublicMethods
18252		 * @param {Number} index  - index of the slide
18253		 * @param {HTMLElement} element - Which image lightGallery should zoom from
18254		 *
18255		 * @example
18256		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
18257		 * const dynamicGallery = lightGallery($dynamicGallery, {
18258		 *     dynamic: true,
18259		 *     dynamicEl: [
18260		 *         {
18261		 *              src: 'img/1.jpg',
18262		 *              thumb: 'img/thumb-1.jpg',
18263		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
18264		 *         },
18265		 *         ...
18266		 *     ],
18267		 * });
18268		 * $dynamicGallery.addEventListener('click', function () {
18269		 *     // Starts with third item.(Optional).
18270		 *     // This is useful if you want use dynamic mode with
18271		 *     // custom thumbnails (thumbnails outside gallery),
18272		 *     dynamicGallery.openGallery(2);
18273		 * });
18274		 *
18275		 */
18276		LightGallery.prototype.openGallery = function (index, element) {
18277			var _this = this;
18278			if (index === void 0) { index = this.settings.index; }
18279			// prevent accidental double execution
18280			if (this.lgOpened)
18281				return;
18282			this.lgOpened = true;
18283			this.outer.removeClass('lg-hide-items');
18284			this.hideScrollbar();
18285			// Add display block, but still has opacity 0
18286			this.$container.addClass('lg-show');
18287			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
18288			this.currentItemsInDom = itemsToBeInsertedToDom;
18289			var items = '';
18290			itemsToBeInsertedToDom.forEach(function (item) {
18291				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18292			});
18293			this.$inner.append(items);
18294			this.addHtml(index);
18295			var transform = '';
18296			this.mediaContainerPosition = this.getMediaContainerPosition();
18297			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
18298			if (!this.settings.allowMediaOverlap) {
18299				this.setMediaContainerPosition(top, bottom);
18300			}
18301			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
18302			if (this.zoomFromOrigin && element) {
18303				//Uncode edit ##START##
18304				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18305				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18306				//Uncode edit ##END##
18307				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
18308			}
18309			if (!this.zoomFromOrigin || !transform) {
18310				this.outer.addClass(this.settings.startClass);
18311				this.getSlideItem(index).removeClass('lg-complete');
18312			}
18313			var timeout = this.settings.zoomFromOrigin
18314				? 100
18315				: this.settings.backdropDuration;
18316			setTimeout(function () {
18317				_this.outer.addClass('lg-components-open');
18318			}, timeout);
18319			this.index = index;
18320			//Uncode edit ##START##
18321			// this.LGel.trigger(lGEvents.beforeOpen);
18322			this.LGel.trigger(lGEvents.beforeOpen, {
18323				galleryItems: this.galleryItems,
18324				items: this.items,
18325				outer: this.outer,
18326			});
18327			//Uncode edit ##END##
18328			// add class lg-current to remove initial transition
18329			this.getSlideItem(index).addClass('lg-current');
18330			this.lGalleryOn = false;
18331			// Store the current scroll top value to scroll back after closing the gallery..
18332			this.prevScrollTop = $LG(window).scrollTop();
18333			setTimeout(function () {
18334				// Need to check both zoomFromOrigin and transform values as we need to set set the
18335				// default opening animation if user missed to add the lg-size attribute
18336				if (_this.zoomFromOrigin && transform) {
18337					var currentSlide_1 = _this.getSlideItem(index);
18338					currentSlide_1.css('transform', transform);
18339					setTimeout(function () {
18340						currentSlide_1
18341							.addClass('lg-start-progress lg-start-end-progress')
18342							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
18343						_this.outer.addClass('lg-zoom-from-image');
18344					});
18345					setTimeout(function () {
18346						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
18347					}, 100);
18348				}
18349				setTimeout(function () {
18350					_this.$backdrop.addClass('in');
18351					_this.$container.addClass('lg-show-in');
18352				}, 10);
18353				setTimeout(function () {
18354					if (_this.settings.trapFocus &&
18355						document.body === _this.settings.container) {
18356						_this.trapFocus();
18357					}
18358				}, _this.settings.backdropDuration + 50);
18359				// lg-visible class resets gallery opacity to 1
18360				if (!_this.zoomFromOrigin || !transform) {
18361					setTimeout(function () {
18362						_this.outer.addClass('lg-visible');
18363					}, _this.settings.backdropDuration);
18364				}
18365				// initiate slide function
18366				_this.slide(index, false, false, false);
18367				_this.LGel.trigger(lGEvents.afterOpen);
18368			});
18369			if (document.body === this.settings.container) {
18370				$LG('html').addClass('lg-on');
18371			}
18372		};
18373		/**
18374		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
18375		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
18376		 * if you have dynamic captions for each media,
18377		 * you can provide an appropriate height for the captions via allowMediaOverlap option
18378		 */
18379		LightGallery.prototype.getMediaContainerPosition = function () {
18380			if (this.settings.allowMediaOverlap) {
18381				return {
18382					top: 0,
18383					bottom: 0,
18384				};
18385			}
18386			var top = this.$toolbar.get().clientHeight || 0;
18387			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
18388			var captionHeight = this.settings.defaultCaptionHeight ||
18389				(subHtml && subHtml.clientHeight) ||
18390				0;
18391			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
18392			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
18393			var bottom = thumbHeight + captionHeight;
18394			//Uncode edit ##START##
18395			bottom = bottom < 55 ? 55 : bottom;
18396			//Uncode edit ##END##
18397			return {
18398				top: top,
18399				bottom: bottom,
18400			};
18401		};
18402		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
18403			if (top === void 0) { top = 0; }
18404			if (bottom === void 0) { bottom = 0; }
18405			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
18406		};
18407		LightGallery.prototype.hideBars = function () {
18408			var _this = this;
18409			// Hide controllers if mouse doesn't move for some period
18410			setTimeout(function () {
18411				_this.outer.removeClass('lg-hide-items');
18412				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 18413-18543
18413					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
18414						_this.outer.removeClass('lg-hide-items');
18415						clearTimeout(_this.hideBarTimeout);
18416						// Timeout will be cleared on each slide movement also
18417						_this.hideBarTimeout = setTimeout(function () {
18418							_this.outer.addClass('lg-hide-items');
18419						}, _this.settings.hideBarsDelay);
18420					});
18421					_this.outer.trigger('mousemove.lg');
18422				}
18423			}, this.settings.showBarsAfter);
18424		};
18425		LightGallery.prototype.initPictureFill = function ($img) {
18426			if (this.settings.supportLegacyBrowser) {
18427				try {
18428					picturefill({
18429						elements: [$img.get()],
18430					});
18431				}
18432				catch (e) {
18433					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
18434				}
18435			}
18436		};
18437		/**
18438		 *  @desc Create image counter
18439		 *  Ex: 1/10
18440		 */
18441		LightGallery.prototype.counter = function () {
18442			if (this.settings.counter) {
18443				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>";
18444				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
18445			}
18446		};
18447		/**
18448		 *  @desc add sub-html into the slide
18449		 *  @param {Number} index - index of the slide
18450		 */
18451		LightGallery.prototype.addHtml = function (index) {
18452			var subHtml;
18453			var subHtmlUrl;
18454			if (this.galleryItems[index].subHtmlUrl) {
18455				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
18456			}
18457			else {
18458				subHtml = this.galleryItems[index].subHtml;
18459			}
18460			if (!subHtmlUrl) {
18461				if (subHtml) {
18462					// get first letter of sub-html
18463					// if first letter starts with . or # get the html form the jQuery object
18464					var fL = subHtml.substring(0, 1);
18465					if (fL === '.' || fL === '#') {
18466						if (this.settings.subHtmlSelectorRelative &&
18467							!this.settings.dynamic) {
18468							subHtml = $LG(this.items)
18469								.eq(index)
18470								.find(subHtml)
18471								.first()
18472								.html();
18473						}
18474						else {
18475							subHtml = $LG(subHtml).first().html();
18476						}
18477					}
18478				}
18479				else {
18480					subHtml = '';
18481				}
18482			}
18483			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18484				if (subHtmlUrl) {
18485					this.outer.find('.lg-sub-html').load(subHtmlUrl);
18486				}
18487				else {
18488					this.outer.find('.lg-sub-html').html(subHtml);
18489				}
18490			}
18491			else {
18492				var currentSlide = $LG(this.getSlideItemId(index));
18493				if (subHtmlUrl) {
18494					currentSlide.load(subHtmlUrl);
18495				}
18496				else {
18497					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
18498				}
18499			}
18500			// Add lg-empty-html class if title doesn't exist
18501			if (typeof subHtml !== 'undefined' && subHtml !== null) {
18502				if (subHtml === '') {
18503					this.outer
18504						.find(this.settings.appendSubHtmlTo)
18505						.addClass('lg-empty-html');
18506				}
18507				else {
18508					this.outer
18509						.find(this.settings.appendSubHtmlTo)
18510						.removeClass('lg-empty-html');
18511				}
18512			}
18513			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
18514				index: index,
18515			});
18516		};
18517		/**
18518		 *  @desc Preload slides
18519		 *  @param {Number} index - index of the slide
18520		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
18521		 */
18522		LightGallery.prototype.preload = function (index) {
18523			for (var i = 1; i <= this.settings.preload; i++) {
18524				if (i >= this.galleryItems.length - index) {
18525					break;
18526				}
18527				this.loadContent(index + i, false);
18528			}
18529			for (var j = 1; j <= this.settings.preload; j++) {
18530				if (index - j < 0) {
18531					break;
18532				}
18533				this.loadContent(index - j, false);
18534			}
18535		};
18536		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
18537			if (!imageSize)
18538				return '';
18539			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
18540		};
18541		LightGallery.prototype.getVideoContStyle = function (imageSize) {
18542			if (!imageSize)
18543				return '';
18544			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
18545		};
18546		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
18547			var $currentItem;
18548			if (!this.settings.dynamic) {
18549				$currentItem = $LG(this.items).eq(index);
18550			}
18551			if ($currentItem) {
18552				var _dummyImgSrc = void 0;
18553				if (!this.settings.exThumbImage) {
18554					_dummyImgSrc = $currentItem.find('img').first().attr('src');
18555				}
18556				else {
18557					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
18558				}
18559				if (!_dummyImgSrc)
18560					return '';
18561				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18562				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
18563				$currentSlide.addClass('lg-first-slide');
18564				this.outer.addClass('lg-first-slide-loading');
18565				return dummyImgContent;
18566			}
18567			return '';
18568		};
18569		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
18570			var currentGalleryItem = this.galleryItems[index];
18571			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18572			// Use the thumbnail as dummy image which will be resized to actual image size and
18573			// displayed on top of actual image
18574			var imgContent = '';
18575			var altAttr = alt ? 'alt="' + alt + '"' : '';
18576			if (this.isFirstSlideWithZoomAnimation()) {
18577				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
18578			}
18579			else {
18580				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
18581			}
18582			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
18583			$currentSlide.prepend(imgMarkup);
18584		};
18585		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
18586			var mediaObject = $slide.find('.lg-object').first();
18587			if (utils.isImageLoaded(mediaObject.get()) ||
18588				isHTML5VideoWithoutPoster) {
18589				onLoad();
18590			}
18591			else {
18592				mediaObject.on('load.lg error.lg', function () {
18593					onLoad && onLoad();
18594				});
18595				mediaObject.on('error.lg', function () {
18596					onError && onError();
18597				});
18598			}
18599		};
18600		/**
18601		 *
18602		 * @param $el Current slide item
18603		 * @param index
18604		 * @param delay Delay is 0 except first time
18605		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
18606		 * @param isFirstSlide
18607		 */
18608		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
18609			var _this = this;
18610			//Uncode edit ##START##
18611			var $item = _this.galleryItems[index],
18612				type = $item.type;
18613
18614			if ( typeof $item.src !== 'undefined' ) {
18615				var inline_id = $item.src.replace('#', ''),
18616					$inline = document.getElementById(inline_id),
18617					inline_html;
18618
18619				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18620					inline_html = $inline.innerHTML;
18621				} else {
18622					inline_html = '';
18623				}
18624			}
18625			//Uncode edit ##END##
18626			this.onSlideObjectLoad(currentSlide, true, function () {
18627				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
18628			}, function () {
18629				currentSlide.addClass('lg-complete lg-complete_');
18630				//Uncode edit ##START##
18631				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18632				if ( inline_html !== '' ) {
18633					currentSlide.html(inline_html);
18634				} else {
18635					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18636				}
18637				//Uncode edit ##END##
18638			});
18639		};
18640		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
18641			var _this = this;
18642			var currentGalleryItem = this.galleryItems[index];
18643			// Adding delay for video slides without poster for better performance and user experience
18644			// Videos should start playing once once the gallery is completely loaded
18645			var _speed = isFirstSlide &&
vendor: 37,932 bytes, lines 18646-19735
18646				this.getSlideType(currentGalleryItem) === 'video' &&
18647				!currentGalleryItem.poster
18648				? speed
18649				: 0;
18650			setTimeout(function () {
18651				$currentSlide.addClass('lg-complete lg-complete_');
18652				_this.LGel.trigger(lGEvents.slideItemLoad, {
18653					index: index,
18654					delay: delay || 0,
18655					isFirstSlide: isFirstSlide,
18656				});
18657			}, _speed);
18658		};
18659		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
18660			return !!(!this.lGalleryOn &&
18661				this.zoomFromOrigin &&
18662				this.currentImageSize);
18663		};
18664		// Add video slideInfo
18665		LightGallery.prototype.addSlideVideoInfo = function (items) {
18666			var _this = this;
18667			items.forEach(function (element, index) {
18668				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
18669				if (element.__slideVideoInfo &&
18670					_this.settings.loadYouTubePoster &&
18671					!element.poster &&
18672					element.__slideVideoInfo.youtube) {
18673					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
18674				}
18675			});
18676		};
18677		/**
18678		 *  Load slide content into slide.
18679		 *  This is used to load content into slides that is not visible too
18680		 *  @param {Number} index - index of the slide.
18681		 *  @param {Boolean} rec - if true call loadcontent() function again.
18682		 */
18683		LightGallery.prototype.loadContent = function (index, rec) {
18684			var _this = this;
18685			var currentGalleryItem = this.galleryItems[index];
18686			var $currentSlide = $LG(this.getSlideItemId(index));
18687			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18688			var src = currentGalleryItem.src;
18689			var video = currentGalleryItem.video;
18690			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
18691			if (currentGalleryItem.responsive) {
18692				var srcDyItms = currentGalleryItem.responsive.split(',');
18693				src = utils.getResponsiveSrc(srcDyItms) || src;
18694			}
18695			var videoInfo = currentGalleryItem.__slideVideoInfo;
18696			var lgVideoStyle = '';
18697			var iframe = !!currentGalleryItem.iframe;
18698			var isFirstSlide = !this.lGalleryOn;
18699			// delay for adding complete class. it is 0 except first time.
18700			var delay = 0;
18701			if (isFirstSlide) {
18702				if (this.zoomFromOrigin && this.currentImageSize) {
18703					delay = this.settings.startAnimationDuration + 10;
18704				}
18705				else {
18706					delay = this.settings.backdropDuration + 10;
18707				}
18708			}
18709			if (!$currentSlide.hasClass('lg-loaded')) {
18710				if (videoInfo) {
18711					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
18712					//Uncode edit ##START##
18713					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18714					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
18715					//Uncode edit ##END##
18716					lgVideoStyle = this.getVideoContStyle(videoSize);
18717				}
18718				if (iframe) {
18719					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18720					$currentSlide.prepend(markup);
18721				}
18722				else if (poster) {
18723					var dummyImg = '';
18724					var hasStartAnimation = isFirstSlide &&
18725						this.zoomFromOrigin &&
18726						this.currentImageSize;
18727					if (hasStartAnimation) {
18728						dummyImg = this.getDummyImageContent($currentSlide, index, '');
18729					}
18730					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18731					$currentSlide.prepend(markup);
18732				}
18733				//Uncode edit ##START##
18734				// else if (videoInfo) {
18735				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18736					if (! _html5Video) {
18737						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18738					}
18739					//Uncode edit ##END##
18740					$currentSlide.prepend(markup);
18741				}
18742				else {
18743					this.setImgMarkup(src, $currentSlide, index);
18744					if (srcset || sources) {
18745						var $img = $currentSlide.find('.lg-object');
18746						this.initPictureFill($img);
18747					}
18748				}
18749				if (poster || videoInfo) {
18750					this.LGel.trigger(lGEvents.hasVideo, {
18751						index: index,
18752						src: src,
18753						html5Video: _html5Video,
18754						hasPoster: !!poster,
18755					});
18756				}
18757				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18758				if (this.lGalleryOn &&
18759					this.settings.appendSubHtmlTo === '.lg-item') {
18760					this.addHtml(index);
18761				}
18762			}
18763			// For first time add some delay for displaying the start animation.
18764			var _speed = 0;
18765			// Do not change the delay value because it is required for zoom plugin.
18766			// If gallery opened from direct url (hash) speed value should be 0
18767			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18768				_speed = delay;
18769			}
18770			// Only for first slide and zoomFromOrigin is enabled
18771			if (this.isFirstSlideWithZoomAnimation()) {
18772				setTimeout(function () {
18773					$currentSlide
18774						.removeClass('lg-start-end-progress lg-start-progress')
18775						.removeAttr('style');
18776				}, this.settings.startAnimationDuration + 100);
18777				if (!$currentSlide.hasClass('lg-loaded')) {
18778					setTimeout(function () {
18779						if (_this.getSlideType(currentGalleryItem) === 'image') {
18780							var alt = currentGalleryItem.alt;
18781							var altAttr = alt ? 'alt="' + alt + '"' : '';
18782							$currentSlide
18783								.find('.lg-img-wrap')
18784								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
18785							if (srcset || sources) {
18786								var $img = $currentSlide.find('.lg-object');
18787								_this.initPictureFill($img);
18788							}
18789						}
18790						if (_this.getSlideType(currentGalleryItem) === 'image' ||
18791							(_this.getSlideType(currentGalleryItem) === 'video' &&
18792								poster)) {
18793							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18794							// load remaining slides once the slide is completely loaded
18795							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18796								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18797							}, function () {
18798								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18799							});
18800						}
18801					}, this.settings.startAnimationDuration + 100);
18802				}
18803			}
18804			// SLide content has been added to dom
18805			$currentSlide.addClass('lg-loaded');
18806			if (!this.isFirstSlideWithZoomAnimation() ||
18807				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18808				//Uncode edit ##START##
18809				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18810				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.getSlideType(currentGalleryItem) === 'audio'));
18811				//Uncode edit ##END##
18812			}
18813			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18814			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18815				$currentSlide.hasClass('lg-complete_') &&
18816				!this.lGalleryOn) {
18817				setTimeout(function () {
18818					$currentSlide.addClass('lg-complete');
18819				}, this.settings.backdropDuration);
18820			}
18821			// Content loaded
18822			// Need to set lGalleryOn before calling preload function
18823			this.lGalleryOn = true;
18824			if (rec === true) {
18825				if (!$currentSlide.hasClass('lg-complete_')) {
18826					$currentSlide
18827						.find('.lg-object')
18828						.first()
18829						.on('load.lg error.lg', function () {
18830						_this.preload(index);
18831					});
18832				}
18833				else {
18834					this.preload(index);
18835				}
18836			}
18837		};
18838		/**
18839		 * @desc Remove dummy image content and load next slides
18840		 * Called only for the first time if zoomFromOrigin animation is enabled
18841		 * @param index
18842		 * @param $currentSlide
18843		 * @param speed
18844		 */
18845		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18846			var _this = this;
18847			setTimeout(function () {
18848				$currentSlide.find('.lg-dummy-img').remove();
18849				$currentSlide.removeClass('lg-first-slide');
18850				_this.outer.removeClass('lg-first-slide-loading');
18851				_this.isDummyImageRemoved = true;
18852				_this.preload(index);
18853			}, speed + 300);
18854		};
18855		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18856			var _this = this;
18857			if (numberOfItems === void 0) { numberOfItems = 0; }
18858			var itemsToBeInsertedToDom = [];
18859			// Minimum 2 items should be there
18860			var possibleNumberOfItems = Math.max(numberOfItems, 3);
18861			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18862			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18863			if (this.galleryItems.length <= 3) {
18864				this.galleryItems.forEach(function (_element, index) {
18865					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18866				});
18867				return itemsToBeInsertedToDom;
18868			}
18869			if (index < (this.galleryItems.length - 1) / 2) {
18870				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18871					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18872				}
18873				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18874				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18875					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18876				}
18877			}
18878			else {
18879				for (var idx = index; idx <= this.galleryItems.length - 1 &&
18880					idx < index + possibleNumberOfItems / 2; idx++) {
18881					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18882				}
18883				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18884				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18885					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18886				}
18887			}
18888			if (this.settings.loop) {
18889				if (index === this.galleryItems.length - 1) {
18890					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18891				}
18892				else if (index === 0) {
18893					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18894				}
18895			}
18896			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18897				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18898			}
18899			return itemsToBeInsertedToDom;
18900		};
18901		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18902			var _this = this;
18903			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18904			itemsToBeInsertedToDom.forEach(function (item) {
18905				if (_this.currentItemsInDom.indexOf(item) === -1) {
18906					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18907				}
18908			});
18909			this.currentItemsInDom.forEach(function (item) {
18910				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18911					$LG("#" + item).remove();
18912				}
18913			});
18914			return itemsToBeInsertedToDom;
18915		};
18916		/**
18917		 * Get previous index of the slide
18918		 */
18919		LightGallery.prototype.getPreviousSlideIndex = function () {
18920			var prevIndex = 0;
18921			try {
18922				var currentItemId = this.outer
18923					.find('.lg-current')
18924					.first()
18925					.attr('id');
18926				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18927			}
18928			catch (error) {
18929				prevIndex = 0;
18930			}
18931			return prevIndex;
18932		};
18933		LightGallery.prototype.setDownloadValue = function (index) {
18934			if (this.settings.download) {
18935				var currentGalleryItem = this.galleryItems[index];
18936				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18937					currentGalleryItem.downloadUrl === 'false';
18938				if (hideDownloadBtn) {
18939					this.outer.addClass('lg-hide-download');
18940				}
18941				else {
18942					var $download = this.getElementById('lg-download');
18943					this.outer.removeClass('lg-hide-download');
18944					$download.attr('href', currentGalleryItem.downloadUrl ||
18945						currentGalleryItem.src);
18946					if (currentGalleryItem.download) {
18947						//Uncode edit ##START##
18948						var currentVideo, download_url, download_name;
18949						if ( currentGalleryItem.video ) {
18950							currentVideo = JSON.parse( currentGalleryItem.video );
18951							download_name = currentVideo.source[0].src;
18952							$download.attr('href', download_name).removeAttr('download');
18953						} else {
18954							download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src;
18955							download_name = download_url.substring(download_url.lastIndexOf('/')+1);
18956							$download.attr('download', download_name).removeAttr('href');
18957						}
18958						// $download.attr('download', currentGalleryItem.download);
18959						//Uncode edit ##END##
18960					}
18961				}
18962			}
18963		};
18964		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
18965			var _this = this;
18966			if (this.lGalleryOn) {
18967				previousSlideItem.addClass('lg-slide-progress');
18968			}
18969			setTimeout(function () {
18970				// remove all transitions
18971				_this.outer.addClass('lg-no-trans');
18972				_this.outer
18973					.find('.lg-item')
18974					.removeClass('lg-prev-slide lg-next-slide');
18975				if (direction === 'prev') {
18976					//prevslide
18977					currentSlideItem.addClass('lg-prev-slide');
18978					previousSlideItem.addClass('lg-next-slide');
18979				}
18980				else {
18981					// next slide
18982					currentSlideItem.addClass('lg-next-slide');
18983					previousSlideItem.addClass('lg-prev-slide');
18984				}
18985				// give 50 ms for browser to add/remove class
18986				setTimeout(function () {
18987					_this.outer.find('.lg-item').removeClass('lg-current');
18988					currentSlideItem.addClass('lg-current');
18989					// reset all transitions
18990					_this.outer.removeClass('lg-no-trans');
18991				}, 50);
18992			}, this.lGalleryOn ? this.settings.slideDelay : 0);
18993		};
18994		/**
18995		 * Goto a specific slide.
18996		 * @param {Number} index - index of the slide
18997		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
18998		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
18999		 * @param {String} direction - Direction of the slide(next/prev)
19000		 * @category lGPublicMethods
19001		 * @example
19002		 *  const plugin = lightGallery();
19003		 *  // to go to 3rd slide
19004		 *  plugin.slide(2);
19005		 *
19006		 */
19007		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
19008			var _this = this;
19009			var prevIndex = this.getPreviousSlideIndex();
19010			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
19011			// Prevent multiple call, Required for hsh plugin
19012			if (this.lGalleryOn && prevIndex === index) {
19013				return;
19014			}
19015			var numberOfGalleryItems = this.galleryItems.length;
19016			if (!this.lgBusy) {
19017				if (this.settings.counter) {
19018					this.updateCurrentCounter(index);
19019				}
19020				var currentSlideItem = this.getSlideItem(index);
19021				var previousSlideItem_1 = this.getSlideItem(prevIndex);
19022				var currentGalleryItem = this.galleryItems[index];
19023				var videoInfo = currentGalleryItem.__slideVideoInfo;
19024				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
19025				this.setDownloadValue(index);
19026				if (videoInfo) {
19027					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
19028					//Uncode edit ##START##
19029					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19030					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
19031					//Uncode edit ##END##
19032					this.resizeVideoSlide(index, videoSize);
19033				}
19034				this.LGel.trigger(lGEvents.beforeSlide, {
19035					prevIndex: prevIndex,
19036					index: index,
19037					fromTouch: !!fromTouch,
19038					fromThumb: !!fromThumb,
19039					//Uncode edit ##START##
19040					currentSlide: currentSlideItem,
19041					previousSlide: previousSlideItem_1,
19042					info: currentGalleryItem,
19043					item: this.items[index]
19044					//Uncode edit ##END##
19045				});
19046				this.lgBusy = true;
19047				clearTimeout(this.hideBarTimeout);
19048				this.arrowDisable(index);
19049				if (!direction) {
19050					if (index < prevIndex) {
19051						direction = 'prev';
19052					}
19053					else if (index > prevIndex) {
19054						direction = 'next';
19055					}
19056				}
19057				if (!fromTouch) {
19058					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
19059				}
19060				else {
19061					this.outer
19062						.find('.lg-item')
19063						.removeClass('lg-prev-slide lg-current lg-next-slide');
19064					var touchPrev = void 0;
19065					var touchNext = void 0;
19066					if (numberOfGalleryItems > 2) {
19067						touchPrev = index - 1;
19068						touchNext = index + 1;
19069						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
19070							// next slide
19071							touchNext = 0;
19072							touchPrev = numberOfGalleryItems - 1;
19073						}
19074						else if (index === numberOfGalleryItems - 1 &&
19075							prevIndex === 0) {
19076							// prev slide
19077							touchNext = 0;
19078							touchPrev = numberOfGalleryItems - 1;
19079						}
19080					}
19081					else {
19082						touchPrev = 0;
19083						touchNext = 1;
19084					}
19085					if (direction === 'prev') {
19086						this.getSlideItem(touchNext).addClass('lg-next-slide');
19087					}
19088					else {
19089						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
19090					}
19091					currentSlideItem.addClass('lg-current');
19092				}
19093				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
19094				if (!this.lGalleryOn) {
19095					this.loadContent(index, true);
19096				}
19097				else {
19098					setTimeout(function () {
19099						_this.loadContent(index, true);
19100						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
19101						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
19102							_this.addHtml(index);
19103						}
19104					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
19105				}
19106				setTimeout(function () {
19107					_this.lgBusy = false;
19108					previousSlideItem_1.removeClass('lg-slide-progress');
19109					_this.LGel.trigger(lGEvents.afterSlide, {
19110						prevIndex: prevIndex,
19111						index: index,
19112						fromTouch: fromTouch,
19113						fromThumb: fromThumb,
19114					});
19115				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
19116			}
19117			this.index = index;
19118		};
19119		LightGallery.prototype.updateCurrentCounter = function (index) {
19120			this.getElementById('lg-counter-current').html(index + 1 + '');
19121		};
19122		LightGallery.prototype.updateCounterTotal = function () {
19123			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
19124		};
19125		LightGallery.prototype.getSlideType = function (item) {
19126			if (item.__slideVideoInfo) {
19127				return 'video';
19128			}
19129			else if (item.iframe) {
19130				return 'iframe';
19131			}
19132			//Uncode edit ##START##
19133			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
19134				return 'audio';
19135			}
19136			//Uncode edit ##END##
19137			else {
19138				return 'image';
19139			}
19140		};
19141		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
19142			var distanceX = endCoords.pageX - startCoords.pageX;
19143			var distanceY = endCoords.pageY - startCoords.pageY;
19144			var allowSwipe = false;
19145			if (this.swipeDirection) {
19146				allowSwipe = true;
19147			}
19148			else {
19149				if (Math.abs(distanceX) > 15) {
19150					this.swipeDirection = 'horizontal';
19151					allowSwipe = true;
19152				}
19153				else if (Math.abs(distanceY) > 15) {
19154					this.swipeDirection = 'vertical';
19155					allowSwipe = true;
19156				}
19157			}
19158			if (!allowSwipe) {
19159				return;
19160			}
19161			var $currentSlide = this.getSlideItem(this.index);
19162			if (this.swipeDirection === 'horizontal') {
19163				e === null || e === void 0 ? void 0 : e.preventDefault();
19164				// reset opacity and transition duration
19165				this.outer.addClass('lg-dragging');
19166				// move current slide
19167				this.setTranslate($currentSlide, distanceX, 0);
19168				// move next and prev slide with current slide
19169				var width = $currentSlide.get().offsetWidth;
19170				var slideWidthAmount = (width * 15) / 100;
19171				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
19172				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
19173				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
19174			}
19175			else if (this.swipeDirection === 'vertical') {
19176				if (this.settings.swipeToClose) {
19177					e === null || e === void 0 ? void 0 : e.preventDefault();
19178					this.$container.addClass('lg-dragging-vertical');
19179					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
19180					this.$backdrop.css('opacity', opacity);
19181					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
19182					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
19183					if (Math.abs(distanceY) > 100) {
19184						this.outer
19185							.addClass('lg-hide-items')
19186							.removeClass('lg-components-open');
19187					}
19188				}
19189			}
19190		};
19191		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
19192			var _this = this;
19193			var distance;
19194			// keep slide animation for any mode while dragg/swipe
19195			if (this.settings.mode !== 'lg-slide') {
19196				this.outer.addClass('lg-slide');
19197			}
19198			// set transition duration
19199			setTimeout(function () {
19200				_this.$container.removeClass('lg-dragging-vertical');
19201				_this.outer
19202					.removeClass('lg-dragging lg-hide-items')
19203					.addClass('lg-components-open');
19204				var triggerClick = true;
19205				if (_this.swipeDirection === 'horizontal') {
19206					distance = endCoords.pageX - startCoords.pageX;
19207					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
19208					if (distance < 0 &&
19209						distanceAbs > _this.settings.swipeThreshold) {
19210						_this.goToNextSlide(true);
19211						triggerClick = false;
19212					}
19213					else if (distance > 0 &&
19214						distanceAbs > _this.settings.swipeThreshold) {
19215						_this.goToPrevSlide(true);
19216						triggerClick = false;
19217					}
19218				}
19219				else if (_this.swipeDirection === 'vertical') {
19220					distance = Math.abs(endCoords.pageY - startCoords.pageY);
19221					if (_this.settings.closable &&
19222						_this.settings.swipeToClose &&
19223						distance > 100) {
19224						_this.closeGallery();
19225						return;
19226					}
19227					else {
19228						_this.$backdrop.css('opacity', 1);
19229					}
19230				}
19231				_this.outer.find('.lg-item').removeAttr('style');
19232				if (triggerClick &&
19233					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
19234					// Trigger click if distance is less than 5 pix
19235					var target = $LG(event.target);
19236					if (_this.isPosterElement(target)) {
19237						_this.LGel.trigger(lGEvents.posterClick);
19238					}
19239				}
19240				_this.swipeDirection = undefined;
19241			});
19242			// remove slide class once drag/swipe is completed if mode is not slide
19243			setTimeout(function () {
19244				if (!_this.outer.hasClass('lg-dragging') &&
19245					_this.settings.mode !== 'lg-slide') {
19246					_this.outer.removeClass('lg-slide');
19247				}
19248			}, this.settings.speed + 100);
19249		};
19250		LightGallery.prototype.enableSwipe = function () {
19251			var _this = this;
19252			var startCoords = {};
19253			var endCoords = {};
19254			var isMoved = false;
19255			var isSwiping = false;
19256			if (this.settings.enableSwipe) {
19257				this.$inner.on('touchstart.lg', function (e) {
19258					_this.dragOrSwipeEnabled = true;
19259					var $item = _this.getSlideItem(_this.index);
19260					if (($LG(e.target).hasClass('lg-item') ||
19261						$item.get().contains(e.target)) &&
19262						!_this.outer.hasClass('lg-zoomed') &&
19263						!_this.lgBusy &&
19264						e.targetTouches.length === 1) {
19265						isSwiping = true;
19266						_this.touchAction = 'swipe';
19267						_this.manageSwipeClass();
19268						startCoords = {
19269							pageX: e.targetTouches[0].pageX,
19270							pageY: e.targetTouches[0].pageY,
19271						};
19272					}
19273				});
19274				this.$inner.on('touchmove.lg', function (e) {
19275					if (isSwiping &&
19276						_this.touchAction === 'swipe' &&
19277						e.targetTouches.length === 1) {
19278						endCoords = {
19279							pageX: e.targetTouches[0].pageX,
19280							pageY: e.targetTouches[0].pageY,
19281						};
19282						_this.touchMove(startCoords, endCoords, e);
19283						isMoved = true;
19284					}
19285				});
19286				this.$inner.on('touchend.lg', function (event) {
19287					if (_this.touchAction === 'swipe') {
19288						if (isMoved) {
19289							isMoved = false;
19290							_this.touchEnd(endCoords, startCoords, event);
19291						}
19292						else if (isSwiping) {
19293							var target = $LG(event.target);
19294							if (_this.isPosterElement(target)) {
19295								_this.LGel.trigger(lGEvents.posterClick);
19296							}
19297						}
19298						_this.touchAction = undefined;
19299						isSwiping = false;
19300					}
19301				});
19302			}
19303		};
19304		LightGallery.prototype.enableDrag = function () {
19305			var _this = this;
19306			var startCoords = {};
19307			var endCoords = {};
19308			var isDraging = false;
19309			var isMoved = false;
19310			if (this.settings.enableDrag) {
19311				this.outer.on('mousedown.lg', function (e) {
19312					_this.dragOrSwipeEnabled = true;
19313					var $item = _this.getSlideItem(_this.index);
19314					if ($LG(e.target).hasClass('lg-item') ||
19315						$item.get().contains(e.target)) {
19316						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
19317							e.preventDefault();
19318							if (!_this.lgBusy) {
19319								_this.manageSwipeClass();
19320								startCoords = {
19321									pageX: e.pageX,
19322									pageY: e.pageY,
19323								};
19324								isDraging = true;
19325								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
19326								_this.outer.get().scrollLeft += 1;
19327								_this.outer.get().scrollLeft -= 1;
19328								// *
19329								_this.outer
19330									.removeClass('lg-grab')
19331									.addClass('lg-grabbing');
19332								_this.LGel.trigger(lGEvents.dragStart);
19333							}
19334						}
19335					}
19336				});
19337				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
19338					if (isDraging && _this.lgOpened) {
19339						isMoved = true;
19340						endCoords = {
19341							pageX: e.pageX,
19342							pageY: e.pageY,
19343						};
19344						_this.touchMove(startCoords, endCoords);
19345						_this.LGel.trigger(lGEvents.dragMove);
19346					}
19347				});
19348				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
19349					if (!_this.lgOpened) {
19350						return;
19351					}
19352					var target = $LG(event.target);
19353					if (isMoved) {
19354						isMoved = false;
19355						_this.touchEnd(endCoords, startCoords, event);
19356						_this.LGel.trigger(lGEvents.dragEnd);
19357					}
19358					else if (_this.isPosterElement(target)) {
19359						_this.LGel.trigger(lGEvents.posterClick);
19360					}
19361					// Prevent execution on click
19362					if (isDraging) {
19363						isDraging = false;
19364						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
19365					}
19366				});
19367			}
19368		};
19369		LightGallery.prototype.triggerPosterClick = function () {
19370			var _this = this;
19371			this.$inner.on('click.lg', function (event) {
19372				if (!_this.dragOrSwipeEnabled &&
19373					_this.isPosterElement($LG(event.target))) {
19374					_this.LGel.trigger(lGEvents.posterClick);
19375				}
19376			});
19377		};
19378		LightGallery.prototype.manageSwipeClass = function () {
19379			var _touchNext = this.index + 1;
19380			var _touchPrev = this.index - 1;
19381			if (this.settings.loop && this.galleryItems.length > 2) {
19382				if (this.index === 0) {
19383					_touchPrev = this.galleryItems.length - 1;
19384				}
19385				else if (this.index === this.galleryItems.length - 1) {
19386					_touchNext = 0;
19387				}
19388			}
19389			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
19390			if (_touchPrev > -1) {
19391				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
19392			}
19393			this.getSlideItem(_touchNext).addClass('lg-next-slide');
19394		};
19395		/**
19396		 * Go to next slide
19397		 * @param {Boolean} fromTouch - true if slide function called via touch event
19398		 * @category lGPublicMethods
19399		 * @example
19400		 *  const plugin = lightGallery();
19401		 *  plugin.goToNextSlide();
19402		 * @see <a href="/demos/methods/">Demo</a>
19403		 */
19404		LightGallery.prototype.goToNextSlide = function (fromTouch) {
19405			var _this = this;
19406			var _loop = this.settings.loop;
19407			if (fromTouch && this.galleryItems.length < 3) {
19408				_loop = false;
19409			}
19410			if (!this.lgBusy) {
19411				if (this.index + 1 < this.galleryItems.length) {
19412					this.index++;
19413					this.LGel.trigger(lGEvents.beforeNextSlide, {
19414						index: this.index,
19415					});
19416					this.slide(this.index, !!fromTouch, false, 'next');
19417				}
19418				else {
19419					if (_loop) {
19420						this.index = 0;
19421						this.LGel.trigger(lGEvents.beforeNextSlide, {
19422							index: this.index,
19423						});
19424						this.slide(this.index, !!fromTouch, false, 'next');
19425					}
19426					else if (this.settings.slideEndAnimation && !fromTouch) {
19427						this.outer.addClass('lg-right-end');
19428						setTimeout(function () {
19429							_this.outer.removeClass('lg-right-end');
19430						}, 400);
19431					}
19432				}
19433			}
19434		};
19435		/**
19436		 * Go to previous slides
19437		 * @param {Boolean} fromTouch - true if slide function called via touch event
19438		 * @category lGPublicMethods
19439		 * @example
19440		 *  const plugin = lightGallery({});
19441		 *  plugin.goToPrevSlide();
19442		 * @see <a href="/demos/methods/">Demo</a>
19443		 *
19444		 */
19445		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
19446			var _this = this;
19447			var _loop = this.settings.loop;
19448			if (fromTouch && this.galleryItems.length < 3) {
19449				_loop = false;
19450			}
19451			if (!this.lgBusy) {
19452				if (this.index > 0) {
19453					this.index--;
19454					this.LGel.trigger(lGEvents.beforePrevSlide, {
19455						index: this.index,
19456						fromTouch: fromTouch,
19457					});
19458					this.slide(this.index, !!fromTouch, false, 'prev');
19459				}
19460				else {
19461					if (_loop) {
19462						this.index = this.galleryItems.length - 1;
19463						this.LGel.trigger(lGEvents.beforePrevSlide, {
19464							index: this.index,
19465							fromTouch: fromTouch,
19466						});
19467						this.slide(this.index, !!fromTouch, false, 'prev');
19468					}
19469					else if (this.settings.slideEndAnimation && !fromTouch) {
19470						this.outer.addClass('lg-left-end');
19471						setTimeout(function () {
19472							_this.outer.removeClass('lg-left-end');
19473						}, 400);
19474					}
19475				}
19476			}
19477		};
19478		LightGallery.prototype.keyPress = function () {
19479			var _this = this;
19480			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19481				if (_this.lgOpened &&
19482					_this.settings.escKey === true &&
19483					e.keyCode === 27) {
19484					e.preventDefault();
19485					if (_this.settings.allowMediaOverlap &&
19486						_this.outer.hasClass('lg-can-toggle') &&
19487						_this.outer.hasClass('lg-components-open')) {
19488						_this.outer.removeClass('lg-components-open');
19489					}
19490					else {
19491						_this.closeGallery();
19492					}
19493				}
19494				if (_this.lgOpened && _this.galleryItems.length > 1) {
19495					if (e.keyCode === 37) {
19496						e.preventDefault();
19497						_this.goToPrevSlide();
19498					}
19499					if (e.keyCode === 39) {
19500						e.preventDefault();
19501						_this.goToNextSlide();
19502					}
19503				}
19504			});
19505		};
19506		LightGallery.prototype.arrow = function () {
19507			var _this = this;
19508			this.getElementById('lg-prev').on('click.lg', function () {
19509				_this.goToPrevSlide();
19510			});
19511			this.getElementById('lg-next').on('click.lg', function () {
19512				_this.goToNextSlide();
19513			});
19514		};
19515		LightGallery.prototype.arrowDisable = function (index) {
19516			// Disable arrows if settings.hideControlOnEnd is true
19517			if (!this.settings.loop && this.settings.hideControlOnEnd) {
19518				var $prev = this.getElementById('lg-prev');
19519				var $next = this.getElementById('lg-next');
19520				if (index + 1 === this.galleryItems.length) {
19521					$next.attr('disabled', 'disabled').addClass('disabled');
19522				}
19523				else {
19524					$next.removeAttr('disabled').removeClass('disabled');
19525				}
19526				if (index === 0) {
19527					$prev.attr('disabled', 'disabled').addClass('disabled');
19528				}
19529				else {
19530					$prev.removeAttr('disabled').removeClass('disabled');
19531				}
19532			}
19533		};
19534		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
19535			if (scaleX === void 0) { scaleX = 1; }
19536			if (scaleY === void 0) { scaleY = 1; }
19537			$el.css('transform', 'translate3d(' +
19538				xValue +
19539				'px, ' +
19540				yValue +
19541				'px, 0px) scale3d(' +
19542				scaleX +
19543				', ' +
19544				scaleY +
19545				', 1)');
19546		};
19547		LightGallery.prototype.mousewheel = function () {
19548			var _this = this;
19549			var lastCall = 0;
19550			this.outer.on('wheel.lg', function (e) {
19551				if (!e.deltaY || _this.galleryItems.length < 2) {
19552					return;
19553				}
19554				e.preventDefault();
19555				var now = new Date().getTime();
19556				if (now - lastCall < 1000) {
19557					return;
19558				}
19559				lastCall = now;
19560				if (e.deltaY > 0) {
19561					_this.goToNextSlide();
19562				}
19563				else if (e.deltaY < 0) {
19564					_this.goToPrevSlide();
19565				}
19566			});
19567		};
19568		LightGallery.prototype.isSlideElement = function (target) {
19569			return (target.hasClass('lg-outer') ||
19570				target.hasClass('lg-item') ||
19571				target.hasClass('lg-img-wrap'));
19572		};
19573		LightGallery.prototype.isPosterElement = function (target) {
19574			var playButton = this.getSlideItem(this.index)
19575				.find('.lg-video-play-button')
19576				.get();
19577			return (target.hasClass('lg-video-poster') ||
19578				target.hasClass('lg-video-play-button') ||
19579				(playButton && playButton.contains(target.get())));
19580		};
19581		/**
19582		 * Maximize minimize inline gallery.
19583		 * @category lGPublicMethods
19584		 */
19585		LightGallery.prototype.toggleMaximize = function () {
19586			var _this = this;
19587			this.getElementById('lg-maximize').on('click.lg', function () {
19588				_this.$container.toggleClass('lg-inline');
19589				_this.refreshOnResize();
19590			});
19591		};
19592		LightGallery.prototype.invalidateItems = function () {
19593			for (var index = 0; index < this.items.length; index++) {
19594				var element = this.items[index];
19595				var $element = $LG(element);
19596				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
19597			}
19598		};
19599		LightGallery.prototype.trapFocus = function () {
19600			var _this = this;
19601			this.$container.get().focus({
19602				preventScroll: true,
19603			});
19604			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19605				if (!_this.lgOpened) {
19606					return;
19607				}
19608				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
19609				if (!isTabPressed) {
19610					return;
19611				}
19612				var focusableEls = utils.getFocusableElements(_this.$container.get());
19613				var firstFocusableEl = focusableEls[0];
19614				var lastFocusableEl = focusableEls[focusableEls.length - 1];
19615				if (e.shiftKey) {
19616					if (document.activeElement === firstFocusableEl) {
19617						lastFocusableEl.focus();
19618						e.preventDefault();
19619					}
19620				}
19621				else {
19622					if (document.activeElement === lastFocusableEl) {
19623						firstFocusableEl.focus();
19624						e.preventDefault();
19625					}
19626				}
19627			});
19628		};
19629		LightGallery.prototype.manageCloseGallery = function () {
19630			var _this = this;
19631			if (!this.settings.closable)
19632				return;
19633			var mousedown = false;
19634			this.getElementById('lg-close').on('click.lg', function () {
19635				_this.closeGallery();
19636			});
19637			if (this.settings.closeOnTap) {
19638				// If you drag the slide and release outside gallery gets close on chrome
19639				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
19640				this.outer.on('mousedown.lg', function (e) {
19641					var target = $LG(e.target);
19642					if (_this.isSlideElement(target)) {
19643						mousedown = true;
19644					}
19645					else {
19646						mousedown = false;
19647					}
19648				});
19649				this.outer.on('mousemove.lg', function () {
19650					mousedown = false;
19651				});
19652				this.outer.on('mouseup.lg', function (e) {
19653					var target = $LG(e.target);
19654					if (_this.isSlideElement(target) && mousedown) {
19655						if (!_this.outer.hasClass('lg-dragging')) {
19656							_this.closeGallery();
19657						}
19658					}
19659				});
19660			}
19661		};
19662		/**
19663		 * Close lightGallery if it is opened.
19664		 *
19665		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
19666		 * @return returns the estimated time to close gallery completely including the close animation duration
19667		 * @category lGPublicMethods
19668		 * @example
19669		 *  const plugin = lightGallery();
19670		 *  plugin.closeGallery();
19671		 *
19672		 */
19673		LightGallery.prototype.closeGallery = function (force) {
19674			var _this = this;
19675			if (!this.lgOpened || (!this.settings.closable && !force)) {
19676				return 0;
19677			}
19678			this.LGel.trigger(lGEvents.beforeClose);
19679			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
19680				$LG(window).scrollTop(this.prevScrollTop);
19681			}
19682			var currentItem = this.items[this.index];
19683			var transform;
19684			if (this.zoomFromOrigin && currentItem) {
19685				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
19686				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
19687				//Uncode edit ##START##
19688				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
19689				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
19690				//Uncode edit ##END##
19691				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
19692			}
19693			if (this.zoomFromOrigin && transform) {
19694				this.outer.addClass('lg-closing lg-zoom-from-image');
19695				this.getSlideItem(this.index)
19696					.addClass('lg-start-end-progress')
19697					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
19698					.css('transform', transform);
19699			}
19700			else {
19701				this.outer.addClass('lg-hide-items');
19702				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
19703				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
19704				this.outer.removeClass('lg-zoom-from-image');
19705			}
19706			// Unbind all events added by lightGallery
19707			// @todo
19708			//this.$el.off('.lg.tm');
19709			this.destroyModules();
19710			this.lGalleryOn = false;
19711			this.isDummyImageRemoved = false;
19712			this.zoomFromOrigin = this.settings.zoomFromOrigin;
19713			clearTimeout(this.hideBarTimeout);
19714			this.hideBarTimeout = false;
19715			$LG('html').removeClass('lg-on');
19716			this.outer.removeClass('lg-visible lg-components-open');
19717			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
19718			this.$backdrop.removeClass('in').css('opacity', 0);
19719			var removeTimeout = this.zoomFromOrigin && transform
19720				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
19721				: this.settings.backdropDuration;
19722			this.$container.removeClass('lg-show-in');
19723			// Once the closign animation is completed and gallery is invisible
19724			setTimeout(function () {
19725				if (_this.zoomFromOrigin && transform) {
19726					_this.outer.removeClass('lg-zoom-from-image');
19727				}
19728				_this.$container.removeClass('lg-show');
19729				// Reset scrollbar
19730				_this.resetScrollBar();
19731				// Need to remove inline opacity as it is used in the stylesheet as well
19732				_this.$backdrop
19733					.removeAttr('style')
19734					.css('transition-duration', _this.settings.backdropDuration + 'ms');
19735				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 19736-19939
19736				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
19737				_this.$inner.empty();
19738				if (_this.lgOpened) {
19739					_this.LGel.trigger(lGEvents.afterClose, {
19740						instance: _this,
19741					});
19742				}
19743				if (_this.$container.get()) {
19744					_this.$container.get().blur();
19745				}
19746				_this.lgOpened = false;
19747			}, removeTimeout + 100);
19748			return removeTimeout + 100;
19749		};
19750		LightGallery.prototype.initModules = function () {
19751			this.plugins.forEach(function (module) {
19752				try {
19753					module.init();
19754				}
19755				catch (err) {
19756					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
19757				}
19758			});
19759		};
19760		LightGallery.prototype.destroyModules = function (destroy) {
19761			this.plugins.forEach(function (module) {
19762				try {
19763					if (destroy) {
19764						module.destroy();
19765					}
19766					else {
19767						module.closeGallery && module.closeGallery();
19768					}
19769				}
19770				catch (err) {
19771					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19772				}
19773			});
19774		};
19775		/**
19776		 * Refresh lightGallery with new set of children.
19777		 *
19778		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19779		 *
19780		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19781		 * @see <a href="/demos/dynamic-mode/">Demo</a>
19782		 * @category lGPublicMethods
19783		 * @example
19784		 *  const plugin = lightGallery();
19785		 *  // Delete or add children, then call
19786		 *  plugin.refresh();
19787		 *
19788		 */
19789		LightGallery.prototype.refresh = function (galleryItems) {
19790			if (!this.settings.dynamic) {
19791				this.invalidateItems();
19792			}
19793			if (galleryItems) {
19794				this.galleryItems = galleryItems;
19795			}
19796			else {
19797				this.galleryItems = this.getItems();
19798			}
19799			this.updateControls();
19800			this.openGalleryOnItemClick();
19801			this.LGel.trigger(lGEvents.updateSlides);
19802		};
19803		LightGallery.prototype.updateControls = function () {
19804			this.addSlideVideoInfo(this.galleryItems);
19805			this.updateCounterTotal();
19806			this.manageSingleSlideClassName();
19807		};
19808		/**
19809		 * Destroy lightGallery.
19810		 * Destroy lightGallery and its plugin instances completely
19811		 *
19812		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19813		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19814		 * You can use refresh method most of the times.
19815		 * @category lGPublicMethods
19816		 * @example
19817		 *  const plugin = lightGallery();
19818		 *  plugin.destroy();
19819		 *
19820		 */
19821		LightGallery.prototype.destroy = function () {
19822			var _this = this;
19823			var closeTimeout = this.closeGallery(true);
19824			setTimeout(function () {
19825				_this.destroyModules(true);
19826				if (!_this.settings.dynamic) {
19827					_this.invalidateItems();
19828				}
19829				$LG(window).off(".lg.global" + _this.lgId);
19830				_this.LGel.off('.lg');
19831				_this.$container.remove();
19832			}, closeTimeout);
19833			return closeTimeout;
19834		};
19835		return LightGallery;
19836	}());
19837
19838	function lightGallery(el, options) {
19839		return new LightGallery(el, options);
19840	}
19841
19842	return lightGallery;
19843
19844})));
19845
19846/*!
19847 * lightgallery | 2.5.0 | June 13th 2022
19848 * http://www.lightgalleryjs.com/
19849 * Copyright (c) 2020 Sachin Neravath;
19850 * @license GPLv3
19851 */
19852
19853(function (global, factory) {
19854	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19855	typeof define === 'function' && define.amd ? define(factory) :
19856	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19857}(this, (function () { 'use strict';
19858
19859	/*! *****************************************************************************
19860	Copyright (c) Microsoft Corporation.
19861
19862	Permission to use, copy, modify, and/or distribute this software for any
19863	purpose with or without fee is hereby granted.
19864
19865	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19866	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19867	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19868	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19869	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19870	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19871	PERFORMANCE OF THIS SOFTWARE.
19872	***************************************************************************** */
19873
19874	var __assign = function() {
19875		__assign = Object.assign || function __assign(t) {
19876			for (var s, i = 1, n = arguments.length; i < n; i++) {
19877				s = arguments[i];
19878				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19879			}
19880			return t;
19881		};
19882		return __assign.apply(this, arguments);
19883	};
19884
19885	var zoomSettings = {
19886		scale: 1,
19887		zoom: true,
19888		actualSize: true,
19889		showZoomInOutIcons: false,
19890		actualSizeIcons: {
19891			zoomIn: 'lg-zoom-in',
19892			zoomOut: 'lg-zoom-out',
19893		},
19894		enableZoomAfter: 300,
19895		zoomPluginStrings: {
19896			zoomIn: 'Zoom in',
19897			zoomOut: 'Zoom out',
19898			viewActualSize: 'View actual size',
19899		},
19900	};
19901
19902	/**
19903	 * List of lightGallery events
19904	 * All events should be documented here
19905	 * Below interfaces are used to build the website documentations
19906	 * */
19907	var lGEvents = {
19908		afterAppendSlide: 'lgAfterAppendSlide',
19909		init: 'lgInit',
19910		hasVideo: 'lgHasVideo',
19911		containerResize: 'lgContainerResize',
19912		updateSlides: 'lgUpdateSlides',
19913		afterAppendSubHtml: 'lgAfterAppendSubHtml',
19914		beforeOpen: 'lgBeforeOpen',
19915		afterOpen: 'lgAfterOpen',
19916		slideItemLoad: 'lgSlideItemLoad',
19917		beforeSlide: 'lgBeforeSlide',
19918		afterSlide: 'lgAfterSlide',
19919		posterClick: 'lgPosterClick',
19920		dragStart: 'lgDragStart',
19921		dragMove: 'lgDragMove',
19922		dragEnd: 'lgDragEnd',
19923		beforeNextSlide: 'lgBeforeNextSlide',
19924		beforePrevSlide: 'lgBeforePrevSlide',
19925		beforeClose: 'lgBeforeClose',
19926		afterClose: 'lgAfterClose',
19927		rotateLeft: 'lgRotateLeft',
19928		rotateRight: 'lgRotateRight',
19929		flipHorizontal: 'lgFlipHorizontal',
19930		flipVertical: 'lgFlipVertical',
19931		autoplay: 'lgAutoplay',
19932		autoplayStart: 'lgAutoplayStart',
19933		autoplayStop: 'lgAutoplayStop',
19934	};
19935
19936	var Zoom = /** @class */ (function () {
19937		function Zoom(instance, $LG) {
19938			// get lightGallery core plugin instance
19939			this.core = instance;
19940			this.$LG = $LG;
19941			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19942			return this;
19943		}
19944		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
19945		Zoom.prototype.buildTemplates = function () {
19946			var zoomIcons = this.settings.showZoomInOutIcons
19947				? "<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>"
19948				: '';
19949			if (this.settings.actualSize) {
19950				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>";
19951			}
19952			this.core.outer.addClass('lg-use-transition-for-zoom');
19953			this.core.$toolbar.first().append(zoomIcons);
19954		};
19955		/**
19956		 * @desc Enable zoom option only once the image is completely loaded
19957		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
19958		 *
19959		 * Zoom styles are defined under lg-zoomable CSS class.
19960		 */
19961		Zoom.prototype.enableZoom = function (event) {
19962			var _this = this;
19963			// delay will be 0 except first time
19964			var _speed = this.settings.enableZoomAfter + event.detail.delay;
19965			// set _speed value 0 if gallery opened from direct url and if it is first slide
19966			if (this.$LG('body').first().hasClass('lg-from-hash') &&
19967				event.detail.delay) {
19968				// will execute only once
19969				_speed = 0;
19970			}
19971			else {
19972				// Remove lg-from-hash to enable starting animation.
19973				this.$LG('body').first().removeClass('lg-from-hash');
19974			}
19975			this.zoomableTimeout = setTimeout(function () {
19976				if (!_this.isImageSlide()) {
19977					return;
19978				}
19979				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
19980				if (event.detail.index === _this.core.index) {
19981					_this.setZoomEssentials();
19982				}
19983			}, _speed + 30);
19984		};
19985		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
19986			// Add zoomable class
19987			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
19988		};
19989		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
19990			var originalRotate = rotateValue;
19991			rotateValue = Math.abs(rotateValue);
19992			var transformValues = this.getCurrentTransform(el);
19993			if (!transformValues) {
19994				return 1;
19995			}
19996			var modifier = 1;
19997			if (axis === 'X') {
19998				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
19999				if (rotateValue === 0 || rotateValue === 180) {
20000					modifier = 1;
20001				}
20002				else if (rotateValue === 90) {
20003					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
20004						(originalRotate === 90 && flipHorizontalValue === -1)) {
20005						modifier = -1;
20006					}
20007					else {
20008						modifier = 1;
20009					}
20010				}
20011				modifier = modifier * flipHorizontalValue;
20012			}
20013			else {
20014				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
20015				if (rotateValue === 0 || rotateValue === 180) {
20016					modifier = 1;
20017				}
20018				else if (rotateValue === 90) {
20019					var sinX = parseFloat(transformValues[1]);
20020					var sinMinusX = parseFloat(transformValues[2]);
20021					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
20022				}
20023				modifier = modifier * flipVerticalValue;
20024			}
20025			return modifier;
20026		};
20027		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
20028			var imageSizes = {
20029				y: 'offsetHeight',
20030				x: 'offsetWidth',
20031			};
20032			if (Math.abs(rotateValue) === 90) {
20033				// Swap axis
20034				if (axis === 'x') {
20035					axis = 'y';
20036				}
20037				else {
20038					axis = 'x';
20039				}
20040			}
20041			return $image[imageSizes[axis]];
20042		};
20043		Zoom.prototype.getDragCords = function (e, rotateValue) {
20044			if (rotateValue === 90) {
20045				return {
20046					x: e.pageY,
20047					y: e.pageX,
20048				};
20049			}
20050			else {
20051				return {
20052					x: e.pageX,
20053					y: e.pageY,
20054				};
20055			}
20056		};
20057		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
20058			var x = e.targetTouches[0].pageX;
20059			var y = e.targetTouches[0].pageY;
20060			if (rotateValue === 90) {
20061				return {
20062					x: y,
20063					y: x,
20064				};
20065			}
20066			else {
20067				return {
20068					x: x,
20069					y: y,
20070				};
20071			}
20072		};
20073		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
20074			scale = scale || this.scale || 1;
20075			var allowY = this.imageYSize * scale > this.containerRect.height;
20076			var allowX = this.imageXSize * scale > this.containerRect.width;
20077			if (rotateValue === 90) {
20078				return {
20079					allowX: allowY,
20080					allowY: allowX,
20081				};
20082			}
20083			else {
20084				return {
20085					allowX: allowX,
20086					allowY: allowY,
20087				};
20088			}
20089		};
20090		/**
20091		 *
20092		 * @param {Element} el
20093		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
20094		 * Get the current transform value
20095		 */
20096		Zoom.prototype.getCurrentTransform = function (el) {
20097			if (!el) {
20098				return;
20099			}
20100			var st = window.getComputedStyle(el, null);
20101			var tm = st.getPropertyValue('-webkit-transform') ||
20102				st.getPropertyValue('-moz-transform') ||
20103				st.getPropertyValue('-ms-transform') ||
20104				st.getPropertyValue('-o-transform') ||
20105				st.getPropertyValue('transform') ||
20106				'none';
20107			if (tm !== 'none') {
20108				return tm.split('(')[1].split(')')[0].split(',');
20109			}
20110			return;
20111		};
20112		Zoom.prototype.getCurrentRotation = function (el) {
20113			if (!el) {
20114				return 0;
20115			}
20116			var values = this.getCurrentTransform(el);
20117			if (values) {
20118				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
20119					(180 / Math.PI));
20120				// If you want rotate in 360
20121				//return (angle < 0 ? angle + 360 : angle);
20122			}
20123			return 0;
20124		};
20125		Zoom.prototype.setZoomEssentials = function () {
20126			var $image = this.core
20127				.getSlideItem(this.core.index)
20128				.find('.lg-image')
20129				.first();
20130			var rotateEl = this.core
20131				.getSlideItem(this.core.index)
20132				.find('.lg-img-rotate')
20133				.first()
20134				.get();
20135			this.rotateValue = this.getCurrentRotation(rotateEl);
20136			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
20137			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
20138			this.containerRect = this.core.outer.get().getBoundingClientRect();
20139			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
20140			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
20141		};
20142		/**
20143		 * @desc Image zoom
20144		 * Translate the wrap and scale the image to get better user experience
20145		 *
20146		 * @param {String} scale - Zoom decrement/increment value
20147		 */
20148		Zoom.prototype.zoomImage = function (scale) {
20149			// Find offset manually to avoid issue after zoom
20150			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
20151				this.containerRect.left;
20152			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20153			var topBottomSpacing = Math.abs(top - bottom) / 2;
20154			var offsetY = (this.containerRect.height -
20155				this.imageYSize -
20156				topBottomSpacing * this.modifierX) /
20157				2 +
20158				this.scrollTop +
20159				this.containerRect.top;
20160			var originalX;
20161			var originalY;
20162			if (scale === 1) {
20163				this.positionChanged = false;
20164			}
20165			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
20166			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
20167			if (this.positionChanged) {
20168				originalX = this.left / (this.scale - 1);
20169				originalY = this.top / (this.scale - 1);
20170				this.pageX = Math.abs(originalX) + offsetX;
20171				this.pageY = Math.abs(originalY) + offsetY;
20172				this.positionChanged = false;
20173			}
20174			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
20175			var _x = offsetX - this.pageX;
20176			var _y = offsetY - this.pageY;
20177			var x = (scale - 1) * _x;
20178			var y = (scale - 1) * _y;
20179			if (allowX) {
20180				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
20181					x = possibleSwipeCords.minX;
20182				}
20183				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
20184					x = possibleSwipeCords.maxX;
20185				}
20186			}
20187			else {
20188				if (scale > 1) {
20189					if (x < possibleSwipeCords.minX) {
20190						x = possibleSwipeCords.minX;
20191					}
20192					else if (x > possibleSwipeCords.maxX) {
20193						x = possibleSwipeCords.maxX;
20194					}
20195				}
20196			}
20197			if (allowY) {
20198				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
20199					y = possibleSwipeCords.minY;
20200				}
20201				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
20202					y = possibleSwipeCords.maxY;
20203				}
20204			}
20205			else {
20206				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
20207				if (scale > 1) {
20208					//If image goes beyond viewport top, use the minim possible translate value
20209					if (y < possibleSwipeCords.minY) {
20210						y = possibleSwipeCords.minY;
20211					}
20212					else if (y > possibleSwipeCords.maxY) {
20213						y = possibleSwipeCords.maxY;
20214					}
20215				}
20216			}
20217			this.setZoomStyles({
20218				x: x,
20219				y: y,
20220				scale: scale,
20221			});
20222		};
20223		/**
20224		 * @desc apply scale3d to image and translate to image wrap
20225		 * @param {style} X,Y and scale
20226		 */
20227		Zoom.prototype.setZoomStyles = function (style) {
20228			var $image = this.core
20229				.getSlideItem(this.core.index)
20230				.find('.lg-image')
20231				.first();
20232			var $dummyImage = this.core.outer
20233				.find('.lg-current .lg-dummy-img')
20234				.first();
20235			var $imageWrap = $image.parent();
20236			this.scale = style.scale;
20237			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20238			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20239			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
20240			$imageWrap.css('transform', transform);
20241			this.left = style.x;
20242			this.top = style.y;
20243		};
20244		/**
20245		 * @param index - Index of the current slide
20246		 * @param event - event will be available only if the function is called on clicking/taping the imags
20247		 */
20248		Zoom.prototype.setActualSize = function (index, event) {
20249			var _this = this;
20250			// Allow zoom only on image
20251			if (!this.isImageSlide() ||
20252				this.core.outer.hasClass('lg-first-slide-loading')) {
20253				return;
20254			}
20255			var scale = this.getCurrentImageActualSizeScale();
20256			if (this.core.outer.hasClass('lg-zoomed')) {
20257				this.scale = 1;
20258			}
20259			else {
20260				this.scale = this.getScale(scale);
20261			}
20262			this.setPageCords(event);
20263			this.beginZoom(this.scale);
20264			this.zoomImage(this.scale);
20265			setTimeout(function () {
20266				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20267			}, 10);
20268		};
20269		Zoom.prototype.getNaturalWidth = function (index) {
20270			var $image = this.core.getSlideItem(index).find('.lg-image').first();
20271			var naturalWidth = this.core.galleryItems[index].width;
20272			return naturalWidth
20273				? parseFloat(naturalWidth)
20274				: $image.get().naturalWidth;
20275		};
20276		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
20277			var _scale;
20278			var scale;
20279			if (naturalWidth > width) {
20280				_scale = naturalWidth / width;
20281				scale = _scale || 2;
20282			}
20283			else {
20284				scale = 1;
20285			}
20286			return scale;
20287		};
20288		Zoom.prototype.getCurrentImageActualSizeScale = function () {
20289			var $image = this.core
20290				.getSlideItem(this.core.index)
20291				.find('.lg-image')
20292				.first();
20293			var width = $image.get().offsetWidth;
20294			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
20295			return this.getActualSizeScale(naturalWidth, width);
20296		};
20297		Zoom.prototype.getPageCords = function (event) {
20298			var cords = {};
20299			if (event) {
20300				cords.x = event.pageX || event.targetTouches[0].pageX;
20301				cords.y = event.pageY || event.targetTouches[0].pageY;
20302			}
20303			else {
20304				var containerRect = this.core.outer.get().getBoundingClientRect();
20305				cords.x = containerRect.width / 2 + containerRect.left;
20306				cords.y =
20307					containerRect.height / 2 + this.scrollTop + containerRect.top;
20308			}
20309			return cords;
20310		};
20311		Zoom.prototype.setPageCords = function (event) {
20312			var pageCords = this.getPageCords(event);
20313			this.pageX = pageCords.x;
20314			this.pageY = pageCords.y;
20315		};
20316		// If true, zoomed - in else zoomed out
20317		Zoom.prototype.beginZoom = function (scale) {
20318			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20319			if (scale > 1) {
20320				this.core.outer.addClass('lg-zoomed');
20321				var $actualSize = this.core.getElementById('lg-actual-size');
20322				$actualSize
20323					.removeClass(this.settings.actualSizeIcons.zoomIn)
20324					.addClass(this.settings.actualSizeIcons.zoomOut);
20325			}
20326			else {
20327				this.resetZoom();
20328			}
20329			return scale > 1;
20330		};
20331		Zoom.prototype.getScale = function (scale) {
20332			var actualSizeScale = this.getCurrentImageActualSizeScale();
20333			if (scale < 1) {
20334				scale = 1;
20335			}
20336			else if (scale > actualSizeScale) {
20337				scale = actualSizeScale;
20338			}
20339			return scale;
20340		};
20341		Zoom.prototype.init = function () {
20342			var _this = this;
20343			if (!this.settings.zoom) {
20344				return;
20345			}
20346			this.buildTemplates();
20347			this.enableZoomOnSlideItemLoad();
20348			var tapped = null;
20349			this.core.outer.on('dblclick.lg', function (event) {
20350				if (!_this.$LG(event.target).hasClass('lg-image')) {
20351					return;
20352				}
20353				_this.setActualSize(_this.core.index, event);
20354			});
20355			this.core.outer.on('touchstart.lg', function (event) {
20356				var $target = _this.$LG(event.target);
20357				if (event.targetTouches.length === 1 &&
20358					$target.hasClass('lg-image')) {
20359					if (!tapped) {
20360						tapped = setTimeout(function () {
20361							tapped = null;
20362						}, 300);
20363					}
20364					else {
20365						clearTimeout(tapped);
20366						tapped = null;
20367						event.preventDefault();
20368						_this.setActualSize(_this.core.index, event);
20369					}
20370				}
20371			});
20372			// Update zoom on resize and orientationchange
20373			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
20374				if (!_this.core.lgOpened || !_this.isImageSlide())
20375					return;
20376				_this.setPageCords();
20377				_this.setZoomEssentials();
20378				_this.zoomImage(_this.scale);
20379			});
20380			// Update zoom on resize and orientationchange
20381			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
20382				if (!_this.core.lgOpened)
20383					return;
20384				_this.scrollTop = _this.$LG(window).scrollTop();
20385			});
20386			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
20387				if (_this.core.outer.find('.lg-current .lg-image').get()) {
20388					_this.scale -= _this.settings.scale;
20389					_this.scale = _this.getScale(_this.scale);
20390					_this.beginZoom(_this.scale);
20391					_this.zoomImage(_this.scale);
20392				}
20393			});
20394			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
20395				_this.zoomIn();
20396			});
20397			this.core.getElementById('lg-actual-size').on('click.lg', function () {
20398				_this.setActualSize(_this.core.index);
20399			});
20400			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
20401				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
20402			});
20403			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
20404				_this.scrollTop = _this.$LG(window).scrollTop();
20405				// Set the initial value center
20406				_this.pageX = _this.core.outer.width() / 2;
20407				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
20408				_this.scale = 1;
20409			});
20410			// Reset zoom on slide change
20411			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
20412				var prevIndex = event.detail.prevIndex;
20413				_this.scale = 1;
20414				_this.positionChanged = false;
20415				_this.resetZoom(prevIndex);
20416				if (_this.isImageSlide()) {
20417					_this.setZoomEssentials();
20418				}
20419			});
20420			// Drag option after zoom
20421			this.zoomDrag();
20422			this.pinchZoom();
20423			this.zoomSwipe();
20424			// Store the zoomable timeout value just to clear it while closing
20425			this.zoomableTimeout = false;
20426			this.positionChanged = false;
20427		};
20428		Zoom.prototype.zoomIn = function (scale) {
20429			// Allow zoom only on image
20430			if (!this.isImageSlide()) {
20431				return;
20432			}
20433			if (scale) {
20434				this.scale = scale;
20435			}
20436			else {
20437				this.scale += this.settings.scale;
20438			}
20439			this.scale = this.getScale(this.scale);
20440			this.beginZoom(this.scale);
20441			this.zoomImage(this.scale);
20442		};
20443		// Reset zoom effect
20444		Zoom.prototype.resetZoom = function (index) {
20445			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
20446			var $actualSize = this.core.getElementById('lg-actual-size');
20447			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
20448			$actualSize
20449				.removeClass(this.settings.actualSizeIcons.zoomOut)
20450				.addClass(this.settings.actualSizeIcons.zoomIn);
20451			$item.find('.lg-img-wrap').first().removeAttr('style');
20452			$item.find('.lg-image').first().removeAttr('style');
20453			this.scale = 1;
20454			this.left = 0;
20455			this.top = 0;
20456			// Reset pagx pagy values to center
20457			this.setPageCords();
20458		};
20459		Zoom.prototype.getTouchDistance = function (e) {
20460			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
20461				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
20462				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
20463					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
20464		};
20465		Zoom.prototype.pinchZoom = function () {
20466			var _this = this;
20467			var startDist = 0;
20468			var pinchStarted = false;
20469			var initScale = 1;
20470			var $item = this.core.getSlideItem(this.core.index);
20471			this.core.$inner.on('touchstart.lg', function (e) {
20472				$item = _this.core.getSlideItem(_this.core.index);
20473				if (!_this.isImageSlide()) {
20474					return;
20475				}
20476				if (e.targetTouches.length === 2 &&
20477					!_this.core.outer.hasClass('lg-first-slide-loading') &&
20478					(_this.$LG(e.target).hasClass('lg-item') ||
20479						$item.get().contains(e.target))) {
20480					initScale = _this.scale || 1;
20481					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20482					_this.core.touchAction = 'pinch';
20483					startDist = _this.getTouchDistance(e);
20484				}
20485			});
20486			this.core.$inner.on('touchmove.lg', function (e) {
20487				if (e.targetTouches.length === 2 &&
20488					_this.core.touchAction === 'pinch' &&
20489					(_this.$LG(e.target).hasClass('lg-item') ||
20490						$item.get().contains(e.target))) {
20491					e.preventDefault();
20492					var endDist = _this.getTouchDistance(e);
20493					var distance = startDist - endDist;
20494					if (!pinchStarted && Math.abs(distance) > 5) {
20495						pinchStarted = true;
20496					}
20497					if (pinchStarted) {
20498						_this.scale = Math.max(1, initScale + -distance * 0.008);
20499						_this.zoomImage(_this.scale);
20500					}
20501				}
20502			});
20503			this.core.$inner.on('touchend.lg', function (e) {
20504				if (_this.core.touchAction === 'pinch' &&
20505					(_this.$LG(e.target).hasClass('lg-item') ||
20506						$item.get().contains(e.target))) {
20507					pinchStarted = false;
20508					startDist = 0;
20509					if (_this.scale <= 1) {
20510						_this.resetZoom();
20511					}
20512					else {
20513						_this.scale = _this.getScale(_this.scale);
20514						_this.zoomImage(_this.scale);
20515						_this.core.outer.addClass('lg-zoomed');
20516					}
20517					_this.core.touchAction = undefined;
20518				}
20519			});
20520		};
20521		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
20522			var distanceXnew = endCoords.x - startCoords.x;
20523			var distanceYnew = endCoords.y - startCoords.y;
20524			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
20525			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
20526			if (speedX > 2) {
20527				speedX += 1;
20528			}
20529			if (speedY > 2) {
20530				speedY += 1;
20531			}
20532			distanceXnew = distanceXnew * speedX;
20533			distanceYnew = distanceYnew * speedY;
20534			var _LGel = this.core
20535				.getSlideItem(this.core.index)
20536				.find('.lg-img-wrap')
20537				.first();
20538			var distance = {};
20539			distance.x = this.left + distanceXnew * this.modifierX;
20540			distance.y = this.top + distanceYnew * this.modifierY;
20541			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
20542			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
20543				if (allowY) {
20544					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20545						distance.y = possibleSwipeCords.minY;
20546					}
20547					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20548						distance.y = possibleSwipeCords.maxY;
20549					}
20550				}
20551				if (allowX) {
20552					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20553						distance.x = possibleSwipeCords.minX;
20554					}
20555					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20556						distance.x = possibleSwipeCords.maxX;
20557					}
20558				}
20559				if (allowY) {
20560					this.top = distance.y;
20561				}
20562				else {
20563					distance.y = this.top;
20564				}
20565				if (allowX) {
20566					this.left = distance.x;
20567				}
20568				else {
20569					distance.x = this.left;
20570				}
20571				this.setZoomSwipeStyles(_LGel, distance);
20572				this.positionChanged = true;
20573			}
20574		};
20575		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
20576			var distance = {};
20577			if (allowY) {
20578				distance.y =
20579					this.top + (endCoords.y - startCoords.y) * this.modifierY;
20580				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20581					var diffMinY = possibleSwipeCords.minY - distance.y;
20582					distance.y = possibleSwipeCords.minY - diffMinY / 6;
20583				}
20584				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20585					var diffMaxY = distance.y - possibleSwipeCords.maxY;
20586					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
20587				}
20588			}
20589			else {
20590				distance.y = this.top;
20591			}
20592			if (allowX) {
20593				distance.x =
20594					this.left + (endCoords.x - startCoords.x) * this.modifierX;
20595				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20596					var diffMinX = possibleSwipeCords.minX - distance.x;
20597					distance.x = possibleSwipeCords.minX - diffMinX / 6;
20598				}
20599				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20600					var difMaxX = distance.x - possibleSwipeCords.maxX;
20601					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
20602				}
20603			}
20604			else {
20605				distance.x = this.left;
20606			}
20607			return distance;
20608		};
20609		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
20610			return x >= minX;
20611		};
20612		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
20613			return x <= maxX;
20614		};
20615		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
20616			return y >= minY;
20617		};
20618		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
20619			return y <= maxY;
20620		};
20621		Zoom.prototype.isImageSlide = function () {
20622			var currentItem = this.core.galleryItems[this.core.index];
20623			return this.core.getSlideType(currentItem) === 'image';
20624		};
20625		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
20626			var dataScale = scale || this.scale || 1;
20627			var elDataScale = Math.abs(dataScale);
20628			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20629			var topBottomSpacing = Math.abs(top - bottom) / 2;
20630			var minY = (this.imageYSize - this.containerRect.height) / 2 +
20631				topBottomSpacing * this.modifierX;
20632			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
20633			var minX = (this.imageXSize - this.containerRect.width) / 2;
20634			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
20635			var possibleSwipeCords = {
20636				minY: minY,
20637				maxY: maxY,
20638				minX: minX,
20639				maxX: maxX,
20640			};
20641			if (Math.abs(rotateValue) === 90) {
20642				possibleSwipeCords = {
20643					minY: minX,
20644					maxY: maxX,
20645					minX: minY,
20646					maxX: maxY,
20647				};
20648			}
20649			return possibleSwipeCords;
20650		};
20651		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
20652			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
20653		};
20654		Zoom.prototype.zoomSwipe = function () {
20655			var _this = this;
20656			var startCoords = {};
20657			var endCoords = {};
20658			var isMoved = false;
20659			// Allow x direction drag
20660			var allowX = false;
20661			// Allow Y direction drag
20662			var allowY = false;
20663			var startTime = new Date();
20664			var endTime = new Date();
20665			var possibleSwipeCords;
20666			var _LGel;
20667			var $item = this.core.getSlideItem(this.core.index);
20668			this.core.$inner.on('touchstart.lg', function (e) {
20669				// Allow zoom only on image
20670				if (!_this.isImageSlide()) {
20671					return;
20672				}
20673				$item = _this.core.getSlideItem(_this.core.index);
20674				if ((_this.$LG(e.target).hasClass('lg-item') ||
20675					$item.get().contains(e.target)) &&
20676					e.targetTouches.length === 1 &&
20677					_this.core.outer.hasClass('lg-zoomed')) {
20678					e.preventDefault();
20679					startTime = new Date();
20680					_this.core.touchAction = 'zoomSwipe';
20681					_LGel = _this.core
20682						.getSlideItem(_this.core.index)
20683						.find('.lg-img-wrap')
20684						.first();
20685					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20686					allowY = dragAllowedAxises.allowY;
20687					allowX = dragAllowedAxises.allowX;
20688					if (allowX || allowY) {
20689						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20690					}
20691					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20692					// reset opacity and transition duration
20693					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
20694				}
20695			});
20696			this.core.$inner.on('touchmove.lg', function (e) {
20697				if (e.targetTouches.length === 1 &&
20698					_this.core.touchAction === 'zoomSwipe' &&
20699					(_this.$LG(e.target).hasClass('lg-item') ||
20700						$item.get().contains(e.target))) {
20701					e.preventDefault();
20702					_this.core.touchAction = 'zoomSwipe';
20703					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20704					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20705					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
20706						Math.abs(endCoords.y - startCoords.y) > 15) {
20707						isMoved = true;
20708						_this.setZoomSwipeStyles(_LGel, distance);
20709					}
20710				}
20711			});
20712			this.core.$inner.on('touchend.lg', function (e) {
20713				if (_this.core.touchAction === 'zoomSwipe' &&
20714					(_this.$LG(e.target).hasClass('lg-item') ||
20715						$item.get().contains(e.target))) {
20716					_this.core.touchAction = undefined;
20717					_this.core.outer.removeClass('lg-zoom-dragging');
20718					if (!isMoved) {
20719						return;
20720					}
20721					isMoved = false;
20722					endTime = new Date();
20723					var touchDuration = endTime.valueOf() - startTime.valueOf();
20724					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20725				}
20726			});
20727		};
20728		Zoom.prototype.zoomDrag = function () {
20729			var _this = this;
20730			var startCoords = {};
20731			var endCoords = {};
20732			var isDragging = false;
20733			var isMoved = false;
20734			// Allow x direction drag
20735			var allowX = false;
20736			// Allow Y direction drag
20737			var allowY = false;
20738			var startTime;
20739			var endTime;
20740			var possibleSwipeCords;
20741			var _LGel;
20742			this.core.outer.on('mousedown.lg.zoom', function (e) {
20743				// Allow zoom only on image
20744				if (!_this.isImageSlide()) {
20745					return;
20746				}
20747				var $item = _this.core.getSlideItem(_this.core.index);
20748				if (_this.$LG(e.target).hasClass('lg-item') ||
20749					$item.get().contains(e.target)) {
20750					startTime = new Date();
20751					_LGel = _this.core
20752						.getSlideItem(_this.core.index)
20753						.find('.lg-img-wrap')
20754						.first();
20755					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20756					allowY = dragAllowedAxises.allowY;
20757					allowX = dragAllowedAxises.allowX;
20758					if (_this.core.outer.hasClass('lg-zoomed')) {
20759						if (_this.$LG(e.target).hasClass('lg-object') &&
20760							(allowX || allowY)) {
20761							e.preventDefault();
20762							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20763							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20764							isDragging = true;
20765							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20766							_this.core.outer.get().scrollLeft += 1;
20767							_this.core.outer.get().scrollLeft -= 1;
20768							_this.core.outer
20769								.removeClass('lg-grab')
20770								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20771							// reset opacity and transition duration
20772						}
20773					}
20774				}
20775			});
20776			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20777				if (isDragging) {
20778					isMoved = true;
20779					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20780					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20781					_this.setZoomSwipeStyles(_LGel, distance);
20782				}
20783			});
20784			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20785				if (isDragging) {
20786					endTime = new Date();
20787					isDragging = false;
20788					_this.core.outer.removeClass('lg-zoom-dragging');
20789					// Fix for chrome mouse move on click
20790					if (isMoved &&
20791						(startCoords.x !== endCoords.x ||
20792							startCoords.y !== endCoords.y)) {
20793						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20794						var touchDuration = endTime.valueOf() - startTime.valueOf();
20795						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20796					}
20797					isMoved = false;
20798				}
20799				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20800			});
20801		};
20802		Zoom.prototype.closeGallery = function () {
20803			this.resetZoom();
20804		};
20805		Zoom.prototype.destroy = function () {
20806			// Unbind all events added by lightGallery zoom plugin
20807			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20808			this.core.LGel.off('.lg.zoom');
20809			this.core.LGel.off('.zoom');
20810			clearTimeout(this.zoomableTimeout);
20811			this.zoomableTimeout = false;
20812		};
20813		return Zoom;
20814	}());
20815
20816	return Zoom;
20817
20818})));
20819/*!
20820 * lightgallery | 2.5.0 | June 13th 2022
20821 * http://www.lightgalleryjs.com/
20822 * Copyright (c) 2020 Sachin Neravath;
20823 * @license GPLv3
20824 */
20825
20826(function (global, factory) {
20827	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20828	typeof define === 'function' && define.amd ? define(factory) :
20829	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20830}(this, (function () { 'use strict';
20831
20832	/*! *****************************************************************************
20833	Copyright (c) Microsoft Corporation.
20834
20835	Permission to use, copy, modify, and/or distribute this software for any
20836	purpose with or without fee is hereby granted.
20837
20838	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20839	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20840	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20841	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20842	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20843	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20844	PERFORMANCE OF THIS SOFTWARE.
20845	***************************************************************************** */
20846
20847	var __assign = function() {
20848		__assign = Object.assign || function __assign(t) {
20849			for (var s, i = 1, n = arguments.length; i < n; i++) {
20850				s = arguments[i];
20851				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20852			}
20853			return t;
20854		};
20855		return __assign.apply(this, arguments);
20856	};
20857
20858	var fullscreenSettings = {
20859		fullScreen: true,
20860		fullscreenPluginStrings: {
20861			toggleFullscreen: 'Toggle Fullscreen',
20862		},
20863	};
20864
20865	var FullScreen = /** @class */ (function () {
20866		function FullScreen(instance, $LG) {
20867			// get lightGallery core plugin instance
20868			this.core = instance;
20869			this.$LG = $LG;
20870			// extend module default settings with lightGallery core settings
20871			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20872			return this;
20873		}
20874		FullScreen.prototype.init = function () {
20875			var fullScreen = '';
20876			if (this.settings.fullScreen) {
20877				// check for fullscreen browser support
20878				if (!document.fullscreenEnabled &&
20879					!document.webkitFullscreenEnabled &&
20880					!document.mozFullScreenEnabled &&
20881					!document.msFullscreenEnabled) {
20882					return;
20883				}
20884				else {
20885					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20886					this.core.$toolbar.append(fullScreen);
20887					this.fullScreen();
20888				}
20889			}
20890		};
20891		FullScreen.prototype.isFullScreen = function () {
20892			return (document.fullscreenElement ||
20893				document.mozFullScreenElement ||
20894				document.webkitFullscreenElement ||
20895				document.msFullscreenElement);
20896		};
20897		FullScreen.prototype.requestFullscreen = function () {
20898			var el = document.documentElement;
20899			if (el.requestFullscreen) {
20900				el.requestFullscreen();
20901			}
20902			else if (el.msRequestFullscreen) {
20903				el.msRequestFullscreen();
20904			}
20905			else if (el.mozRequestFullScreen) {
20906				el.mozRequestFullScreen();
20907			}
20908			else if (el.webkitRequestFullscreen) {
20909				el.webkitRequestFullscreen();
20910			}
20911		};
20912		FullScreen.prototype.exitFullscreen = function () {
20913			if (document.exitFullscreen) {
20914				document.exitFullscreen();
20915			}
20916			else if (document.msExitFullscreen) {
20917				document.msExitFullscreen();
20918			}
20919			else if (document.mozCancelFullScreen) {
20920				document.mozCancelFullScreen();
20921			}
20922			else if (document.webkitExitFullscreen) {
20923				document.webkitExitFullscreen();
20924			}
20925		};
20926		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20927		FullScreen.prototype.fullScreen = function () {
20928			var _this = this;
20929			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 () {
20930				if (!_this.core.lgOpened)
20931					return;
20932				_this.core.outer.toggleClass('lg-fullscreen-on');
20933			});
20934			this.core.outer
20935				.find('.lg-fullscreen')
20936				.first()
20937				.on('click.lg', function () {
20938				if (_this.isFullScreen()) {
20939					_this.exitFullscreen();
20940				}
20941				else {
20942					_this.requestFullscreen();
20943				}
20944			});
20945		};
20946		FullScreen.prototype.closeGallery = function () {
20947			// exit from fullscreen if activated
20948			if (this.isFullScreen()) {
20949				this.exitFullscreen();
20950			}
20951		};
20952		FullScreen.prototype.destroy = function () {
20953			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);
20954		};
20955		return FullScreen;
20956	}());
20957
20958	return FullScreen;
20959
20960})));
20961
20962/*!
20963 * lightgallery | 2.5.0 | June 13th 2022
20964 * http://www.lightgalleryjs.com/
20965 * Copyright (c) 2020 Sachin Neravath;
20966 * @license GPLv3
20967 */
20968
20969(function (global, factory) {
20970	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20971	typeof define === 'function' && define.amd ? define(factory) :
20972	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
20973}(this, (function () { 'use strict';
20974
20975	/*! *****************************************************************************
20976	Copyright (c) Microsoft Corporation.
20977
20978	Permission to use, copy, modify, and/or distribute this software for any
20979	purpose with or without fee is hereby granted.
20980
20981	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20982	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20983	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20984	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20985	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20986	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20987	PERFORMANCE OF THIS SOFTWARE.
20988	***************************************************************************** */
20989
20990	var __assign = function() {
20991		__assign = Object.assign || function __assign(t) {
20992			for (var s, i = 1, n = arguments.length; i < n; i++) {
20993				s = arguments[i];
20994				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20995			}
20996			return t;
20997		};
20998		return __assign.apply(this, arguments);
20999	};
21000
21001	/**
21002	 * List of lightGallery events
21003	 * All events should be documented here
21004	 * Below interfaces are used to build the website documentations
21005	 * */
21006	var lGEvents = {
21007		afterAppendSlide: 'lgAfterAppendSlide',
21008		init: 'lgInit',
21009		hasVideo: 'lgHasVideo',
21010		containerResize: 'lgContainerResize',
21011		updateSlides: 'lgUpdateSlides',
21012		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21013		beforeOpen: 'lgBeforeOpen',
21014		afterOpen: 'lgAfterOpen',
21015		slideItemLoad: 'lgSlideItemLoad',
21016		beforeSlide: 'lgBeforeSlide',
21017		afterSlide: 'lgAfterSlide',
21018		posterClick: 'lgPosterClick',
21019		dragStart: 'lgDragStart',
21020		dragMove: 'lgDragMove',
21021		dragEnd: 'lgDragEnd',
21022		beforeNextSlide: 'lgBeforeNextSlide',
21023		beforePrevSlide: 'lgBeforePrevSlide',
21024		beforeClose: 'lgBeforeClose',
21025		afterClose: 'lgAfterClose',
21026		rotateLeft: 'lgRotateLeft',
21027		rotateRight: 'lgRotateRight',
21028		flipHorizontal: 'lgFlipHorizontal',
21029		flipVertical: 'lgFlipVertical',
21030		autoplay: 'lgAutoplay',
21031		autoplayStart: 'lgAutoplayStart',
21032		autoplayStop: 'lgAutoplayStop',
21033	};
21034
21035	var hashSettings = {
21036		hash: true,
21037		galleryId: '1',
21038		customSlideName: false,
21039	};
21040
21041	var Hash = /** @class */ (function () {
21042		function Hash(instance, $LG) {
21043			// get lightGallery core plugin instance
21044			this.core = instance;
21045			this.$LG = $LG;
21046			// extend module default settings with lightGallery core settings
21047			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
21048			return this;
21049		}
21050		Hash.prototype.init = function () {
21051			var _this = this;
21052			if (!this.settings.hash) {
21053				return;
21054			}
21055			this.oldHash = window.location.hash;
21056			setTimeout(function () {
21057				_this.buildFromHash();
21058			}, 100);
21059			// Change hash value on after each slide transition
21060			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
21061			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
21062			// Listen hash change and change the slide according to slide value
21063			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
21064		};
21065		Hash.prototype.onAfterSlide = function (event) {
21066			var slideName = this.core.galleryItems[event.detail.index].slideName;
21067			slideName = this.settings.customSlideName
21068				? slideName || event.detail.index
21069				: event.detail.index;
21070			if (history.replaceState) {
21071				history.replaceState(null, '', window.location.pathname +
21072					window.location.search +
21073					'#lg=' +
21074					this.settings.galleryId +
21075					'&slide=' +
21076					slideName);
21077			}
21078			else {
21079				window.location.hash =
21080					'lg=' + this.settings.galleryId + '&slide=' + slideName;
21081			}
21082		};
21083		/**
21084		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
21085		 * @param {String} hash
21086		 * @returns {Number} Index of the slide.
21087		 */
21088		Hash.prototype.getIndexFromUrl = function (hash) {
21089			if (hash === void 0) { hash = window.location.hash; }
21090			var slideName = hash.split('&slide=')[1];
21091			var _idx = 0;
21092			if (this.settings.customSlideName) {
21093				for (var index = 0; index < this.core.galleryItems.length; index++) {
21094					var dynamicEl = this.core.galleryItems[index];
21095					if (dynamicEl.slideName === slideName) {
21096						_idx = index;
21097						break;
21098					}
21099				}
21100			}
21101			else {
21102				_idx = parseInt(slideName, 10);
21103			}
21104			return isNaN(_idx) ? 0 : _idx;
21105		};
21106		// Build Gallery if gallery id exist in the URL
21107		Hash.prototype.buildFromHash = function () {
21108			// if dynamic option is enabled execute immediately
21109			var _hash = window.location.hash;
21110			//Uncode edit ##START##
21111			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
21112			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
21113			//Uncode edit ##END##
21114				// This class is used to remove the initial animation if galleryId present in the URL
21115				this.$LG(document.body).addClass('lg-from-hash');
21116				var index = this.getIndexFromUrl(_hash);
21117				this.core.openGallery(index);
21118				return true;
21119			}
21120		};
21121		Hash.prototype.onCloseAfter = function () {
21122			// Reset to old hash value
21123			if (this.oldHash &&
21124				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
21125				if (history.replaceState) {
21126					history.replaceState(null, '', this.oldHash);
21127				}
21128				else {
21129					window.location.hash = this.oldHash;
21130				}
21131			}
21132			else {
21133				if (history.replaceState) {
21134					history.replaceState(null, document.title, window.location.pathname + window.location.search);
21135				}
21136				else {
21137					window.location.hash = '';
21138				}
21139			}
21140		};
21141		Hash.prototype.onHashchange = function () {
21142			if (!this.core.lgOpened)
21143				return;
21144			var _hash = window.location.hash;
21145			var index = this.getIndexFromUrl(_hash);
21146			// it galleryId doesn't exist in the url close the gallery
21147			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
21148				this.core.slide(index, false, false);
21149			}
21150			else if (this.core.lGalleryOn) {
21151				this.core.closeGallery();
21152			}
21153		};
21154		Hash.prototype.closeGallery = function () {
21155			if (this.settings.hash) {
21156				this.$LG(document.body).removeClass('lg-from-hash');
21157			}
21158		};
21159		Hash.prototype.destroy = function () {
21160			this.core.LGel.off('.lg.hash');
21161			this.core.LGel.off('.hash');
21162			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
21163		};
21164		return Hash;
21165	}());
21166
21167	return Hash;
21168
21169})));
21170/*!
21171 * lightgallery | 2.5.0 | June 13th 2022
21172 * http://www.lightgalleryjs.com/
21173 * Copyright (c) 2020 Sachin Neravath;
21174 * @license GPLv3
21175 */
21176
21177(function (global, factory) {
21178	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21179	typeof define === 'function' && define.amd ? define(factory) :
21180	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
21181}(this, (function () { 'use strict';
21182
21183	/*! *****************************************************************************
21184	Copyright (c) Microsoft Corporation.
21185
21186	Permission to use, copy, modify, and/or distribute this software for any
21187	purpose with or without fee is hereby granted.
21188
21189	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21190	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21191	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21192	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21193	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21194	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21195	PERFORMANCE OF THIS SOFTWARE.
21196	***************************************************************************** */
21197
21198	var __assign = function() {
21199		__assign = Object.assign || function __assign(t) {
21200			for (var s, i = 1, n = arguments.length; i < n; i++) {
21201				s = arguments[i];
21202				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21203			}
21204			return t;
21205		};
21206		return __assign.apply(this, arguments);
21207	};
21208
21209	function __spreadArrays() {
21210		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
21211		for (var r = Array(s), k = 0, i = 0; i < il; i++)
21212			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
21213				r[k] = a[j];
21214		return r;
21215	}
21216
21217	var shareSettings = {
21218		share: true,
21219		facebook: true,
21220		facebookDropdownText: 'Facebook',
21221		twitter: true,
21222		twitterDropdownText: 'Twitter',
21223		pinterest: true,
21224		pinterestDropdownText: 'Pinterest',
21225		additionalShareOptions: [],
21226		sharePluginStrings: { share: 'Share' },
21227	};
21228
21229	function getFacebookShareLink(galleryItem) {
21230		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
21231		return (facebookBaseUrl +
21232			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
21233	}
21234
21235	function getTwitterShareLink(galleryItem) {
21236		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
21237		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
21238		var text = galleryItem.tweetText;
21239		return twitterBaseUrl + text + '&url=' + url;
21240	}
21241
21242	function getPinterestShareLink(galleryItem) {
21243		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
21244		var description = galleryItem.pinterestText;
21245		var media = encodeURIComponent(galleryItem.src);
21246		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
21247		return (pinterestBaseUrl +
21248			url +
21249			'&media=' +
21250			media +
21251			'&description=' +
21252			description);
21253	}
21254
21255	/**
21256	 * List of lightGallery events
21257	 * All events should be documented here
21258	 * Below interfaces are used to build the website documentations
21259	 * */
21260	var lGEvents = {
21261		afterAppendSlide: 'lgAfterAppendSlide',
21262		init: 'lgInit',
21263		hasVideo: 'lgHasVideo',
21264		containerResize: 'lgContainerResize',
21265		updateSlides: 'lgUpdateSlides',
21266		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21267		beforeOpen: 'lgBeforeOpen',
21268		afterOpen: 'lgAfterOpen',
21269		slideItemLoad: 'lgSlideItemLoad',
21270		beforeSlide: 'lgBeforeSlide',
21271		afterSlide: 'lgAfterSlide',
21272		posterClick: 'lgPosterClick',
21273		dragStart: 'lgDragStart',
21274		dragMove: 'lgDragMove',
21275		dragEnd: 'lgDragEnd',
21276		beforeNextSlide: 'lgBeforeNextSlide',
21277		beforePrevSlide: 'lgBeforePrevSlide',
21278		beforeClose: 'lgBeforeClose',
21279		afterClose: 'lgAfterClose',
21280		rotateLeft: 'lgRotateLeft',
21281		rotateRight: 'lgRotateRight',
21282		flipHorizontal: 'lgFlipHorizontal',
21283		flipVertical: 'lgFlipVertical',
21284		autoplay: 'lgAutoplay',
21285		autoplayStart: 'lgAutoplayStart',
21286		autoplayStop: 'lgAutoplayStop',
21287	};
21288
21289	var Share = /** @class */ (function () {
21290		function Share(instance) {
21291			this.shareOptions = [];
21292			// get lightGallery core plugin instance
21293			this.core = instance;
21294			// extend module default settings with lightGallery core settings
21295			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
21296			return this;
21297		}
21298		Share.prototype.init = function () {
21299			if (!this.settings.share) {
21300				return;
21301			}
21302			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
21303			this.setLgShareMarkup();
21304			this.core.outer
21305				.find('.lg-share .lg-dropdown')
21306				.append(this.getShareListHtml());
21307			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
21308		};
21309		Share.prototype.getShareListHtml = function () {
21310			var shareHtml = '';
21311			this.shareOptions.forEach(function (shareOption) {
21312				shareHtml += shareOption.dropdownHTML;
21313			});
21314			return shareHtml;
21315		};
21316		Share.prototype.setLgShareMarkup = function () {
21317			var _this = this;
21318			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>");
21319			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
21320			var $shareButton = this.core.outer.find('.lg-share');
21321			$shareButton.first().on('click.lg', function () {
21322				_this.core.outer.toggleClass('lg-dropdown-active');
21323				if (_this.core.outer.hasClass('lg-dropdown-active')) {
21324					_this.core.outer.attr('aria-expanded', true);
21325				}
21326				else {
21327					_this.core.outer.attr('aria-expanded', false);
21328				}
21329			});
21330			this.core.outer
21331				.find('.lg-dropdown-overlay')
21332				.first()
21333				.on('click.lg', function () {
21334				_this.core.outer.removeClass('lg-dropdown-active');
21335				_this.core.outer.attr('aria-expanded', false);
21336			});
21337		};
21338		Share.prototype.onAfterSlide = function (event) {
21339			var _this = this;
21340			var index = event.detail.index;
21341			var currentItem = this.core.galleryItems[index];
21342			setTimeout(function () {
21343				_this.shareOptions.forEach(function (shareOption) {
21344					var selector = shareOption.selector;
21345					_this.core.outer
21346						.find(selector)
21347						.attr('href', shareOption.generateLink(currentItem));
21348				});
21349			}, 100);
21350		};
21351		Share.prototype.getShareListItemHTML = function (type, text) {
21352			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>";
21353		};
21354		Share.prototype.getDefaultShareOptions = function () {
21355			return __spreadArrays((this.settings.facebook
21356				? [
21357					{
21358						type: 'facebook',
21359						generateLink: getFacebookShareLink,
21360						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
21361						selector: '.lg-share-facebook',
21362					},
21363				]
21364				: []), (this.settings.twitter
21365				? [
21366					{
21367						type: 'twitter',
21368						generateLink: getTwitterShareLink,
21369						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
21370						selector: '.lg-share-twitter',
21371					},
21372				]
21373				: []), (this.settings.pinterest
21374				? [
21375					{
21376						type: 'pinterest',
21377						generateLink: getPinterestShareLink,
21378						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
21379						selector: '.lg-share-pinterest',
21380					},
21381				]
21382				: []));
21383		};
21384		Share.prototype.destroy = function () {
21385			this.core.outer.find('.lg-dropdown-overlay').remove();
21386			this.core.outer.find('.lg-share').remove();
21387			this.core.LGel.off('.lg.share');
21388			this.core.LGel.off('.share');
21389		};
21390		return Share;
21391	}());
21392
21393	return Share;
21394
21395})));
21396/*!
21397 * lightgallery | 2.5.0 | June 13th 2022
21398 * http://www.lightgalleryjs.com/
21399 * Copyright (c) 2020 Sachin Neravath;
21400 * @license GPLv3
21401 */
21402
21403(function (global, factory) {
21404	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21405	typeof define === 'function' && define.amd ? define(factory) :
21406	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
21407}(this, (function () { 'use strict';
21408
21409	/*! *****************************************************************************
21410	Copyright (c) Microsoft Corporation.
21411
21412	Permission to use, copy, modify, and/or distribute this software for any
21413	purpose with or without fee is hereby granted.
21414
21415	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21416	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21417	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21418	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21419	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21420	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21421	PERFORMANCE OF THIS SOFTWARE.
21422	***************************************************************************** */
21423
21424	var __assign = function() {
21425		__assign = Object.assign || function __assign(t) {
21426			for (var s, i = 1, n = arguments.length; i < n; i++) {
21427				s = arguments[i];
21428				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21429			}
21430			return t;
21431		};
21432		return __assign.apply(this, arguments);
21433	};
21434
21435	var thumbnailsSettings = {
21436		thumbnail: true,
21437		animateThumb: true,
21438		currentPagerPosition: 'middle',
21439		alignThumbnails: 'middle',
21440		thumbWidth: 100,
21441		thumbHeight: '80px',
21442		thumbMargin: 5,
21443		appendThumbnailsTo: '.lg-components',
21444		toggleThumb: false,
21445		enableThumbDrag: true,
21446		enableThumbSwipe: true,
21447		thumbnailSwipeThreshold: 10,
21448		loadYouTubeThumbnail: true,
21449		youTubeThumbSize: 1,
21450		thumbnailPluginStrings: {
21451			toggleThumbnails: 'Toggle thumbnails',
21452		},
21453	};
21454
21455	/**
21456	 * List of lightGallery events
21457	 * All events should be documented here
21458	 * Below interfaces are used to build the website documentations
21459	 * */
21460	var lGEvents = {
21461		afterAppendSlide: 'lgAfterAppendSlide',
21462		init: 'lgInit',
21463		hasVideo: 'lgHasVideo',
21464		containerResize: 'lgContainerResize',
21465		updateSlides: 'lgUpdateSlides',
21466		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21467		beforeOpen: 'lgBeforeOpen',
21468		afterOpen: 'lgAfterOpen',
21469		slideItemLoad: 'lgSlideItemLoad',
21470		beforeSlide: 'lgBeforeSlide',
21471		afterSlide: 'lgAfterSlide',
21472		posterClick: 'lgPosterClick',
21473		dragStart: 'lgDragStart',
21474		dragMove: 'lgDragMove',
21475		dragEnd: 'lgDragEnd',
21476		beforeNextSlide: 'lgBeforeNextSlide',
21477		beforePrevSlide: 'lgBeforePrevSlide',
21478		beforeClose: 'lgBeforeClose',
21479		afterClose: 'lgAfterClose',
21480		rotateLeft: 'lgRotateLeft',
21481		rotateRight: 'lgRotateRight',
21482		flipHorizontal: 'lgFlipHorizontal',
21483		flipVertical: 'lgFlipVertical',
21484		autoplay: 'lgAutoplay',
21485		autoplayStart: 'lgAutoplayStart',
21486		autoplayStop: 'lgAutoplayStop',
21487	};
21488
21489	var Thumbnail = /** @class */ (function () {
21490		function Thumbnail(instance, $LG) {
21491			this.thumbOuterWidth = 0;
21492			this.thumbTotalWidth = 0;
21493			this.translateX = 0;
21494			this.thumbClickable = false;
21495			// get lightGallery core plugin instance
21496			this.core = instance;
21497			this.$LG = $LG;
21498			return this;
21499		}
21500		Thumbnail.prototype.init = function () {
21501			// extend module default settings with lightGallery core settings
21502			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
21503			this.thumbOuterWidth = 0;
21504			this.thumbTotalWidth =
21505				this.core.galleryItems.length *
21506					(this.settings.thumbWidth + this.settings.thumbMargin);
21507			// Thumbnail animation value
21508			this.translateX = 0;
21509			this.setAnimateThumbStyles();
21510			if (!this.core.settings.allowMediaOverlap) {
21511				this.settings.toggleThumb = false;
21512			}
21513			if (this.settings.thumbnail) {
21514				this.build();
21515				if (this.settings.animateThumb) {
21516					if (this.settings.enableThumbDrag) {
21517						this.enableThumbDrag();
21518					}
21519					if (this.settings.enableThumbSwipe) {
21520						this.enableThumbSwipe();
21521					}
21522					this.thumbClickable = false;
21523				}
21524				else {
21525					this.thumbClickable = true;
21526				}
21527				this.toggleThumbBar();
21528				this.thumbKeyPress();
21529			}
21530		};
21531		Thumbnail.prototype.build = function () {
21532			var _this = this;
21533			this.setThumbMarkup();
21534			this.manageActiveClassOnSlideChange();
21535			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
21536				var $target = _this.$LG(e.target);
21537				if (!$target.hasAttribute('data-lg-item-id')) {
21538					return;
21539				}
21540				setTimeout(function () {
21541					// In IE9 and bellow touch does not support
21542					// Go to slide if browser does not support css transitions
21543					if (_this.thumbClickable && !_this.core.lgBusy) {
21544						var index = parseInt($target.attr('data-lg-item-id'));
21545						_this.core.slide(index, false, true, false);
21546					}
21547				}, 50);
21548			});
21549			//Uncode edit ##START##
21550			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21551			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21552			//Uncode edit ##END##
21553				var index = event.detail.index;
21554				_this.animateThumb(index);
21555			});
21556			//Uncode edit ##START##
21557			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
21558			this.core.LGel.on(lGEvents.beforeOpen, function () {
21559			//Uncode edit ##END##
21560				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21561			});
21562			//Uncode edit ##START##
21563			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
21564			this.core.LGel.on(lGEvents.updateSlides, function () {
21565			//Uncode edit ##END##
21566				_this.rebuildThumbnails();
21567			});
21568			//Uncode edit ##START##
21569			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
21570			this.core.LGel.on(lGEvents.containerResize, function () {
21571			//Uncode edit ##END##
21572				if (!_this.core.lgOpened)
21573					return;
21574				setTimeout(function () {
21575					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21576					_this.animateThumb(_this.core.index);
21577					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21578				}, 50);
21579			});
21580		};
21581		Thumbnail.prototype.setThumbMarkup = function () {
21582			var thumbOuterClassNames = 'lg-thumb-outer ';
21583			if (this.settings.alignThumbnails) {
21584				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
21585			}
21586			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
21587			this.core.outer.addClass('lg-has-thumb');
21588			if (this.settings.appendThumbnailsTo === '.lg-components') {
21589				this.core.$lgComponents.append(html);
21590			}
21591			else {
21592				this.core.outer.append(html);
21593			}
21594			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
21595			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
21596			if (this.settings.animateThumb) {
21597				this.core.outer
21598					.find('.lg-thumb')
21599					.css('transition-duration', this.core.settings.speed + 'ms')
21600					.css('width', this.thumbTotalWidth + 'px')
21601					.css('position', 'relative');
21602			}
21603			this.setThumbItemHtml(this.core.galleryItems);
21604		};
21605		Thumbnail.prototype.enableThumbDrag = function () {
21606			var _this = this;
21607			var thumbDragUtils = {
21608				cords: {
21609					startX: 0,
21610					endX: 0,
21611				},
21612				isMoved: false,
21613				newTranslateX: 0,
21614				startTime: new Date(),
21615				endTime: new Date(),
21616				touchMoveTime: 0,
21617			};
21618			var isDragging = false;
21619			this.$thumbOuter.addClass('lg-grab');
21620			this.core.outer
21621				.find('.lg-thumb')
21622				.first()
21623				.on('mousedown.lg.thumb', function (e) {
21624				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21625					// execute only on .lg-object
21626					e.preventDefault();
21627					thumbDragUtils.cords.startX = e.pageX;
21628					thumbDragUtils.startTime = new Date();
21629					_this.thumbClickable = false;
21630					isDragging = true;
21631					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
21632					_this.core.outer.get().scrollLeft += 1;
21633					_this.core.outer.get().scrollLeft -= 1;
21634					// *
21635					_this.$thumbOuter
21636						.removeClass('lg-grab')
21637						.addClass('lg-grabbing');
21638				}
21639			});
21640			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
21641				if (!_this.core.lgOpened)
21642					return;
21643				if (isDragging) {
21644					thumbDragUtils.cords.endX = e.pageX;
21645					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21646				}
21647			});
21648			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
21649				if (!_this.core.lgOpened)
21650					return;
21651				if (thumbDragUtils.isMoved) {
21652					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21653				}
21654				else {
21655					_this.thumbClickable = true;
21656				}
21657				if (isDragging) {
21658					isDragging = false;
21659					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
21660				}
21661			});
21662		};
21663		Thumbnail.prototype.enableThumbSwipe = function () {
21664			var _this = this;
21665			var thumbDragUtils = {
21666				cords: {
21667					startX: 0,
21668					endX: 0,
21669				},
21670				isMoved: false,
21671				newTranslateX: 0,
21672				startTime: new Date(),
21673				endTime: new Date(),
21674				touchMoveTime: 0,
21675			};
21676			this.$lgThumb.on('touchstart.lg', function (e) {
21677				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21678					e.preventDefault();
21679					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
21680					_this.thumbClickable = false;
21681					thumbDragUtils.startTime = new Date();
21682				}
21683			});
21684			this.$lgThumb.on('touchmove.lg', function (e) {
21685				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21686					e.preventDefault();
21687					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
21688					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21689				}
21690			});
21691			this.$lgThumb.on('touchend.lg', function () {
21692				if (thumbDragUtils.isMoved) {
21693					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21694				}
21695				else {
21696					_this.thumbClickable = true;
21697				}
21698			});
21699		};
21700		// Rebuild thumbnails
21701		Thumbnail.prototype.rebuildThumbnails = function () {
21702			var _this = this;
21703			// Remove transitions
21704			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
21705			setTimeout(function () {
21706				_this.thumbTotalWidth =
21707					_this.core.galleryItems.length *
21708						(_this.settings.thumbWidth + _this.settings.thumbMargin);
21709				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
21710				_this.$lgThumb.empty();
21711				_this.setThumbItemHtml(_this.core.galleryItems);
21712				_this.animateThumb(_this.core.index);
21713			}, 50);
21714			setTimeout(function () {
21715				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
21716			}, 200);
21717		};
21718		// @ts-check
21719		Thumbnail.prototype.setTranslate = function (value) {
21720			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
21721		};
21722		Thumbnail.prototype.getPossibleTransformX = function (left) {
21723			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
21724				left = this.thumbTotalWidth - this.thumbOuterWidth;
21725			}
21726			if (left < 0) {
21727				left = 0;
21728			}
21729			return left;
21730		};
21731		Thumbnail.prototype.animateThumb = function (index) {
21732			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
21733			if (this.settings.animateThumb) {
21734				var position = 0;
21735				switch (this.settings.currentPagerPosition) {
21736					case 'left':
21737						position = 0;
21738						break;
21739					case 'middle':
21740						position =
21741							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
21742						break;
21743					case 'right':
21744						position = this.thumbOuterWidth - this.settings.thumbWidth;
21745				}
21746				this.translateX =
21747					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
21748						1 -
21749						position;
21750				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
21751					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
21752				}
21753				if (this.translateX < 0) {
21754					this.translateX = 0;
21755				}
21756				this.setTranslate(this.translateX);
21757			}
21758		};
21759		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21760			thumbDragUtils.newTranslateX = this.translateX;
21761			thumbDragUtils.isMoved = true;
21762			thumbDragUtils.touchMoveTime = new Date().valueOf();
21763			thumbDragUtils.newTranslateX -=
21764				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21765			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21766			// move current slide
21767			this.setTranslate(thumbDragUtils.newTranslateX);
21768			this.$thumbOuter.addClass('lg-dragging');
21769			return thumbDragUtils;
21770		};
21771		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21772			thumbDragUtils.isMoved = false;
21773			thumbDragUtils.endTime = new Date();
21774			this.$thumbOuter.removeClass('lg-dragging');
21775			var touchDuration = thumbDragUtils.endTime.valueOf() -
21776				thumbDragUtils.startTime.valueOf();
21777			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21778			var speedX = Math.abs(distanceXnew) / touchDuration;
21779			// Some magical numbers
21780			// Can be improved
21781			if (speedX > 0.15 &&
21782				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21783				speedX += 1;
21784				if (speedX > 2) {
21785					speedX += 1;
21786				}
21787				speedX =
21788					speedX +
21789						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21790				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21791				distanceXnew = distanceXnew * speedX;
21792				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21793				this.setTranslate(this.translateX);
21794			}
21795			else {
21796				this.translateX = thumbDragUtils.newTranslateX;
21797			}
21798			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21799				this.settings.thumbnailSwipeThreshold) {
21800				this.thumbClickable = true;
21801			}
21802			return thumbDragUtils;
21803		};
21804		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21805			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21806			var thumbImg;
21807			if (slideVideoInfo.youtube) {
21808				if (this.settings.loadYouTubeThumbnail) {
21809					thumbImg =
21810						'//img.youtube.com/vi/' +
21811							slideVideoInfo.youtube[1] +
21812							'/' +
21813							this.settings.youTubeThumbSize +
21814							'.jpg';
21815				}
21816				else {
21817					thumbImg = thumb;
21818				}
21819			}
21820			else {
21821				thumbImg = thumb;
21822			}
21823			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>";
21824		};
21825		Thumbnail.prototype.getThumbItemHtml = function (items) {
21826			var thumbList = '';
21827			for (var i = 0; i < items.length; i++) {
21828				thumbList += this.getThumbHtml(items[i].thumb, i);
21829			}
21830			return thumbList;
21831		};
21832		Thumbnail.prototype.setThumbItemHtml = function (items) {
21833			var thumbList = this.getThumbItemHtml(items);
21834			this.$lgThumb.html(thumbList);
21835		};
21836		Thumbnail.prototype.setAnimateThumbStyles = function () {
21837			if (this.settings.animateThumb) {
21838				this.core.outer.addClass('lg-animate-thumb');
21839			}
21840		};
21841		// Manage thumbnail active calss
21842		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21843			var _this = this;
21844			// manage active class for thumbnail
21845			//Uncode edit ##START##
21846			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21847			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21848			//Uncode edit ##END##
21849				var $thumb = _this.core.outer.find('.lg-thumb-item');
21850				var index = event.detail.index;
21851				$thumb.removeClass('active');
21852				$thumb.eq(index).addClass('active');
21853			});
21854		};
21855		// Toggle thumbnail bar
21856		Thumbnail.prototype.toggleThumbBar = function () {
21857			var _this = this;
21858			if (this.settings.toggleThumb) {
21859				this.core.outer.addClass('lg-can-toggle');
21860				this.core.$toolbar.append('<button type="button" aria-label="' +
21861					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21862					'" class="lg-toggle-thumb lg-icon"></button>');
21863				this.core.outer
21864					.find('.lg-toggle-thumb')
21865					.first()
21866					.on('click.lg', function () {
21867					_this.core.outer.toggleClass('lg-components-open');
21868				});
21869			}
21870		};
21871		Thumbnail.prototype.thumbKeyPress = function () {
21872			var _this = this;
21873			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21874				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21875					return;
21876				if (e.keyCode === 38) {
21877					e.preventDefault();
21878					_this.core.outer.addClass('lg-components-open');
21879				}
21880				else if (e.keyCode === 40) {
21881					e.preventDefault();
21882					_this.core.outer.removeClass('lg-components-open');
21883				}
21884			});
21885		};
21886		Thumbnail.prototype.destroy = function () {
21887			if (this.settings.thumbnail) {
21888				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21889				this.core.LGel.off('.lg.thumb');
21890				this.core.LGel.off('.thumb');
21891				this.$thumbOuter.remove();
21892				this.core.outer.removeClass('lg-has-thumb');
21893			}
21894		};
21895		return Thumbnail;
21896	}());
21897
21898	return Thumbnail;
21899
21900})));
21901/*!
21902 * lightgallery | 2.5.0 | June 13th 2022
21903 * http://www.lightgalleryjs.com/
21904 * Copyright (c) 2020 Sachin Neravath;
21905 * @license GPLv3
21906 */
21907
21908(function (global, factory) {
21909	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21910	typeof define === 'function' && define.amd ? define(factory) :
21911	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21912}(this, (function () { 'use strict';
21913
21914	/*! *****************************************************************************
21915	Copyright (c) Microsoft Corporation.
21916
21917	Permission to use, copy, modify, and/or distribute this software for any
21918	purpose with or without fee is hereby granted.
21919
21920	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21921	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21922	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21923	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21924	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21925	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21926	PERFORMANCE OF THIS SOFTWARE.
21927	***************************************************************************** */
21928
21929	var __assign = function() {
21930		__assign = Object.assign || function __assign(t) {
21931			for (var s, i = 1, n = arguments.length; i < n; i++) {
21932				s = arguments[i];
21933				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21934			}
21935			return t;
21936		};
21937		return __assign.apply(this, arguments);
21938	};
21939
21940	var videoSettings = {
21941		autoplayFirstVideo: true,
21942		youTubePlayerParams: false,
21943		vimeoPlayerParams: false,
21944		wistiaPlayerParams: false,
21945		gotoNextSlideOnVideoEnd: true,
21946		autoplayVideoOnSlide: false,
21947		videojs: false,
21948		videojsTheme: '',
21949		videojsOptions: {},
21950	};
21951
21952	/**
21953	 * List of lightGallery events
21954	 * All events should be documented here
21955	 * Below interfaces are used to build the website documentations
21956	 * */
21957	var lGEvents = {
21958		afterAppendSlide: 'lgAfterAppendSlide',
21959		init: 'lgInit',
21960		hasVideo: 'lgHasVideo',
21961		containerResize: 'lgContainerResize',
21962		updateSlides: 'lgUpdateSlides',
21963		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21964		beforeOpen: 'lgBeforeOpen',
21965		afterOpen: 'lgAfterOpen',
21966		slideItemLoad: 'lgSlideItemLoad',
21967		beforeSlide: 'lgBeforeSlide',
21968		afterSlide: 'lgAfterSlide',
21969		posterClick: 'lgPosterClick',
21970		dragStart: 'lgDragStart',
21971		dragMove: 'lgDragMove',
21972		dragEnd: 'lgDragEnd',
21973		beforeNextSlide: 'lgBeforeNextSlide',
21974		beforePrevSlide: 'lgBeforePrevSlide',
21975		beforeClose: 'lgBeforeClose',
21976		afterClose: 'lgAfterClose',
21977		rotateLeft: 'lgRotateLeft',
21978		rotateRight: 'lgRotateRight',
21979		flipHorizontal: 'lgFlipHorizontal',
21980		flipVertical: 'lgFlipVertical',
21981		autoplay: 'lgAutoplay',
21982		autoplayStart: 'lgAutoplayStart',
21983		autoplayStop: 'lgAutoplayStop',
21984	};
21985
21986	var param = function (obj) {
21987		return Object.keys(obj)
21988			.map(function (k) {
21989			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
21990		})
21991			.join('&');
21992	};
21993	var getVimeoURLParams = function (defaultParams, videoInfo) {
21994		if (!videoInfo || !videoInfo.vimeo)
21995			return '';
21996		var urlParams = videoInfo.vimeo[2] || '';
21997		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
21998			? '&' + param(defaultParams)
21999			: '';
22000		// Support private video
22001		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
22002		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
22003		var hash = urlWithHashWithParams.split('#')[0];
22004		var isPrivate = videoInfo.vimeo[1] !== hash;
22005		if (isPrivate) {
22006			urlParams = urlParams.replace("/" + hash, '');
22007		}
22008		urlParams =
22009			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
22010		// For vimeo last params gets priority if duplicates found
22011		// Uncode edit ##START##
22012		var vimeoPlayerParams = '?autoplay=0';
22013		if ( videoInfo.autoplay !== '' ) {
22014			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22015			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
22016		} else {
22017			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
22018				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
22019			}
22020		}
22021		if ( videoInfo.muted !== '' ) {
22022			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
22023		} else {
22024			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
22025				vimeoPlayerParams += '&muted=1';
22026			}
22027		}
22028		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22029		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22030		// Uncode edit ##END##
22031		return vimeoPlayerParams;
22032	};
22033
22034	/**
22035	 * Video module for lightGallery
22036	 * Supports HTML5, YouTube, Vimeo, wistia videos
22037	 *
22038	 *
22039	 * @ref Wistia
22040	 * https://wistia.com/support/integrations/wordpress(How to get url)
22041	 * https://wistia.com/support/developers/embed-options#using-embed-options
22042	 * https://wistia.com/support/developers/player-api
22043	 * https://wistia.com/support/developers/construct-an-embed-code
22044	 * http://jsfiddle.net/xvnm7xLm/
22045	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
22046	 * https://wistia.com/support/embed-and-share/sharing-videos
22047	 * https://private-sharing.wistia.com/medias/mwhrulrucj
22048	 *
22049	 * @ref Youtube
22050	 * https://developers.google.com/youtube/player_parameters#enablejsapi
22051	 * https://developers.google.com/youtube/iframe_api_reference
22052	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
22053	 *
22054	 * @ref Vimeo
22055	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
22056	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
22057	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
22058	 */
22059	var Video = /** @class */ (function () {
22060		function Video(instance) {
22061			// get lightGallery core plugin instance
22062			this.core = instance;
22063			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
22064			return this;
22065		}
22066		Video.prototype.init = function () {
22067			var _this = this;
22068			/**
22069			 * Event triggered when video url found without poster
22070			 * Append video HTML
22071			 * Play if autoplayFirstVideo is true
22072			 */
22073			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
22074			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
22075				var $el = _this.core.getSlideItem(_this.core.index);
22076				_this.loadVideoOnPosterClick($el);
22077			});
22078			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
22079			// @desc fired immediately before each slide transition.
22080			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
22081			// @desc fired immediately after each slide transition.
22082			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
22083		};
22084		/**
22085		 * @desc Event triggered when a slide is completely loaded
22086		 *
22087		 * @param {Event} event - lightGalley custom event
22088		 */
22089		Video.prototype.onSlideItemLoad = function (event) {
22090			var _this = this;
22091			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
22092			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
22093			if (this.settings.autoplayFirstVideo &&
22094				isFirstSlide &&
22095				index === this.core.index) {
22096				// Delay is just for the transition effect on video load
22097				setTimeout(function () {
22098					_this.loadAndPlayVideo(index);
22099				}, 200);
22100			}
22101			// Should not call on first slide. should check only if the slide is active
22102			if (!isFirstSlide &&
22103				this.settings.autoplayVideoOnSlide &&
22104				index === this.core.index) {
22105					setTimeout(function () {
22106						_this.loadAndPlayVideo(index);
22107					}, 500);
22108				}
22109		};
22110		/**
22111		 * @desc Event triggered when video url or poster found
22112		 * Append video HTML is poster is not given
22113		 * Play if autoplayFirstVideo is true
22114		 *
22115		 * @param {Event} event - Javascript Event object.
22116		 */
22117		Video.prototype.onHasVideo = function (event) {
22118			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
22119			if (!hasPoster) {
22120				// All functions are called separately if poster exist in loadVideoOnPosterClick function
22121				this.appendVideos(this.core.getSlideItem(index), {
22122					src: src,
22123					addClass: 'lg-object',
22124					index: index,
22125					html5Video: html5Video,
22126					// Uncode edit ##START##
22127					autoplay: event.target.getAttribute('data-lb-autoplay'),
22128					muted: event.target.getAttribute('data-lb-muted'),
22129					// Uncode edit ##END##
22130				});
22131				// Automatically navigate to next slide once video reaches the end.
22132				this.gotoNextSlideOnVideoEnd(src, index);
22133			}
22134		};
22135		/**
22136		 * @desc fired immediately before each slide transition.
22137		 * Pause the previous video
22138		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
22139		 *
22140		 * @param {Event} event - Javascript Event object.
22141		 * @param {number} prevIndex - Previous index of the slide.
22142		 * @param {number} index - Current index of the slide
22143		 */
22144		Video.prototype.onBeforeSlide = function (event) {
22145			if (this.core.lGalleryOn) {
22146				var prevIndex = event.detail.prevIndex;
22147				this.pauseVideo(prevIndex);
22148			}
22149			// Uncode edit ##START##
22150			var _a = event.detail, index = _a.index;
22151			var $slide = this.core.getSlideItem(index);
22152			
22153			var iframe = $slide.selector.querySelector('iframe');
22154			if ( iframe != null ) {
22155
22156				var data_play = iframe.getAttribute('data-autoplay');
22157				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
22158					this.loadAndPlayVideo(index);
22159
22160					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
22161						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
22162					if (videoInfo.vimeo) {
22163						var vimeoPlayer = new Vimeo.Player($videoElement.get());
22164						vimeoPlayer.on('play', function () {
22165							vimeoPlayer.setCurrentTime(0);
22166						});
22167					} else if ( videoInfo.youtube ) {
22168						try {
22169							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
22170						}
22171						catch (e) {
22172							console.warn(e);
22173						}
22174					}
22175				}
22176			}
22177			// Uncode edit ##END##
22178		};
22179		/**
22180		 * @desc fired immediately after each slide transition.
22181		 * Play video if autoplayVideoOnSlide option is enabled.
22182		 *
22183		 * @param {Event} event - Javascript Event object.
22184		 * @param {number} prevIndex - Previous index of the slide.
22185		 * @param {number} index - Current index of the slide
22186		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
22187		 */
22188		Video.prototype.onAfterSlide = function (event) {
22189			var _this = this;
22190			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
22191			// Do not call on first slide
22192			var $slide = this.core.getSlideItem(index);
22193			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
22194				if ($slide.hasClass('lg-complete')) {
22195					setTimeout(function () {
22196						_this.loadAndPlayVideo(index);
22197					}, 100);
22198				}
22199			}
22200		};
22201		Video.prototype.loadAndPlayVideo = function (index) {
22202			var $slide = this.core.getSlideItem(index);
22203			var currentGalleryItem = this.core.galleryItems[index];
22204			if (currentGalleryItem.poster) {
22205				this.loadVideoOnPosterClick($slide, true);
22206			}
22207			else {
22208				//Uncode edit ##START##
22209				// this.playVideo(index);
22210				var iframe = $slide.selector.querySelector('iframe');
22211				if ( iframe != null ) {
22212					var data_play = iframe.getAttribute('data-autoplay');
22213					if ( typeof data_play !== 'undefined' ) {
22214						if ( data_play === '1' && this.core.index == index ) {
22215							this.playVideo(index);
22216						} else {
22217							this.pauseVideo(index);
22218						}
22219					}
22220				}
22221				//Uncode edit ##END##
22222			}
22223		};
22224		/**
22225		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22226		 * @param {number} index - Index of the slide
22227		 */
22228		Video.prototype.playVideo = function (index) {
22229			this.controlVideo(index, 'play');
22230		};
22231		/**
22232		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22233		 * @param {number} index - Index of the slide
22234		 */
22235		Video.prototype.pauseVideo = function (index) {
22236			this.controlVideo(index, 'pause');
22237		};
22238		// Uncode edit ##START##
22239		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
22240		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
22241		// Uncode edit ##END##
22242			var video = '';
22243			var videoInfo = this.core.galleryItems[index]
22244				.__slideVideoInfo || {};
22245			var currentGalleryItem = this.core.galleryItems[index];
22246			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
22247			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
22248			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
22249			if (videoInfo.youtube) {
22250				var videoId = 'lg-youtube' + index;
22251				var slideUrlParams = videoInfo.youtube[2]
22252					? videoInfo.youtube[2] + '&'
22253					: '';
22254				// For youtube first parms gets priority if duplicates found
22255				// Uncode edit ##START##
22256				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
22257				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
22258				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
22259					youTubePlayerParams += '&autoplay=0';
22260				}
22261				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
22262					youTubePlayerParams += '&mute=1';
22263				}
22264				var data_video = '';
22265				if ( autoplay !== '' ) {
22266					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
22267					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22268					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
22269					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22270				}
22271				// if ( muted !== '' ) {
22272				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
22273				// }
22274				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
22275
22276				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
22277				// Uncode edit ##END##
22278				var playerParams = youTubePlayerParams +
22279					(this.settings.youTubePlayerParams
22280						? '&' + param(this.settings.youTubePlayerParams)
22281						: '');
22282				// Uncode edit ##START##
22283				// 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>";
22284				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>";
22285				var tag = document.createElement('script');
22286				tag.src = "//www.youtube.com/player_api";
22287				var firstScriptTag = document.getElementsByTagName('script')[0];
22288				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
22289
22290				// Replace the 'ytplayer' element with an <iframe> and
22291				// YouTube player after the API code downloads.
22292				var ytIframeplayer,
22293					setMute = muted === 'yes' ? 0 : 100;
22294				window.onYouTubePlayerAPIReady = function() {
22295					ytIframeplayer = new YT.Player(videoId, {
22296						videoId: videoInfo.youtube[1],
22297						events: {
22298							'onReady': function (event) {
22299								event.target.setVolume(setMute);
22300							}
22301						}
22302					});
22303				}
22304				// Uncode edit ##END##
22305			}
22306			else if (videoInfo.vimeo) {
22307				var videoId = 'lg-vimeo' + index;
22308				// Uncode edit ##START##
22309				videoInfo.autoplay = autoplay;
22310				videoInfo.muted = muted;
22311				// Uncode edit ##END##
22312				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
22313				// Uncode edit ##START##
22314				// 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>";
22315				var data_video = '';
22316				if ( autoplay !== '' ) {
22317					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22318				}
22319				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>";
22320				// Uncode edit ##END##
22321			}
22322			else if (videoInfo.wistia) {
22323				var wistiaId = 'lg-wistia' + index;
22324				var playerParams = param(this.settings.wistiaPlayerParams);
22325				playerParams = playerParams ? '?' + playerParams : '';
22326				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>";
22327			}
22328			else if (videoInfo.html5) {
22329				var html5VideoMarkup = '';
22330				for (var i = 0; i < html5Video.source.length; i++) {
22331					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
22332				}
22333				if (html5Video.tracks) {
22334					var _loop_1 = function (i) {
22335						var trackAttributes = '';
22336						var track = html5Video.tracks[i];
22337						Object.keys(track || {}
22337).forEach(function (key) {
22338							trackAttributes += key + "=\"" + track[key] + "\" ";
22339						});
22340						html5VideoMarkup += "<track " + trackAttributes + ">";
22341					};
22342					for (var i = 0; i < html5Video.tracks.length; i++) {
22343						_loop_1(i);
22344					}
22345				}
22346				var html5VideoAttrs_1 = '';
22347				var videoAttributes_1 = html5Video.attributes || {};
22348				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
22349					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
22350				});
22351				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
22352					? this.settings.videojsTheme + ' '
22353					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
22354			}
22355			return video;
22356		};
22357		/**
22358		 * @desc - Append videos to the slide
22359		 *
22360		 * @param {HTMLElement} el - slide element
22361		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
22362		 */
22363		Video.prototype.appendVideos = function (el, videoParams) {
22364			var _a;
22365			// Uncode edit ##START##
22366			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
22367			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
22368			// Uncode edit ##END##
22369			el.find('.lg-video-cont').append(videoHtml);
22370			var $videoElement = el.find('.lg-video-object').first();
22371			if (videoParams.html5Video) {
22372				$videoElement.on('mousedown.lg.video', function (e) {
22373					e.stopPropagation();
22374				});
22375			}
22376			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
22377				try {
22378					return videojs($videoElement.get(), this.settings.videojsOptions);
22379				}
22380				catch (e) {
22381					console.warn('lightGallery:- Make sure you have included videojs');
22382				}
22383			}
22384		};
22385		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
22386			var _this = this;
22387			var $videoElement = this.core
22388				.getSlideItem(index)
22389				.find('.lg-video-object')
22390				.first();
22391			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22392			if (this.settings.gotoNextSlideOnVideoEnd) {
22393				if (videoInfo.html5) {
22394					$videoElement.on('ended', function () {
22395						_this.core.goToNextSlide();
22396					});
22397				}
22398				else if (videoInfo.vimeo) {
22399					try {
22400						// https://github.com/vimeo/player.js/#ended
22401						new Vimeo.Player($videoElement.get()).on('ended', function () {
22402							_this.core.goToNextSlide();
22403						});
22404					}
22405					catch (e) {
22406						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22407					}
22408				}
22409				else if (videoInfo.wistia) {
22410					try {
22411						window._wq = window._wq || [];
22412						// @todo Event is gettign triggered multiple times
22413						window._wq.push({
22414							id: $videoElement.attr('id'),
22415							onReady: function (video) {
22416								video.bind('end', function () {
22417									_this.core.goToNextSlide();
22418								});
22419							},
22420						});
22421					}
22422					catch (e) {
22423						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22424					}
22425				}
22426			}
22427		};
22428		Video.prototype.controlVideo = function (index, action) {
22429			var $videoElement = this.core
22430				.getSlideItem(index)
22431				.find('.lg-video-object')
22432				.first();
22433			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22434			if (!$videoElement.get())
22435				return;
22436			if (videoInfo.youtube) {
22437				try {
22438					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
22439				}
22440				catch (e) {
22441					console.warn("lightGallery:- " + e);
22442				}
22443			}
22444			else if (videoInfo.vimeo) {
22445				try {
22446					new Vimeo.Player($videoElement.get())[action]();
22447				}
22448				catch (e) {
22449					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22450				}
22451			}
22452			else if (videoInfo.html5) {
22453				if (this.settings.videojs) {
22454					try {
22455						videojs($videoElement.get())[action]();
22456					}
22457					catch (e) {
22458						console.warn('lightGallery:- Make sure you have included videojs');
22459					}
22460				}
22461				else {
22462					$videoElement.get()[action]();
22463				}
22464			}
22465			else if (videoInfo.wistia) {
22466				try {
22467					window._wq = window._wq || [];
22468					// @todo Find a way to destroy wistia player instance
22469					window._wq.push({
22470						id: $videoElement.attr('id'),
22471						onReady: function (video) {
22472							video[action]();
22473						},
22474					});
22475				}
22476				catch (e) {
22477					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22478				}
22479			}
22480		};
22481		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
22482			var _this = this;
22483			// check slide has poster
22484			if (!$el.hasClass('lg-video-loaded')) {
22485				// check already video element present
22486				if (!$el.hasClass('lg-has-video')) {
22487					$el.addClass('lg-has-video');
22488					var _html = void 0;
22489					var _src = this.core.galleryItems[this.core.index].src;
22490					var video = this.core.galleryItems[this.core.index].video;
22491					if (video) {
22492						_html =
22493							typeof video === 'string' ? JSON.parse(video) : video;
22494					}
22495					var videoJsPlayer_1 = this.appendVideos($el, {
22496						src: _src,
22497						addClass: '',
22498						index: this.core.index,
22499						html5Video: _html,
22500					});
22501					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
22502					var $tempImg = $el.find('.lg-object').first().get();
22503					// @todo make sure it is working
22504					$el.find('.lg-video-cont').first().append($tempImg);
22505					$el.addClass('lg-video-loading');
22506					videoJsPlayer_1 &&
22507						videoJsPlayer_1.ready(function () {
22508							videoJsPlayer_1.on('loadedmetadata', function () {
22509								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22510							});
22511						});
22512					$el.find('.lg-video-object')
22513						.first()
22514						.on('load.lg error.lg loadedmetadata.lg', function () {
22515						setTimeout(function () {
22516							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22517						}, 50);
22518					});
22519				}
22520				else {
22521					this.playVideo(this.core.index);
22522				}
22523			}
22524			else if (forcePlay) {
22525				this.playVideo(this.core.index);
22526			}
22527		};
22528		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
22529			$el.addClass('lg-video-loaded');
22530			this.playVideo(index);
22531		};
22532		Video.prototype.destroy = function () {
22533			this.core.LGel.off('.lg.video');
22534			this.core.LGel.off('.video');
22535		};
22536		return Video;
22537	}());
22538
22539	return Video;
22540
22541})));
22542
22543
22544/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
22545!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:{}}
22545),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 22545
22545var 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)}
22545},{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 22545-23752
22545))}(),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});
22546
22547/**
22548 * Owl carousel
22549 * @version 2.0.0-beta.3
22550 * @author Bartosz Wojciechowski
22551 * @license The MIT License (MIT)
22552 * @todo Lazy Load Icon
22553 * @todo prevent animationend bubling
22554 * @todo itemsScaleUp
22555 * @todo Test Zepto
22556 * @todo stagePadding calculate wrong active classes
22557 */
22558;(function($, window, document, undefined) {
22559
22560	/**
22561	 * Creates a carousel.
22562	 * @class The Owl Carousel.
22563	 * @public
22564	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
22565	 * @param {Object} [options] - The options
22566	 */
22567	function Owl(element, options) {
22568
22569		/**
22570		 * Current settings for the carousel.
22571		 * @public
22572		 */
22573		this.settings = null;
22574
22575		/**
22576		 * Current options set by the caller including defaults.
22577		 * @public
22578		 */
22579		this.options = $.extend({}, Owl.Defaults, options);
22580
22581		/**
22582		 * Plugin element.
22583		 * @public
22584		 */
22585		this.$element = $(element);
22586
22587		/**
22588		 * Proxied event handlers.
22589		 * @protected
22590		 */
22591		this._handlers = {};
22592
22593		/**
22594		 * References to the running plugins of this carousel.
22595		 * @protected
22596		 */
22597		this._plugins = {};
22598
22599		/**
22600		 * Currently suppressed events to prevent them from beeing retriggered.
22601		 * @protected
22602		 */
22603		this._supress = {};
22604
22605		/**
22606		 * Absolute current position.
22607		 * @protected
22608		 */
22609		this._current = null;
22610
22611		/**
22612		 * Animation speed in milliseconds.
22613		 * @protected
22614		 */
22615		this._speed = null;
22616
22617		/**
22618		 * Coordinates of all items in pixel.
22619		 * @todo The name of this member is missleading.
22620		 * @protected
22621		 */
22622		this._coordinates = [];
22623
22624		/**
22625		 * Current breakpoint.
22626		 * @todo Real media queries would be nice.
22627		 * @protected
22628		 */
22629		this._breakpoint = null;
22630
22631		/**
22632		 * Current width of the plugin element.
22633		 */
22634		this._width = null;
22635
22636		/**
22637		 * All real items.
22638		 * @protected
22639		 */
22640		this._items = [];
22641
22642		/**
22643		 * All cloned items.
22644		 * @protected
22645		 */
22646		this._clones = [];
22647
22648		/**
22649		 * Merge values of all items.
22650		 * @todo Maybe this could be part of a plugin.
22651		 * @protected
22652		 */
22653		this._mergers = [];
22654
22655		/**
22656		 * Widths of all items.
22657		 */
22658		this._widths = [];
22659
22660		/**
22661		 * Invalidated parts within the update process.
22662		 * @protected
22663		 */
22664		this._invalidated = {};
22665
22666		/**
22667		 * Ordered list of workers for the update process.
22668		 * @protected
22669		 */
22670		this._pipe = [];
22671
22672		/**
22673		 * Current state information for the drag operation.
22674		 * @todo #261
22675		 * @protected
22676		 */
22677		this._drag = {
22678			time: null,
22679			target: null,
22680			pointer: null,
22681			stage: {
22682				start: null,
22683				current: null
22684			},
22685			direction: null
22686		};
22687
22688		/**
22689		 * Current state information and their tags.
22690		 * @type {Object}
22691		 * @protected
22692		 */
22693		this._states = {
22694			current: {},
22695			tags: {
22696				'initializing': [ 'busy' ],
22697				'animating': [ 'busy' ],
22698				'dragging': [ 'interacting' ]
22699			}
22700		};
22701
22702		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
22703			this._handlers[handler] = $.proxy(this[handler], this);
22704		}, this));
22705
22706		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
22707			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
22708				= new plugin(this);
22709		}, this));
22710
22711		$.each(Owl.Workers, $.proxy(function(priority, worker) {
22712			this._pipe.push({
22713				'filter': worker.filter,
22714				'run': $.proxy(worker.run, this)
22715			});
22716		}, this));
22717
22718		this.setup();
22719		this.initialize();
22720	}
22721
22722	/**
22723	 * Default options for the carousel.
22724	 * @public
22725	 */
22726	Owl.Defaults = {
22727		items: 3,
22728		loop: false,
22729		center: false,
22730		rewind: false,
22731
22732		mouseDrag: true,
22733		touchDrag: true,
22734		pullDrag: true,
22735		freeDrag: false,
22736
22737		margin: 0,
22738		stagePadding: 0,
22739
22740		merge: false,
22741		mergeFit: true,
22742		autoWidth: false,
22743
22744		startPosition: 0,
22745		rtl: false,
22746
22747		smartSpeed: 250,
22748		fluidSpeed: false,
22749		dragEndSpeed: false,
22750
22751		responsive: {},
22752		responsiveRefreshRate: 200,
22753		responsiveBaseElement: window,
22754
22755		fallbackEasing: 'swing',
22756
22757		info: false,
22758
22759		nestedItemSelector: false,
22760		itemElement: 'div',
22761		stageElement: 'div',
22762
22763		refreshClass: 'owl-refresh',
22764		loadedClass: 'owl-loaded',
22765		loadingClass: 'owl-loading',
22766		rtlClass: 'owl-rtl',
22767		responsiveClass: 'owl-responsive',
22768		dragClass: 'owl-drag',
22769		itemClass: 'owl-item',
22770		stageClass: 'owl-stage',
22771		stageOuterClass: 'owl-stage-outer',
22772		grabClass: 'owl-grab'
22773	};
22774
22775	/**
22776	 * Enumeration for width.
22777	 * @public
22778	 * @readonly
22779	 * @enum {String}
22780	 */
22781	Owl.Width = {
22782		Default: 'default',
22783		Inner: 'inner',
22784		Outer: 'outer'
22785	};
22786
22787	/**
22788	 * Enumeration for types.
22789	 * @public
22790	 * @readonly
22791	 * @enum {String}
22792	 */
22793	Owl.Type = {
22794		Event: 'event',
22795		State: 'state'
22796	};
22797
22798	/**
22799	 * Contains all registered plugins.
22800	 * @public
22801	 */
22802	Owl.Plugins = {};
22803
22804	/**
22805	 * List of workers involved in the update process.
22806	 */
22807	Owl.Workers = [ {
22808		filter: [ 'width', 'settings' ],
22809		run: function() {
22810			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
22811			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
22812		}
22813	}, {
22814		filter: [ 'width', 'items', 'settings' ],
22815		run: function(cache) {
22816			cache.current = this._items && this._items[this.relative(this._current)];
22817		}
22818	}, {
22819		filter: [ 'items', 'settings' ],
22820		run: function() {
22821			this.$stage.children('.cloned').remove();
22822		}
22823	}, {
22824		filter: [ 'width', 'items', 'settings' ],
22825		run: function(cache) {
22826			var margin = this.settings.margin || '',
22827				grid = !this.settings.autoWidth,
22828				rtl = this.settings.rtl,
22829				css = {
22830					'width': 'auto',
22831					'margin-left': rtl ? margin : '',
22832					'margin-right': rtl ? '' : margin
22833				};
22834
22835			!grid && this.$stage.children().css(css);
22836
22837			cache.css = css;
22838		}
22839	}, {
22840		filter: [ 'width', 'items', 'settings' ],
22841		run: function(cache) {
22842			//UNCODE edit to fix Chrome stage padding issue
22843			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
22844				merge = null,
22845				iterator = this._items.length,
22846				grid = !this.settings.autoWidth,
22847				widths = [];
22848
22849			cache.items = {
22850				merge: false,
22851				width: width
22852			};
22853
22854			while (iterator--) {
22855				merge = this._mergers[iterator];
22856				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
22857
22858				cache.items.merge = merge > 1 || cache.items.merge;
22859
22860				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22861			}
22862
22863			this._widths = widths;
22864		}
22865	}, {
22866		filter: [ 'items', 'settings' ],
22867		run: function() {
22868			var clones = [],
22869				items = this._items,
22870				settings = this.settings,
22871				view = Math.max(settings.items * 2, 4),
22872				size = Math.ceil(items.length / 2) * 2,
22873				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22874				append = '',
22875				prepend = '';
22876
22877			repeat /= 2;
22878
22879			while (repeat--) {
22880				clones.push(this.normalize(clones.length / 2, true));
22881				append = append + items[clones[clones.length - 1]][0].outerHTML;
22882				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22883				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22884			}
22885
22886			this._clones = clones;
22887
22888			// var appendVideo = $(append).find('.uncode-video-container');
22889			// if (appendVideo.length) {
22890			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22891			// }
22892			// var prependVideo = $(prepend).find('.uncode-video-container');
22893			// if (prependVideo.length) {
22894			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22895			// }
22896			$(append).addClass('cloned').appendTo(this.$stage);
22897			$(prepend).addClass('cloned').prependTo(this.$stage);
22898		}
22899	}, {
22900		filter: [ 'width', 'items', 'settings' ],
22901		run: function() {
22902			var rtl = this.settings.rtl ? 1 : -1,
22903				size = this._clones.length + this._items.length,
22904				iterator = -1,
22905				previous = 0,
22906				current = 0,
22907				coordinates = [];
22908
22909			while (++iterator < size) {
22910				previous = coordinates[iterator - 1] || 0;
22911				current = this._widths[this.relative(iterator)] + this.settings.margin;
22912				coordinates.push(previous + current * rtl);
22913			}
22914
22915			this._coordinates = coordinates;
22916		}
22917	}, {
22918		filter: [ 'width', 'items', 'settings' ],
22919		run: function() {
22920			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22921				padding = stagePadding,
22922				coordinates = this._coordinates,
22923				css = {
22924					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22925					'padding-left': padding || '',
22926					'padding-right': padding || ''
22927				};
22928
22929			this.$stage.css(css);
22930		}
22931	}, {
22932		filter: [ 'width', 'items', 'settings' ],
22933		run: function(cache) {
22934			var iterator = this._coordinates.length,
22935				grid = !this.settings.autoWidth,
22936				items = this.$stage.children();
22937
22938			if (grid && cache.items.merge) {
22939				while (iterator--) {
22940					cache.css.width = this._widths[this.relative(iterator)];
22941					items.eq(iterator).css(cache.css);
22942				}
22943			} else if (grid) {
22944				cache.css.width = cache.items.width;
22945				items.css(cache.css);
22946			}
22947		}
22948	}, {
22949		filter: [ 'items' ],
22950		run: function() {
22951			this._coordinates.length < 1 && this.$stage.removeAttr('style');
22952		}
22953	}, {
22954		filter: [ 'width', 'items', 'settings' ],
22955		run: function(cache) {
22956			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
22957			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
22958			this.reset(cache.current);
22959		}
22960	}, {
22961		filter: [ 'position' ],
22962		run: function() {
22963			this.animate(this.coordinates(this._current));
22964		}
22965	}, {
22966		filter: [ 'width', 'position', 'items', 'settings' ],
22967		run: function() {
22968			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22969				rtl = this.settings.rtl ? 1 : -1,
22970				padding = this.settings.stagePadding * 2,
22971				begin = this.coordinates(this.current()) + padding,
22972				end = begin + this.width() * rtl,
22973				inner, outer, matches = [], i, n;
22974
22975			for (i = 0, n = this._coordinates.length; i < n; i++) {
22976				inner = this._coordinates[i - 1] || 0;
22977				outer = Math.abs(this._coordinates[i]) + padding * rtl;
22978
22979				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
22980					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
22981					matches.push(i);
22982				}
22983			}
22984
22985			this.$stage.children('.active').removeClass('active');
22986			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
22987
22988			if (this.settings.center) {
22989				this.$stage.children('.center').removeClass('center');
22990				this.$stage.children().eq(this.current()).addClass('center');
22991			}
22992		}
22993	} ];
22994
22995	/**
22996	 * Initializes the carousel.
22997	 * @protected
22998	 */
22999	Owl.prototype.initialize = function() {
23000		this.enter('initializing');
23001		this.trigger('initialize');
23002
23003		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
23004
23005		if (this.settings.autoWidth && !this.is('pre-loading')) {
23006			var imgs, nestedSelector, width;
23007			imgs = this.$element.find('img');
23008			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
23009			width = this.$element.children(nestedSelector).width();
23010
23011			if (imgs.length && width <= 0) {
23012				this.preloadAutoWidthImages(imgs);
23013			}
23014		}
23015
23016		this.$element.addClass(this.options.loadingClass);
23017
23018		// create stage
23019		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
23020			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
23021
23022		// append stage
23023		this.$element.append(this.$stage.parent());
23024
23025		// append content
23026		this.replace(this.$element.children().not(this.$stage.parent()));
23027
23028		// check visibility
23029		if (this.$element.is(':visible')) {
23030			// update view
23031			this.refresh();
23032		} else {
23033			// invalidate width
23034			this.invalidate('width');
23035		}
23036
23037		this.$element
23038			.removeClass(this.options.loadingClass)
23039			.addClass(this.options.loadedClass);
23040
23041		// register event handlers
23042		this.registerEventHandlers();
23043
23044		this.leave('initializing');
23045		this.trigger('initialized');
23046	};
23047
23048	/**
23049	 * Setups the current settings.
23050	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
23051	 * @todo Support for media queries by using `matchMedia` would be nice.
23052	 * @public
23053	 */
23054	Owl.prototype.setup = function() {
23055		var viewport = this.viewport(),
23056			overwrites = this.options.responsive,
23057			match = -1,
23058			settings = null;
23059
23060		if (!overwrites) {
23061			settings = $.extend({}, this.options);
23062		} else {
23063			$.each(overwrites, function(breakpoint) {
23064				if (breakpoint <= viewport && breakpoint > match) {
23065					match = Number(breakpoint);
23066				}
23067			});
23068
23069			settings = $.extend({}, this.options, overwrites[match]);
23070			delete settings.responsive;
23071
23072			// responsive class
23073			if (settings.responsiveClass) {
23074				this.$element.attr('class',
23075					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
23076				);
23077			}
23078		}
23079
23080		if (this.settings === null || this._breakpoint !== match) {
23081			this.trigger('change', { property: { name: 'settings', value: settings } });
23082			this._breakpoint = match;
23083			this.settings = settings;
23084			this.invalidate('settings');
23085			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
23086		}
23087	};
23088
23089	/**
23090	 * Updates option logic if necessery.
23091	 * @protected
23092	 */
23093	Owl.prototype.optionsLogic = function() {
23094		if (this.settings.autoWidth) {
23095			this.settings.stagePadding = false;
23096			this.settings.merge = false;
23097		}
23098	};
23099
23100	/**
23101	 * Prepares an item before add.
23102	 * @todo Rename event parameter `content` to `item`.
23103	 * @protected
23104	 * @returns {jQuery|HTMLElement} - The item container.
23105	 */
23106	Owl.prototype.prepare = function(item, index) {
23107		var event = this.trigger('prepare', { content: item });
23108		if (!event.data) {
23109			event.data = $('<' + this.settings.itemElement + '/>')
23110				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
23111		}
23112
23113		this.trigger('prepared', { content: event.data });
23114
23115		return event.data;
23116	};
23117
23118	/**
23119	 * Updates the view.
23120	 * @public
23121	 */
23122	Owl.prototype.update = function() {
23123		var i = 0,
23124			n = this._pipe.length,
23125			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
23126			cache = {};
23127
23128		while (i < n) {
23129			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
23130				this._pipe[i].run(cache);
23131			}
23132			i++;
23133		}
23134
23135		this._invalidated = {};
23136
23137		!this.is('valid') && this.enter('valid');
23138	};
23139
23140	/**
23141	 * Gets the width of the view.
23142	 * @public
23143	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
23144	 * @returns {Number} - The width of the view in pixel.
23145	 */
23146	Owl.prototype.width = function(dimension) {
23147		dimension = dimension || Owl.Width.Default;
23148		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
23149		switch (dimension) {
23150			case Owl.Width.Inner:
23151			case Owl.Width.Outer:
23152				return this._width;
23153			default:
23154				return this._width - stagePadding * 2 + this.settings.margin;
23155		}
23156	};
23157
23158	/**
23159	 * Refreshes the carousel primarily for adaptive purposes.
23160	 * @public
23161	 */
23162	Owl.prototype.refresh = function() {
23163		this.enter('refreshing');
23164		this.trigger('refresh');
23165
23166		this.setup();
23167
23168		this.optionsLogic();
23169
23170		this.$element.addClass(this.options.refreshClass);
23171
23172		this.update();
23173
23174		this.$element.removeClass(this.options.refreshClass);
23175
23176		this.leave('refreshing');
23177		this.trigger('refreshed');
23178	};
23179
23180	/**
23181	 * Checks window `resize` event.
23182	 * @protected
23183	 */
23184	Owl.prototype.onThrottledResize = function() {
23185		window.clearTimeout(this.resizeTimer);
23186		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
23187	};
23188
23189	/**
23190	 * Checks window `resize` event.
23191	 * @protected
23192	 */
23193	Owl.prototype.onResize = function() {
23194		if (!this._items.length) {
23195			return false;
23196		}
23197
23198		if (this._width === this.$element.width()) {
23199			return false;
23200		}
23201
23202		if (!this.$element.is(':visible')) {
23203			return false;
23204		}
23205
23206		this.enter('resizing');
23207
23208		if (this.trigger('resize').isDefaultPrevented()) {
23209			this.leave('resizing');
23210			return false;
23211		}
23212
23213		this.invalidate('width');
23214
23215		this.refresh();
23216
23217		this.leave('resizing');
23218		this.trigger('resized');
23219	};
23220
23221	/**
23222	 * Registers event handlers.
23223	 * @todo Check `msPointerEnabled`
23224	 * @todo #261
23225	 * @protected
23226	 */
23227	Owl.prototype.registerEventHandlers = function() {
23228		if ($.support.transition) {
23229			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
23230		}
23231
23232		if (this.settings.responsive !== false) {
23233			this.on(window, 'resize', this._handlers.onThrottledResize);
23234		}
23235
23236		if (this.settings.mouseDrag) {
23237			this.$element.addClass(this.options.dragClass);
23238			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
23239			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
23240		}
23241
23242		if (this.settings.touchDrag){
23243			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
23244			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
23245		}
23246	};
23247
23248	/**
23249	 * Handles `touchstart` and `mousedown` events.
23250	 * @todo Horizontal swipe threshold as option
23251	 * @todo #261
23252	 * @protected
23253	 * @param {Event} event - The event arguments.
23254	 */
23255	Owl.prototype.onDragStart = function(event) {
23256		var stage = null;
23257
23258		if (event.which === 3) {
23259			return;
23260		}
23261
23262		if ($.support.transform) {
23263			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
23264			stage = {
23265				x: stage[stage.length === 16 ? 12 : 4],
23266				y: stage[stage.length === 16 ? 13 : 5]
23267			};
23268		} else {
23269			stage = this.$stage.position();
23270			stage = {
23271				x: this.settings.rtl ?
23272					stage.left + this.$stage.width() - this.width() + this.settings.margin :
23273					stage.left,
23274				y: stage.top
23275			};
23276		}
23277
23278		if (this.is('animating')) {
23279			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
23280			this.invalidate('position');
23281		}
23282
23283		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
23284
23285		this.speed(0);
23286
23287		this._drag.time = new Date().getTime();
23288		this._drag.target = $(event.target);
23289		this._drag.stage.start = stage;
23290		this._drag.stage.current = stage;
23291		this._drag.pointer = this.pointer(event);
23292
23293		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
23294
23295		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
23296			var delta = this.difference(this._drag.pointer, this.pointer(event));
23297
23298			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
23299
23300			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
23301				return;
23302			}
23303
23304			event.preventDefault();
23305
23306			this.enter('dragging');
23307			this.trigger('drag');
23308		}, this));
23309	};
23310
23311	/**
23312	 * Handles the `touchmove` and `mousemove` events.
23313	 * @todo #261
23314	 * @protected
23315	 * @param {Event} event - The event arguments.
23316	 */
23317	Owl.prototype.onDragMove = function(event) {
23318		var minimum = null,
23319			maximum = null,
23320			pull = null,
23321			delta = this.difference(this._drag.pointer, this.pointer(event)),
23322			stage = this.difference(this._drag.stage.start, delta);
23323
23324		if (!this.is('dragging')) {
23325			return;
23326		}
23327
23328		event.preventDefault();
23329
23330		if (this.settings.loop) {
23331			minimum = this.coordinates(this.minimum());
23332			maximum = this.coordinates(this.maximum() + 1) - minimum;
23333			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
23334		} else {
23335			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
23336			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
23337			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
23338			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
23339		}
23340
23341		this._drag.stage.current = stage;
23342
23343		this.animate(stage.x);
23344	};
23345
23346	/**
23347	 * Handles the `touchend` and `mouseup` events.
23348	 * @todo #261
23349	 * @todo Threshold for click event
23350	 * @protected
23351	 * @param {Event} event - The event arguments.
23352	 */
23353	Owl.prototype.onDragEnd = function(event) {
23354		var delta = this.difference(this._drag.pointer, this.pointer(event)),
23355			stage = this._drag.stage.current,
23356			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
23357
23358		$(document).off('.owl.core');
23359
23360		this.$element.removeClass(this.options.grabClass);
23361
23362		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
23363			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
23364			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
23365			this.invalidate('position');
23366			this.update();
23367
23368			this._drag.direction = direction;
23369
23370			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
23371				this._drag.target.one('click.owl.core', function() { return false; });
23372			}
23373		}
23374
23375		if (!this.is('dragging')) {
23376			return;
23377		}
23378
23379		this.leave('dragging');
23380		this.trigger('dragged');
23381	};
23382
23383	/**
23384	 * Gets absolute position of the closest item for a coordinate.
23385	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
23386	 * @protected
23387	 * @param {Number} coordinate - The coordinate in pixel.
23388	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
23389	 * @return {Number} - The absolute position of the closest item.
23390	 */
23391	Owl.prototype.closest = function(coordinate, direction) {
23392		var position = -1,
23393			pull = 30,
23394			width = this.width(),
23395			coordinates = this.coordinates();
23396
23397		if (!this.settings.freeDrag) {
23398			// check closest item
23399			$.each(coordinates, $.proxy(function(index, value) {
23400				if (coordinate > value - pull && coordinate < value + pull) {
23401					position = index;
23402				} else if (this.op(coordinate, '<', value)
23403					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
23404					position = direction === 'left' ? index + 1 : index;
23405				}
23406				return position === -1;
23407			}, this));
23408		}
23409
23410		if (!this.settings.loop) {
23411			// non loop boundries
23412			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
23413				position = coordinate = this.minimum();
23414			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
23415				position = coordinate = this.maximum();
23416			}
23417		}
23418
23419		return position;
23420	};
23421
23422	/**
23423	 * Animates the stage.
23424	 * @todo #270
23425	 * @public
23426	 * @param {Number} coordinate - The coordinate in pixels.
23427	 */
23428	Owl.prototype.animate = function(coordinate) {
23429		var animate = this.speed() > 0;
23430
23431		this.is('animating') && this.onTransitionEnd();
23432
23433		if (animate) {
23434			this.enter('animating');
23435			this.trigger('translate');
23436		}
23437
23438		if ($.support.transform3d && $.support.transition) {
23439			this.$stage.css({
23440				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
23441				transition: (this.speed() / 1000) + 's'
23442			});
23443		} else if (animate) {
23444			this.$stage.animate({
23445				left: coordinate + 'px'
23446			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
23447		} else {
23448			this.$stage.css({
23449				left: coordinate + 'px'
23450			});
23451		}
23452	};
23453
23454	/**
23455	 * Checks whether the carousel is in a specific state or not.
23456	 * @param {String} state - The state to check.
23457	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
23458	 */
23459	Owl.prototype.is = function(state) {
23460		return this._states.current[state] && this._states.current[state] > 0;
23461	};
23462
23463	/**
23464	 * Sets the absolute position of the current item.
23465	 * @public
23466	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
23467	 * @returns {Number} - The absolute position of the current item.
23468	 */
23469	Owl.prototype.current = function(position) {
23470		if (position === undefined) {
23471			return this._current;
23472		}
23473
23474		if (this._items.length === 0) {
23475			return undefined;
23476		}
23477
23478		position = this.normalize(position);
23479
23480		if (this._current !== position) {
23481			var event = this.trigger('change', { property: { name: 'position', value: position } });
23482
23483			if (event.data !== undefined) {
23484				position = this.normalize(event.data);
23485			}
23486
23487			this._current = position;
23488
23489			this.invalidate('position');
23490
23491			this.trigger('changed', { property: { name: 'position', value: this._current } });
23492		}
23493
23494		return this._current;
23495	};
23496
23497	/**
23498	 * Invalidates the given part of the update routine.
23499	 * @param {String} [part] - The part to invalidate.
23500	 * @returns {Array.<String>} - The invalidated parts.
23501	 */
23502	Owl.prototype.invalidate = function(part) {
23503		if ($.type(part) === 'string') {
23504			this._invalidated[part] = true;
23505			this.is('valid') && this.leave('valid');
23506		}
23507		return $.map(this._invalidated, function(v, i) { return i });
23508	};
23509
23510	/**
23511	 * Resets the absolute position of the current item.
23512	 * @public
23513	 * @param {Number} position - The absolute position of the new item.
23514	 */
23515	Owl.prototype.reset = function(position) {
23516		position = this.normalize(position);
23517
23518		if (position === undefined) {
23519			return;
23520		}
23521
23522		this._speed = 0;
23523		this._current = position;
23524
23525		this.suppress([ 'translate', 'translated' ]);
23526
23527		this.animate(this.coordinates(position));
23528
23529		this.release([ 'translate', 'translated' ]);
23530	};
23531
23532	/**
23533	 * Normalizes an absolute or a relative position of an item.
23534	 * @public
23535	 * @param {Number} position - The absolute or relative position to normalize.
23536	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
23537	 * @returns {Number} - The normalized position.
23538	 */
23539	Owl.prototype.normalize = function(position, relative) {
23540		var n = this._items.length,
23541			m = relative ? 0 : this._clones.length;
23542
23543		if (!$.isNumeric(position) || n < 1) {
23544			position = undefined;
23545		} else if (position < 0 || position >= n + m) {
23546			position = ((position - m / 2) % n + n) % n + m / 2;
23547		}
23548
23549		return position;
23550	};
23551
23552	/**
23553	 * Converts an absolute position of an item into a relative one.
23554	 * @public
23555	 * @param {Number} position - The absolute position to convert.
23556	 * @returns {Number} - The converted position.
23557	 */
23558	Owl.prototype.relative = function(position) {
23559		position -= this._clones.length / 2;
23560		return this.normalize(position, true);
23561	};
23562
23563	/**
23564	 * Gets the maximum position for the current item.
23565	 * @public
23566	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23567	 * @returns {Number}
23568	 */
23569	Owl.prototype.maximum = function(relative) {
23570		var settings = this.settings,
23571			maximum = this._coordinates.length,
23572			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
23573			i = -1, j;
23574
23575		if (settings.loop) {
23576			maximum = this._clones.length / 2 + this._items.length - 1;
23577		} else if (settings.autoWidth || settings.merge) {
23578			// binary search
23579			while (maximum - i > 1) {
23580				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
23581					? i = j : maximum = j;
23582			}
23583		} else if (settings.center) {
23584			maximum = this._items.length - 1;
23585		} else {
23586			maximum = this._items.length - settings.items;
23587		}
23588
23589		if (relative) {
23590			maximum -= this._clones.length / 2;
23591		}
23592
23593		return Math.max(maximum, 0);
23594	};
23595
23596	/**
23597	 * Gets the minimum position for the current item.
23598	 * @public
23599	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23600	 * @returns {Number}
23601	 */
23602	Owl.prototype.minimum = function(relative) {
23603		return relative ? 0 : this._clones.length / 2;
23604	};
23605
23606	/**
23607	 * Gets an item at the specified relative position.
23608	 * @public
23609	 * @param {Number} [position] - The relative position of the item.
23610	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23611	 */
23612	Owl.prototype.items = function(position) {
23613		if (position === undefined) {
23614			return this._items.slice();
23615		}
23616
23617		position = this.normalize(position, true);
23618		return this._items[position];
23619	};
23620
23621	/**
23622	 * Gets an item at the specified relative position.
23623	 * @public
23624	 * @param {Number} [position] - The relative position of the item.
23625	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23626	 */
23627	Owl.prototype.mergers = function(position) {
23628		if (position === undefined) {
23629			return this._mergers.slice();
23630		}
23631
23632		position = this.normalize(position, true);
23633		return this._mergers[position];
23634	};
23635
23636	/**
23637	 * Gets the absolute positions of clones for an item.
23638	 * @public
23639	 * @param {Number} [position] - The relative position of the item.
23640	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
23641	 */
23642	Owl.prototype.clones = function(position) {
23643		var odd = this._clones.length / 2,
23644			even = odd + this._items.length,
23645			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
23646
23647		if (position === undefined) {
23648			return $.map(this._clones, function(v, i) { return map(i) });
23649		}
23650
23651		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
23652	};
23653
23654	/**
23655	 * Sets the current animation speed.
23656	 * @public
23657	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
23658	 * @returns {Number} - The current animation speed in milliseconds.
23659	 */
23660	Owl.prototype.speed = function(speed) {
23661		if (speed !== undefined) {
23662			this._speed = speed;
23663		}
23664
23665		return this._speed;
23666	};
23667
23668	/**
23669	 * Gets the coordinate of an item.
23670	 * @todo The name of this method is missleanding.
23671	 * @public
23672	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
23673	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
23674	 */
23675	Owl.prototype.coordinates = function(position) {
23676		var coordinate = null;
23677
23678		if (position === undefined) {
23679			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
23680				return this.coordinates(index);
23681			}, this));
23682		}
23683
23684		if (this.settings.center) {
23685			coordinate = this._coordinates[position];
23686			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
23687		} else {
23688			coordinate = this._coordinates[position - 1] || 0;
23689		}
23690
23691		return coordinate;
23692	};
23693
23694	/**
23695	 * Calculates the speed for a translation.
23696	 * @protected
23697	 * @param {Number} from - The absolute position of the start item.
23698	 * @param {Number} to - The absolute position of the target item.
23699	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
23700	 * @returns {Number} - The time in milliseconds for the translation.
23701	 */
23702	Owl.prototype.duration = function(from, to, factor) {
23703		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
23704	};
23705
23706	/**
23707	 * Slides to the specified item.
23708	 * @public
23709	 * @param {Number} position - The position of the item.
23710	 * @param {Number} [speed] - The time in milliseconds for the transition.
23711	 */
23712	Owl.prototype.to = function(position, speed) {
23713		var current = this.current(),
23714			revert = null,
23715			distance = position - this.relative(current),
23716			direction = (distance > 0) - (distance < 0),
23717			items = this._items.length,
23718			minimum = this.minimum(),
23719			maximum = this.maximum();
23720
23721		if (this.settings.loop) {
23722			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
23723				distance += direction * -1 * items;
23724			}
23725
23726			position = current + distance;
23727			revert = ((position - minimum) % items + items) % items + minimum;
23728
23729			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
23730				current = revert - distance;
23731				position = revert;
23732				this.reset(current);
23733			}
23734		} else if (this.settings.rewind) {
23735			maximum += 1;
23736			position = (position % maximum + maximum) % maximum;
23737		} else {
23738			position = Math.max(minimum, Math.min(maximum, position));
23739		}
23740
23741		this.speed(this.duration(current, position, speed));
23742		this.current(position);
23743
23744		if (this.$element.is(':visible')) {
23745			this.update();
23746		}
23747	};
23748
23749	/**
23750	 * Slides to the next item.
23751	 * @public
23752	 * @param {Number}
vendor: 12,284 bytes, lines 23752-24172
23752 [speed] - The time in milliseconds for the transition.
23753	 */
23754	Owl.prototype.next = function(speed) {
23755		speed = speed || false;
23756		this.to(this.relative(this.current()) + 1, speed);
23757	};
23758
23759	/**
23760	 * Slides to the previous item.
23761	 * @public
23762	 * @param {Number} [speed] - The time in milliseconds for the transition.
23763	 */
23764	Owl.prototype.prev = function(speed) {
23765		speed = speed || false;
23766		this.to(this.relative(this.current()) - 1, speed);
23767	};
23768
23769	/**
23770	 * Handles the end of an animation.
23771	 * @protected
23772	 * @param {Event} event - The event arguments.
23773	 */
23774	Owl.prototype.onTransitionEnd = function(event) {
23775
23776		// if css2 animation then event object is undefined
23777		if (event !== undefined) {
23778			event.stopPropagation();
23779
23780			// Catch only owl-stage transitionEnd event
23781			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
23782				return false;
23783			}
23784		}
23785
23786		this.leave('animating');
23787		this.trigger('translated');
23788	};
23789
23790	/**
23791	 * Gets viewport width.
23792	 * @protected
23793	 * @return {Number} - The width in pixel.
23794	 */
23795	Owl.prototype.viewport = function() {
23796		var width;
23797		if (this.options.responsiveBaseElement !== window) {
23798			width = $(this.options.responsiveBaseElement).width();
23799		} else if (window.innerWidth) {
23800			width = window.innerWidth;
23801		} else if (document.documentElement && document.documentElement.clientWidth) {
23802			width = document.documentElement.clientWidth;
23803		} else {
23804			throw 'Can not detect viewport width.';
23805		}
23806
23807		return width;
23808	};
23809
23810	/**
23811	 * Replaces the current content.
23812	 * @public
23813	 * @param {HTMLElement|jQuery|String} content - The new content.
23814	 */
23815	Owl.prototype.replace = function(content) {
23816		this.$stage.empty();
23817		this._items = [];
23818
23819		if (content) {
23820			content = (content instanceof jQuery) ? content : $(content);
23821		}
23822
23823		if (this.settings.nestedItemSelector) {
23824			content = content.find('.' + this.settings.nestedItemSelector);
23825		}
23826
23827		content.filter(function() {
23828			return this.nodeType === 1;
23829		}).each($.proxy(function(index, item) {
23830			item = this.prepare(item, index);
23831			this.$stage.append(item);
23832			this._items.push(item);
23833			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
23834		}, this));
23835
23836		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
23837
23838		this.invalidate('items');
23839	};
23840
23841	/**
23842	 * Adds an item.
23843	 * @todo Use `item` instead of `content` for the event arguments.
23844	 * @public
23845	 * @param {HTMLElement|jQuery|String} content - The item content to add.
23846	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
23847	 */
23848	Owl.prototype.add = function(content, position) {
23849		var current = this.relative(this._current);
23850
23851		position = position === undefined ? this._items.length : this.normalize(position, true);
23852		content = content instanceof jQuery ? content : $(content);
23853
23854		this.trigger('add', { content: content, position: position });
23855
23856		content = this.prepare(content, this._items[current].index());
23857
23858		if (this._items.length === 0 || position === this._items.length) {
23859			this._items.length === 0 && this.$stage.append(content);
23860			this._items.length !== 0 && this._items[position - 1].after(content);
23861			this._items.push(content);
23862			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23863		} else {
23864			this._items[position].before(content);
23865			this._items.splice(position, 0, content);
23866			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23867		}
23868
23869		this._items[current] && this.reset(this._items[current].index());
23870
23871		this.invalidate('items');
23872
23873		this.trigger('added', { content: content, position: position });
23874	};
23875
23876	/**
23877	 * Removes an item by its position.
23878	 * @todo Use `item` instead of `content` for the event arguments.
23879	 * @public
23880	 * @param {Number} position - The relative position of the item to remove.
23881	 */
23882	Owl.prototype.remove = function(position) {
23883		position = this.normalize(position, true);
23884
23885		if (position === undefined) {
23886			return;
23887		}
23888
23889		this.trigger('remove', { content: this._items[position], position: position });
23890
23891		this._items[position].remove();
23892		this._items.splice(position, 1);
23893		this._mergers.splice(position, 1);
23894
23895		this.invalidate('items');
23896
23897		this.trigger('removed', { content: null, position: position });
23898	};
23899
23900	/**
23901	 * Preloads images with auto width.
23902	 * @todo Replace by a more generic approach
23903	 * @protected
23904	 */
23905	Owl.prototype.preloadAutoWidthImages = function(images) {
23906		images.each($.proxy(function(i, element) {
23907			this.enter('pre-loading');
23908			element = $(element);
23909			$(new Image()).one('load', $.proxy(function(e) {
23910				element.attr('src', e.target.src);
23911				element.css('opacity', 1);
23912				this.leave('pre-loading');
23913				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23914			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23915		}, this));
23916	};
23917
23918	/**
23919	 * Destroys the carousel.
23920	 * @public
23921	 */
23922	Owl.prototype.destroy = function() {
23923
23924		this.$element.off('.owl.core');
23925		this.$stage.off('.owl.core');
23926		$(document).off('.owl.core');
23927
23928		if (this.settings.responsive !== false) {
23929			window.clearTimeout(this.resizeTimer);
23930			this.off(window, 'resize', this._handlers.onThrottledResize);
23931		}
23932
23933		for (var i in this._plugins) {
23934			this._plugins[i].destroy();
23935		}
23936
23937		this.$stage.children('.cloned').remove();
23938
23939		this.$stage.unwrap();
23940		this.$stage.children().contents().unwrap();
23941		this.$stage.children().unwrap();
23942
23943		this.$element
23944			.removeClass(this.options.refreshClass)
23945			.removeClass(this.options.loadingClass)
23946			.removeClass(this.options.loadedClass)
23947			.removeClass(this.options.rtlClass)
23948			.removeClass(this.options.dragClass)
23949			.removeClass(this.options.grabClass)
23950			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
23951			.removeData('owl.carousel');
23952	};
23953
23954	/**
23955	 * Operators to calculate right-to-left and left-to-right.
23956	 * @protected
23957	 * @param {Number} [a] - The left side operand.
23958	 * @param {String} [o] - The operator.
23959	 * @param {Number} [b] - The right side operand.
23960	 */
23961	Owl.prototype.op = function(a, o, b) {
23962		var rtl = this.settings.rtl;
23963		switch (o) {
23964			case '<':
23965				return rtl ? a > b : a < b;
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			default:
23973				break;
23974		}
23975	};
23976
23977	/**
23978	 * Attaches to an internal event.
23979	 * @protected
23980	 * @param {HTMLElement} element - The event source.
23981	 * @param {String} event - The event name.
23982	 * @param {Function} listener - The event handler to attach.
23983	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
23984	 */
23985	Owl.prototype.on = function(element, event, listener, capture) {
23986		if (element.addEventListener) {
23987			element.addEventListener(event, listener, capture);
23988		} else if (element.attachEvent) {
23989			element.attachEvent('on' + event, listener);
23990		}
23991	};
23992
23993	/**
23994	 * Detaches from an internal event.
23995	 * @protected
23996	 * @param {HTMLElement} element - The event source.
23997	 * @param {String} event - The event name.
23998	 * @param {Function} listener - The attached event handler to detach.
23999	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
24000	 */
24001	Owl.prototype.off = function(element, event, listener, capture) {
24002		if (element.removeEventListener) {
24003			element.removeEventListener(event, listener, capture);
24004		} else if (element.detachEvent) {
24005			element.detachEvent('on' + event, listener);
24006		}
24007	};
24008
24009	/**
24010	 * Triggers a public event.
24011	 * @todo Remove `status`, `relatedTarget` should be used instead.
24012	 * @protected
24013	 * @param {String} name - The event name.
24014	 * @param {*} [data=null] - The event data.
24015	 * @param {String} [namespace=carousel] - The event namespace.
24016	 * @param {String} [state] - The state which is associated with the event.
24017	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
24018	 * @returns {Event} - The event arguments.
24019	 */
24020	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
24021		var status = {
24022			item: { count: this._items.length, index: this.current() }
24023		}, handler = $.camelCase(
24024			$.grep([ 'on', name, namespace ], function(v) { return v })
24025				.join('-').toLowerCase()
24026		), event = $.Event(
24027			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
24028			$.extend({ relatedTarget: this }, status, data)
24029		);
24030
24031		if (!this._supress[name]) {
24032			$.each(this._plugins, function(name, plugin) {
24033				if (plugin.onTrigger) {
24034					plugin.onTrigger(event);
24035				}
24036			});
24037
24038			this.register({ type: Owl.Type.Event, name: name });
24039			this.$element.trigger(event);
24040
24041			if (this.settings && typeof this.settings[handler] === 'function') {
24042				this.settings[handler].call(this, event);
24043			}
24044		}
24045
24046		return event;
24047	};
24048
24049	/**
24050	 * Enters a state.
24051	 * @param name - The state name.
24052	 */
24053	Owl.prototype.enter = function(name) {
24054		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24055			if (this._states.current[name] === undefined) {
24056				this._states.current[name] = 0;
24057			}
24058
24059			this._states.current[name]++;
24060		}, this));
24061	};
24062
24063	/**
24064	 * Leaves a state.
24065	 * @param name - The state name.
24066	 */
24067	Owl.prototype.leave = function(name) {
24068		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24069			this._states.current[name]--;
24070		}, this));
24071	};
24072
24073	/**
24074	 * Registers an event or state.
24075	 * @public
24076	 * @param {Object} object - The event or state to register.
24077	 */
24078	Owl.prototype.register = function(object) {
24079		if (object.type === Owl.Type.Event) {
24080			if (!$.event.special[object.name]) {
24081				$.event.special[object.name] = {};
24082			}
24083
24084			if (!$.event.special[object.name].owl) {
24085				var _default = $.event.special[object.name]._default;
24086				$.event.special[object.name]._default = function(e) {
24087					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
24088						return _default.apply(this, arguments);
24089					}
24090					return e.namespace && e.namespace.indexOf('owl') > -1;
24091				};
24092				$.event.special[object.name].owl = true;
24093			}
24094		} else if (object.type === Owl.Type.State) {
24095			if (!this._states.tags[object.name]) {
24096				this._states.tags[object.name] = object.tags;
24097			} else {
24098				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
24099			}
24100
24101			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
24102				return $.inArray(tag, this._states.tags[object.name]) === i;
24103			}, this));
24104		}
24105	};
24106
24107	/**
24108	 * Suppresses events.
24109	 * @protected
24110	 * @param {Array.<String>} events - The events to suppress.
24111	 */
24112	Owl.prototype.suppress = function(events) {
24113		$.each(events, $.proxy(function(index, event) {
24114			this._supress[event] = true;
24115		}, this));
24116	};
24117
24118	/**
24119	 * Releases suppressed events.
24120	 * @protected
24121	 * @param {Array.<String>} events - The events to release.
24122	 */
24123	Owl.prototype.release = function(events) {
24124		$.each(events, $.proxy(function(index, event) {
24125			delete this._supress[event];
24126		}, this));
24127	};
24128
24129	/**
24130	 * Gets unified pointer coordinates from event.
24131	 * @todo #261
24132	 * @protected
24133	 * @param {Event} - The `mousedown` or `touchstart` event.
24134	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
24135	 */
24136	Owl.prototype.pointer = function(event) {
24137		var result = { x: null, y: null };
24138
24139		event = event.originalEvent || event || window.event;
24140
24141		event = event.touches && event.touches.length ?
24142			event.touches[0] : event.changedTouches && event.changedTouches.length ?
24143				event.changedTouches[0] : event;
24144
24145		if (event.pageX) {
24146			result.x = event.pageX;
24147			result.y = event.pageY;
24148		} else {
24149			result.x = event.clientX;
24150			result.y = event.clientY;
24151		}
24152
24153		return result;
24154	};
24155
24156	/**
24157	 * Gets the difference of two vectors.
24158	 * @todo #261
24159	 * @protected
24160	 * @param {Object} - The first vector.
24161	 * @param {Object} - The second vector.
24162	 * @returns {Object} - The difference.
24163	 */
24164	Owl.prototype.difference = function(first, second) {
24165		return {
24166			x: first.x - second.x,
24167			y: first.y - second.y
24168		};
24169	};
24170
24171	/**
24172	 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 24173-25455
24173	 * @todo Navigation plugin `next` and `prev`
24174	 * @public
24175	 */
24176	$.fn.owlCarousel = function(option) {
24177		var args = Array.prototype.slice.call(arguments, 1);
24178
24179		return this.each(function() {
24180			var $this = $(this),
24181				data = $this.data('owl.carousel');
24182
24183			if (!data) {
24184				data = new Owl(this, typeof option == 'object' && option);
24185				$this.data('owl.carousel', data);
24186
24187				$.each([
24188					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
24189				], function(i, event) {
24190					data.register({ type: Owl.Type.Event, name: event });
24191					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
24192						if (e.namespace && e.relatedTarget !== this) {
24193							this.suppress([ event ]);
24194							data[event].apply(this, [].slice.call(arguments, 1));
24195							this.release([ event ]);
24196						}
24197					}, data));
24198				});
24199			}
24200
24201			if (typeof option == 'string' && option.charAt(0) !== '_') {
24202				data[option].apply(data, args);
24203			}
24204		});
24205	};
24206
24207	/**
24208	 * The constructor for the jQuery Plugin
24209	 * @public
24210	 */
24211	$.fn.owlCarousel.Constructor = Owl;
24212
24213})(window.Zepto || window.jQuery, window, document);
24214
24215/**
24216 * AutoRefresh Plugin
24217 * @version 2.0.0-beta.3
24218 * @author Artus Kolanowski
24219 * @license The MIT License (MIT)
24220 */
24221;(function($, window, document, undefined) {
24222
24223	/**
24224	 * Creates the auto refresh plugin.
24225	 * @class The Auto Refresh Plugin
24226	 * @param {Owl} carousel - The Owl Carousel
24227	 */
24228	var AutoRefresh = function(carousel) {
24229		/**
24230		 * Reference to the core.
24231		 * @protected
24232		 * @type {Owl}
24233		 */
24234		this._core = carousel;
24235
24236		/**
24237		 * Refresh interval.
24238		 * @protected
24239		 * @type {number}
24240		 */
24241		this._interval = null;
24242
24243		/**
24244		 * Whether the element is currently visible or not.
24245		 * @protected
24246		 * @type {Boolean}
24247		 */
24248		this._visible = null;
24249
24250		/**
24251		 * All event handlers.
24252		 * @protected
24253		 * @type {Object}
24254		 */
24255		this._handlers = {
24256			'initialized.owl.carousel': $.proxy(function(e) {
24257				if (e.namespace && this._core.settings.autoRefresh) {
24258					this.watch();
24259				}
24260			}, this)
24261		};
24262
24263		// set default options
24264		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
24265
24266		// register event handlers
24267		this._core.$element.on(this._handlers);
24268	};
24269
24270	/**
24271	 * Default options.
24272	 * @public
24273	 */
24274	AutoRefresh.Defaults = {
24275		autoRefresh: true,
24276		autoRefreshInterval: 500
24277	};
24278
24279	/**
24280	 * Watches the element.
24281	 */
24282	AutoRefresh.prototype.watch = function() {
24283		if (this._interval) {
24284			return;
24285		}
24286
24287		this._visible = this._core.$element.is(':visible');
24288		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
24289	};
24290
24291	/**
24292	 * Refreshes the element.
24293	 */
24294	AutoRefresh.prototype.refresh = function() {
24295		if (this._core.$element.is(':visible') === this._visible) {
24296			return;
24297		}
24298
24299		this._visible = !this._visible;
24300
24301		this._core.$element.toggleClass('owl-hidden', !this._visible);
24302
24303		this._visible && (this._core.invalidate('width') && this._core.refresh());
24304	};
24305
24306	/**
24307	 * Destroys the plugin.
24308	 */
24309	AutoRefresh.prototype.destroy = function() {
24310		var handler, property;
24311
24312		window.clearInterval(this._interval);
24313
24314		for (handler in this._handlers) {
24315			this._core.$element.off(handler, this._handlers[handler]);
24316		}
24317		for (property in Object.getOwnPropertyNames(this)) {
24318			typeof this[property] != 'function' && (this[property] = null);
24319		}
24320	};
24321
24322	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
24323
24324})(window.Zepto || window.jQuery, window, document);
24325
24326/**
24327 * Lazy Plugin
24328 * @version 2.0.0-beta.3
24329 * @author Bartosz Wojciechowski
24330 * @license The MIT License (MIT)
24331 */
24332;(function($, window, document, undefined) {
24333
24334	/**
24335	 * Creates the lazy plugin.
24336	 * @class The Lazy Plugin
24337	 * @param {Owl} carousel - The Owl Carousel
24338	 */
24339	var Lazy = function(carousel) {
24340
24341		/**
24342		 * Reference to the core.
24343		 * @protected
24344		 * @type {Owl}
24345		 */
24346		this._core = carousel;
24347
24348		/**
24349		 * Already loaded items.
24350		 * @protected
24351		 * @type {Array.<jQuery>}
24352		 */
24353		this._loaded = [];
24354
24355		/**
24356		 * Event handlers.
24357		 * @protected
24358		 * @type {Object}
24359		 */
24360		this._handlers = {
24361			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
24362				if (!e.namespace) {
24363					return;
24364				}
24365
24366				if (!this._core.settings || !this._core.settings.lazyLoad) {
24367					return;
24368				}
24369
24370				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
24371					var settings = this._core.settings,
24372						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
24373						i = ((settings.center && n * -1) || 0),
24374						position = ((e.property && e.property.value) || this._core.current()) + i,
24375						clones = this._core.clones().length,
24376						load = $.proxy(function(i, v) { this.load(v) }, this);
24377
24378					while (i++ < n) {
24379						this.load(clones / 2 + this._core.relative(position));
24380						clones && $.each(this._core.clones(this._core.relative(position)), load);
24381						position++;
24382					}
24383				}
24384			}, this)
24385		};
24386
24387		// set the default options
24388		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
24389
24390		// register event handler
24391		this._core.$element.on(this._handlers);
24392	}
24393
24394	/**
24395	 * Default options.
24396	 * @public
24397	 */
24398	Lazy.Defaults = {
24399		lazyLoad: false
24400	}
24401
24402	/**
24403	 * Loads all resources of an item at the specified position.
24404	 * @param {Number} position - The absolute position of the item.
24405	 * @protected
24406	 */
24407	Lazy.prototype.load = function(position) {
24408		var $item = this._core.$stage.children().eq(position),
24409			$elements = $item && $item.find('.owl-lazy');
24410
24411		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
24412			return;
24413		}
24414
24415		$elements.each($.proxy(function(index, element) {
24416			var $element = $(element), image,
24417				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
24418
24419			this._core.trigger('load', { element: $element, url: url }, 'lazy');
24420
24421			if ($element.is('img')) {
24422				$element.one('load.owl.lazy', $.proxy(function() {
24423					$element.css('opacity', 1);
24424					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24425				}, this)).attr('src', url);
24426			} else {
24427				image = new Image();
24428				image.onload = $.proxy(function() {
24429					$element.css({
24430						'background-image': 'url(' + url + ')',
24431						'opacity': '1'
24432					});
24433					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24434				}, this);
24435				image.src = url;
24436			}
24437		}, this));
24438
24439		this._loaded.push($item.get(0));
24440	}
24441
24442	/**
24443	 * Destroys the plugin.
24444	 * @public
24445	 */
24446	Lazy.prototype.destroy = function() {
24447		var handler, property;
24448
24449		for (handler in this.handlers) {
24450			this._core.$element.off(handler, this.handlers[handler]);
24451		}
24452		for (property in Object.getOwnPropertyNames(this)) {
24453			typeof this[property] != 'function' && (this[property] = null);
24454		}
24455	};
24456
24457	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
24458
24459})(window.Zepto || window.jQuery, window, document);
24460
24461/**
24462 * AutoHeight Plugin
24463 * @version 2.0.0-beta.3
24464 * @author Bartosz Wojciechowski
24465 * @license The MIT License (MIT)
24466 */
24467;(function($, window, document, undefined) {
24468
24469	/**
24470	 * Creates the auto height plugin.
24471	 * @class The Auto Height Plugin
24472	 * @param {Owl} carousel - The Owl Carousel
24473	 */
24474	var AutoHeight = function(carousel) {
24475		/**
24476		 * Reference to the core.
24477		 * @protected
24478		 * @type {Owl}
24479		 */
24480		this._core = carousel;
24481
24482		/**
24483		 * All event handlers.
24484		 * @protected
24485		 * @type {Object}
24486		 */
24487		this._handlers = {
24488			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
24489				if (e.namespace && this._core.settings.autoHeight) {
24490					this.update();
24491				}
24492			}, this),
24493			'changed.owl.carousel': $.proxy(function(e) {
24494				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
24495					this.update();
24496				}
24497			}, this),
24498			'loaded.owl.lazy': $.proxy(function(e) {
24499				if (e.namespace && this._core.settings.autoHeight
24500					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
24501					this.update();
24502				}
24503			}, this)
24504		};
24505
24506		// set default options
24507		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
24508
24509		// register event handlers
24510		this._core.$element.on(this._handlers);
24511	};
24512
24513	/**
24514	 * Default options.
24515	 * @public
24516	 */
24517	AutoHeight.Defaults = {
24518		autoHeight: false,
24519		autoHeightClass: 'owl-height'
24520	};
24521
24522	/**
24523	 * Updates the view.
24524	 */
24525	AutoHeight.prototype.update = function() {
24526		var start = this._core._current,
24527			end = start + this._core.settings.items,
24528			visible = this._core.$stage.children().toArray().slice(start, end);
24529			heights = [],
24530			maxheight = 0;
24531
24532		$.each(visible, function(index, item) {
24533			heights.push($(item).height());
24534		});
24535
24536		maxheight = Math.max.apply(null, heights);
24537
24538		this._core.$stage.parent()
24539			.height(maxheight)
24540			.addClass(this._core.settings.autoHeightClass);
24541	};
24542
24543	AutoHeight.prototype.destroy = function() {
24544		var handler, property;
24545
24546		for (handler in this._handlers) {
24547			this._core.$element.off(handler, this._handlers[handler]);
24548		}
24549		for (property in Object.getOwnPropertyNames(this)) {
24550			typeof this[property] != 'function' && (this[property] = null);
24551		}
24552	};
24553
24554	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
24555
24556})(window.Zepto || window.jQuery, window, document);
24557
24558/**
24559 * Video Plugin
24560 * @version 2.0.0-beta.3
24561 * @author Bartosz Wojciechowski
24562 * @license The MIT License (MIT)
24563 */
24564;(function($, window, document, undefined) {
24565
24566	/**
24567	 * Creates the video plugin.
24568	 * @class The Video Plugin
24569	 * @param {Owl} carousel - The Owl Carousel
24570	 */
24571	var Video = function(carousel) {
24572		/**
24573		 * Reference to the core.
24574		 * @protected
24575		 * @type {Owl}
24576		 */
24577		this._core = carousel;
24578
24579		/**
24580		 * Cache all video URLs.
24581		 * @protected
24582		 * @type {Object}
24583		 */
24584		this._videos = {};
24585
24586		/**
24587		 * Current playing item.
24588		 * @protected
24589		 * @type {jQuery}
24590		 */
24591		this._playing = null;
24592
24593		/**
24594		 * All event handlers.
24595		 * @todo The cloned content removale is too late
24596		 * @protected
24597		 * @type {Object}
24598		 */
24599		this._handlers = {
24600			'initialized.owl.carousel': $.proxy(function(e) {
24601				if (e.namespace) {
24602					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
24603				}
24604			}, this),
24605			'resize.owl.carousel': $.proxy(function(e) {
24606				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
24607					e.preventDefault();
24608				}
24609			}, this),
24610			'refreshed.owl.carousel': $.proxy(function(e) {
24611				if (e.namespace && this._core.is('resizing')) {
24612					this._core.$stage.find('.cloned .owl-video-frame').remove();
24613				}
24614			}, this),
24615			'changed.owl.carousel': $.proxy(function(e) {
24616				if (e.namespace && e.property.name === 'position' && this._playing) {
24617					this.stop();
24618				}
24619			}, this),
24620			'prepared.owl.carousel': $.proxy(function(e) {
24621				if (!e.namespace) {
24622					return;
24623				}
24624
24625				var $element = $(e.content).find('.owl-video');
24626
24627				if ($element.length) {
24628					$element.css('display', 'none');
24629					this.fetch($element, $(e.content));
24630				}
24631			}, this)
24632		};
24633
24634		// set default options
24635		this._core.options = $.extend({}, Video.Defaults, this._core.options);
24636
24637		// register event handlers
24638		this._core.$element.on(this._handlers);
24639
24640		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
24641			this.play(e);
24642		}, this));
24643	};
24644
24645	/**
24646	 * Default options.
24647	 * @public
24648	 */
24649	Video.Defaults = {
24650		video: false,
24651		videoHeight: false,
24652		videoWidth: false
24653	};
24654
24655	/**
24656	 * Gets the video ID and the type (YouTube/Vimeo only).
24657	 * @protected
24658	 * @param {jQuery} target - The target containing the video data.
24659	 * @param {jQuery} item - The item containing the video.
24660	 */
24661	Video.prototype.fetch = function(target, item) {
24662		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
24663			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
24664			width = target.attr('data-width') || this._core.settings.videoWidth,
24665			height = target.attr('data-height') || this._core.settings.videoHeight,
24666			url = target.attr('href');
24667
24668		if (url) {
24669			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+)?/);
24670
24671			if (id[3].indexOf('youtu') > -1) {
24672				type = 'youtube';
24673			} else if (id[3].indexOf('vimeo') > -1) {
24674				type = 'vimeo';
24675			} else {
24676				throw new Error('Video URL not supported.');
24677			}
24678			id = id[6];
24679		} else {
24680			throw new Error('Missing video URL.');
24681		}
24682
24683		this._videos[url] = {
24684			type: type,
24685			id: id,
24686			width: width,
24687			height: height
24688		};
24689
24690		item.attr('data-video', url);
24691
24692		this.thumbnail(target, this._videos[url]);
24693	};
24694
24695	/**
24696	 * Creates video thumbnail.
24697	 * @protected
24698	 * @param {jQuery} target - The target containing the video data.
24699	 * @param {Object} info - The video info object.
24700	 * @see `fetch`
24701	 */
24702	Video.prototype.thumbnail = function(target, video) {
24703		var tnLink,
24704			icon,
24705			path,
24706			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
24707			customTn = target.find('img'),
24708			srcType = 'src',
24709			lazyClass = '',
24710			settings = this._core.settings,
24711			create = function(path) {
24712				icon = '<div class="owl-video-play-icon"></div>';
24713
24714				if (settings.lazyLoad) {
24715					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
24716				} else {
24717					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
24718				}
24719				target.after(tnLink);
24720				target.after(icon);
24721			};
24722
24723		// wrap video content into owl-video-wrapper div
24724		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
24725
24726		if (this._core.settings.lazyLoad) {
24727			srcType = 'data-src';
24728			lazyClass = 'owl-lazy';
24729		}
24730
24731		// custom thumbnail
24732		if (customTn.length) {
24733			create(customTn.attr(srcType));
24734			customTn.remove();
24735			return false;
24736		}
24737
24738		if (video.type === 'youtube') {
24739			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
24740			create(path);
24741		} else if (video.type === 'vimeo') {
24742			$.ajax({
24743				type: 'GET',
24744				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
24745				jsonp: 'callback',
24746				dataType: 'jsonp',
24747				success: function(data) {
24748					path = data[0].thumbnail_large;
24749					create(path);
24750				}
24751			});
24752		}
24753	};
24754
24755	/**
24756	 * Stops the current video.
24757	 * @public
24758	 */
24759	Video.prototype.stop = function() {
24760		this._core.trigger('stop', null, 'video');
24761		this._playing.find('.owl-video-frame').remove();
24762		this._playing.removeClass('owl-video-playing');
24763		this._playing = null;
24764		this._core.leave('playing');
24765		this._core.trigger('stopped', null, 'video');
24766	};
24767
24768	/**
24769	 * Starts the current video.
24770	 * @public
24771	 * @param {Event} event - The event arguments.
24772	 */
24773	Video.prototype.play = function(event) {
24774		var target = $(event.target),
24775			item = target.closest('.' + this._core.settings.itemClass),
24776			video = this._videos[item.attr('data-video')],
24777			width = video.width || '100%',
24778			height = video.height || this._core.$stage.height(),
24779			html;
24780
24781		if (this._playing) {
24782			return;
24783		}
24784
24785		this._core.enter('playing');
24786		this._core.trigger('play', null, 'video');
24787
24788		item = this._core.items(this._core.relative(item.index()));
24789
24790		this._core.reset(item.index());
24791
24792		if (video.type === 'youtube') {
24793			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
24794				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
24795		} else if (video.type === 'vimeo') {
24796			html = '<iframe src="//player.vimeo.com/video/' + video.id +
24797				'?autoplay=1" width="' + width + '" height="' + height +
24798				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
24799		}
24800
24801		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
24802
24803		this._playing = item.addClass('owl-video-playing');
24804	};
24805
24806	/**
24807	 * Checks whether an video is currently in full screen mode or not.
24808	 * @todo Bad style because looks like a readonly method but changes members.
24809	 * @protected
24810	 * @returns {Boolean}
24811	 */
24812	Video.prototype.isInFullScreen = function() {
24813		var element = document.fullscreenElement || document.mozFullScreenElement ||
24814				document.webkitFullscreenElement;
24815
24816		return element && $(element).parent().hasClass('owl-video-frame');
24817	};
24818
24819	/**
24820	 * Destroys the plugin.
24821	 */
24822	Video.prototype.destroy = function() {
24823		var handler, property;
24824
24825		this._core.$element.off('click.owl.video');
24826
24827		for (handler in this._handlers) {
24828			this._core.$element.off(handler, this._handlers[handler]);
24829		}
24830		for (property in Object.getOwnPropertyNames(this)) {
24831			typeof this[property] != 'function' && (this[property] = null);
24832		}
24833	};
24834
24835	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
24836
24837})(window.Zepto || window.jQuery, window, document);
24838
24839/**
24840 * Animate Plugin
24841 * @version 2.0.0-beta.3
24842 * @author Bartosz Wojciechowski
24843 * @license The MIT License (MIT)
24844 */
24845;(function($, window, document, undefined) {
24846
24847	/**
24848	 * Creates the animate plugin.
24849	 * @class The Navigation Plugin
24850	 * @param {Owl} scope - The Owl Carousel
24851	 */
24852	var Animate = function(scope) {
24853		this.core = scope;
24854		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
24855		this.swapping = true;
24856		this.previous = undefined;
24857		this.next = undefined;
24858
24859		this.handlers = {
24860			'change.owl.carousel': $.proxy(function(e) {
24861				if (e.namespace && e.property.name == 'position') {
24862					this.previous = this.core.current();
24863					this.next = e.property.value;
24864				}
24865			}, this),
24866			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24867				if (e.namespace) {
24868					this.swapping = e.type == 'translated';
24869				}
24870			}, this),
24871			'translate.owl.carousel': $.proxy(function(e) {
24872				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24873					this.swap();
24874				}
24875			}, this)
24876		};
24877
24878		this.core.$element.on(this.handlers);
24879	};
24880
24881	/**
24882	 * Default options.
24883	 * @public
24884	 */
24885	Animate.Defaults = {
24886		animateOut: false,
24887		animateIn: false
24888	};
24889
24890	/**
24891	 * Toggles the animation classes whenever an translations starts.
24892	 * @protected
24893	 * @returns {Boolean|undefined}
24894	 */
24895	Animate.prototype.swap = function() {
24896
24897		if (this.core.settings.items !== 1) {
24898			return;
24899		}
24900
24901		if (!$.support.animation || !$.support.transition) {
24902			return;
24903		}
24904
24905		this.core.speed(0);
24906
24907		var left,
24908			clear = $.proxy(this.clear, this),
24909			previous = this.core.$stage.children().eq(this.previous),
24910			next = this.core.$stage.children().eq(this.next),
24911			incoming = this.core.settings.animateIn,
24912			outgoing = this.core.settings.animateOut;
24913
24914		if (this.core.current() === this.previous) {
24915			return;
24916		}
24917
24918		if (outgoing) {
24919			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24920			previous.css( { 'left': left + 'px' } )
24921				.addClass('animated owl-animated-out')
24922				.addClass(outgoing)
24923				.on($.support.animation.end, clear);
24924		}
24925
24926		if (incoming) {
24927			next.addClass('animated owl-animated-in')
24928				.addClass(incoming)
24929				.on($.support.animation.end, clear);
24930		}
24931	};
24932
24933	Animate.prototype.clear = function(e) {
24934		if ($(e.target).hasClass('animated')) {
24935			$(e.target).css( { 'left': '' } )
24936				.removeClass('animated owl-animated-out owl-animated-in')
24937				.removeClass(this.core.settings.animateIn)
24938				.removeClass(this.core.settings.animateOut);
24939			this.core.onTransitionEnd();
24940		}
24941	};
24942
24943	/**
24944	 * Destroys the plugin.
24945	 * @public
24946	 */
24947	Animate.prototype.destroy = function() {
24948		var handler, property;
24949
24950		for (handler in this.handlers) {
24951			this.core.$element.off(handler, this.handlers[handler]);
24952		}
24953		for (property in Object.getOwnPropertyNames(this)) {
24954			typeof this[property] != 'function' && (this[property] = null);
24955		}
24956	};
24957
24958	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
24959
24960})(window.Zepto || window.jQuery, window, document);
24961
24962/**
24963 * Autoplay Plugin
24964 * @version 2.0.0-beta.3
24965 * @author Bartosz Wojciechowski
24966 * @author Artus Kolanowski
24967 * @license The MIT License (MIT)
24968 */
24969;(function($, window, document, undefined) {
24970
24971	/**
24972	 * Creates the autoplay plugin.
24973	 * @class The Autoplay Plugin
24974	 * @param {Owl} scope - The Owl Carousel
24975	 */
24976	var Autoplay = function(carousel) {
24977		/**
24978		 * Reference to the core.
24979		 * @protected
24980		 * @type {Owl}
24981		 */
24982		this._core = carousel;
24983
24984		/**
24985		 * The autoplay interval.
24986		 * @type {Number}
24987		 */
24988		this._interval = null;
24989
24990		/**
24991		 * Indicates whenever the autoplay is paused.
24992		 * @type {Boolean}
24993		 */
24994		this._paused = false;
24995
24996		/**
24997		 * All event handlers.
24998		 * @protected
24999		 * @type {Object}
25000		 */
25001		this._handlers = {
25002			'changed.owl.carousel': $.proxy(function(e) {
25003				if (e.namespace && e.property.name === 'settings') {
25004					if (this._core.settings.autoplay) {
25005						this.play();
25006					} else {
25007						this.stop();
25008					}
25009				}
25010			}, this),
25011			'initialized.owl.carousel': $.proxy(function(e) {
25012				if (e.namespace && this._core.settings.autoplay) {
25013					this.play();
25014				}
25015			}, this),
25016			'play.owl.autoplay': $.proxy(function(e, t, s) {
25017				if (e.namespace) {
25018					this.play(t, s);
25019				}
25020			}, this),
25021			'stop.owl.autoplay': $.proxy(function(e) {
25022				if (e.namespace) {
25023					this.stop();
25024				}
25025			}, this),
25026			'mouseover.owl.autoplay': $.proxy(function() {
25027				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25028					this.pause();
25029				}
25030			}, this),
25031			'mouseleave.owl.autoplay': $.proxy(function() {
25032				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25033					this.play();
25034				}
25035			}, this)
25036		};
25037
25038		// register event handlers
25039		this._core.$element.on(this._handlers);
25040
25041		// set default options
25042		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
25043	};
25044
25045	/**
25046	 * Default options.
25047	 * @public
25048	 */
25049	Autoplay.Defaults = {
25050		autoplay: false,
25051		autoplayTimeout: 5000,
25052		autoplayHoverPause: false,
25053		autoplaySpeed: false
25054	};
25055
25056	/**
25057	 * Starts the autoplay.
25058	 * @public
25059	 * @param {Number} [timeout] - The interval before the next animation starts.
25060	 * @param {Number} [speed] - The animation speed for the animations.
25061	 */
25062	Autoplay.prototype.play = function(timeout, speed) {
25063		this._paused = false;
25064
25065		if (this._core.is('rotating')) {
25066			return;
25067		}
25068
25069		this._core.enter('rotating');
25070
25071		this._interval = window.setInterval($.proxy(function() {
25072			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
25073				return;
25074			}
25075			this._core.next(speed || this._core.settings.autoplaySpeed);
25076		}, this), timeout || this._core.settings.autoplayTimeout);
25077	};
25078
25079	/**
25080	 * Stops the autoplay.
25081	 * @public
25082	 */
25083	Autoplay.prototype.stop = function() {
25084		if (!this._core.is('rotating')) {
25085			return;
25086		}
25087
25088		window.clearInterval(this._interval);
25089		this._core.leave('rotating');
25090	};
25091
25092	/**
25093	 * Stops the autoplay.
25094	 * @public
25095	 */
25096	Autoplay.prototype.pause = function() {
25097		if (!this._core.is('rotating')) {
25098			return;
25099		}
25100
25101		this._paused = true;
25102	};
25103
25104	/**
25105	 * Destroys the plugin.
25106	 */
25107	Autoplay.prototype.destroy = function() {
25108		var handler, property;
25109
25110		this.stop();
25111
25112		for (handler in this._handlers) {
25113			this._core.$element.off(handler, this._handlers[handler]);
25114		}
25115		for (property in Object.getOwnPropertyNames(this)) {
25116			typeof this[property] != 'function' && (this[property] = null);
25117		}
25118	};
25119
25120	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
25121
25122})(window.Zepto || window.jQuery, window, document);
25123
25124/**
25125 * Navigation Plugin
25126 * @version 2.0.0-beta.3
25127 * @author Artus Kolanowski
25128 * @license The MIT License (MIT)
25129 */
25130;(function($, window, document, undefined) {
25131	'use strict';
25132
25133	/**
25134	 * Creates the navigation plugin.
25135	 * @class The Navigation Plugin
25136	 * @param {Owl} carousel - The Owl Carousel.
25137	 */
25138	var Navigation = function(carousel) {
25139		/**
25140		 * Reference to the core.
25141		 * @protected
25142		 * @type {Owl}
25143		 */
25144		this._core = carousel;
25145
25146		/**
25147		 * Indicates whether the plugin is initialized or not.
25148		 * @protected
25149		 * @type {Boolean}
25150		 */
25151		this._initialized = false;
25152
25153		/**
25154		 * The current paging indexes.
25155		 * @protected
25156		 * @type {Array}
25157		 */
25158		this._pages = [];
25159
25160		/**
25161		 * All DOM elements of the user interface.
25162		 * @protected
25163		 * @type {Object}
25164		 */
25165		this._controls = {};
25166
25167		/**
25168		 * Markup for an indicator.
25169		 * @protected
25170		 * @type {Array.<String>}
25171		 */
25172		this._templates = [];
25173
25174		/**
25175		 * The carousel element.
25176		 * @type {jQuery}
25177		 */
25178		this.$element = this._core.$element;
25179
25180		/**
25181		 * Overridden methods of the carousel.
25182		 * @protected
25183		 * @type {Object}
25184		 */
25185		this._overrides = {
25186			next: this._core.next,
25187			prev: this._core.prev,
25188			to: this._core.to
25189		};
25190
25191		/**
25192		 * All event handlers.
25193		 * @protected
25194		 * @type {Object}
25195		 */
25196		this._handlers = {
25197			'prepared.owl.carousel': $.proxy(function(e) {
25198				if (e.namespace && this._core.settings.dotsData) {
25199					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
25200						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
25201				}
25202			}, this),
25203			'added.owl.carousel': $.proxy(function(e) {
25204				if (e.namespace && this._core.settings.dotsData) {
25205					this._templates.splice(e.position, 0, this._templates.pop());
25206				}
25207			}, this),
25208			'remove.owl.carousel': $.proxy(function(e) {
25209				if (e.namespace && this._core.settings.dotsData) {
25210					this._templates.splice(e.position, 1);
25211				}
25212			}, this),
25213			'changed.owl.carousel': $.proxy(function(e) {
25214				if (e.namespace && e.property.name == 'position') {
25215					this.draw();
25216				}
25217			}, this),
25218			'initialized.owl.carousel': $.proxy(function(e) {
25219				if (e.namespace && !this._initialized) {
25220					this._core.trigger('initialize', null, 'navigation');
25221					this.initialize();
25222					this.update();
25223					this.draw();
25224					this._initialized = true;
25225					this._core.trigger('initialized', null, 'navigation');
25226				}
25227			}, this),
25228			'refreshed.owl.carousel': $.proxy(function(e) {
25229				if (e.namespace && this._initialized) {
25230					this._core.trigger('refresh', null, 'navigation');
25231					this.update();
25232					this.draw();
25233					this._core.trigger('refreshed', null, 'navigation');
25234				}
25235			}, this)
25236		};
25237
25238		// set default options
25239		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
25240
25241		// register event handlers
25242		this.$element.on(this._handlers);
25243	};
25244
25245	/**
25246	 * Default options.
25247	 * @public
25248	 * @todo Rename `slideBy` to `navBy`
25249	 */
25250	Navigation.Defaults = {
25251		nav: false,
25252		navText: [ 'prev', 'next' ],
25253		navSpeed: false,
25254		navElement: 'div',
25255		navContainer: false,
25256		navContainerClass: 'owl-nav',
25257		navClass: [ 'owl-prev', 'owl-next' ],
25258		slideBy: 1,
25259		dotClass: 'owl-dot',
25260		dotsClass: 'owl-dots',
25261		dots: true,
25262		dotsEach: false,
25263		dotsData: false,
25264		dotsSpeed: false,
25265		dotsContainer: false
25266	};
25267
25268	/**
25269	 * Initializes the layout of the plugin and extends the carousel.
25270	 * @protected
25271	 */
25272	Navigation.prototype.initialize = function() {
25273		var override,
25274			settings = this._core.settings;
25275
25276		// create DOM structure for relative navigation
25277		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
25278			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
25279
25280		this._controls.$previous = $('<' + settings.navElement + '>')
25281			.addClass(settings.navClass[0])
25282			.html(settings.navText[0])
25283			.prependTo(this._controls.$relative)
25284			.on('click', $.proxy(function(e) {
25285				this.prev(settings.navSpeed);
25286			}, this));
25287		this._controls.$next = $('<' + settings.navElement + '>')
25288			.addClass(settings.navClass[1])
25289			.html(settings.navText[1])
25290			.appendTo(this._controls.$relative)
25291			.on('click', $.proxy(function(e) {
25292				this.next(settings.navSpeed);
25293			}, this));
25294
25295		// create DOM structure for absolute navigation
25296		if (!settings.dotsData) {
25297			this._templates = [ $('<div>')
25298				.addClass(settings.dotClass)
25299				.append($('<span>'))
25300				.prop('outerHTML') ];
25301		}
25302
25303		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
25304			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
25305
25306		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
25307			var index = $(e.target).parent().is(this._controls.$absolute)
25308				? $(e.target).index() : $(e.target).parent().index();
25309
25310			e.preventDefault();
25311
25312			this.to(index, settings.dotsSpeed);
25313		}, this));
25314
25315		// override public methods of the carousel
25316		for (override in this._overrides) {
25317			this._core[override] = $.proxy(this[override], this);
25318		}
25319	};
25320
25321	/**
25322	 * Destroys the plugin.
25323	 * @protected
25324	 */
25325	Navigation.prototype.destroy = function() {
25326		var handler, control, property, override;
25327
25328		for (handler in this._handlers) {
25329			this.$element.off(handler, this._handlers[handler]);
25330		}
25331		for (control in this._controls) {
25332			this._controls[control].remove();
25333		}
25334		for (override in this.overides) {
25335			this._core[override] = this._overrides[override];
25336		}
25337		for (property in Object.getOwnPropertyNames(this)) {
25338			typeof this[property] != 'function' && (this[property] = null);
25339		}
25340	};
25341
25342	/**
25343	 * Updates the internal state.
25344	 * @protected
25345	 */
25346	Navigation.prototype.update = function() {
25347		var i, j, k,
25348			lower = this._core.clones().length / 2,
25349			upper = lower + this._core.items().length,
25350			maximum = this._core.maximum(true),
25351			settings = this._core.settings,
25352			size = settings.center || settings.autoWidth || settings.dotsData
25353				? 1 : settings.dotsEach || settings.items;
25354
25355		if (settings.slideBy !== 'page') {
25356			settings.slideBy = Math.min(settings.slideBy, settings.items);
25357		}
25358
25359		if (settings.dots || settings.slideBy == 'page') {
25360			this._pages = [];
25361
25362			for (i = lower, j = 0, k = 0; i < upper; i++) {
25363				if (j >= size || j === 0) {
25364					this._pages.push({
25365						start: Math.min(maximum, i - lower),
25366						end: i - lower + size - 1
25367					});
25368					if (Math.min(maximum, i - lower) === maximum) {
25369						break;
25370					}
25371					j = 0, ++k;
25372				}
25373				j += this._core.mergers(this._core.relative(i));
25374			}
25375		}
25376	};
25377
25378	/**
25379	 * Draws the user interface.
25380	 * @todo The option `dotsData` wont work.
25381	 * @protected
25382	 */
25383	Navigation.prototype.draw = function() {
25384		var difference,
25385			settings = this._core.settings,
25386			disabled = this._core.items().length <= settings.items,
25387			index = this._core.relative(this._core.current()),
25388			loop = settings.loop || settings.rewind;
25389
25390		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
25391
25392		if (settings.nav) {
25393			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
25394			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
25395		}
25396
25397		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
25398
25399		if (settings.dots) {
25400			difference = this._pages.length - this._controls.$absolute.children().length;
25401
25402			if (settings.dotsData && difference !== 0) {
25403				this._controls.$absolute.html(this._templates.join(''));
25404			} else if (difference > 0) {
25405				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
25406			} else if (difference < 0) {
25407				this._controls.$absolute.children().slice(difference).remove();
25408			}
25409
25410			this._controls.$absolute.find('.active').removeClass('active');
25411			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
25412		}
25413	};
25414
25415	/**
25416	 * Extends event data.
25417	 * @protected
25418	 * @param {Event} event - The event object which gets thrown.
25419	 */
25420	Navigation.prototype.onTrigger = function(event) {
25421		var settings = this._core.settings;
25422
25423		event.page = {
25424			index: $.inArray(this.current(), this._pages),
25425			count: this._pages.length,
25426			size: settings && (settings.center || settings.autoWidth || settings.dotsData
25427				? 1 : settings.dotsEach || settings.items)
25428		};
25429	};
25430
25431	/**
25432	 * Gets the current page position of the carousel.
25433	 * @protected
25434	 * @returns {Number}
25435	 */
25436	Navigation.prototype.current = function() {
25437		var current = this._core.relative(this._core.current());
25438		return $.grep(this._pages, $.proxy(function(page, index) {
25439			return page.start <= current && page.end >= current;
25440		}, this)).pop();
25441	};
25442
25443	/**
25444	 * Gets the current succesor/predecessor position.
25445	 * @protected
25446	 * @returns {Number}
25447	 */
25448	Navigation.prototype.getPosition = function(successor) {
25449		var position, length,
25450			settings = this._core.settings;
25451
25452		if (settings.slideBy == 'page') {
25453			position = $.inArray(this.current(), this._pages);
25454			length = this._pages.length;
25455			successor ? ++position : --position;
vendor: 5,678 bytes, lines 25456-25680
25456			position = this._pages[((position % length) + length) % length].start;
25457		} else {
25458			position = this._core.relative(this._core.current());
25459			length = this._core.items().length;
25460			successor ? position += settings.slideBy : position -= settings.slideBy;
25461		}
25462
25463		return position;
25464	};
25465
25466	/**
25467	 * Slides to the next item or page.
25468	 * @public
25469	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25470	 */
25471	Navigation.prototype.next = function(speed) {
25472		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
25473	};
25474
25475	/**
25476	 * Slides to the previous item or page.
25477	 * @public
25478	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25479	 */
25480	Navigation.prototype.prev = function(speed) {
25481		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
25482	};
25483
25484	/**
25485	 * Slides to the specified item or page.
25486	 * @public
25487	 * @param {Number} position - The position of the item or page.
25488	 * @param {Number} [speed] - The time in milliseconds for the transition.
25489	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
25490	 */
25491	Navigation.prototype.to = function(position, speed, standard) {
25492		var length;
25493
25494		if (!standard) {
25495			length = this._pages.length;
25496			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
25497		} else {
25498			$.proxy(this._overrides.to, this._core)(position, speed);
25499		}
25500	};
25501
25502	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
25503
25504})(window.Zepto || window.jQuery, window, document);
25505
25506/**
25507 * Hash Plugin
25508 * @version 2.0.0-beta.3
25509 * @author Artus Kolanowski
25510 * @license The MIT License (MIT)
25511 */
25512;(function($, window, document, undefined) {
25513	'use strict';
25514
25515	/**
25516	 * Creates the hash plugin.
25517	 * @class The Hash Plugin
25518	 * @param {Owl} carousel - The Owl Carousel
25519	 */
25520	var Hash = function(carousel) {
25521		/**
25522		 * Reference to the core.
25523		 * @protected
25524		 * @type {Owl}
25525		 */
25526		this._core = carousel;
25527
25528		/**
25529		 * Hash index for the items.
25530		 * @protected
25531		 * @type {Object}
25532		 */
25533		this._hashes = {};
25534
25535		/**
25536		 * The carousel element.
25537		 * @type {jQuery}
25538		 */
25539		this.$element = this._core.$element;
25540
25541		/**
25542		 * All event handlers.
25543		 * @protected
25544		 * @type {Object}
25545		 */
25546		this._handlers = {
25547			/*'initialized.owl.carousel': $.proxy(function(e) {
25548				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
25549					$(window).trigger('hashchange.owl.navigation');
25550				}
25551			}, this),*/
25552			'prepared.owl.carousel': $.proxy(function(e) {
25553				if (e.namespace) {
25554					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
25555
25556					if (!hash) {
25557						return;
25558					}
25559
25560					this._hashes[hash] = e.content;
25561				}
25562			}, this),
25563			'changed.owl.carousel': $.proxy(function(e) {
25564				if (e.namespace && e.property.name === 'position') {
25565					var current = this._core.items(this._core.relative(this._core.current())),
25566						hash = $.map(this._hashes, function(item, hash) {
25567							return item === current ? hash : null;
25568						}).join();
25569
25570					if (!hash || window.location.hash.slice(1) === hash) {
25571						return;
25572					}
25573
25574					window.location.hash = hash;
25575				}
25576			}, this)
25577		};
25578
25579		// set default options
25580		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
25581
25582		// register the event handlers
25583		this.$element.on(this._handlers);
25584
25585		// register event listener for hash navigation
25586		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
25587			var hash = window.location.hash.substring(1),
25588				items = this._core.$stage.children(),
25589				position = this._hashes[hash] && items.index(this._hashes[hash]);
25590
25591			if (position === undefined || position === this._core.current()) {
25592				return;
25593			}
25594
25595			this._core.to(this._core.relative(position), false, true);
25596		}, this));*/
25597	};
25598
25599	/**
25600	 * Default options.
25601	 * @public
25602	 */
25603	Hash.Defaults = {
25604		URLhashListener: false
25605	};
25606
25607	/**
25608	 * Destroys the plugin.
25609	 * @public
25610	 */
25611	Hash.prototype.destroy = function() {
25612		var handler, property;
25613
25614		$(window).off('hashchange.owl.navigation');
25615
25616		for (handler in this._handlers) {
25617			this._core.$element.off(handler, this._handlers[handler]);
25618		}
25619		for (property in Object.getOwnPropertyNames(this)) {
25620			typeof this[property] != 'function' && (this[property] = null);
25621		}
25622	};
25623
25624	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
25625
25626})(window.Zepto || window.jQuery, window, document);
25627
25628/**
25629 * Support Plugin
25630 *
25631 * @version 2.0.0-beta.3
25632 * @author Vivid Planet Software GmbH
25633 * @author Artus Kolanowski
25634 * @license The MIT License (MIT)
25635 */
25636;(function($, window, document, undefined) {
25637
25638	var style = $('<support>').get(0).style,
25639		prefixes = 'Webkit Moz O ms'.split(' '),
25640		events = {
25641			transition: {
25642				end: {
25643					WebkitTransition: 'webkitTransitionEnd',
25644					MozTransition: 'transitionend',
25645					OTransition: 'oTransitionEnd',
25646					transition: 'transitionend'
25647				}
25648			},
25649			animation: {
25650				end: {
25651					WebkitAnimation: 'webkitAnimationEnd',
25652					MozAnimation: 'animationend',
25653					OAnimation: 'oAnimationEnd',
25654					animation: 'animationend'
25655				}
25656			}
25657		},
25658		tests = {
25659			csstransforms: function() {
25660				return !!test('transform');
25661			},
25662			csstransforms3d: function() {
25663				return !!test('perspective');
25664			},
25665			csstransitions: function() {
25666				return !!test('transition');
25667			},
25668			cssanimations: function() {
25669				return !!test('animation');
25670			}
25671		};
25672
25673	function test(property, prefixed) {
25674		var result = false,
25675			upper = property.charAt(0).toUpperCase() + property.slice(1);
25676
25677		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
25678			if (style[property] !== undefined) {
25679				result = prefixed ? property : true;
25680				return false;
25681			}
25682		});
25683
25684		return result;
25685	}
25686
25687	function prefixed(property) {
25688		return test(property, true);
25689	}
25690
25691	if (tests.csstransitions()) {
25692		/* jshint -W053 */
25693		$.support.transition = new String(prefixed('transition'))
25694		$.support.transition.end = events.transition.end[ $.support.transition ];
25695	}
25696
25697	if (tests.cssanimations()) {
25698		/* jshint -W053 */
25699		$.support.animation = new String(prefixed('animation'))
25700		$.support.animation.end = events.animation.end[ $.support.animation ];
25701	}
25702
25703	if (tests.csstransforms()) {
25704		/* jshint -W053 */
25705		$.support.transform = new String(prefixed('transform'));
25706		$.support.transform3d = tests.csstransforms3d();
25707	}
25708
25709})(window.Zepto || window.jQuery, window, document);
25710
25711(function(window, document, undefined) {
25712
25713	/**
25714	 * Find the absolute position of an element
25715	 */
25716	var absPos = function(element) {
25717		var offsetLeft, offsetTop;
25718		offsetLeft = offsetTop = 0;
25719		if (element.offsetParent) {
25720			do {
25721				offsetLeft += element.offsetLeft;
25722				offsetTop += element.offsetTop;
25723			} while (element = element.offsetParent);
25724		}
25725		return [offsetLeft, offsetTop];
25726	};
25727
25728	/**
25729	 * @constructor Progress Circle class
25730	 * @param params.canvas Canvas on which the circles will be drawn.
25731	 * @param params.minRadius Inner radius of the innermost circle, in px.
25732	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
25733	 * @param params.gapWidth Space between each circle.
25734	 * @param params.centerX X coordinate of the center of circles.
25735	 * @param params.centerY Y coordinate of the center of circles.
25736	 * @param params.infoLineBaseAngle Base angle of the info line.
25737	 * @param params.infoLineAngleInterval Angles between the info lines.
25738	 */
25739	var ProgressCircle = function(params) {
25740		this.canvas = params.canvas;
25741		this.minRadius = params.minRadius || 15;
25742		this.arcWidth = params.arcWidth || 5;
25743		this.gapWidth = params.gapWidth || 3;
25744		this.centerX = params.centerX || this.canvas.width / 2;
25745		this.centerY = params.centerY || this.canvas.height / 2;
25746		this.infoLineLength = params.infoLineLength || 60;
25747		this.horizLineLength = params.horizLineLength || 10;
25748		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
25749		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
25750
25751		this.context = this.canvas.getContext('2d');
25752
25753		this.width = this.canvas.width;
25754		this.height = this.canvas.height;
25755
25756		this.circles = [];
25757		this.runningCount = 0;
25758	};
25759
25760	ProgressCircle.prototype = {
25761		constructor: ProgressCircle,
25762
25763		/**
25764		 * @method Adds an progress monitor entry.
25765		 * @param params.fillColor Color to fill in the circle.
25766		 * @param params.outlineColor Color to outline the circle.
25767		 * @param params.progressListener Callback function to fetch the progress.
25768		 * @param params.infoListener Callback function to fetch the info.
25769		 * @returns this
25770		 */
25771		addEntry: function(params) {
25772			this.circles.push(new Circle({
25773				canvas: this.canvas,
25774				context: this.context,
25775				centerX: this.centerX,
25776				centerY: this.centerY,
25777				innerRadius: this.minRadius + this.circles.length *
25778					(this.gapWidth + this.arcWidth),
25779				arcWidth: this.arcWidth,
25780				infoLineLength: this.infoLineLength,
25781				horizLineLength: this.horizLineLength,
25782
25783				id: this.circles.length,
25784				fillColor: params.fillColor,
25785				outlineColor: params.outlineColor,
25786				progressListener: params.progressListener,
25787				infoListener: params.infoListener,
25788				infoLineAngle: this.infoLineBaseAngle +
25789					this.circles.length * this.infoLineAngleInterval,
25790			}));
25791
25792			return this;
25793		},
25794
25795		/**
25796		 * @method Starts the monitor and updates with the given interval.
25797		 * @param interval Interval between updates, in millisecond.
25798		 * @returns this
25799		 */
25800		start: function(interval) {
25801			var self = this;
25802			this.timer = setInterval(function() {
25803				self._update();
25804			}, interval || 33);
25805
25806			return this;
25807		},
25808
25809		/**
25810		 * @method Stop the animation.
25811		 */
25812		stop: function() {
25813			clearTimeout(this.timer);
25814		},
25815
25816		/**
25817		 * @private
25818		 * @method Call update on each circle and redraw them.
25819		 * @returns this
25820		 */
25821		_update: function() {
25822			this._clear();
25823			this.circles.forEach(function(circle, idx, array) {
25824				circle.update();
25825			});
25826
25827			return this;
25828		},
25829
25830		/**
25831		 * @private
25832		 * @method Clear the canvas.
25833		 * @returns this
25834		 */
25835		_clear: function() {
25836			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
25837
25838			return this;
25839		},
25840
25841	};
25842
25843	/**
25844	 * @private
25845	 * @class Individual progress circle.
25846	 * @param params.canvas Canvas on which the circle will be drawn.
25847	 * @param params.context Context of the canvas.
25848	 * @param params.innerRadius Inner radius of the circle, in px.
25849	 * @param params.arcWidth Width of each arc(circle).
25850	 * @param params.gapWidth Distance between each arc.
25851	 * @param params.centerX X coordinate of the center of circles.
25852	 * @param params.centerY Y coordinate of the center of circles.
25853	 * @param params.fillColor Color to fill in the circle.
25854	 * @param params.outlineColor Color to outline the circle.
25855	 * @param params.progressListener Callback function to fetch the progress.
25856	 * @param params.infoListener Callback function to fetch the info.
25857	 * @param params.infoLineAngle Angle of info line.
25858	 */
25859	var Circle = function(params) {
25860		this.id = params.id;
25861		this.canvas = params.canvas;
25862		this.context = params.context;
25863		this.centerX = params.centerX;
25864		this.centerY = params.centerY;
25865		this.arcWidth = params.arcWidth;
25866		this.innerRadius = params.innerRadius || 0;
25867		this.fillColor = params.fillColor || '#fff';
25868		this.outlineColor = params.outlineColor || this.fillColor;
25869		this.progressListener = params.progressListener;
25870		this.infoLineLength = params.infoLineLength || 250;
25871		this.horizLineLength = params.horizLineLength || 50;
25872		this.infoListener = params.infoListener;
25873		this.infoLineAngle = params.infoLineAngle;
25874
25875		this.outerRadius = this.innerRadius + this.arcWidth;
25876
25877		// If the info listener is not registered, then don't calculate
25878		// the related coordinates
25879		if (!this.infoListener) return;
25880
25881		// calculate the info-line turning points
25882		var angle = this.infoLineAngle,
25883			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25884
25885			sinA = Math.sin(angle),
25886			cosA = Math.cos(angle);
25887
25888		this.infoLineStartX = this.centerX + sinA * arcDistance;
25889		this.infoLineStartY = this.centerY - cosA * arcDistance;
25890
25891		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25892		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25893
25894		this.infoLineEndX = this.infoLineMidX +
25895			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25896		this.infoLineEndY = this.infoLineMidY;
25897
25898		var infoText = document.createElement('div'),
25899			style = infoText.style;
25900
25901		style.color = this.fillColor;
25902		style.position = 'absolute';
25903		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25904		// style.top will be calculated in the `drawInfo` method. Since
25905		// user may want to change the size of the font, so the top offset
25906		// must be updated in each loop.
25907		infoText.className = 'ProgressCircleInfo'; // For css styling
25908		infoText.id = 'progress_circle_info_' + this.id;
25909		document.body.appendChild(infoText);
25910		this.infoText = infoText;
25911	};
25912
25913	Circle.prototype = {
25914		constructor: Circle,
25915
25916		update: function() {
25917			this.progress = this.progressListener();
25918			this._draw();
25919
25920			if (this.infoListener) {
25921				this.info = this.infoListener();
25922				this._drawInfo();
25923			}
25924		},
25925
25926		/**
25927		 * @private
25928		 * @method Draw the circle on the canvas.
25929		 * @returns this
25930		 */
25931		_draw: function() {
25932			var ctx = this.context,
25933
25934				ANGLE_OFFSET = -Math.PI / 2,
25935
25936				startAngle = 0 + ANGLE_OFFSET,
25937				endAngle= startAngle + this.progress * Math.PI * 2,
25938
25939				x = this.centerX,
25940				y = this.centerY,
25941
25942				innerRadius = this.innerRadius - this.arcWidth - 1,
25943				outerRadius = this.outerRadius - this.arcWidth - 1;
25944
25945			if ( innerRadius < 0 )
25946				return;
25947
25948			ctx.fillStyle = this.fillColor;
25949			ctx.strokeStyle = this.outlineColor;
25950
25951			ctx.beginPath();
25952			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
25953			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
25954			ctx.closePath();
25955			ctx.stroke();
25956			ctx.fill();
25957
25958			return this;
25959		},
25960
25961		/**
25962		 * @private
25963		 * @method Draw the info lines and info text.
25964		 * @returns this
25965		 */
25966		_drawInfo: function() {
25967
25968			var pointList, lineHeight;
25969
25970			pointList = [
25971				[this.infoLineStartX, this.infoLineStartY],
25972				[this.infoLineMidX, this.infoLineMidY],
25973				[this.infoLineEndX, this.infoLineEndY],
25974			];
25975			this._drawSegments(pointList, false);
25976
25977			this.infoText.innerHTML = this.info;
25978
25979			lineHeight = this.infoText.offsetHeight;
25980			this.infoText.style.top = this.infoLineEndY +
25981				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
25982
25983			return this;
25984		},
25985
25986		/**
25987		 * @private
25988		 * @method Helper function to draw the segments
25989		 * @param pointList An array of points in the form of [x, y].
25990		 * @param close Whether to connect the first and last point.
25991		 */
25992		_drawSegments: function(pointList, close) {
25993			var ctx = this.context;
25994
25995			ctx.beginPath();
25996			ctx.moveTo(pointList[0][0], pointList[0][1]);
25997			for (var i = 1; i < pointList.length; ++i) {
25998				ctx.lineTo(pointList[i][0], pointList[i][1]);
25999			}
26000
26001			if (close) {
26002				ctx.closePath();
26003			}
26004			ctx.stroke();
26005		},
26006	};
26007
26008	window.ProgressCircle = ProgressCircle;
26009
26010})(window, document);
26011
26012
26013
26014
26015/* =========================================================
26016 * jquery.vc_chart.js v1.0
26017 * =========================================================
26018 * Copyright 2013 Wpbakery
26019 *
26020 * Jquery chart plugin for the Visual Composer.
26021 * ========================================================= */
26022(function($){
26023	/**
26024	 * Pie chart animated.
26025	 * @param element - DOM element
26026	 * @param options - settings object.
26027	 * @constructor
26028	 */
26029	var VcChart = function(element, options) {
26030		this.el = element;
26031		this.$el = $(this.el);
26032		var $this = this;
26033		$this.options = $.extend({
26034			color: 'wpb_button',
26035			units: '',
26036			width: '',
26037			label_selector: '.vc_pie_chart_value',
26038			back_selector: '.vc_pie_chart_back',
26039			responsive: true
26040		}, options);
26041		$this.init();
26042	};
26043	VcChart.prototype = {
26044		constructor: VcChart,
26045		_progress_v: 0,
26046		animated: false,
26047		colors: {
26048			'wpb_button': 'rgba(247, 247, 247, 1)',
26049			'btn-primary': 'rgba(0, 136, 204, 1)',
26050			'btn-info': 'rgba(88, 185, 218, 1)',
26051			'btn-success': 'rgba(106, 177, 101, 1)',
26052			'btn-warning': 'rgba(255, 153, 0, 1)',
26053			'btn-danger': 'rgba(255, 103, 91, 1)',
26054			'btn-inverse': 'rgba(85, 85, 85, 1)'
26055		},
26056		init: function() {
26057			this.setupColor();
26058			this.value = this.$el.data('pie-value')/100;
26059			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
26060			this.$wrapper = $('.vc_pie_wrapper', this.$el);
26061			this.$label = $(this.options.label_selector, this.$el);
26062			this.$back = $(this.options.back_selector, this.$el);
26063			this.$canvas = this.$el.find('canvas');
26064			this.arcWidth = this.$el.data('pie-width') * 2;
26065			this.draw();
26066			this.setWayPoint();
26067			if(this.options.responsive === true) this.setResponsive();
26068			if (UNCODE.isMobile) this._progress_v = this.value;
26069		},
26070		setupColor: function() {
26071			// if(typeof this.colors[this.options.color] !== 'undefined') {
26072			//     this.color = this.colors[this.options.color];
26073			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
26074			//     this.color = this.options.color;
26075			// } else {
26076			//     this.color = 'rgba(247, 247, 247, 0.2)';
26077			// }
26078			if(typeof this.options.color !== 'undefined') {
26079				this.color = this.options.color;
26080			} else this.color = 'rgba(247, 247, 247, 0.2)';
26081
26082		},
26083		setResponsive: function() {
26084			var that = this;
26085			if (!UNCODE.isMobile) {
26086				$(window).resize(function(){
26087					if(that.animated === true) that.circle.stop();
26088					that.draw(true);
26089				});
26090			}
26091		},
26092		draw: function(redraw) {
26093			var w = this.$el.addClass('vc_ready').width() * 2,
26094				border_w = this.arcWidth,
26095				radius;
26096			if(!w) w = this.$el.parents(':visible').first().width()-2;
26097			//w = Math.round(w/100*80);
26098			//if (w < 250) w = 250;
26099			radius = w/2;
26100			this.$wrapper.css({"width" : (w / 2) + "px"});
26101			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
26102			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
26103			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
26104			this.$el.addClass('vc_ready');
26105			this.circle = new ProgressCircle({
26106				canvas: this.$canvas.get(0),
26107				minRadius: radius,
26108				arcWidth: border_w
26109			});
26110			if(redraw === true && this.animated === true) {
26111				this._progress_v = this.value;
26112				this.circle.addEntry({
26113					fillColor: this.color,
26114					progressListener: $.proxy(this.setProgress, this)
26115				}).start();
26116			}
26117		},
26118		setProgress: function() {
26119			if (this._progress_v >= this.value) {
26120				this.circle.stop();
26121				this.animated = true;
26122				this.$label.html(this.label_value + this.options.units);
26123				return this._progress_v;
26124			}
26125			this._progress_v += 0.01;
26126			if (!isNaN(this.label_value)) {
26127				var label_value = this._progress_v/this.value*this.label_value;
26128				var val = Math.round(label_value) + this.options.units;
26129				this.$label.html(val);
26130			} else this.$label.html(this.label_value + this.options.units);
26131			return this._progress_v;
26132		},
26133		animate: function() {
26134			if(this.animated !== true) {
26135				this.circle.addEntry({
26136					fillColor: this.color,
26137					progressListener: $.proxy(this.setProgress, this)
26138				}).start(10);
26139			}
26140		},
26141		setWayPoint: function() {
26142			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
26143				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
26144			} else {
26145				this.animate();
26146			}
26147		}
26148	};
26149	/**
26150	 * jQuery plugin
26151	 * @param option - object with settings
26152	 * @return {*}
26153	 */
26154	$.fn.vcChat = function(option, value) {
26155		return this.each(function () {
26156			var $this = $(this),
26157				data = $this.data('vc_chart'),
26158				options = typeof option === 'object' ? option : {
26159					color: $this.data('pie-color'),
26160					units: $this.data('pie-units')
26161				};
26162			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
26163			if (typeof option == 'string') data[option](value);
26164		});
26165	};
26166	/**
26167	 * Allows users to rewrite function inside theme.
26168	 */
26169	if ( typeof window['vc_pieChart'] !== 'function' ) {
26170		window.vc_pieChart = function() {
26171			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
26172		}
26173	}
26174	$(document).ready(function(){
26175		!window.vc_iframe && vc_pieChart();
26176
26177		/**
26178		* Tab and collapse integration.
26179		*/
26180		$('.nav-tabs a').on('shown.bs.tab', function(e){
26181			var $cont = $(e.target).closest('.tab-container'),
26182				$active = $('.tab-pane.active', $cont);
26183			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
26184		});
26185
26186		$('.panel-collapse').on('shown.bs.collapse', function (e) {
26187			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
26188		})
26189	});
26190
26191})(window.jQuery);
26192
26193/* Progress bar
26194 ---------------------------------------------------------- */
26195function uncode_progress_bar() {
26196	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
26197		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
26198			return;
26199		}
26200		if (!UNCODE.isMobile) {
26201			new Waypoint({
26202				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26203				element: val,
26204				handler: function() {
26205					var element = jQuery(this.element);
26206					element.find('.vc_single_bar').each(function(index) {
26207						var $this = jQuery(this),
26208							bar = $this.find('.vc_bar'),
26209							val = bar.data('percentage-value');
26210						setTimeout(function() {
26211							bar.css({
26212								"width": val + '%'
26213							});
26214						}, index * 200);
26215					});
26216				},
26217				offset: '80%'
26218			});
26219		} else {
26220			var element = jQuery(val);
26221			element.find('.vc_single_bar').each(function(index) {
26222				var $this = jQuery(this),
26223					bar = $this.find('.vc_bar'),
26224					val = bar.data('percentage-value');
26225				setTimeout(function() {
26226					bar.css({
26227						"width": val + '%'
26228					});
26229				}, index * 200);
26230			});
26231		}
26232	});
26233};
26234uncode_progress_bar();
26235
26236/*!
26237 * jquery.counterup.js 1.0
26238 *
26239 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
26240 * Released under the GPL v2 License
26241 *
26242 * Date: Nov 26, 2013
26243 */
26244(function($) {
26245	"use strict";
26246	$.fn.counterUp = function(options) {
26247		// Defaults
26248		var settings = $.extend({
26249			'time': 400,
26250			'delay': 10
26251		}, options);
26252		return this.each(function() {
26253			// Store the object
26254			var $this = $(this);
26255			var $settings = settings;
26256			var counterUpper = function() {
26257				var nums = [];
26258				var divisions = $settings.time / $settings.delay;
26259				var numReal = $this.attr('data-val'),
26260				num = numReal;
26261				var isComma = /[0-9]+,[0-9]+/.test(num);
26262				num = num.replace(/,/g, '');
26263				var isInt = /^[0-9]+$/.test(num);
26264				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
26265				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
26266				// Generate list of incremental numbers to display
26267				for (var i = divisions; i >= 1; i--) {
26268					// Preserve as int if input was int
26269					var newNum = parseInt(num / divisions * i);
26270					// Preserve float if input was float
26271					if (isFloat) {
26272						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
26273					}
26274					// Preserve commas if input had commas
26275					if (isComma) {
26276						while (/(\d+)(\d{3})/.test(newNum.toString())) {
26277							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
26278						}
26279					}
26280					nums.unshift(newNum);
26281				}
26282				nums.push(numReal);
26283				$this.data('counterup-nums', nums);
26284				$this.text('0');
26285				// Updates the number until we're done
26286				var f = function() {
26287					if ($this.data('counterup-nums') != null) {
26288						$this.text($this.data('counterup-nums').shift());
26289						if ($this.data('counterup-nums').length) {
26290							setTimeout($this.data('counterup-func'), $settings.delay);
26291						} else {
26292							delete $this.data('counterup-nums');
26293							$this.data('counterup-nums', null);
26294							$this.data('counterup-func', null);
26295						}
26296					}
26297				};
26298				$this.data('counterup-func', f);
26299				// Start the count up
26300				setTimeout($this.data('counterup-func'), $settings.delay);
26301			};
26302			// Perform counts when the element gets into view
26303			new Waypoint({
26304				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26305				element: this,
26306				handler: function() {
26307					counterUpper();
26308					if (!UNCODE.isUnmodalOpen) {
26309						this.destroy();
26310					}
26311				},
26312				offset: '100%'
26313			});
26314		});
26315	};
26316})(jQuery);
26317
26318/*!
26319 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
26320 * Copyright (c) 2016 Edson Hilios
26321 *
26322 * Permission is hereby granted, free of charge, to any person obtaining a copy of
26323 * this software and associated documentation files (the "Software"), to deal in
26324 * the Software without restriction, including without limitation the rights to
26325 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
26326 * the Software, and to permit persons to whom the Software is furnished to do so,
26327 * subject to the following conditions:
26328 *
26329 * The above copyright notice and this permission notice shall be included in all
26330 * copies or substantial portions of the Software.
26331 *
26332 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26333 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26334 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26335 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26336 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26337 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26338 */
26339(function(factory) {
26340	"use strict";
26341	if (typeof define === "function" && define.amd) {
26342		define([ "jquery" ], factory);
26343	} else {
26344		factory(jQuery);
26345	}
26346})(function($) {
26347	"use strict";
26348	var instances = [], matchers = [], defaultOptions = {
26349		precision: 100,
26350		elapse: false,
26351		defer: false
26352	};
26353	matchers.push(/^[0-9]*$/.source);
26354	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26355	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26356	matchers = new RegExp(matchers.join("|"));
26357	function parseDateString(dateString) {
26358		if (dateString instanceof Date) {
26359			return dateString;
26360		}
26361		if (String(dateString).match(matchers)) {
26362			if (String(dateString).match(/^[0-9]*$/)) {
26363				dateString = Number(dateString);
26364			}
26365			if (String(dateString).match(/\-/)) {
26366				dateString = String(dateString).replace(/\-/g, "/");
26367			}
26368			return new Date(dateString);
26369		} else {
26370			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
26371		}
26372	}
26373	var DIRECTIVE_KEY_MAP = {
26374		Y: "years",
26375		m: "months",
26376		n: "daysToMonth",
26377		d: "daysToWeek",
26378		w: "weeks",
26379		W: "weeksToMonth",
26380		H: "hours",
26381		M: "minutes",
26382		S: "seconds",
26383		D: "totalDays",
26384		I: "totalHours",
26385		N: "totalMinutes",
26386		T: "totalSeconds"
26387	};
26388	function escapedRegExp(str) {
26389		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
26390		return new RegExp(sanitize);
26391	}
26392	function strftime(offsetObject) {
26393		return function(format) {
26394			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
26395			if (directives) {
26396				for (var i = 0, len = directives.length; i < len; ++i) {
26397					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
26398					directive = directive[2];
26399					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
26400						value = DIRECTIVE_KEY_MAP[directive];
26401						value = Number(offsetObject[value]);
26402					}
26403					if (value !== null) {
26404						if (modifier === "!") {
26405							value = pluralize(plural, value);
26406						}
26407						if (modifier === "") {
26408							if (value < 10) {
26409								value = "0" + value.toString();
26410							}
26411						}
26412						format = format.replace(regexp, value.toString());
26413					}
26414				}
26415			}
26416			format = format.replace(/%%/, "%");
26417			return format;
26418		};
26419	}
26420	function pluralize(format, count) {
26421		var plural = "s", singular = "";
26422		if (format) {
26423			format = format.rep
vendor: 8,618 bytes, lines 26423-26567
26423lace(/(:|;|\s)/gi, "").split(/\,/);
26424			if (format.length === 1) {
26425				plural = format[0];
26426			} else {
26427				singular = format[0];
26428				plural = format[1];
26429			}
26430		}
26431		if (Math.abs(count) > 1) {
26432			return plural;
26433		} else {
26434			return singular;
26435		}
26436	}
26437	var Countdown = function(el, finalDate, options) {
26438		this.el = el;
26439		this.$el = $(el);
26440		this.interval = null;
26441		this.offset = {};
26442		this.options = $.extend({}, defaultOptions);
26443		this.instanceNumber = instances.length;
26444		instances.push(this);
26445		this.$el.data("countdown-instance", this.instanceNumber);
26446		if (options) {
26447			if (typeof options === "function") {
26448				this.$el.on("update.countdown", options);
26449				this.$el.on("stoped.countdown", options);
26450				this.$el.on("finish.countdown", options);
26451			} else {
26452				this.options = $.extend({}, defaultOptions, options);
26453			}
26454		}
26455		this.setFinalDate(finalDate);
26456		if (this.options.defer === false) {
26457			this.start();
26458		}
26459	};
26460	$.extend(Countdown.prototype, {
26461		start: function() {
26462			if (this.interval !== null) {
26463				clearInterval(this.interval);
26464			}
26465			var self = this;
26466			this.update();
26467			this.interval = setInterval(function() {
26468				self.update.call(self);
26469			}, this.options.precision);
26470		},
26471		stop: function() {
26472			clearInterval(this.interval);
26473			this.interval = null;
26474			this.dispatchEvent("stoped");
26475		},
26476		toggle: function() {
26477			if (this.interval) {
26478				this.stop();
26479			} else {
26480				this.start();
26481			}
26482		},
26483		pause: function() {
26484			this.stop();
26485		},
26486		resume: function() {
26487			this.start();
26488		},
26489		remove: function() {
26490			this.stop.call(this);
26491			instances[this.instanceNumber] = null;
26492			delete this.$el.data().countdownInstance;
26493		},
26494		setFinalDate: function(value) {
26495			this.finalDate = parseDateString(value);
26496		},
26497		update: function() {
26498			if (this.$el.closest("html").length === 0) {
26499				this.remove();
26500				return;
26501			}
26502			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
26503			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
26504			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
26505			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
26506			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
26507				return;
26508			} else {
26509				this.totalSecsLeft = newTotalSecsLeft;
26510			}
26511			this.elapsed = now >= this.finalDate;
26512			this.offset = {
26513				seconds: this.totalSecsLeft % 60,
26514				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
26515				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
26516				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26517				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26518				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
26519				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
26520				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
26521				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
26522				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
26523				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
26524				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
26525				totalMinutes: Math.floor(this.totalSecsLeft / 60),
26526				totalSeconds: this.totalSecsLeft
26527			};
26528			if (!this.options.elapse && this.totalSecsLeft === 0) {
26529				this.stop();
26530				this.dispatchEvent("finish");
26531			} else {
26532				this.dispatchEvent("update");
26533			}
26534		},
26535		dispatchEvent: function(eventName) {
26536			var event = $.Event(eventName + ".countdown");
26537			event.finalDate = this.finalDate;
26538			event.elapsed = this.elapsed;
26539			event.offset = $.extend({}, this.offset);
26540			event.strftime = strftime(this.offset);
26541			this.$el.trigger(event);
26542		}
26543	});
26544	$.fn.countdown = function() {
26545		var argumentsArray = Array.prototype.slice.call(arguments, 0);
26546		return this.each(function() {
26547			var instanceNumber = $(this).data("countdown-instance");
26548			if (instanceNumber !== undefined) {
26549				var instance = instances[instanceNumber], method = argumentsArray[0];
26550				if (Countdown.prototype.hasOwnProperty(method)) {
26551					instance[method].apply(instance, argumentsArray.slice(1));
26552				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
26553					instance.setFinalDate.call(instance, method);
26554					instance.start();
26555				} else {
26556					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
26557				}
26558			} else {
26559				new Countdown(this, argumentsArray[0], argumentsArray[1]);
26560			}
26561		});
26562	};
26563});
26564
26565!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;
26566function getStyles(config){
26567  // 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;
26567left: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+"}"
26568};
26569  var ShareUtils;
26570
26571if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
26572  Object.defineProperty(HTMLElement.prototype, "classList", {
26573    get: function() {
26574      var ret, self, update;
26575      update = function(fn) {
26576        return function(value) {
26577          var classes, index;
26578          classes = self.className.split(/\s+/);
26579          index = classes.indexOf(value);
26580          fn(classes, index, value);
26581          self.className = classes.join(" ");
26582        };
26583      };
26584      self = this;
26585      ret = {
26586        add: update(function(classes, index, value) {
26587          ~index || classes.push(value);
26588        }),
26589        remove: update(function(classes, index) {
26590          ~index && classes.splice(index, 1);
26591        }),
26592        toggle: update(function(classes, index, value) {
26593          if (~index) {
26594            classes.splice(index, 1);
26595          } else {
26596            classes.push(value);
26597          }
26598        }),
26599        contains: function(value) {
26600          return !!~self.className.split(/\s+/).indexOf(value);
26601        },
26602        item: function(i) {
26603          return self.className.split(/\s+/)[i] || null;
26604        }
26605      };
26606      Object.defineProperty(ret, "length", {
26607        get: function() {
26608          return self.className.split(/\s+/).length;
26609        }
26610      });
26611      return ret;
26612    }
26613  });
26614}
26615
26616String.prototype.to_rfc3986 = function() {
26617  var tmp;
26618  tmp = encodeURIComponent(this);
26619  return tmp.replace(/[!'()*]/g, function(c) {
26620    return "%" + c.charCodeAt(0).toString(16);
26621  });
26622};
26623
26624ShareUtils = (function() {
26625  function ShareUtils() {}
26626
26627  ShareUtils.prototype.extend = function(to, from, overwrite) {
26628    var hasProp, prop;
26629    for (prop in from) {
26630      hasProp = to[prop] !== undefined;
26631      if (hasProp && typeof from[prop] === "object") {
26632        this.extend(to[prop], from[prop], overwrite);
26633      } else {
26634        if (overwrite || !hasProp) {
26635          to[prop] = from[prop];
26636        }
26637      }
26638    }
26639  };
26640
26641  ShareUtils.prototype.hide = function(el) {
26642    return el.style.display = "none";
26643  };
26644
26645  ShareUtils.prototype.show = function(el) {
26646    return el.style.display = "block";
26647  };
26648
26649  ShareUtils.prototype.has_class = function(el, class_name) {
26650    return el.classList.contains(class_name);
26651  };
26652
26653  ShareUtils.prototype.add_class = function(el, class_name) {
26654    return el.classList.add(class_name);
26655  };
26656
26657  ShareUtils.prototype.remove_class = function(el, class_name) {
26658    return el.classList.remove(class_name);
26659  };
26660
26661  ShareUtils.prototype.is_encoded = function(str) {
26662    str = str.to_rfc3986();
26663    return decodeURIComponent(str) !== str;
26664  };
26665
26666  ShareUtils.prototype.encode = function(str) {
26667    if (typeof str === "undefined" || this.is_encoded(str)) {
26668      return str;
26669    } else {
26670      return str.to_rfc3986();
26671    }
26672  };
26673
26674  ShareUtils.prototype.popup = function(url, params) {
26675    var k, popup, qs, v;
26676    if (params == null) {
26677      params = {};
26678    }
26679    popup = {
26680      width: 500,
26681      height: 350
26682    };
26683    popup.top = (screen.height / 2) - (popup.height / 2);
26684    popup.left = (screen.width / 2) - (popup.width / 2);
26685    qs = ((function() {
26686      var _results;
26687      _results = [];
26688      for (k in params) {
26689        v = params[k];
26690        _results.push("" + k + "=" + (this.encode(v)));
26691      }
26692      return _results;
26693    }).call(this)).join('&');
26694    if (qs) {
26695      qs = "?" + qs;
26696    }
26697    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=" 
26697+ popup.width + ",height=" + popup.height);
26698  };
26699
26700  return ShareUtils;
26701
26702})();
26703var Share,
26704  __hasProp = {}.hasOwnProperty,
26705  __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; };
26706
26707Share = (function(_super) {
26708  __extends(Share, _super);
26709
26710  function Share(element, options) {
26711    this.element = element;
26712    this.el = {
26713      head: document.getElementsByTagName('head')[0],
26714      body: document.getElementsByTagName('body')[0]
26715    };
26716    this.config = {
26717      enabled_networks: 0,
26718      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
26719      url: window.location.href.replace("&", "%26"),
26720      caption: null,
26721      title: this.default_title(),
26722      image: this.default_image(),
26723      description: this.default_description(),
26724      ui: {
26725        flyout: 'top center',
26726        button_text: 'Share',
26727        button_font: true,
26728        icon_font: true
26729      },
26730      networks: {
26731        twitter: {
26732          enabled: true,
26733          url: null,
26734          title: null,
26735          description: null
26736        },
26737        facebook: {
26738          enabled: true,
26739          load_sdk: true,
26740          url: null,
26741          app_id: null,
26742          title: null,
26743          caption: null,
26744          description: null,
26745          image: null
26746        },
26747        pinterest: {
26748          enabled: true,
26749          url: null,
26750          image: null,
26751          description: null
26752        },
26753        reddit: {
26754          enabled: true,
26755          url: null,
26756          title: null
26757        },
26758        linkedin: {
26759          enabled: true,
26760          url: null,
26761          title: null,
26762          description: null
26763        },
26764        xing: {
26765          enabled: true,
26766          url: null,
26767          title: null,
26768          image: null,
26769          description: null
26770        },
26771        whatsapp: {
26772          enabled: true,
26773          title: null,
26774          url: null
26775        },
26776        email: {
26777          enabled: true,
26778          title: null,
26779          description: null,
26780          url: null
26781        }
26782      }
26783    };
26784    this.setup(element, options);
26785    return this;
26786  }
26787
26788  Share.prototype.setup = function(element, opts) {
26789    var index, instance, instances, _i, _len;
26790    instances = document.querySelectorAll(element);
26791    this.extend(this.config, opts, true);
26792    this.set_global_configuration();
26793    this.normalize_network_configuration();
26794    if (this.config.ui.icon_font) {
26795      this.inject_icons();
26796    }
26797    if (this.config.ui.button_font) {
26798      this.inject_fonts();
26799    }
26800    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
26801      this.inject_facebook_sdk();
26802    }
26803    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
26804      instance = instances[index];
26805      this.setup_instance(element, index);
26806    }
26807  };
26808
26809  Share.prototype.setup_instance = function(element, index) {
26810    var button, instance, label, network, networks, _i, _len, _results,
26811      _this = this;
26812    instance = document.querySelectorAll(element)[index];
26813    this.hide(instance);
26814    this.add_class(instance, "sharer-" + index);
26815    instance = document.querySelectorAll(element)[index];
26816    this.inject_css(instance);
26817    this.inject_html(instance);
26818    this.show(instance);
26819    label = instance.getElementsByTagName("label")[0];
26820    button = instance.getElementsByClassName("social")[0];
26821    networks = instance.getElementsByTagName('li');
26822    this.add_class(button, "networks-" + this.config.enabled_networks);
26823    label.addEventListener("click", function() {
26824      return _this.event_toggle(button);
26825    });
26826    _this = this;
26827    _results = [];
26828    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
26829      network = networks[index];
26830      _results.push(network.addEventListener("click", function() {
26831        _this.event_network(instance, this);
26832        return _this.event_close(button);
26833      }));
26834    }
26835    return _results;
26836  };
26837
26838  Share.prototype.event_toggle = function(button) {
26839    if (this.has_class(button, "active")) {
26840      return this.event_close(button);
26841    } else {
26842      return this.event_open(button);
26843    }
26844  };
26845
26846  Share.prototype.event_open = function(button) {
26847    if (this.has_class(button, "load")) {
26848      this.remove_class(button, "load");
26849    }
26850    return this.add_class(button, "active");
26851  };
26852
26853  Share.prototype.event_close = function(button) {
26854    return this.remove_class(button, "active");
26855  };
26856
26857  Share.prototype.event_network = function(instance, network) {
26858    var name;
26859    name = network.getAttribute("data-network");
26860    this.hook("before", name, instance);
26861    this["network_" + name]();
26862    return this.hook("after", name, instance);
26863  };
26864
26865  Share.prototype.open = function() {
26866    return this["public"]("open");
26867  };
26868
26869  Share.prototype.close = function() {
26870    return this["public"]("close");
26871  };
26872
26873  Share.prototype.toggle = function() {
26874    return this["public"]("toggle");
26875  };
26876
26877  Share.prototype["public"] = function(action) {
26878    var button, index, instance, _i, _len, _ref, _results;
26879    _ref = document.querySelectorAll(this.element);
26880    _results = [];
26881    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26882      instance = _ref[index];
26883      button = instance.getElementsByClassName("social")[0];
26884      _results.push(this["event_" + action](button));
26885    }
26886    return _results;
26887  };
26888
26889  Share.prototype.network_facebook = function() {
26890    if (this.config.networks.facebook.load_sdk) {
26891      if (!window.FB) {
26892        return console.error("The Facebook JS SDK hasn't loaded yet.");
26893      }
26894      return FB.ui({
26895        method: 'feed',
26896        name: this.config.networks.facebook.title,
26897        link: this.config.networks.facebook.url,
26898        picture: this.config.networks.facebook.image,
26899        caption: this.config.networks.facebook.caption,
26900        description: this.config.networks.facebook.description
26901      });
26902    } else {
26903      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26904        u: this.config.networks.facebook.url
26905      });
26906    }
26907  };
26908
26909  Share.prototype.network_twitter = function() {
26910    return this.popup('https://twitter.com/intent/tweet', {
26911      text: this.config.networks.twitter.title,
26912      url: this.config.networks.twitter.url
26913    });
26914  };
26915
26916  Share.prototype.network_pinterest = function() {
26917    return this.popup('https://www.pinterest.com/pin/create/button', {
26918      url: this.config.networks.pinterest.url,
26919      media: this.config.networks.pinterest.image,
26920      description: this.config.networks.pinterest.description
26921    });
26922  };
26923
26924  Share.prototype.network_linkedin = function() {
26925    return this.popup('https://www.linkedin.com/shareArticle', {
26926      url: this.config.networks.linkedin.url,
26927      title: this.config.networks.linkedin.title,
26928      summary: this.config.networks.linkedin.description
26929    });
26930  }
26931
26932  Share.prototype.network_xing = function() {
26933    return this.popup('https://www.xing.com/spi/shares/new', {
26934      url: this.config.networks.xing.url,
26935      image: this.config.networks.xing.image,
26936      title: this.config.networks.xing.title,
26937      summary: this.config.networks.xing.description
26938    });
26939  }
26940
26941  Share.prototype.network_whatsapp = function() {
26942    return this.popup('https://api.whatsapp.com/send', {
26943      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
26944    });
26945  }
26946
26947  Share.prototype.network_email = function() {
26948    return this.popup('mailto:', {
26949      subject: this.config.networks.email.title,
26950      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26951    });
26952  };
26953
26954  Share.prototype.inject_icons = function() {
26955  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
26956  };
26957
26958  Share.prototype.inject_fonts = function() {
26959   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
26960  };
26961
26962  Share.prototype.inject_stylesheet = function(url) {
26963    var link;
26964    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
26965      link = document.createElement("link");
26966      link.setAttribute("rel", "stylesheet");
26967      link.setAttribute("href", url);
26968      return this.el.head.appendChild(link);
26969    }
26970  };
26971
26972  Share.prototype.inject_css = function(instance) {
26973    var css, meta, selector, style;
26974    selector = "." + (instance.getAttribute('class').split(" ").join("."));
26975    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
26976      this.config.selector = selector;
26977      css = getStyles(this.config);
26978      style = document.createElement("style");
26979      style.type = "text/css";
26980      if (style.styleSheet) {
26981        style.styleSheet.cssText = css;
26982      } else {
26983        style.appendChild(document.createTextNode(css));
26984      }
26985      this.el.head.appendChild(style);
26986      delete this.config.selector;
26987      meta = document.createElement("meta");
26988      meta.setAttribute("name", "sharer" + selector);
26989      return this.el.head.appendChild(meta);
26990    }
26991  };
26992
26993  Share.prototype.inject_html = function(instance) {
26994    //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>";
26995    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>";
26996  };
26997
26998  Share.prototype.inject_facebook_sdk = function() {
26999    var fb_root, script;
27000    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
27001      script = document.createElement("script");
27002      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')";
27003      fb_root = document.createElement("div");
27004      fb_root.id = "fb-root";
27005      this.el.body.appendChild(fb_root);
27006      return this.el.body.appendChild(script);
27007    }
27008  };
27009
27010  Share.prototype.hook = function(type, network, instance) {
27011    var fn, opts;
27012    fn = this.config.networks[network][type];
27013    if (typeof fn === "function") {
27014      opts = fn.call(this.config.networks[network], instance);
27015      if (opts !== void 0) {
27016        opts = this.normalize_filter_config_updates(opts);
27017        this.extend(this.config.networks[network], opts, true);
27018        this.normalize_network_configuration();
27019      }
27020    }
27021  };
27022
27023  Share.prototype.default_title = function() {
27024    var content;
27025    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27026      return encodeURIComponent(content.getAttribute('content'));
27027    } else if (content = document.querySelector('title')) {
27028      return encodeURIComponent(content.innerText);
27029    }
27030  };
27031
27032  Share.prototype.default_image = function() {
27033    var content;
27034    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27035      return content.getAttribute('content');
27036    }
27037  };
27038
27039  Share.prototype.default_description = function() {
27040    var content;
27041    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27042      return encodeURIComponent(content.getAttribute('content'));
27043    } else {
27044      return '';
27045    }
27046  };
27047
27048  Share.prototype.set_global_configuration = function() {
27049    var display, network, option, options, _ref, _results;
27050    _ref = this.config.networks;
27051    _results = [];
27052    for (network in _ref) {
27053      options = _ref[network];
27054      for (option in options) {
27055        if (this.config.networks[network][option] == null) {
27056          this.config.networks[network][option] = this.config[option];
27057        }
27058      }
27059      if (this.config.networks[network].enabled) {
27060        display = 'block';
27061        this.config.enabled_networks += 1;
27062      } else {
27063        display = 'none';
27064      }
27065      _results.push(this.config.networks[network].display = display);
27066    }
27067    return _results;
27068  };
27069
27070  Share.prototype.normalize_network_configuration = function() {
27071    if (!this.config.networks.facebook.app_id) {
27072      this.config.networks.facebook.load_sdk = false;
27073    }
27074    if (!this.is_encoded(this.config.networks.twitter.description)) {
27075      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
27076    }
27077    if (typeof this.config.networks.facebook.app_id === 'number') {
27078      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
27079    }
27080  };
27081
27082  Share.prototype.normalize_filter_config_updates = function(opts) {
27083    if (this.config.networks.facebook.app_id !== opts.app_id) {
27084      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.");
27085      delete opts.app_id;
27086    }
27087    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
27088      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.");
27089      delete opts.app_id;
27090    }
27091    return opts;
27092  };
27093
27094  return Share;
27095
27096})(ShareUtils);
27097 return Share;
27098});
27099
27100// Generated by CoffeeScript 1.9.2
27101
27102// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
27103
27104(function() {
27105  var $, win;
27106
27107  $ = this.jQuery || window.jQuery;
27108
27109  win = $(window);
27110
27111  $.fn.stick_in_parent = function(opts) {
27112    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
27113    if (opts == null) {
27114      opts = {};
27115    }
27116    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;
27117    if (offset_top == null) {
27118      offset_top = 0;
27119    }
27120    if (parent_selector == null) {
27121      parent_selector = void 0;
27122    }
27123    if (inner_scrolling == null) {
27124      inner_scrolling = true;
27125    }
27126    if (sticky_class == null) {
27127      sticky_class = "is_stuck";
27128    }
27129    doc = $(document);
27130    if (enable_bottoming == null) {
27131      enable_bottoming = true;
27132    }
27133    outer_width = function(el) {
27134      var _el, computed, w;
27135      if (window.getComputedStyle) {
27136        _el = el[0];
27137        computed = window.getComputedStyle(el[0]);
27138        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
27139        if (computed.getPropertyValue("box-sizing") !== "border-box") {
27140          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
27141        }
27142        return w;
27143      } else {
27144        return el.outerWidth(true);
27145      }
27146    };
27147    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
27148      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
27149      if (elm.data("sticky_kit")) {
27150        return;
27151      }
27152      elm.data("sticky_kit", true);
27153      last_scroll_height = doc.height();
27154      parent = elm.parent();
27155      if (parent_selector != null) {
27156        parent = parent.closest(parent_selector);
27157      }
27158      if (!parent.length) {
27159        throw "failed to find stick parent";
27160      }
27161      fixed = false;
27162      bottomed = false;
27163      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
27164      if (spacer) {
27165        spacer.css('position', elm.css('position'));
27166      }
27167      recalc = function() {
27168        var border_top, padding_top, restore;
27169        if (detached) {
27170          return;
27171        }
27172        last_scroll_height = doc.height();
27173        border_top = parseInt(parent.css("border-top-width"), 10);
27174        padding_top = parseInt(parent.css("padding-top"), 10);
27175        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
27176        parent_top = parent.offset().top + border_top + padding_top;
27177        parent_height = parent.height();
27178        if (fixed) {
27179          fixed = false;
vendor: 6,068 bytes, lines 27180-27374
27180          bottomed = false;
27181          if (manual_spacer == null) {
27182            elm.insertAfter(spacer);
27183            spacer.detach();
27184          }
27185          elm.css({
27186            position: "",
27187            top: "",
27188            width: "",
27189            bottom: ""
27190          }).removeClass(sticky_class);
27191          restore = true;
27192        }
27193        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
27194        height = elm.outerHeight(true);
27195        el_float = elm.css("float");
27196        if (spacer) {
27197          spacer.css({
27198            width: outer_width(elm),
27199            height: height,
27200            display: elm.css("display"),
27201            "vertical-align": elm.css("vertical-align"),
27202            "float": el_float
27203          });
27204        }
27205        if (restore) {
27206          return tick();
27207        }
27208      };
27209      recalc();
27210      if (height === parent_height) {
27211        return;
27212      }
27213      last_pos = void 0;
27214      offset = offset_top;
27215      recalc_counter = recalc_every;
27216      tick = function() {
27217        var css, delta, recalced, scroll, will_bottom, win_height;
27218        if (detached) {
27219          return;
27220        }
27221        recalced = false;
27222        if (recalc_counter != null) {
27223          recalc_counter -= 1;
27224          if (recalc_counter <= 0) {
27225            recalc_counter = recalc_every;
27226            recalc();
27227            recalced = true;
27228          }
27229        }
27230        if (!recalced && doc.height() !== last_scroll_height) {
27231          recalc();
27232          recalced = true;
27233        }
27234        scroll = win.scrollTop();
27235        if (last_pos != null) {
27236          delta = scroll - last_pos;
27237        }
27238        last_pos = scroll;
27239        if (fixed) {
27240          if (enable_bottoming) {
27241            will_bottom = scroll + height + offset > parent_height + parent_top;
27242            if (bottomed && !will_bottom) {
27243              bottomed = false;
27244              elm.css({
27245                position: "fixed",
27246                bottom: "",
27247                top: offset
27248              }).trigger("sticky_kit:unbottom");
27249            }
27250          }
27251          if (scroll < top) {
27252            fixed = false;
27253            offset = offset_top;
27254            if (manual_spacer == null) {
27255              if (el_float === "left" || el_float === "right") {
27256                elm.insertAfter(spacer);
27257              }
27258              spacer.detach();
27259            }
27260            css = {
27261              position: "",
27262              width: "",
27263              top: ""
27264            };
27265            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
27266          }
27267          if (inner_scrolling) {
27268            win_height = win.height();
27269            if (height + offset_top > win_height) {
27270              if (!bottomed) {
27271                offset -= delta;
27272                offset = Math.max(win_height - height, offset);
27273                offset = Math.min(offset_top, offset);
27274                if (fixed) {
27275                  elm.css({
27276                    top: offset + "px"
27277                  });
27278                }
27279              }
27280            }
27281          }
27282        } else {
27283          if (scroll > top) {
27284            fixed = true;
27285            css = {
27286              position: "fixed",
27287              top: offset
27288            };
27289            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
27290            elm.css(css).addClass(sticky_class);
27291            if (manual_spacer == null) {
27292              elm.after(spacer);
27293              if (el_float === "left" || el_float === "right") {
27294                spacer.append(elm);
27295              }
27296            }
27297            elm.trigger("sticky_kit:stick");
27298          }
27299        }
27300        if (fixed && enable_bottoming) {
27301          if (will_bottom == null) {
27302            will_bottom = scroll + height + offset > parent_height + parent_top;
27303          }
27304          if (!bottomed && will_bottom) {
27305            bottomed = true;
27306            if (parent.css("position") === "static") {
27307              parent.css({
27308                position: "relative"
27309              });
27310            }
27311            return elm.css({
27312              position: "absolute",
27313              bottom: padding_bottom,
27314              top: "auto"
27315            }).trigger("sticky_kit:bottom");
27316          }
27317        }
27318      };
27319      recalc_and_tick = function() {
27320        recalc();
27321        return tick();
27322      };
27323      detach = function() {
27324        detached = true;
27325        win.off("touchmove", tick);
27326        win.off("scroll", tick);
27327        win.off("resize", recalc_and_tick);
27328        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
27329        elm.off("sticky_kit:detach", detach);
27330        elm.removeData("sticky_kit");
27331        elm.css({
27332          position: "",
27333          bottom: "",
27334          top: "",
27335          width: ""
27336        });
27337        parent.position("position", "");
27338        if (fixed) {
27339          if (manual_spacer == null) {
27340            if (el_float === "left" || el_float === "right") {
27341              elm.insertAfter(spacer);
27342            }
27343            spacer.remove();
27344          }
27345          return elm.removeClass(sticky_class);
27346        }
27347      };
27348      win.on("touchmove", tick);
27349      win.on("scroll", tick);
27350      win.on("resize", recalc_and_tick);
27351      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
27352      elm.on("sticky_kit:detach", detach);
27353      return setTimeout(tick, 0);
27354    };
27355    for (i = 0, len = this.length; i < len; i++) {
27356      elm = this[i];
27357      fn($(elm));
27358    }
27359    return this;
27360  };
27361
27362}).call(this);
27363/* ==========================================================================
27364 * bootstrap-tab-history.js
27365 * Author: Michael Narayan <[email protected]>
27366 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
27367 * ==========================================================================
27368 * Licensed under the Apache License, Version 2.0 (the "License"); you may
27369 * not use this file except in compliance with the License. You may obtain a
27370 * copy of the License at
27371 *
27372 * http://www.apache.org/licenses/LICENSE-2.0
27373 *
27374 * Unless required by applicable law or agreed to in writing, softw
27374are
27375 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
27376 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
27377 * License for the specific language governing permissions and limitations
27378 * under the License.
27379 * ========================================================================== */
27380
27381/* ========================================================================== */
27382/* JSHint directives                                                          */
27383/*                                                                            */
27384/* global BootstrapTabHistory: true                                           */
27385/*                                                                            */
27386/* global document                                                            */
27387/* global jQuery                                                              */
27388/* global history                                                             */
27389/* global window                                                              */
27390/* ========================================================================== */
27391
27392/**
27393 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
27394 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
27395 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
27396 *
27397 * See the README for additional information.
27398 *
27399 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
27400 */
27401
27402BootstrapTabHistory = {
27403  options: {
27404    /**
27405     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
27406     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
27407     *
27408     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
27409     *
27410     * @public
27411     * @type {?number}
27412     */
27413    defaultAnchorYOffset: 0,
27414    /**
27415     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
27416     *
27417     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
27418     *
27419     * @public
27420     * @type {string}
27421     */
27422    defaultChanger: 'replace',
27423    /**
27424     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
27425     * `null` is passed as the third parameter to these calls.
27426     *
27427     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
27428     *
27429     * @public
27430     * @type {boolean}
27431     */
27432    defaultUpdateURL: false,
27433    /**
27434     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
27435     * load.
27436     *
27437     * @public
27438     * @type {boolean}
27439     */
27440    showTabsBasedOnAnchor: true
27441  }
27442};
27443
27444(function () {
27445  'use strict';
27446
27447  jQuery(function () {
27448    if(history && history.pushState && history.replaceState) {
27449      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27450
27451      if(bootstrapTabHistory) {
27452        showTabsBasedOnState(bootstrapTabHistory);
27453      } else {
27454        showTabsBasedOnAnchor();
27455      }
27456
27457      backfillHistoryState();
27458
27459      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
27460      jQuery(window).on('popstate', onPopState);
27461    } else {
27462      showTabsBasedOnAnchor();
27463    }
27464  });
27465
27466  /**
27467   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
27468   *
27469   * @type {boolean}
27470   */
27471  var showingTabsBasedOnState = false;
27472
27473  /**
27474   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
27475   * `history.back` handling when `data-tab-history-update-url` is true.
27476   */
27477  function backfillHistoryState() {
27478    var newState = null;
27479
27480    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
27481      var $activeTabElement = jQuery(this);
27482      var selector = getTabSelector($activeTabElement);
27483
27484      if(selector) {
27485        var tabGroup = getTabGroup($activeTabElement);
27486
27487        if(tabGroup) {
27488          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
27489        }
27490      }
27491    });
27492
27493    if(newState) {
27494      history.replaceState(newState, '', null);
27495    }
27496  }
27497
27498  /**
27499   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
27500   * said bootstrapTabHistory attribute.
27501   *
27502   * @param {?object} existingState
27503   * @param {!string} tabGroup
27504   * @param {!string} selector
27505   * @returns {!object}
27506   */
27507  function createNewHistoryState(existingState, tabGroup, selector) {
27508    // Clone history.state and ensure it has a bootstrapTabHistory entry.
27509    var newState = jQuery.extend(true, {}, existingState, {
27510      bootstrapTabHistory: {}
27511    });
27512
27513    newState.bootstrapTabHistory[tabGroup] = selector;
27514
27515    return newState;
27516  }
27517
27518  /**
27519   * @param {jQuery} $tab
27520   * @returns {?string}
27521   */
27522  function getTabGroup($tab) {
27523    return parseTruthyAttributeValue($tab.data('tab-history'));
27524  }
27525
27526  /**
27527   * @param {jQuery} $tab
27528   * @returns {?string}
27529   */
27530  function getTabSelector($tab) {
27531    return $tab.data('target') || $tab.attr('href');
27532  }
27533
27534  /**
27535   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
27536   *
27537   * @param {jQuery.Event} shownEvt
27538   */
27539  function onShownTab(shownEvt) {
27540    if(!showingTabsBasedOnState) {
27541      var $activatedTab = jQuery(shownEvt.target);
27542      if ( $activatedTab.hasClass('panel-collapse') )
27543        $activatedTab = $activatedTab.closest('.panel').find('a');
27544      var selector = getTabSelector($activatedTab);
27545
27546      if(selector) {
27547        var tabGroup = getTabGroup($activatedTab);
27548
27549        if(tabGroup) {
27550          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
27551          var newState = createNewHistoryState(history.state, tabGroup, selector);
27552          var updateURL = (function ($activatedTab) {
27553            if(selector[0] === '#') {
27554              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
27555
27556              if(elementUpdateURLOption === undefined) {
27557                return BootstrapTabHistory.options.defaultUpdateURL;
27558              } else {
27559                return elementUpdateURLOption;
27560              }
27561            } else {
27562              return false;
27563            }
27564          })($activatedTab);
27565
27566          switch(historyChanger) {
27567            case 'push':
27568              history.pushState(newState, '', updateURL ? selector : null);
27569              break;
27570            case 'replace':
27571              history.replaceState(newState, '', updateURL ? selector : null);
27572              break;
27573            default:
27574              throw new Error('Unknown tab-history-changer: ' + historyChanger);
27575          }
27576        }
27577      }
27578    }
27579  }
27580
27581  /**
27582   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
27583   */
27584  function onPopState() {
27585    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27586
27587    if(bootstrapTabHistory) {
27588      showTabsBasedOnState(bootstrapTabHistory);
27589    }
27590  }
27591
27592  /**
27593   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
27594   *
27595   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
27596   *
27597   * @param {*} value
27598   * @returns {*}
27599   */
27600  function parseTruthyAttributeValue(value) {
27601    if(value) {
27602      return value;
27603    } else if(value === '') {
27604      return true;
27605    } else {
27606      return value;
27607    }
27608  }
27609
27610  /**
27611   * Show tabs based upon the anchor component of `window.location`.
27612   */
27613  function showTabsBasedOnAnchor() {
27614    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
27615      var anchor = window.location && window.location.hash;
27616
27617      if(anchor) {
27618        var $tabElement = showTabForSelector(anchor);
27619
27620        if($tabElement && window.addEventListener && window.removeEventListener) {
27621          var anchorYOffset = (function ($tabElement) {
27622            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
27623
27624            if(elementSetting === undefined) {
27625              return BootstrapTabHistory.options.defaultAnchorYOffset;
27626            } else {
27627              return elementSetting;
27628            }
27629          })($tabElement);
27630
27631          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
27632          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
27633          //   `history.state` object should have been used (unless the browser did not support the modern History API).
27634          if(anchorYOffset || anchorYOffset === 0) {
27635            var scrollListener = function resetAnchorScroll () {
27636              window.removeEventListener('scroll', scrollListener);
27637              window.scrollTo(0, anchorYOffset);
27638            };
27639
27640            window.addEventListener('scroll', scrollListener);
27641          }
27642        }
27643      }
27644    }
27645  }
27646
27647  /**
27648   * Show a tab which corresponds to the provided selector.
27649   *
27650   * @param {string} selector - A CSS selector.
27651   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
27652   */
27653  function showTabForSelector(selector) {
27654    var $tabElement = (function (selector) {
27655      var $ret = null;
27656
27657      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
27658        var $potentialTab = jQuery(this);
27659
27660        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
27661          $ret = $potentialTab;
27662          return false;
vendor: 43,483 bytes, lines 27663-28879
27663        } else {
27664         return null;
27665        }
27666      });
27667
27668      return $ret;
27669    })(selector);
27670
27671    if($tabElement) {
27672      if ( !$tabElement.parent().hasClass('active') ) {
27673        $tabElement.trigger('click');
27674      }
27675      //$tabElement.tab('show');
27676    }
27677
27678    return $tabElement;
27679  }
27680
27681  /**
27682   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
27683   *
27684   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
27685   */
27686  function showTabsBasedOnState(bootstrapTabHistory) {
27687    showingTabsBasedOnState = true;
27688
27689    try {
27690      for(var k in bootstrapTabHistory) {
27691        if(bootstrapTabHistory.hasOwnProperty(k)) {
27692          showTabForSelector(bootstrapTabHistory[k]);
27693        }
27694      }
27695    } finally {
27696      showingTabsBasedOnState = false;
27697    }
27698  }
27699})();
27700
27701/*!
27702 * justifiedGallery - v3.8.1
27703 * http://miromannino.github.io/Justified-Gallery/
27704 * Copyright (c) 2020 Miro Mannino
27705 * Licensed under the MIT license.
27706 */
27707(function (factory) {
27708  if (typeof define === 'function' && define.amd) {
27709    // AMD. Register as an anonymous module.
27710    define(['jquery'], factory);
27711  } else if (typeof module === 'object' && module.exports) {
27712    // Node/CommonJS
27713    module.exports = function (root, jQuery) {
27714      if (jQuery === undefined) {
27715        // require('jQuery') returns a factory that requires window to
27716        // build a jQuery instance, we normalize how we use modules
27717        // that require this pattern but the window provided is a noop
27718        // if it's defined (how jquery works)
27719        if (typeof window !== 'undefined') {
27720          jQuery = require('jquery');
27721        }
27722        else {
27723          jQuery = require('jquery')(root);
27724        }
27725      }
27726      factory(jQuery);
27727      return jQuery;
27728    };
27729  } else {
27730    // Browser globals
27731    factory(jQuery);
27732  }
27733}(function ($) {
27734
27735  /**
27736   * Justified Gallery controller constructor
27737   *
27738   * @param $gallery the gallery to build
27739   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
27740   * @constructor
27741   */
27742  var JustifiedGallery = function ($gallery, settings) {
27743
27744    this.settings = settings;
27745    this.checkSettings();
27746
27747    this.imgAnalyzerTimeout = null;
27748    this.entries = null;
27749    this.buildingRow = {
27750      entriesBuff: [],
27751      width: 0,
27752      height: 0,
27753      aspectRatio: 0
27754    };
27755    this.lastFetchedEntry = null;
27756    this.lastAnalyzedIndex = -1;
27757    this.yield = {
27758      every: 2, // do a flush every n flushes (must be greater than 1)
27759      flushed: 0 // flushed rows without a yield
27760    };
27761    this.border = settings.border >= 0 ? settings.border : settings.margins;
27762    this.maxRowHeight = this.retrieveMaxRowHeight();
27763    this.suffixRanges = this.retrieveSuffixRanges();
27764    this.offY = this.border;
27765    this.rows = 0;
27766    this.spinner = {
27767      phase: 0,
27768      timeSlot: 150,
27769      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
27770      intervalId: null
27771    };
27772    this.scrollBarOn = false;
27773    this.checkWidthIntervalId = null;
27774    this.galleryWidth = $gallery.width();
27775    this.$gallery = $gallery;
27776
27777  };
27778
27779  /** @returns {String} the best suffix given the width and the height */
27780  JustifiedGallery.prototype.getSuffix = function (width, height) {
27781    var longestSide, i;
27782    longestSide = (width > height) ? width : height;
27783    for (i = 0; i < this.suffixRanges.length; i++) {
27784      if (longestSide <= this.suffixRanges[i]) {
27785        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27786      }
27787    }
27788    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27789  };
27790
27791  /**
27792   * Remove the suffix from the string
27793   *
27794   * @returns {string} a new string without the suffix
27795   */
27796  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27797    return str.substring(0, str.length - suffix.length);
27798  };
27799
27800  /**
27801   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27802   */
27803  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27804    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27805  };
27806
27807  /**
27808   * Get the used suffix of a particular url
27809   *
27810   * @param str
27811   * @returns {String} return the used suffix
27812   */
27813  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27814    for (var si in this.settings.sizeRangeSuffixes) {
27815      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27816        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27817        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27818      }
27819    }
27820    return '';
27821  };
27822
27823  /**
27824   * Given an image src, with the width and the height, returns the new image src with the
27825   * best suffix to show the best quality thumbnail.
27826   *
27827   * @returns {String} the suffix to use
27828   */
27829  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27830    var newImageSrc;
27831
27832    if (this.settings.thumbnailPath) {
27833      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27834    } else {
27835      var matchRes = imageSrc.match(this.settings.extension);
27836      var ext = (matchRes !== null) ? matchRes[0] : '';
27837      newImageSrc = imageSrc.replace(this.settings.extension, '');
27838      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27839      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27840    }
27841
27842    return newImageSrc;
27843  };
27844
27845  /**
27846   * Shows the images that is in the given entry
27847   *
27848   * @param $entry the entry
27849   * @param callback the callback that is called when the show animation is finished
27850   */
27851  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27852    if (this.settings.cssAnimation) {
27853      $entry.addClass('jg-entry-visible');
27854      if (callback) callback();
27855    } else {
27856      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27857      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27858    }
27859  };
27860
27861  /**
27862   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27863   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27864   *
27865   * @param $image the image to analyze
27866   * @returns {String} the extracted src
27867   */
27868  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27869    var imageSrc = $image.data('safe-src');
27870    var imageSrcLoc = 'data-safe-src';
27871    // Begin Uncode edit
27872    if (typeof imageSrc === 'undefined') {
27873    	var imageCurrentSrc = $image[0].currentSrc;
27874    	if (imageCurrentSrc) {
27875    		imageSrc = imageCurrentSrc;
27876    	} else {
27877    		imageSrc = $image.attr('src');
27878    	}
27879		imageSrcLoc = 'src';
27880    }
27881    // End Uncode edit
27882    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27883    $image.data('jg.src', imageSrc); // this will change overtime
27884    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27885    return imageSrc;
27886  };
27887
27888  /** @returns {jQuery} the image in the given entry */
27889  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27890    var $img = $entry.find(this.settings.imgSelector);
27891    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27892    return $img.length === 0 ? null : $img;
27893  };
27894
27895  /** @returns {jQuery} the caption in the given entry */
27896  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27897    var $caption = $entry.find('> .jg-caption');
27898    return $caption.length === 0 ? null : $caption;
27899  };
27900
27901  /**
27902   * Display the entry
27903   *
27904   * @param {jQuery} $entry the entry to display
27905   * @param {int} x the x position where the entry must be positioned
27906   * @param y the y position where the entry must be positioned
27907   * @param imgWidth the image width
27908   * @param imgHeight the image height
27909   * @param rowHeight the row height of the row that owns the entry
27910   */
27911  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27912    $entry.width(imgWidth);
27913    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27914    $entry.css('top', Math.floor(y));//hacked by Uncode
27915    $entry.css('left', x);
27916
27917    var $image = this.imgFromEntry($entry);
27918    if ($image !== null) {
27919      $image.css('width', imgWidth);
27920      $image.css('height', imgHeight);
27921      $image.css('margin-left', - imgWidth / 2);
27922      $image.css('margin-top', - imgHeight / 2);
27923
27924      // Image reloading for an high quality of thumbnails
27925      var imageSrc = $image.data('jg.src');
27926      if (imageSrc) {
27927        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27928
27929        $image.one('error', function () {
27930           this.resetImgSrc($image); //revert to the original thumbnail
27931        });
27932
27933        var loadNewImage = function () {
27934          // if (imageSrc !== newImageSrc) {
27935            $image.attr('src', imageSrc);
27936          // }
27937        };
27938
27939        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27940          this.onImageEvent(imageSrc, (function() {
27941            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27942            $entry.data('jg.loaded', true);
27943          }).bind(this));
27944        } else {
27945          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27946        }
27947
27948      }
27949
27950    } else {
27951      this.showImg($entry);
27952    }
27953
27954    this.displayEntryCaption($entry);
27955  };
27956
27957  /**
27958   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
27959   * or the 'title' attributes.
27960   *
27961   * @param {jQuery} $entry the entry to process
27962   */
27963  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
27964    var $image = this.imgFromEntry($entry);
27965    if ($image !== null && this.settings.captions) {
27966      var $imgCaption = this.captionFromEntry($entry);
27967
27968      // Create it if it doesn't exists
27969      if ($imgCaption === null) {
27970        var caption = $image.attr('alt');
27971        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
27972        if (this.isValidCaption(caption)) { // Create only we found something
27973          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
27974          $entry.append($imgCaption);
27975          $entry.data('jg.createdCaption', true);
27976        }
27977      }
27978
27979      // Create events (we check again the $imgCaption because it can be still inexistent)
27980      if ($imgCaption !== null) {
27981        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
27982        this.addCaptionEventsHandlers($entry);
27983      }
27984    } else {
27985      this.removeCaptionEventsHandlers($entry);
27986    }
27987  };
27988
27989  /**
27990   * Validates the caption
27991   *
27992   * @param caption The caption that should be validated
27993   * @return {boolean} Validation result
27994   */
27995  JustifiedGallery.prototype.isValidCaption = function (caption) {
27996    return (typeof caption !== 'undefined' && caption.length > 0);
27997  };
27998
27999  /**
28000   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
28001   * It shows the caption using jQuery (or using CSS if it is configured so)
28002   *
28003   * @param {Event} eventObject the event object
28004   */
28005  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
28006    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28007    if (this.settings.cssAnimation) {
28008      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28009    } else {
28010      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28011        this.settings.captionSettings.visibleOpacity);
28012    }
28013  };
28014
28015  /**
28016   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28017   * It hides the caption using jQuery (or using CSS if it is configured so)
28018   *
28019   * @param {Event} eventObject the event object
28020   */
28021  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28022    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28023    if (this.settings.cssAnimation) {
28024      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28025    } else {
28026      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28027        this.settings.captionSettings.nonVisibleOpacity);
28028    }
28029  };
28030
28031  /**
28032   * Add the handlers of the entry for the caption
28033   *
28034   * @param $entry the entry to modify
28035   */
28036  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28037    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28038    if (typeof captionMouseEvents === 'undefined') {
28039      captionMouseEvents = {
28040        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28041        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28042      };
28043      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28044      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28045      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28046    }
28047  };
28048
28049  /**
28050   * Remove the handlers of the entry for the caption
28051   *
28052   * @param $entry the entry to modify
28053   */
28054  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28055    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28056    if (typeof captionMouseEvents !== 'undefined') {
28057      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28058      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28059      $entry.removeData('jg.captionMouseEvents');
28060    }
28061  };
28062
28063  /**
28064   * Clear the building row data to be used for a new row
28065   */
28066  JustifiedGallery.prototype.clearBuildingRow = function () {
28067    this.buildingRow.entriesBuff = [];
28068    this.buildingRow.aspectRatio = 0;
28069    this.buildingRow.width = 0;
28070  };
28071
28072  /**
28073   * Justify the building row, preparing it to
28074   *
28075   * @param isLastRow
28076   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28077   * @returns a boolean to know if the row has been justified or not
28078   */
28079  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
28080    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
28081    var minHeight = 0;
28082    var availableWidth = this.galleryWidth - 2 * this.border - (
28083      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28084    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
28085    var defaultRowHeight = this.settings.rowHeight;
28086    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
28087
28088    //Skip the last row if we can't justify it and the lastRow == 'hide'
28089    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
28090      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28091        $entry = this.buildingRow.entriesBuff[i];
28092        if (this.settings.cssAnimation)
28093          $entry.removeClass('jg-entry-visible');
28094        else {
28095          $entry.stop().fadeTo(0, 0.1);
28096          $entry.find('> img, > a > img').fadeTo(0, 0);
28097        }
28098      }
28099      return -1;
28100    }
28101
28102    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
28103    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
28104      justify = false;
28105
28106      if (this.rows > 0) {
28107        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
28108        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
28109      }
28110    }
28111
28112    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28113      $entry = this.buildingRow.entriesBuff[i];
28114      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28115
28116      if (justify) {
28117        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
28118        newImgH = rowHeight;
28119      } else {
28120        newImgW = defaultRowHeight * imgAspectRatio;
28121        newImgH = defaultRowHeight;
28122      }
28123
28124      availableWidth -= Math.round(newImgW);
28125      $entry.data('jg.jwidth', Math.round(newImgW));
28126      $entry.data('jg.jheight', Math.ceil(newImgH));
28127      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
28128    }
28129
28130    this.buildingRow.height = minHeight;
28131    return justify;
28132  };
28133
28134  /**
28135   * Flush a row: justify it, modify the gallery height accordingly to the row height
28136   *
28137   * @param isLastRow
28138   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28139   */
28140  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
28141    var settings = this.settings;
28142    var $entry, buildingRowRes, offX = this.border, i;
28143
28144    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
28145    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
28146      this.clearBuildingRow();
28147      return;
28148    }
28149
28150    if (this.maxRowHeight) {
28151      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
28152    }
28153
28154    //Align last (unjustified) row
28155    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
28156      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
28157
28158      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28159        $entry = this.buildingRow.entriesBuff[i];
28160        availableWidth -= $entry.data('jg.jwidth');
28161      }
28162
28163      if (settings.lastRow === 'center')
28164        offX += Math.round(availableWidth / 2);
28165      else if (settings.lastRow === 'right')
28166        offX += availableWidth;
28167    }
28168
28169    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
28170    for (i = 0; i <= lastEntryIdx; i++) {
28171      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
28172      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
28173      offX += $entry.data('jg.jwidth') + settings.margins;
28174    }
28175
28176    //Gallery Height
28177    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
28178    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
28179
28180    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
28181      //Ready for a new row
28182      this.offY += this.buildingRow.height + settings.margins;
28183      this.rows += 1;
28184      this.clearBuildingRow();
28185      this.settings.triggerEvent.call(this, 'jg.rowflush');
28186    }
28187  };
28188
28189
28190  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
28191  var galleryPrevStaticHeight = 0;
28192
28193  JustifiedGallery.prototype.rememberGalleryHeight = function () {
28194    galleryPrevStaticHeight = this.$gallery.height();
28195    this.$gallery.height(galleryPrevStaticHeight);
28196  };
28197
28198  // grow only
28199  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
28200    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
28201    this.$gallery.height(galleryPrevStaticHeight);
28202  };
28203
28204  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
28205    galleryPrevStaticHeight = height;
28206    this.$gallery.height(height);
28207  };
28208
28209  /**
28210   * Checks the width of the gallery container, to know if a new justification is needed
28211   */
28212  JustifiedGallery.prototype.checkWidth = function () {
28213    this.checkWidthIntervalId = setInterval($.proxy(function () {
28214
28215      // if the gallery is not currently visible, abort.
28216      if (!this.$gallery.is(":visible")) return;
28217
28218      var galleryWidth = parseFloat(this.$gallery.width());
28219      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
28220        this.galleryWidth = galleryWidth;
28221        this.rewind();
28222
28223        this.rememberGalleryHeight();
28224
28225        // Restart to analyze
28226        this.startImgAnalyzer(true);
28227      }
28228    }, this), this.settings.refreshTime);
28229  };
28230
28231  /**
28232   * @returns {boolean} a boolean saying if the spinner is active or not
28233   */
28234  JustifiedGallery.prototype.isSpinnerActive = function () {
28235    return this.spinner.intervalId !== null;
28236  };
28237
28238  /**
28239   * @returns {int} the spinner height
28240   */
28241  JustifiedGallery.prototype.getSpinnerHeight = function () {
28242    return this.spinner.$el.innerHeight();
28243  };
28244
28245  /**
28246   * Stops the spinner animation and modify the gallery height to exclude the spinner
28247   */
28248  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
28249    clearInterval(this.spinner.intervalId);
28250    this.spinner.intervalId = null;
28251    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
28252    this.spinner.$el.detach();
28253  };
28254
28255  /**
28256   * Starts the spinner animation
28257   */
28258  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
28259    var spinnerContext = this.spinner;
28260    var $spinnerPoints = spinnerContext.$el.find('span');
28261    clearInterval(spinnerContext.intervalId);
28262    this.$gallery.append(spinnerContext.$el);
28263    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
28264    spinnerContext.intervalId = setInterval(function () {
28265      if (spinnerContext.phase < $spinnerPoints.length) {
28266        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
28267      } else {
28268        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
28269      }
28270      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
28271    }, spinnerContext.timeSlot);
28272  };
28273
28274  /**
28275   * Rewind the image analysis to start from the first entry.
28276   */
28277  JustifiedGallery.prototype.rewind = function () {
28278    this.lastFetchedEntry = null;
28279    this.lastAnalyzedIndex = -1;
28280    this.offY = this.border;
28281    this.rows = 0;
28282    this.clearBuildingRow();
28283  };
28284
28285  /**
28286   * @returns {String} `settings.selector` rejecting spinner element
28287   */
28288  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
28289    return this.settings.selector + ', div:not(.jg-spinner)';
28290  };
28291
28292  /**
28293   * @returns {Array} all entries matched by `settings.selector`
28294   */
28295  JustifiedGallery.prototype.getAllEntries = function () {
28296    var selector = this.getSelectorWithoutSpinner();
28297    return this.$gallery.children(selector).toArray();
28298  };
28299
28300  /**
28301   * Update the entries searching it from the justified gallery HTML element
28302   *
28303   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
28304   * @returns {boolean} true if some entries has been founded
28305   */
28306  JustifiedGallery.prototype.updateEntries = function (norewind) {
28307    var newEntries;
28308
28309    if (norewind && this.lastFetchedEntry != null) {
28310      var selector = this.getSelectorWithoutSpinner();
28311      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
28312    } else {
28313      this.entries = [];
28314      newEntries = this.getAllEntries();
28315    }
28316
28317    if (newEntries.length > 0) {
28318
28319      // Sort or randomize
28320      if ($.isFunction(this.settings.sort)) {
28321        newEntries = this.sortArray(newEntries);
28322      } else if (this.settings.randomize) {
28323        newEntries = this.shuffleArray(newEntries);
28324      }
28325      this.lastFetchedEntry = newEntries[newEntries.length - 1];
28326
28327      // Filter
28328      if (this.settings.filter) {
28329        newEntries = this.filterArray(newEntries);
28330      } else {
28331        this.resetFilters(newEntries);
28332      }
28333
28334    }
28335
28336    this.entries = this.entries.concat(newEntries);
28337    return true;
28338  };
28339
28340  /**
28341   * Apply the entries order to the DOM, iterating the entries and appending the images
28342   *
28343   * @param entries the entries that has been modified and that must be re-ordered in the DOM
28344   */
28345  JustifiedGallery.prototype.insertToGallery = function (entries) {
28346    var that = this;
28347    $.each(entries, function () {
28348      $(this).appendTo(that.$gallery);
28349    });
28350  };
28351
28352  /**
28353   * Shuffle the array using the Fisher-Yates shuffle algorithm
28354   *
28355   * @param a the array to shuffle
28356   * @return the shuffled array
28357   */
28358  JustifiedGallery.prototype.shuffleArray = function (a) {
28359    var i, j, temp;
28360    for (i = a.length - 1; i > 0; i--) {
28361      j = Math.floor(Math.random() * (i + 1));
28362      temp = a[i];
28363      a[i] = a[j];
28364      a[j] = temp;
28365    }
28366    this.insertToGallery(a);
28367    return a;
28368  };
28369
28370  /**
28371   * Sort the array using settings.comparator as comparator
28372   *
28373   * @param a the array to sort (it is sorted)
28374   * @return the sorted array
28375   */
28376  JustifiedGallery.prototype.sortArray = function (a) {
28377    a.sort(this.settings.sort);
28378    this.insertToGallery(a);
28379    return a;
28380  };
28381
28382  /**
28383   * Reset the filters removing the 'jg-filtered' class from all the entries
28384   *
28385   * @param a the array to reset
28386   */
28387  JustifiedGallery.prototype.resetFilters = function (a) {
28388    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
28389  };
28390
28391  /**
28392   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
28393   *
28394   * @param a the array to filter
28395   * @return the filtered array
28396   */
28397  JustifiedGallery.prototype.filterArray = function (a) {
28398    var settings = this.settings;
28399    if ($.type(settings.filter) === 'string') {
28400      // Filter only keeping the entries passed in the string
28401      return a.filter(function (el) {
28402        var $el = $(el);
28403        if ($el.is(settings.filter)) {
28404          $el.removeClass('jg-filtered');
28405          return true;
28406        } else {
28407          $el.addClass('jg-filtered').removeClass('jg-visible');
28408          return false;
28409        }
28410      });
28411    } else if ($.isFunction(settings.filter)) {
28412      // Filter using the passed function
28413      var filteredArr = a.filter(settings.filter);
28414      for (var i = 0; i < a.length; i++) {
28415        if (filteredArr.indexOf(a[i]) === -1) {
28416          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
28417        } else {
28418          $(a[i]).removeClass('jg-filtered');
28419        }
28420      }
28421      return filteredArr;
28422    }
28423  };
28424
28425  /**
28426   * Revert the image src to the default value.
28427   */
28428  JustifiedGallery.prototype.resetImgSrc = function ($img) {
28429    if ($img.data('jg.originalSrcLoc') === 'src') {
28430      $img.attr('src', $img.data('jg.originalSrc'));
28431    } else {
28432      $img.attr('src', '');
28433    }
28434  };
28435
28436  /**
28437   * Destroy the Justified Gallery instance.
28438   *
28439   * It clears all the css properties added in the style attributes. We doesn't backup the original
28440   * values for those css attributes, because it costs (performance) and because in general one
28441   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
28442   * classes). Creating a backup is also difficult because JG could be called multiple times and
28443   * with different style attributes.
28444   */
28445  JustifiedGallery.prototype.destroy = function () {
28446    clearInterval(this.checkWidthIntervalId);
28447    this.stopImgAnalyzerStarter();
28448
28449    // Get fresh entries list since filtered entries are absent in `this.entries`
28450    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
28451      var $entry = $(entry);
28452
28453      // Reset entry style
28454      $entry.css('width', '');
28455      $entry.css('height', '');
28456      $entry.css('top', '');
28457      $entry.css('left', '');
28458      $entry.data('jg.loaded', undefined);
28459      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
28460
28461      // Reset image style
28462      var $img = this.imgFromEntry($entry);
28463      if ($img) {
28464        $img.css('width', '');
28465        $img.css('height', '');
28466        $img.css('margin-left', '');
28467        $img.css('margin-top', '');
28468        this.resetImgSrc($img);
28469        $img.data('jg.originalSrc', undefined);
28470        $img.data('jg.originalSrcLoc', undefined);
28471        $img.data('jg.src', undefined);
28472      }
28473
28474      // Remove caption
28475      this.removeCaptionEventsHandlers($entry);
28476      var $caption = this.captionFromEntry($entry);
28477      if ($entry.data('jg.createdCaption')) {
28478        // remove also the caption element (if created by jg)
28479        $entry.data('jg.createdCaption', undefined);
28480        if ($caption !== null) $caption.remove();
28481      } else {
28482        if ($caption !== null) $caption.fadeTo(0, 1);
28483      }
28484
28485    }, this));
28486
28487    this.$gallery.css('height', '');
28488    this.$gallery.removeClass('justified-gallery');
28489    this.$gallery.data('jg.controller', undefined);
28490    this.settings.triggerEvent.call(this, 'jg.destroy');
28491  };
28492
28493  /**
28494   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
28495   *
28496   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
28497   */
28498  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
28499    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
28500      var $entry = $(this.entries[i]);
28501      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
28502        var availableWidth = this.galleryWidth - 2 * this.border - (
28503          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28504        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28505
28506        this.buildingRow.entriesBuff.push($entry);
28507        this.buildingRow.aspectRatio += imgAspectRatio;
28508        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
28509        this.lastAnalyzedIndex = i;
28510
28511        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
28512          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28513
28514          if (++this.yield.flushed >= this.yield.every) {
28515            this.startImgAnalyzer(isForResize);
28516            return;
28517          }
28518        }
28519      } else if ($entry.data('jg.loaded') !== 'error') {
28520        return;
28521      }
28522    }
28523
28524    // Last row flush (the row is not full)
28525    if (this.buildingRow.entriesBuff.length > 0) {
28526      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28527    }
28528
28529    if (this.isSpinnerActive()) {
28530      this.stopLoadingSpinnerAnimation();
28531    }
28532
28533    /* Stop, if there is, the timeout to start the analyzeImages.
28534     This is because an image can be set loaded, and the timeout can be set,
28535     but this image can be analyzed yet.
28536     */
28537    this.stopImgAnalyzerStarter();
28538
28539    this.setGalleryFinalHeight(this.galleryHeightToSet);
28540
28541    //On complete callback
28542    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
28543  };
28544
28545  /**
28546   * Stops any ImgAnalyzer starter (that has an assigned timeout)
28547   */
28548  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
28549    this.yield.flushed = 0;
28550    if (this.imgAnalyzerTimeout !== null) {
28551      clearTimeout(this.imgAnalyzerTimeout);
28552      this.imgAnalyzerTimeout = null;
28553    }
28554  };
28555
28556  /**
28557   * Starts the image analyzer. It is not immediately called to let the browser to update the view
28558   *
28559   * @param isForResize specifies if the image analyzer must be called for resizing or not
28560   */
28561  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
28562    var that = this;
28563    this.stopImgAnalyzerStarter();
28564    this.imgAnalyzerTimeout = setTimeout(function () {
28565      that.analyzeImages(isForResize);
28566    }, 0.001); // we can't start it immediately due to a IE different behaviour
28567  };
28568
28569  /**
28570   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
28571   * because some browsers, with a 404 set complete = true.
28572   *
28573   * @param imageSrc the image src to load
28574   * @param onLoad callback that is called when the image has been loaded
28575   * @param onError callback that is called in case of an error
28576   */
28577  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
28578    if (!onLoad && !onError) return;
28579
28580    var memImage = new Image();
28581    var $memImage = $(memImage);
28582    if (onLoad) {
28583      $memImage.one('load', function () {
28584        $memImage.off('load error');
28585        onLoad(memImage);
28586      });
28587    }
28588    if (onError) {
28589      $memImage.one('error', function () {
28590        $memImage.off('load error');
28591        onError(memImage);
28592      });
28593    }
28594    memImage.src = imageSrc;
28595  };
28596
28597  /**
28598   * Init of Justified Gallery controlled
28599   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
28600   */
28601  JustifiedGallery.prototype.init = function () {
28602    var imagesToLoad = false, skippedImages = false, that = this;
28603    $.each(this.entries, function (index, entry) {
28604      var $entry = $(entry);
28605      var $image = that.imgFromEntry($entry);
28606
28607      $entry.addClass('jg-entry');
28608
28609      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
28610
28611        // Link Rel global overwrite
28612        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
28613
28614        // Link Target global overwrite
28615        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
28616
28617        if ($image !== null) {
28618
28619          // Image src
28620          var imageSrc = that.extractImgSrcFromImage($image);
28621
28622          /* If we have the height and the width, we don't wait that the image is loaded,
28623             but we start directly with the justification */
28624          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
28625            var width = parseFloat($image.attr('width'));
28626            var height = parseFloat($image.attr('height'));
28627            if ($image.prop('tagName') === 'svg') {
28628              width = parseFloat($image[0].getBBox().width);
28629              height = parseFloat($image[0].getBBox().height);
28630            }
28631            if (!isNaN(width) && !isNaN(height)) {
28632              $entry.data('jg.width', width);
28633              $entry.data('jg.height', height);
28634              $entry.data('jg.loaded', 'skipped');
28635              skippedImages = true;
28636              that.startImgAnalyzer(false);
28637              return true; // continue
28638            }
28639          }
28640
28641          $entry.data('jg.loaded', false);
28642          imagesToLoad = true;
28643
28644          // Spinner start
28645          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
28646
28647          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
28648            $entry.data('jg.width', loadImg.width);
28649            $entry.data('jg.height', loadImg.height);
28650            $entry.data('jg.loaded', true);
28651            that.startImgAnalyzer(false);
28652          }, function () { // image load error
28653            $entry.data('jg.loaded', 'error');
28654            that.startImgAnalyzer(false);
28655          });
28656
28657        } else {
28658          $entry.data('jg.loaded', true);
28659          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
28660          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
28661        }
28662
28663      }
28664
28665    });
28666
28667    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
28668    this.checkWidth();
28669  };
28670
28671  /**
28672   * Checks that it is a valid number. If a string is passed it is converted to a number
28673   *
28674   * @param settingContainer the object that contains the setting (to allow the conversion)
28675   * @param settingName the setting name
28676   */
28677  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
28678    if ($.type(settingContainer[settingName]) === 'string') {
28679      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
28680    }
28681
28682    if ($.type(settingContainer[settingName]) === 'number') {
28683      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
28684    } else {
28685      throw settingName + ' must be a number';
28686    }
28687  };
28688
28689  /**
28690   * Checks the sizeRangeSuffixes and, if necessary, converts
28691   * its keys from string (e.g. old settings with 'lt100') to int.
28692   */
28693  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
28694    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
28695      throw 'sizeRangeSuffixes must be defined and must be an object';
28696    }
28697
28698    var suffixRanges = [];
28699    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28700      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
28701    }
28702
28703    var newSizeRngSuffixes = { 0: '' };
28704    for (var i = 0; i < suffixRanges.length; i++) {
28705      if ($.type(suffixRanges[i]) === 'string') {
28706        try {
28707          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
28708          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28709        } catch (e) {
28710          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
28711        }
28712      } else {
28713        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28714      }
28715    }
28716
28717    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
28718  };
28719
28720  /**
28721   * check and convert the maxRowHeight setting
28722   * requires rowHeight to be already set
28723   * TODO: should be always called when only rowHeight is changed
28724   * @return number or null
28725   */
28726  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
28727    var newMaxRowHeight = null;
28728    var rowHeight = this.settings.rowHeight;
28729
28730    if ($.type(this.settings.maxRowHeight) === 'string') {
28731      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
28732        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
28733      } else {
28734        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
28735      }
28736    } else if ($.type(this.settings.maxRowHeight) === 'number') {
28737      newMaxRowHeight = this.settings.maxRowHeight;
28738    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
28739      return null;
28740    } else {
28741      throw 'maxRowHeight must be a number or a percentage';
28742    }
28743
28744    // check if the converted value is not a number
28745    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
28746
28747    // check values, maxRowHeight must be >= rowHeight
28748    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
28749
28750    return newMaxRowHeight;
28751  };
28752
28753  /**
28754   * Checks the settings
28755   */
28756  JustifiedGallery.prototype.checkSettings = function () {
28757    this.checkSizeRangesSuffixes();
28758
28759    this.checkOrConvertNumber(this.settings, 'rowHeight');
28760    this.checkOrConvertNumber(this.settings, 'margins');
28761    this.checkOrConvertNumber(this.settings, 'border');
28762    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
28763
28764    var lastRowModes = [
28765      'justify',
28766      'nojustify',
28767      'left',
28768      'center',
28769      'right',
28770      'hide'
28771    ];
28772    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
28773      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
28774    }
28775
28776    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28777    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28778      throw 'justifyThreshold must be in the interval [0,1]';
28779    }
28780    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28781      throw 'cssAnimation must be a boolean';
28782    }
28783
28784    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28785    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28786
28787    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28788    if (this.settings.captionSettings.visibleOpacity < 0 ||
28789      this.settings.captionSettings.visibleOpacity > 1) {
28790      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28791    }
28792
28793    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28794    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28795      this.settings.captionSettings.nonVisibleOpacity > 1) {
28796      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28797    }
28798
28799    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28800    this.checkOrConvertNumber(this.settings, 'refreshTime');
28801    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28802    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28803    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28804
28805    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28806      throw 'sort must be false or a comparison function';
28807    }
28808
28809    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28810      $.type(this.settings.filter) !== 'string') {
28811      throw 'filter must be false, a string or a filter function';
28812    }
28813  };
28814
28815  /**
28816   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28817   * @returns {Array} sorted suffix ranges
28818   */
28819  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28820    var suffixRanges = [];
28821    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28822      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28823    }
28824    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28825    return suffixRanges;
28826  };
28827
28828  /**
28829   * Update the existing settings only changing some of them
28830   *
28831   * @param newSettings the new settings (or a subgroup of them)
28832   */
28833  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28834    // In this case Justified Gallery has been called again changing only some options
28835    this.settings = $.extend({}, this.settings, newSettings);
28836    this.checkSettings();
28837
28838    // As reported in the settings: negative value = same as margins, 0 = disabled
28839    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28840
28841    this.maxRowHeight = this.retrieveMaxRowHeight();
28842    this.suffixRanges = this.retrieveSuffixRanges();
28843  };
28844
28845  JustifiedGallery.prototype.defaults = {
28846    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28847        {
28848          100: '_t',  // used when longest is less than 100px
28849          240: '_m',  // used when longest is between 101px and 240px
28850          320: '_n',  // ...
28851          500: '',
28852          640: '_z',
28853          1024: '_b'  // used as else case because it is the last
28854        }
28855    */
28856    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28857    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28858    current path, width and height */
28859    rowHeight: 120, // required? required to be > 0?
28860    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28861    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28862    // can't exceed 3 * rowHeight)
28863    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28864    margins: 1,
28865    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28866
28867    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28868
28869    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28870                             * (i.e. lastRow setting is not considered) */
28871    waitThumbnailsLoad: true,
28872    captions: true,
28873    cssAnimation: true,
28874    imagesAnimationDuration: 500, // ignored with css animations
28875    captionSettings: { // ignored with css animations
28876      animationDuration: 500,
28877      visibleOpacity: 0.7,
28878      nonVisibleOpacity: 0.0
28879    },
28880    rel: null, // rewrite the rel of each analyzed links
28881    target: null, // rewrite the target of all links
28882    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28883    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28884    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28885    randomize: false,
28886    rtl: false, // right-to-left mode
28887    sort: false, /*
28888      - false: to do not sort
28889      - function: to sort them using the function as comparator (see Array.prototype.sort())
28890    */
28891    filter: false, /*
28892      - false, null or undefined: for a disabled filter
28893      - a string: an entry is kept if entry.is(filter string) returns true
28894                  see jQuery's .is() function for further information
28895      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28896                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28897    */
28898    selector: 'a', // The selector that is used to know what are the entries of the gallery
28899    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28900    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28901      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28902    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28903  };
28904
28905
28906  /**
28907   * Justified Gallery plugin for jQuery
28908   *
28909   * Events
28910   *  - jg.complete : called when all the gallery has been created
28911   *  - jg.resize : called when the gallery has been resized
28912   *  - jg.rowflush : when a new row appears
28913   *
28914   * @param arg the action (or the settings) passed when the plugin is called
28915   * @returns {*} the object itself
28916   */
28917  $.fn.justifiedGallery = function (arg) {
28918    return this.each(function (index, gallery) {
28919
28920      var $gallery = $(gallery);
28921      $gallery.addClass('justified-gallery');
28922
28923      var controller = $gallery.data('jg.controller');
28924      if (typeof controller === 'undefined') {
28925        // Create controller and assign it to the object data
28926        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28927          if (arg === 'destroy') return; // Just a call to an unexisting object
28928          throw 'The argument must be an object';
28929        }
28930        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28931        $gallery.data('jg.controller', controller);
28932      } else if (arg === 'norewind') {
28933        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28934        // ... left to be more readable
28935      } else if (arg === 'destroy') {
28936        controller.destroy();
28937        return;
28938      } else {
28939        // In this case Justified Gallery has been called again changing only some options
28940        controller.updateSettings(arg);
28941        controller.rewind();
28942      }
28943
28944      // Update the entries list
28945      if (!controller.updateEntries(arg === 'norewind')) return;
28946
28947      // Init justified gallery
28948      controller.init();
28949
28950    });
28951  };
28952
28953}));
28954
28955/*!
28956* Customized version of iScroll.js 0.0.1
28957* It fixes bugs affecting its integration with fullpage.js
28958*/
28959/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
28960(function (window, document, Math) {
28961var rAF = window.requestAnimationFrame  ||
28962    window.webkitRequestAnimationFrame  ||
28963    window.mozRequestAnimationFrame     ||
28964    window.oRequestAnimationFrame       ||
28965    window.msRequestAnimationFrame      ||
28966    function (callback) { window.setTimeout(callback, 1000 / 60); };
28967
28968var utils = (function () {
28969    var me = {};
28970
28971    var _elementStyle = document.createElement('div').style;
28972    var _vendor = (function () {
28973        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
28974            transform,
28975            i = 0,
28976            l = vendors.length;
28977
28978        for ( ; i < l; i++ ) {
28979            transform = vendors[i] + 'ransform';
28980            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
28981        }
28982
28983        return false;
vendor: 5,154 bytes, lines 28984-29136
28984    })();
28985
28986    function _prefixStyle (style) {
28987        if ( _vendor === false ) return false;
28988        if ( _vendor === '' ) return style;
28989        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
28990    }
28991
28992    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
28993
28994    me.extend = function (target, obj) {
28995        for ( var i in obj ) {
28996            target[i] = obj[i];
28997        }
28998    };
28999
29000    me.addEvent = function (el, type, fn, capture) {
29001        el.addEventListener(type, fn, !!capture);
29002    };
29003
29004    me.removeEvent = function (el, type, fn, capture) {
29005        el.removeEventListener(type, fn, !!capture);
29006    };
29007
29008    me.prefixPointerEvent = function (pointerEvent) {
29009        return window.MSPointerEvent ?
29010            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29011            pointerEvent;
29012    };
29013
29014    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29015        var distance = current - start,
29016            speed = Math.abs(distance) / time,
29017            destination,
29018            duration;
29019
29020        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29021
29022        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29023        duration = speed / deceleration;
29024
29025        if ( destination < lowerMargin ) {
29026            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29027            distance = Math.abs(destination - current);
29028            duration = distance / speed;
29029        } else if ( destination > 0 ) {
29030            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29031            distance = Math.abs(current) + destination;
29032            duration = distance / speed;
29033        }
29034
29035        return {
29036            destination: Math.round(destination),
29037            duration: duration
29038        };
29039    };
29040
29041    var _transform = _prefixStyle('transform');
29042
29043    me.extend(me, {
29044        hasTransform: _transform !== false,
29045        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29046        hasTouch: 'ontouchstart' in window,
29047        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29048        hasTransition: _prefixStyle('transition') in _elementStyle
29049    });
29050
29051    /*
29052    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29053    - galaxy S2 is ok
29054    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29055    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29056   - galaxy S3 is badAndroid (stock brower, webview)
29057     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29058   - galaxy S4 is badAndroid (stock brower, webview)
29059     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29060   - galaxy S5 is OK
29061     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29062   - galaxy S6 is OK
29063     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29064  */
29065    me.isBadAndroid = (function() {
29066        var appVersion = window.navigator.appVersion;
29067        // Android browser is not a chrome browser.
29068        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29069            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
29070            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
29071                return parseFloat(safariVersion[1]) < 535.19;
29072            } else {
29073                return true;
29074            }
29075        } else {
29076            return false;
29077        }
29078    })();
29079
29080    me.extend(me.style = {}, {
29081        transform: _transform,
29082        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
29083        transitionDuration: _prefixStyle('transitionDuration'),
29084        transitionDelay: _prefixStyle('transitionDelay'),
29085        transformOrigin: _prefixStyle('transformOrigin')
29086    });
29087
29088    me.hasClass = function (e, c) {
29089        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
29090        return re.test(e.className);
29091    };
29092
29093    me.addClass = function (e, c) {
29094        if ( me.hasClass(e, c) ) {
29095            return;
29096        }
29097
29098        var newclass = e.className.split(' ');
29099        newclass.push(c);
29100        e.className = newclass.join(' ');
29101    };
29102
29103    me.removeClass = function (e, c) {
29104        if ( !me.hasClass(e, c) ) {
29105            return;
29106        }
29107
29108        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
29109        e.className = e.className.replace(re, ' ');
29110    };
29111
29112    me.offset = function (el) {
29113        var left = -el.offsetLeft,
29114            top = -el.offsetTop;
29115
29116        // jshint -W084
29117        while (el = el.offsetParent) {
29118            left -= el.offsetLeft;
29119            top -= el.offsetTop;
29120        }
29121        // jshint +W084
29122
29123        return {
29124            left: left,
29125            top: top
29126        };
29127    };
29128
29129    me.preventDefaultException = function (el, exceptions) {
29130        for ( var i in exceptions ) {
29131            if ( exceptions[i].test(el[i]) ) {
29132                return true;
29133            }
29134        }
29135
29136        return false;
vendor: 5,660 bytes, lines 29137-29302
29137    };
29138
29139    me.extend(me.eventType = {}, {
29140        touchstart: 1,
29141        touchmove: 1,
29142        touchend: 1,
29143
29144        mousedown: 2,
29145        mousemove: 2,
29146        mouseup: 2,
29147
29148        pointerdown: 3,
29149        pointermove: 3,
29150        pointerup: 3,
29151
29152        MSPointerDown: 3,
29153        MSPointerMove: 3,
29154        MSPointerUp: 3
29155    });
29156
29157    me.extend(me.ease = {}, {
29158        quadratic: {
29159            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
29160            fn: function (k) {
29161                return k * ( 2 - k );
29162            }
29163        },
29164        circular: {
29165            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)
29166            fn: function (k) {
29167                return Math.sqrt( 1 - ( --k * k ) );
29168            }
29169        },
29170        back: {
29171            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
29172            fn: function (k) {
29173                var b = 4;
29174                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
29175            }
29176        },
29177        bounce: {
29178            style: '',
29179            fn: function (k) {
29180                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
29181                    return 7.5625 * k * k;
29182                } else if ( k < ( 2 / 2.75 ) ) {
29183                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
29184                } else if ( k < ( 2.5 / 2.75 ) ) {
29185                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
29186                } else {
29187                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
29188                }
29189            }
29190        },
29191        elastic: {
29192            style: '',
29193            fn: function (k) {
29194                var f = 0.22,
29195                    e = 0.4;
29196
29197                if ( k === 0 ) { return 0; }
29198                if ( k == 1 ) { return 1; }
29199
29200                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
29201            }
29202        }
29203    });
29204
29205    me.tap = function (e, eventName) {
29206        var ev = document.createEvent('Event');
29207        ev.initEvent(eventName, true, true);
29208        ev.pageX = e.pageX;
29209        ev.pageY = e.pageY;
29210        e.target.dispatchEvent(ev);
29211    };
29212
29213    me.click = function (e) {
29214        var target = e.target,
29215            ev;
29216
29217        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
29218            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
29219            // initMouseEvent is deprecated.
29220            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
29221            ev.initEvent('click', true, true);
29222            ev.view = e.view || window;
29223            ev.detail = 1;
29224            ev.screenX = target.screenX || 0;
29225            ev.screenY = target.screenY || 0;
29226            ev.clientX = target.clientX || 0;
29227            ev.clientY = target.clientY || 0;
29228            ev.ctrlKey = !!e.ctrlKey;
29229            ev.altKey = !!e.altKey;
29230            ev.shiftKey = !!e.shiftKey;
29231            ev.metaKey = !!e.metaKey;
29232            ev.button = 0;
29233            ev.relatedTarget = null;
29234            ev._constructed = true;
29235            target.dispatchEvent(ev);
29236        }
29237    };
29238
29239    return me;
29240})();
29241function IScroll (el, options) {
29242    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
29243    this.scroller = this.wrapper.children[0];
29244    this.scrollerStyle = this.scroller.style;       // cache style for better performance
29245
29246    this.options = {
29247
29248        resizeScrollbars: true,
29249
29250        mouseWheelSpeed: 20,
29251
29252        snapThreshold: 0.334,
29253
29254// INSERT POINT: OPTIONS
29255        disablePointer : !utils.hasPointer,
29256        disableTouch : utils.hasPointer || !utils.hasTouch,
29257        disableMouse : utils.hasPointer || utils.hasTouch,
29258        startX: 0,
29259        startY: 0,
29260        scrollY: true,
29261        directionLockThreshold: 5,
29262        momentum: true,
29263
29264        bounce: true,
29265        bounceTime: 600,
29266        bounceEasing: '',
29267
29268        preventDefault: true,
29269        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
29270
29271        HWCompositing: true,
29272        useTransition: true,
29273        useTransform: true,
29274        bindToWrapper: typeof window.onmousedown === "undefined"
29275    };
29276
29277    for ( var i in options ) {
29278        this.options[i] = options[i];
29279    }
29280
29281    // Normalize options
29282    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
29283
29284    this.options.useTransition = utils.hasTransition && this.options.useTransition;
29285    this.options.useTransform = utils.hasTransform && this.options.useTransform;
29286
29287    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
29288    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
29289
29290    // If you want eventPassthrough I have to lock one of the axes
29291    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
29292    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
29293
29294    // With eventPassthrough we also need lockDirection mechanism
29295    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
29296    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
29297
29298    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
29299
29300    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
29301
29302    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 29303-29474
29303        this.options.tap = 'tap';
29304    }
29305
29306    // https://github.com/cubiq/iscroll/issues/1029
29307    if (!this.options.useTransition && !this.options.useTransform) {
29308        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
29309            this.scrollerStyle.position = "relative";
29310        }
29311    }
29312
29313    if ( this.options.shrinkScrollbars == 'scale' ) {
29314        this.options.useTransition = false;
29315    }
29316
29317    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
29318
29319// INSERT POINT: NORMALIZATION
29320
29321    // Some defaults
29322    this.x = 0;
29323    this.y = 0;
29324    this.directionX = 0;
29325    this.directionY = 0;
29326    this._events = {};
29327
29328// INSERT POINT: DEFAULTS
29329
29330    this._init();
29331    this.refresh();
29332
29333    this.scrollTo(this.options.startX, this.options.startY);
29334    this.enable();
29335}
29336
29337IScroll.prototype = {
29338    version: '5.2.0',
29339
29340    _init: function () {
29341        this._initEvents();
29342
29343        if ( this.options.scrollbars || this.options.indicators ) {
29344            this._initIndicators();
29345        }
29346
29347        if ( this.options.mouseWheel ) {
29348            this._initWheel();
29349        }
29350
29351        if ( this.options.snap ) {
29352            this._initSnap();
29353        }
29354
29355        if ( this.options.keyBindings ) {
29356            this._initKeys();
29357        }
29358
29359// INSERT POINT: _init
29360
29361    },
29362
29363    destroy: function () {
29364        this._initEvents(true);
29365        clearTimeout(this.resizeTimeout);
29366        this.resizeTimeout = null;
29367        this._execEvent('destroy');
29368    },
29369
29370    _transitionEnd: function (e) {
29371        if ( e.target != this.scroller || !this.isInTransition ) {
29372            return;
29373        }
29374
29375        this._transitionTime();
29376        if ( !this.resetPosition(this.options.bounceTime) ) {
29377            this.isInTransition = false;
29378            this._execEvent('scrollEnd');
29379        }
29380    },
29381
29382    _start: function (e) {
29383        // React to left mouse button only
29384        if ( utils.eventType[e.type] != 1 ) {
29385          // for button property
29386          // http://unixpapa.com/js/mouse.html
29387          var button;
29388        if (!e.which) {
29389          /* IE case */
29390          button = (e.button < 2) ? 0 :
29391                   ((e.button == 4) ? 1 : 2);
29392        } else {
29393          /* All others */
29394          button = e.button;
29395        }
29396            if ( button !== 0 ) {
29397                return;
29398            }
29399        }
29400
29401        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
29402            return;
29403        }
29404
29405        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29406            e.preventDefault();
29407        }
29408
29409        var point = e.touches ? e.touches[0] : e,
29410            pos;
29411
29412        this.initiated  = utils.eventType[e.type];
29413        this.moved      = false;
29414        this.distX      = 0;
29415        this.distY      = 0;
29416        this.directionX = 0;
29417        this.directionY = 0;
29418        this.directionLocked = 0;
29419
29420        this.startTime = utils.getTime();
29421
29422        if ( this.options.useTransition && this.isInTransition ) {
29423            this._transitionTime();
29424            this.isInTransition = false;
29425            pos = this.getComputedPosition();
29426            this._translate(Math.round(pos.x), Math.round(pos.y));
29427            this._execEvent('scrollEnd');
29428        } else if ( !this.options.useTransition && this.isAnimating ) {
29429            this.isAnimating = false;
29430            this._execEvent('scrollEnd');
29431        }
29432
29433        this.startX    = this.x;
29434        this.startY    = this.y;
29435        this.absStartX = this.x;
29436        this.absStartY = this.y;
29437        this.pointX    = point.pageX;
29438        this.pointY    = point.pageY;
29439
29440        this._execEvent('beforeScrollStart');
29441    },
29442
29443    _move: function (e) {
29444        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29445            return;
29446        }
29447
29448        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
29449            e.preventDefault();
29450        }
29451
29452        var point       = e.touches ? e.touches[0] : e,
29453            deltaX      = point.pageX - this.pointX,
29454            deltaY      = point.pageY - this.pointY,
29455            timestamp   = utils.getTime(),
29456            newX, newY,
29457            absDistX, absDistY;
29458
29459        this.pointX     = point.pageX;
29460        this.pointY     = point.pageY;
29461
29462        this.distX      += deltaX;
29463        this.distY      += deltaY;
29464        absDistX        = Math.abs(this.distX);
29465        absDistY        = Math.abs(this.distY);
29466
29467        // We need to move at least 10 pixels for the scrolling to initiate
29468        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
29469            return;
29470        }
29471
29472        // If you are scrolling in one direction lock the other
29473        if ( !this.directionLocked && !this.options.freeScroll ) {
29474            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 29475-29661
29475                this.directionLocked = 'h';     // lock horizontally
29476            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
29477                this.directionLocked = 'v';     // lock vertically
29478            } else {
29479                this.directionLocked = 'n';     // no lock
29480            }
29481        }
29482
29483        if ( this.directionLocked == 'h' ) {
29484            if ( this.options.eventPassthrough == 'vertical' ) {
29485                e.preventDefault();
29486            } else if ( this.options.eventPassthrough == 'horizontal' ) {
29487                this.initiated = false;
29488                return;
29489            }
29490
29491            deltaY = 0;
29492        } else if ( this.directionLocked == 'v' ) {
29493            if ( this.options.eventPassthrough == 'horizontal' ) {
29494                e.preventDefault();
29495            } else if ( this.options.eventPassthrough == 'vertical' ) {
29496                this.initiated = false;
29497                return;
29498            }
29499
29500            deltaX = 0;
29501        }
29502
29503        deltaX = this.hasHorizontalScroll ? deltaX : 0;
29504        deltaY = this.hasVerticalScroll ? deltaY : 0;
29505
29506        newX = this.x + deltaX;
29507        newY = this.y + deltaY;
29508
29509        // Slow down if outside of the boundaries
29510        if ( newX > 0 || newX < this.maxScrollX ) {
29511            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
29512        }
29513        if ( newY > 0 || newY < this.maxScrollY ) {
29514            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
29515        }
29516
29517        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
29518        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
29519
29520        if ( !this.moved ) {
29521            this._execEvent('scrollStart');
29522        }
29523
29524        this.moved = true;
29525
29526        this._translate(newX, newY);
29527
29528/* REPLACE START: _move */
29529
29530        if ( timestamp - this.startTime > 300 ) {
29531            this.startTime = timestamp;
29532            this.startX = this.x;
29533            this.startY = this.y;
29534        }
29535
29536/* REPLACE END: _move */
29537
29538    },
29539
29540    _end: function (e) {
29541        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29542            return;
29543        }
29544
29545        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29546            e.preventDefault();
29547        }
29548
29549        var point = e.changedTouches ? e.changedTouches[0] : e,
29550            momentumX,
29551            momentumY,
29552            duration = utils.getTime() - this.startTime,
29553            newX = Math.round(this.x),
29554            newY = Math.round(this.y),
29555            distanceX = Math.abs(newX - this.startX),
29556            distanceY = Math.abs(newY - this.startY),
29557            time = 0,
29558            easing = '';
29559
29560        this.isInTransition = 0;
29561        this.initiated = 0;
29562        this.endTime = utils.getTime();
29563
29564        // reset if we are outside of the boundaries
29565        if ( this.resetPosition(this.options.bounceTime) ) {
29566            return;
29567        }
29568
29569        this.scrollTo(newX, newY);  // ensures that the last position is rounded
29570
29571        // we scrolled less than 10 pixels
29572        if ( !this.moved ) {
29573            if ( this.options.tap ) {
29574                utils.tap(e, this.options.tap);
29575            }
29576
29577            if ( this.options.click ) {
29578                utils.click(e);
29579            }
29580
29581            this._execEvent('scrollCancel');
29582            return;
29583        }
29584
29585        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
29586            this._execEvent('flick');
29587            return;
29588        }
29589
29590        // start momentum animation if needed
29591        if ( this.options.momentum && duration < 300 ) {
29592            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 };
29593            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 };
29594            newX = momentumX.destination;
29595            newY = momentumY.destination;
29596            time = Math.max(momentumX.duration, momentumY.duration);
29597            this.isInTransition = 1;
29598        }
29599
29600
29601        if ( this.options.snap ) {
29602            var snap = this._nearestSnap(newX, newY);
29603            this.currentPage = snap;
29604            time = this.options.snapSpeed || Math.max(
29605                    Math.max(
29606                        Math.min(Math.abs(newX - snap.x), 1000),
29607                        Math.min(Math.abs(newY - snap.y), 1000)
29608                    ), 300);
29609            newX = snap.x;
29610            newY = snap.y;
29611
29612            this.directionX = 0;
29613            this.directionY = 0;
29614            easing = this.options.bounceEasing;
29615        }
29616
29617// INSERT POINT: _end
29618
29619        if ( newX != this.x || newY != this.y ) {
29620            // change easing function when scroller goes out of the boundaries
29621            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
29622                easing = utils.ease.quadratic;
29623            }
29624
29625            this.scrollTo(newX, newY, time, easing);
29626            return;
29627        }
29628
29629        this._execEvent('scrollEnd');
29630    },
29631
29632    _resize: function () {
29633        var that = this;
29634
29635        clearTimeout(this.resizeTimeout);
29636
29637        this.resizeTimeout = setTimeout(function () {
29638            that.refresh();
29639        }, this.options.resizePolling);
29640    },
29641
29642    resetPosition: function (time) {
29643        var x = this.x,
29644            y = this.y;
29645
29646        time = time || 0;
29647
29648        if ( !this.hasHorizontalScroll || this.x > 0 ) {
29649            x = 0;
29650        } else if ( this.x < this.maxScrollX ) {
29651            x = this.maxScrollX;
29652        }
29653
29654        if ( !this.hasVerticalScroll || this.y > 0 ) {
29655            y = 0;
29656        } else if ( this.y < this.maxScrollY ) {
29657            y = this.maxScrollY;
29658        }
29659
29660        if ( x == this.x && y == this.y ) {
29661            return false;
vendor: 5,509 bytes, lines 29662-29866
29662        }
29663
29664        this.scrollTo(x, y, time, this.options.bounceEasing);
29665
29666        return true;
29667    },
29668
29669    disable: function () {
29670        this.enabled = false;
29671    },
29672
29673    enable: function () {
29674        this.enabled = true;
29675    },
29676
29677    refresh: function () {
29678        var rf = this.wrapper.offsetHeight;     // Force reflow
29679
29680        this.wrapperWidth   = this.wrapper.clientWidth;
29681        this.wrapperHeight  = this.wrapper.clientHeight;
29682
29683/* REPLACE START: refresh */
29684
29685        this.scrollerWidth  = this.scroller.offsetWidth;
29686        this.scrollerHeight = this.scroller.offsetHeight;
29687
29688        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
29689        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
29690
29691/* REPLACE END: refresh */
29692
29693        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
29694        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
29695
29696        if ( !this.hasHorizontalScroll ) {
29697            this.maxScrollX = 0;
29698            this.scrollerWidth = this.wrapperWidth;
29699        }
29700
29701        if ( !this.hasVerticalScroll ) {
29702            this.maxScrollY = 0;
29703            this.scrollerHeight = this.wrapperHeight;
29704        }
29705
29706        this.endTime = 0;
29707        this.directionX = 0;
29708        this.directionY = 0;
29709
29710        this.wrapperOffset = utils.offset(this.wrapper);
29711
29712        this._execEvent('refresh');
29713
29714        this.resetPosition();
29715
29716// INSERT POINT: _refresh
29717
29718    },
29719
29720
29721    on: function (type, fn) {
29722        if ( !this._events[type] ) {
29723            this._events[type] = [];
29724        }
29725
29726        this._events[type].push(fn);
29727    },
29728
29729    off: function (type, fn) {
29730        if ( !this._events[type] ) {
29731            return;
29732        }
29733
29734        var index = this._events[type].indexOf(fn);
29735
29736        if ( index > -1 ) {
29737            this._events[type].splice(index, 1);
29738        }
29739    },
29740
29741    _execEvent: function (type) {
29742        if ( !this._events[type] ) {
29743            return;
29744        }
29745
29746        var i = 0,
29747            l = this._events[type].length;
29748
29749        if ( !l ) {
29750            return;
29751        }
29752
29753        for ( ; i < l; i++ ) {
29754            this._events[type][i].apply(this, [].slice.call(arguments, 1));
29755        }
29756    },
29757
29758    scrollBy: function (x, y, time, easing) {
29759        x = this.x + x;
29760        y = this.y + y;
29761        time = time || 0;
29762
29763        this.scrollTo(x, y, time, easing);
29764    },
29765
29766    scrollTo: function (x, y, time, easing) {
29767        easing = easing || utils.ease.circular;
29768
29769        this.isInTransition = this.options.useTransition && time > 0;
29770        var transitionType = this.options.useTransition && easing.style;
29771        if ( !time || transitionType ) {
29772                if(transitionType) {
29773                    this._transitionTimingFunction(easing.style);
29774                    this._transitionTime(time);
29775                }
29776            this._translate(x, y);
29777        } else {
29778            this._animate(x, y, time, easing.fn);
29779        }
29780    },
29781
29782    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29783        el = el.nodeType ? el : this.scroller.querySelector(el);
29784
29785        if ( !el ) {
29786            return;
29787        }
29788
29789        var pos = utils.offset(el);
29790
29791        pos.left -= this.wrapperOffset.left;
29792        pos.top  -= this.wrapperOffset.top;
29793
29794        // if offsetX/Y are true we center the element to the screen
29795        if ( offsetX === true ) {
29796            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29797        }
29798        if ( offsetY === true ) {
29799            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29800        }
29801
29802        pos.left -= offsetX || 0;
29803        pos.top  -= offsetY || 0;
29804
29805        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29806        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29807
29808        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29809
29810        this.scrollTo(pos.left, pos.top, time, easing);
29811    },
29812
29813    _transitionTime: function (time) {
29814        if (!this.options.useTransition) {
29815            return;
29816        }
29817        time = time || 0;
29818        var durationProp = utils.style.transitionDuration;
29819        if(!durationProp) {
29820            return;
29821        }
29822
29823        this.scrollerStyle[durationProp] = time + 'ms';
29824
29825        if ( !time && utils.isBadAndroid ) {
29826            this.scrollerStyle[durationProp] = '0.0001ms';
29827            // remove 0.0001ms
29828            var self = this;
29829            rAF(function() {
29830                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29831                    self.scrollerStyle[durationProp] = '0s';
29832                }
29833            });
29834        }
29835
29836
29837        if ( this.indicators ) {
29838            for ( var i = this.indicators.length; i--; ) {
29839                this.indicators[i].transitionTime(time);
29840            }
29841        }
29842
29843
29844// INSERT POINT: _transitionTime
29845
29846    },
29847
29848    _transitionTimingFunction: function (easing) {
29849        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29850
29851
29852        if ( this.indicators ) {
29853            for ( var i = this.indicators.length; i--; ) {
29854                this.indicators[i].transitionTimingFunction(easing);
29855            }
29856        }
29857
29858
29859// INSERT POINT: _transitionTimingFunction
29860
29861    },
29862
29863    _translate: function (x, y) {
29864        //Uncode addition
29865        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29866            return false;
vendor: 9,939 bytes, lines 29867-30178
29867
29868        if ( this.options.useTransform ) {
29869
29870/* REPLACE START: _translate */
29871
29872            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29873
29874/* REPLACE END: _translate */
29875
29876        } else {
29877            x = Math.round(x);
29878            y = Math.round(y);
29879            this.scrollerStyle.left = x + 'px';
29880            this.scrollerStyle.top = y + 'px';
29881        }
29882
29883        this.x = x;
29884        this.y = y;
29885
29886
29887        if ( this.indicators ) {
29888            for ( var i = this.indicators.length; i--; ) {
29889                this.indicators[i].updatePosition();
29890            }
29891        }
29892
29893        //Uncode addition
29894        var uncodevent = new CustomEvent('fp-slide-scroll');
29895        window.dispatchEvent(uncodevent);
29896
29897// INSERT POINT: _translate
29898
29899    },
29900
29901    _initEvents: function (remove) {
29902        var eventType = remove ? utils.removeEvent : utils.addEvent,
29903            target = this.options.bindToWrapper ? this.wrapper : window;
29904
29905        eventType(window, 'orientationchange', this);
29906        eventType(window, 'resize', this);
29907
29908        if ( this.options.click ) {
29909            eventType(this.wrapper, 'click', this, true);
29910        }
29911
29912        if ( !this.options.disableMouse ) {
29913            eventType(this.wrapper, 'mousedown', this);
29914            eventType(target, 'mousemove', this);
29915            eventType(target, 'mousecancel', this);
29916            eventType(target, 'mouseup', this);
29917        }
29918
29919        if ( utils.hasPointer && !this.options.disablePointer ) {
29920            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29921            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29922            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29923            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29924        }
29925
29926        if ( utils.hasTouch && !this.options.disableTouch ) {
29927            eventType(this.wrapper, 'touchstart', this);
29928            eventType(target, 'touchmove', this);
29929            eventType(target, 'touchcancel', this);
29930            eventType(target, 'touchend', this);
29931        }
29932
29933        eventType(this.scroller, 'transitionend', this);
29934        eventType(this.scroller, 'webkitTransitionEnd', this);
29935        eventType(this.scroller, 'oTransitionEnd', this);
29936        eventType(this.scroller, 'MSTransitionEnd', this);
29937    },
29938
29939    getComputedPosition: function () {
29940        var matrix = window.getComputedStyle(this.scroller, null),
29941            x, y;
29942
29943        if ( this.options.useTransform ) {
29944            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29945            x = +(matrix[12] || matrix[4]);
29946            y = +(matrix[13] || matrix[5]);
29947        } else {
29948            x = +matrix.left.replace(/[^-\d.]/g, '');
29949            y = +matrix.top.replace(/[^-\d.]/g, '');
29950        }
29951
29952        return { x: x, y: y };
29953    },
29954    _initIndicators: function () {
29955        var interactive = this.options.interactiveScrollbars,
29956            customStyle = typeof this.options.scrollbars != 'string',
29957            indicators = [],
29958            indicator;
29959
29960        var that = this;
29961
29962        this.indicators = [];
29963
29964        if ( this.options.scrollbars ) {
29965            // Vertical scrollbar
29966            if ( this.options.scrollY ) {
29967                indicator = {
29968                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
29969                    interactive: interactive,
29970                    defaultScrollbars: true,
29971                    customStyle: customStyle,
29972                    resize: this.options.resizeScrollbars,
29973                    shrink: this.options.shrinkScrollbars,
29974                    fade: this.options.fadeScrollbars,
29975                    listenX: false
29976                };
29977
29978                this.wrapper.appendChild(indicator.el);
29979                indicators.push(indicator);
29980            }
29981
29982            // Horizontal scrollbar
29983            if ( this.options.scrollX ) {
29984                indicator = {
29985                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
29986                    interactive: interactive,
29987                    defaultScrollbars: true,
29988                    customStyle: customStyle,
29989                    resize: this.options.resizeScrollbars,
29990                    shrink: this.options.shrinkScrollbars,
29991                    fade: this.options.fadeScrollbars,
29992                    listenY: false
29993                };
29994
29995                this.wrapper.appendChild(indicator.el);
29996                indicators.push(indicator);
29997            }
29998        }
29999
30000        if ( this.options.indicators ) {
30001            // TODO: check concat compatibility
30002            indicators = indicators.concat(this.options.indicators);
30003        }
30004
30005        for ( var i = indicators.length; i--; ) {
30006            this.indicators.push( new Indicator(this, indicators[i]) );
30007        }
30008
30009        // TODO: check if we can use array.map (wide compatibility and performance issues)
30010        function _indicatorsMap (fn) {
30011            if (that.indicators) {
30012                for ( var i = that.indicators.length; i--; ) {
30013                    fn.call(that.indicators[i]);
30014                }
30015            }
30016        }
30017
30018        if ( this.options.fadeScrollbars ) {
30019            this.on('scrollEnd', function () {
30020                _indicatorsMap(function () {
30021                    this.fade();
30022                });
30023            });
30024
30025            this.on('scrollCancel', function () {
30026                _indicatorsMap(function () {
30027                    this.fade();
30028                });
30029            });
30030
30031            this.on('scrollStart', function () {
30032                _indicatorsMap(function () {
30033                    this.fade(1);
30034                });
30035            });
30036
30037            this.on('beforeScrollStart', function () {
30038                _indicatorsMap(function () {
30039                    this.fade(1, true);
30040                });
30041            });
30042        }
30043
30044
30045        this.on('refresh', function () {
30046            _indicatorsMap(function () {
30047                this.refresh();
30048            });
30049        });
30050
30051        this.on('destroy', function () {
30052            _indicatorsMap(function () {
30053                this.destroy();
30054            });
30055
30056            delete this.indicators;
30057        });
30058    },
30059
30060    _initWheel: function () {
30061        utils.addEvent(this.wrapper, 'wheel', this);
30062        utils.addEvent(this.wrapper, 'mousewheel', this);
30063        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30064
30065        this.on('destroy', function () {
30066            clearTimeout(this.wheelTimeout);
30067            this.wheelTimeout = null;
30068            utils.removeEvent(this.wrapper, 'wheel', this);
30069            utils.removeEvent(this.wrapper, 'mousewheel', this);
30070            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
30071        });
30072    },
30073
30074    _wheel: function (e) {
30075        if ( !this.enabled ) {
30076            return;
30077        }
30078
30079        var wheelDeltaX, wheelDeltaY,
30080            newX, newY,
30081            that = this;
30082
30083        if ( this.wheelTimeout === undefined ) {
30084            that._execEvent('scrollStart');
30085        }
30086
30087        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
30088        clearTimeout(this.wheelTimeout);
30089        this.wheelTimeout = setTimeout(function () {
30090            if(!that.options.snap) {
30091                that._execEvent('scrollEnd');
30092            }
30093            that.wheelTimeout = undefined;
30094        }, 400);
30095
30096        if ( 'deltaX' in e ) {
30097            if (e.deltaMode === 1) {
30098                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
30099                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
30100            } else {
30101                wheelDeltaX = -e.deltaX;
30102                wheelDeltaY = -e.deltaY;
30103            }
30104        } else if ( 'wheelDeltaX' in e ) {
30105            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
30106            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
30107        } else if ( 'wheelDelta' in e ) {
30108            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
30109        } else if ( 'detail' in e ) {
30110            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
30111        } else {
30112            return;
30113        }
30114
30115        wheelDeltaX *= this.options.invertWheelDirection;
30116        wheelDeltaY *= this.options.invertWheelDirection;
30117
30118        if ( !this.hasVerticalScroll ) {
30119            wheelDeltaX = wheelDeltaY;
30120            wheelDeltaY = 0;
30121        }
30122
30123        if ( this.options.snap ) {
30124            newX = this.currentPage.pageX;
30125            newY = this.currentPage.pageY;
30126
30127            if ( wheelDeltaX > 0 ) {
30128                newX--;
30129            } else if ( wheelDeltaX < 0 ) {
30130                newX++;
30131            }
30132
30133            if ( wheelDeltaY > 0 ) {
30134                newY--;
30135            } else if ( wheelDeltaY < 0 ) {
30136                newY++;
30137            }
30138
30139            this.goToPage(newX, newY);
30140
30141            return;
30142        }
30143
30144        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
30145        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
30146
30147        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
30148        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
30149
30150        if ( newX > 0 ) {
30151            newX = 0;
30152        } else if ( newX < this.maxScrollX ) {
30153            newX = this.maxScrollX;
30154        }
30155
30156        if ( newY > 0 ) {
30157            newY = 0;
30158        } else if ( newY < this.maxScrollY ) {
30159            newY = this.maxScrollY;
30160        }
30161
30162        this.scrollTo(newX, newY, 0);
30163
30164// INSERT POINT: _wheel
30165    },
30166
30167    _initSnap: function () {
30168        this.currentPage = {};
30169
30170        if ( typeof this.options.snap == 'string' ) {
30171            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
30172        }
30173
30174        this.on('refresh', function () {
30175            var i = 0, l,
30176                m = 0, n,
30177                cx, cy,
30178                x = 0, y,
vendor: 7,339 bytes, lines 30179-30432
30179                stepX = this.options.snapStepX || this.wrapperWidth,
30180                stepY = this.options.snapStepY || this.wrapperHeight,
30181                el;
30182
30183            this.pages = [];
30184
30185            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
30186                return;
30187            }
30188
30189            if ( this.options.snap === true ) {
30190                cx = Math.round( stepX / 2 );
30191                cy = Math.round( stepY / 2 );
30192
30193                while ( x > -this.scrollerWidth ) {
30194                    this.pages[i] = [];
30195                    l = 0;
30196                    y = 0;
30197
30198                    while ( y > -this.scrollerHeight ) {
30199                        this.pages[i][l] = {
30200                            x: Math.max(x, this.maxScrollX),
30201                            y: Math.max(y, this.maxScrollY),
30202                            width: stepX,
30203                            height: stepY,
30204                            cx: x - cx,
30205                            cy: y - cy
30206                        };
30207
30208                        y -= stepY;
30209                        l++;
30210                    }
30211
30212                    x -= stepX;
30213                    i++;
30214                }
30215            } else {
30216                el = this.options.snap;
30217                l = el.length;
30218                n = -1;
30219
30220                for ( ; i < l; i++ ) {
30221                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
30222                        m = 0;
30223                        n++;
30224                    }
30225
30226                    if ( !this.pages[m] ) {
30227                        this.pages[m] = [];
30228                    }
30229
30230                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
30231                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
30232                    cx = x - Math.round(el[i].offsetWidth / 2);
30233                    cy = y - Math.round(el[i].offsetHeight / 2);
30234
30235                    this.pages[m][n] = {
30236                        x: x,
30237                        y: y,
30238                        width: el[i].offsetWidth,
30239                        height: el[i].offsetHeight,
30240                        cx: cx,
30241                        cy: cy
30242                    };
30243
30244                    if ( x > this.maxScrollX ) {
30245                        m++;
30246                    }
30247                }
30248            }
30249
30250            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
30251
30252            // Update snap threshold if needed
30253            if ( this.options.snapThreshold % 1 === 0 ) {
30254                this.snapThresholdX = this.options.snapThreshold;
30255                this.snapThresholdY = this.options.snapThreshold;
30256            } else {
30257                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
30258                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
30259            }
30260        });
30261
30262        this.on('flick', function () {
30263            var time = this.options.snapSpeed || Math.max(
30264                    Math.max(
30265                        Math.min(Math.abs(this.x - this.startX), 1000),
30266                        Math.min(Math.abs(this.y - this.startY), 1000)
30267                    ), 300);
30268
30269            this.goToPage(
30270                this.currentPage.pageX + this.directionX,
30271                this.currentPage.pageY + this.directionY,
30272                time
30273            );
30274        });
30275    },
30276
30277    _nearestSnap: function (x, y) {
30278        if ( !this.pages.length ) {
30279            return { x: 0, y: 0, pageX: 0, pageY: 0 };
30280        }
30281
30282        var i = 0,
30283            l = this.pages.length,
30284            m = 0;
30285
30286        // Check if we exceeded the snap threshold
30287        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
30288            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
30289            return this.currentPage;
30290        }
30291
30292        if ( x > 0 ) {
30293            x = 0;
30294        } else if ( x < this.maxScrollX ) {
30295            x = this.maxScrollX;
30296        }
30297
30298        if ( y > 0 ) {
30299            y = 0;
30300        } else if ( y < this.maxScrollY ) {
30301            y = this.maxScrollY;
30302        }
30303
30304        for ( ; i < l; i++ ) {
30305            if ( x >= this.pages[i][0].cx ) {
30306                x = this.pages[i][0].x;
30307                break;
30308            }
30309        }
30310
30311        l = this.pages[i].length;
30312
30313        for ( ; m < l; m++ ) {
30314            if ( y >= this.pages[0][m].cy ) {
30315                y = this.pages[0][m].y;
30316                break;
30317            }
30318        }
30319
30320        if ( i == this.currentPage.pageX ) {
30321            i += this.directionX;
30322
30323            if ( i < 0 ) {
30324                i = 0;
30325            } else if ( i >= this.pages.length ) {
30326                i = this.pages.length - 1;
30327            }
30328
30329            x = this.pages[i][0].x;
30330        }
30331
30332        if ( m == this.currentPage.pageY ) {
30333            m += this.directionY;
30334
30335            if ( m < 0 ) {
30336                m = 0;
30337            } else if ( m >= this.pages[0].length ) {
30338                m = this.pages[0].length - 1;
30339            }
30340
30341            y = this.pages[0][m].y;
30342        }
30343
30344        return {
30345            x: x,
30346            y: y,
30347            pageX: i,
30348            pageY: m
30349        };
30350    },
30351
30352    goToPage: function (x, y, time, easing) {
30353        easing = easing || this.options.bounceEasing;
30354
30355        if ( x >= this.pages.length ) {
30356            x = this.pages.length - 1;
30357        } else if ( x < 0 ) {
30358            x = 0;
30359        }
30360
30361        if ( y >= this.pages[x].length ) {
30362            y = this.pages[x].length - 1;
30363        } else if ( y < 0 ) {
30364            y = 0;
30365        }
30366
30367        var posX = this.pages[x][y].x,
30368            posY = this.pages[x][y].y;
30369
30370        time = time === undefined ? this.options.snapSpeed || Math.max(
30371            Math.max(
30372                Math.min(Math.abs(posX - this.x), 1000),
30373                Math.min(Math.abs(posY - this.y), 1000)
30374            ), 300) : time;
30375
30376        this.currentPage = {
30377            x: posX,
30378            y: posY,
30379            pageX: x,
30380            pageY: y
30381        };
30382
30383        this.scrollTo(posX, posY, time, easing);
30384    },
30385
30386    next: function (time, easing) {
30387        var x = this.currentPage.pageX,
30388            y = this.currentPage.pageY;
30389
30390        x++;
30391
30392        if ( x >= this.pages.length && this.hasVerticalScroll ) {
30393            x = 0;
30394            y++;
30395        }
30396
30397        this.goToPage(x, y, time, easing);
30398    },
30399
30400    prev: function (time, easing) {
30401        var x = this.currentPage.pageX,
30402            y = this.currentPage.pageY;
30403
30404        x--;
30405
30406        if ( x < 0 && this.hasVerticalScroll ) {
30407            x = 0;
30408            y--;
30409        }
30410
30411        this.goToPage(x, y, time, easing);
30412    },
30413
30414    _initKeys: function (e) {
30415        // default key bindings
30416        var keys = {
30417            pageUp: 33,
30418            pageDown: 34,
30419            end: 35,
30420            home: 36,
30421            left: 37,
30422            up: 38,
30423            right: 39,
30424            down: 40
30425        };
30426        var i;
30427
30428        // if you give me characters I give you keycode
30429        if ( typeof this.options.keyBindings == 'object' ) {
30430            for ( i in this.options.keyBindings ) {
30431                if ( typeof this.options.keyBindings[i] == 'string' ) {
30432                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 30432-30785
30432deAt(0);
30433                }
30434            }
30435        } else {
30436            this.options.keyBindings = {};
30437        }
30438
30439        for ( i in keys ) {
30440            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
30441        }
30442
30443        utils.addEvent(window, 'keydown', this);
30444
30445        this.on('destroy', function () {
30446            utils.removeEvent(window, 'keydown', this);
30447        });
30448    },
30449
30450    _key: function (e) {
30451        if ( !this.enabled ) {
30452            return;
30453        }
30454
30455        var snap = this.options.snap,   // we are using this alot, better to cache it
30456            newX = snap ? this.currentPage.pageX : this.x,
30457            newY = snap ? this.currentPage.pageY : this.y,
30458            now = utils.getTime(),
30459            prevTime = this.keyTime || 0,
30460            acceleration = 0.250,
30461            pos;
30462
30463        if ( this.options.useTransition && this.isInTransition ) {
30464            pos = this.getComputedPosition();
30465
30466            this._translate(Math.round(pos.x), Math.round(pos.y));
30467            this.isInTransition = false;
30468        }
30469
30470        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
30471
30472        switch ( e.keyCode ) {
30473            case this.options.keyBindings.pageUp:
30474                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30475                    newX += snap ? 1 : this.wrapperWidth;
30476                } else {
30477                    newY += snap ? 1 : this.wrapperHeight;
30478                }
30479                break;
30480            case this.options.keyBindings.pageDown:
30481                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30482                    newX -= snap ? 1 : this.wrapperWidth;
30483                } else {
30484                    newY -= snap ? 1 : this.wrapperHeight;
30485                }
30486                break;
30487            case this.options.keyBindings.end:
30488                newX = snap ? this.pages.length-1 : this.maxScrollX;
30489                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
30490                break;
30491            case this.options.keyBindings.home:
30492                newX = 0;
30493                newY = 0;
30494                break;
30495            case this.options.keyBindings.left:
30496                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
30497                break;
30498            case this.options.keyBindings.up:
30499                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
30500                break;
30501            case this.options.keyBindings.right:
30502                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
30503                break;
30504            case this.options.keyBindings.down:
30505                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
30506                break;
30507            default:
30508                return;
30509        }
30510
30511        if ( snap ) {
30512            this.goToPage(newX, newY);
30513            return;
30514        }
30515
30516        if ( newX > 0 ) {
30517            newX = 0;
30518            this.keyAcceleration = 0;
30519        } else if ( newX < this.maxScrollX ) {
30520            newX = this.maxScrollX;
30521            this.keyAcceleration = 0;
30522        }
30523
30524        if ( newY > 0 ) {
30525            newY = 0;
30526            this.keyAcceleration = 0;
30527        } else if ( newY < this.maxScrollY ) {
30528            newY = this.maxScrollY;
30529            this.keyAcceleration = 0;
30530        }
30531
30532        this.scrollTo(newX, newY, 0);
30533
30534        this.keyTime = now;
30535    },
30536
30537    _animate: function (destX, destY, duration, easingFn) {
30538        var that = this,
30539            startX = this.x,
30540            startY = this.y,
30541            startTime = utils.getTime(),
30542            destTime = startTime + duration;
30543
30544        function step () {
30545            var now = utils.getTime(),
30546                newX, newY,
30547                easing;
30548
30549            if ( now >= destTime ) {
30550                that.isAnimating = false;
30551                that._translate(destX, destY);
30552
30553                if ( !that.resetPosition(that.options.bounceTime) ) {
30554                    that._execEvent('scrollEnd');
30555                }
30556
30557                return;
30558            }
30559
30560            now = ( now - startTime ) / duration;
30561            easing = easingFn(now);
30562            newX = ( destX - startX ) * easing + startX;
30563            newY = ( destY - startY ) * easing + startY;
30564            that._translate(newX, newY);
30565
30566            if ( that.isAnimating ) {
30567                rAF(step);
30568            }
30569        }
30570
30571        this.isAnimating = true;
30572        step();
30573    },
30574    handleEvent: function (e) {
30575        switch ( e.type ) {
30576            case 'touchstart':
30577            case 'pointerdown':
30578            case 'MSPointerDown':
30579            case 'mousedown':
30580                this._start(e);
30581                break;
30582            case 'touchmove':
30583            case 'pointermove':
30584            case 'MSPointerMove':
30585            case 'mousemove':
30586                this._move(e);
30587                break;
30588            case 'touchend':
30589            case 'pointerup':
30590            case 'MSPointerUp':
30591            case 'mouseup':
30592            case 'touchcancel':
30593            case 'pointercancel':
30594            case 'MSPointerCancel':
30595            case 'mousecancel':
30596                this._end(e);
30597                break;
30598            case 'orientationchange':
30599            case 'resize':
30600                this._resize();
30601                break;
30602            case 'transitionend':
30603            case 'webkitTransitionEnd':
30604            case 'oTransitionEnd':
30605            case 'MSTransitionEnd':
30606                this._transitionEnd(e);
30607                break;
30608            case 'wheel':
30609            case 'DOMMouseScroll':
30610            case 'mousewheel':
30611                this._wheel(e);
30612                break;
30613            case 'keydown':
30614                this._key(e);
30615                break;
30616            case 'click':
30617                if ( this.enabled && !e._constructed ) {
30618                    e.preventDefault();
30619                    e.stopPropagation();
30620                }
30621                break;
30622        }
30623    }
30624};
30625function createDefaultScrollbar (direction, interactive, type) {
30626    var scrollbar = document.createElement('div'),
30627        indicator = document.createElement('div');
30628
30629    if ( type === true ) {
30630        scrollbar.style.cssText = 'position:absolute;z-index:9999';
30631        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';
30632    }
30633
30634    indicator.className = 'iScrollIndicator';
30635
30636    if ( direction == 'h' ) {
30637        if ( type === true ) {
30638            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
30639            indicator.style.height = '100%';
30640        }
30641        scrollbar.className = 'iScrollHorizontalScrollbar';
30642    } else {
30643        if ( type === true ) {
30644            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
30645            indicator.style.width = '100%';
30646        }
30647        scrollbar.className = 'iScrollVerticalScrollbar';
30648    }
30649
30650    scrollbar.style.cssText += ';overflow:hidden';
30651
30652    if ( !interactive ) {
30653        scrollbar.style.pointerEvents = 'none';
30654    }
30655
30656    scrollbar.appendChild(indicator);
30657
30658    return scrollbar;
30659}
30660
30661function Indicator (scroller, options) {
30662    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
30663    this.wrapperStyle = this.wrapper.style;
30664    this.indicator = this.wrapper.children[0];
30665    this.indicatorStyle = this.indicator.style;
30666    this.scroller = scroller;
30667
30668    this.options = {
30669        listenX: true,
30670        listenY: true,
30671        interactive: false,
30672        resize: true,
30673        defaultScrollbars: false,
30674        shrink: false,
30675        fade: false,
30676        speedRatioX: 0,
30677        speedRatioY: 0
30678    };
30679
30680    for ( var i in options ) {
30681        this.options[i] = options[i];
30682    }
30683
30684    this.sizeRatioX = 1;
30685    this.sizeRatioY = 1;
30686    this.maxPosX = 0;
30687    this.maxPosY = 0;
30688
30689    if ( this.options.interactive ) {
30690        if ( !this.options.disableTouch ) {
30691            utils.addEvent(this.indicator, 'touchstart', this);
30692            utils.addEvent(window, 'touchend', this);
30693        }
30694        if ( !this.options.disablePointer ) {
30695            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30696            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
30697        }
30698        if ( !this.options.disableMouse ) {
30699            utils.addEvent(this.indicator, 'mousedown', this);
30700            utils.addEvent(window, 'mouseup', this);
30701        }
30702    }
30703
30704    if ( this.options.fade ) {
30705        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
30706        var durationProp = utils.style.transitionDuration;
30707        if(!durationProp) {
30708            return;
30709        }
30710        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
30711        // remove 0.0001ms
30712        var self = this;
30713        if(utils.isBadAndroid) {
30714            rAF(function() {
30715                if(self.wrapperStyle[durationProp] === '0.0001ms') {
30716                    self.wrapperStyle[durationProp] = '0s';
30717                }
30718            });
30719        }
30720        this.wrapperStyle.opacity = '0';
30721    }
30722}
30723
30724Indicator.prototype = {
30725    handleEvent: function (e) {
30726        switch ( e.type ) {
30727            case 'touchstart':
30728            case 'pointerdown':
30729            case 'MSPointerDown':
30730            case 'mousedown':
30731                this._start(e);
30732                break;
30733            case 'touchmove':
30734            case 'pointermove':
30735            case 'MSPointerMove':
30736            case 'mousemove':
30737                this._move(e);
30738                break;
30739            case 'touchend':
30740            case 'pointerup':
30741            case 'MSPointerUp':
30742            case 'mouseup':
30743            case 'touchcancel':
30744            case 'pointercancel':
30745            case 'MSPointerCancel':
30746            case 'mousecancel':
30747                this._end(e);
30748                break;
30749        }
30750    },
30751
30752    destroy: function () {
30753        if ( this.options.fadeScrollbars ) {
30754            clearTimeout(this.fadeTimeout);
30755            this.fadeTimeout = null;
30756        }
30757        if ( this.options.interactive ) {
30758            utils.removeEvent(this.indicator, 'touchstart', this);
30759            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30760            utils.removeEvent(this.indicator, 'mousedown', this);
30761
30762            utils.removeEvent(window, 'touchmove', this);
30763            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30764            utils.removeEvent(window, 'mousemove', this);
30765
30766            utils.removeEvent(window, 'touchend', this);
30767            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
30768            utils.removeEvent(window, 'mouseup', this);
30769        }
30770
30771        if ( this.options.defaultScrollbars ) {
30772            this.wrapper.parentNode.removeChild(this.wrapper);
30773        }
30774    },
30775
30776    _start: function (e) {
30777        var point = e.touches ? e.touches[0] : e;
30778
30779        e.preventDefault();
30780        e.stopPropagation();
30781
30782        this.transitionTime();
30783
30784        this.initiated = true;
30785        this.moved = false;
vendor: 9,615 bytes, lines 30786-31044
30786        this.lastPointX = point.pageX;
30787        this.lastPointY = point.pageY;
30788
30789        this.startTime  = utils.getTime();
30790
30791        if ( !this.options.disableTouch ) {
30792            utils.addEvent(window, 'touchmove', this);
30793        }
30794        if ( !this.options.disablePointer ) {
30795            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30796        }
30797        if ( !this.options.disableMouse ) {
30798            utils.addEvent(window, 'mousemove', this);
30799        }
30800
30801        this.scroller._execEvent('beforeScrollStart');
30802    },
30803
30804    _move: function (e) {
30805        var point = e.touches ? e.touches[0] : e,
30806            deltaX, deltaY,
30807            newX, newY,
30808            timestamp = utils.getTime();
30809
30810        if ( !this.moved ) {
30811            this.scroller._execEvent('scrollStart');
30812        }
30813
30814        this.moved = true;
30815
30816        deltaX = point.pageX - this.lastPointX;
30817        this.lastPointX = point.pageX;
30818
30819        deltaY = point.pageY - this.lastPointY;
30820        this.lastPointY = point.pageY;
30821
30822        newX = this.x + deltaX;
30823        newY = this.y + deltaY;
30824
30825        this._pos(newX, newY);
30826
30827// INSERT POINT: indicator._move
30828
30829        e.preventDefault();
30830        e.stopPropagation();
30831    },
30832
30833    _end: function (e) {
30834        if ( !this.initiated ) {
30835            return;
30836        }
30837
30838        this.initiated = false;
30839
30840        e.preventDefault();
30841        e.stopPropagation();
30842
30843        utils.removeEvent(window, 'touchmove', this);
30844        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30845        utils.removeEvent(window, 'mousemove', this);
30846
30847        if ( this.scroller.options.snap ) {
30848            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30849
30850            var time = this.options.snapSpeed || Math.max(
30851                    Math.max(
30852                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30853                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30854                    ), 300);
30855
30856            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30857                this.scroller.directionX = 0;
30858                this.scroller.directionY = 0;
30859                this.scroller.currentPage = snap;
30860                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30861            }
30862        }
30863
30864        if ( this.moved ) {
30865            this.scroller._execEvent('scrollEnd');
30866        }
30867    },
30868
30869    transitionTime: function (time) {
30870        time = time || 0;
30871        var durationProp = utils.style.transitionDuration;
30872        if(!durationProp) {
30873            return;
30874        }
30875
30876        this.indicatorStyle[durationProp] = time + 'ms';
30877
30878        if ( !time && utils.isBadAndroid ) {
30879            this.indicatorStyle[durationProp] = '0.0001ms';
30880            // remove 0.0001ms
30881            var self = this;
30882            rAF(function() {
30883                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30884                    self.indicatorStyle[durationProp] = '0s';
30885                }
30886            });
30887        }
30888    },
30889
30890    transitionTimingFunction: function (easing) {
30891        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30892    },
30893
30894    refresh: function () {
30895        this.transitionTime();
30896
30897        if ( this.options.listenX && !this.options.listenY ) {
30898            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30899        } else if ( this.options.listenY && !this.options.listenX ) {
30900            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30901        } else {
30902            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30903        }
30904
30905        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30906            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30907            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30908
30909            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30910                if ( this.options.listenX ) {
30911                    this.wrapper.style.right = '8px';
30912                } else {
30913                    this.wrapper.style.bottom = '8px';
30914                }
30915            }
30916        } else {
30917            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30918            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30919
30920            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30921                if ( this.options.listenX ) {
30922                    this.wrapper.style.right = '2px';
30923                } else {
30924                    this.wrapper.style.bottom = '2px';
30925                }
30926            }
30927        }
30928
30929        var r = this.wrapper.offsetHeight;  // force refresh
30930
30931        if ( this.options.listenX ) {
30932            this.wrapperWidth = this.wrapper.clientWidth;
30933            if ( this.options.resize ) {
30934                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30935                this.indicatorStyle.width = this.indicatorWidth + 'px';
30936            } else {
30937                this.indicatorWidth = this.indicator.clientWidth;
30938            }
30939
30940            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30941
30942            if ( this.options.shrink == 'clip' ) {
30943                this.minBoundaryX = -this.indicatorWidth + 8;
30944                this.maxBoundaryX = this.wrapperWidth - 8;
30945            } else {
30946                this.minBoundaryX = 0;
30947                this.maxBoundaryX = this.maxPosX;
30948            }
30949
30950            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30951        }
30952
30953        if ( this.options.listenY ) {
30954            this.wrapperHeight = this.wrapper.clientHeight;
30955            if ( this.options.resize ) {
30956                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
30957                this.indicatorStyle.height = this.indicatorHeight + 'px';
30958            } else {
30959                this.indicatorHeight = this.indicator.clientHeight;
30960            }
30961
30962            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30963
30964            if ( this.options.shrink == 'clip' ) {
30965                this.minBoundaryY = -this.indicatorHeight + 8;
30966                this.maxBoundaryY = this.wrapperHeight - 8;
30967            } else {
30968                this.minBoundaryY = 0;
30969                this.maxBoundaryY = this.maxPosY;
30970            }
30971
30972            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30973            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
30974        }
30975
30976        this.updatePosition();
30977    },
30978
30979    updatePosition: function () {
30980        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
30981            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
30982
30983        if ( !this.options.ignoreBoundaries ) {
30984            if ( x < this.minBoundaryX ) {
30985                if ( this.options.shrink == 'scale' ) {
30986                    this.width = Math.max(this.indicatorWidth + x, 8);
30987                    this.indicatorStyle.width = this.width + 'px';
30988                }
30989                x = this.minBoundaryX;
30990            } else if ( x > this.maxBoundaryX ) {
30991                if ( this.options.shrink == 'scale' ) {
30992                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
30993                    this.indicatorStyle.width = this.width + 'px';
30994                    x = this.maxPosX + this.indicatorWidth - this.width;
30995                } else {
30996                    x = this.maxBoundaryX;
30997                }
30998            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
30999                this.width = this.indicatorWidth;
31000                this.indicatorStyle.width = this.width + 'px';
31001            }
31002
31003            if ( y < this.minBoundaryY ) {
31004                if ( this.options.shrink == 'scale' ) {
31005                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
31006                    this.indicatorStyle.height = this.height + 'px';
31007                }
31008                y = this.minBoundaryY;
31009            } else if ( y > this.maxBoundaryY ) {
31010                if ( this.options.shrink == 'scale' ) {
31011                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31012                    this.indicatorStyle.height = this.height + 'px';
31013                    y = this.maxPosY + this.indicatorHeight - this.height;
31014                } else {
31015                    y = this.maxBoundaryY;
31016                }
31017            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31018                this.height = this.indicatorHeight;
31019                this.indicatorStyle.height = this.height + 'px';
31020            }
31021        }
31022
31023        this.x = x;
31024        this.y = y;
31025
31026        if ( this.scroller.options.useTransform ) {
31027            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31028        } else {
31029            this.indicatorStyle.left = x + 'px';
31030            this.indicatorStyle.top = y + 'px';
31031        }
31032    },
31033
31034    _pos: function (x, y) {
31035        if ( x < 0 ) {
31036            x = 0;
31037        } else if ( x > this.maxPosX ) {
31038            x = this.maxPosX;
31039        }
31040
31041        if ( y < 0 ) {
31042            y = 0;
31043        } else if ( y > this.maxPosY ) {
31044            y = this.maxPosY;
31045        }
31046
31047        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31048        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31049
31050        this.scroller.scrollTo(x, y);
31051    },
31052
31053    fade: function (val, hold) {
31054        if ( hold && !this.visible ) {
31055            return;
31056        }
31057
31058        clearTimeout(this.fadeTimeout);
31059        this.fadeTimeout = null;
31060
31061        var time = val ? 250 : 500,
31062            delay = val ? 0 : 300;
31063
31064        val = val ? '1' : '0';
31065
31066        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31067
31068        this.fadeTimeout = setTimeout((function (val) {
31069            this.wrapperStyle.opacity = val;
31070            this.visible = +val;
31071        }).bind(this, val), delay);
31072    }
31073};
31074
31075IScroll.utils = utils;
31076
31077if ( typeof module != 'undefined' && module.exports ) {
31078    module.exports = IScroll;
31079} else if ( typeof define == 'function' && define.amd ) {
31080        define( function () { return IScroll; } );
31081} else {
31082    window.IScroll = IScroll;
31083}
31084
31085})(window, document, Math);
31086/*!
31087 * fullPage 2.9.4
31088 * https://github.com/alvarotrigo/fullPage.js
31089 * @license MIT licensed
31090 *
31091 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
31092 */
31093(function(global, factory) {
31094    'use strict';
31095    if (typeof define === 'function' && define.amd) {
31096        define(['jquery'], function($) {
31097          return factory($, global, global.document, global.Math);
31098        });
31099    } else if (typeof exports === "object" && exports) {
31100        module.exports = factory(require('jquery'), global, global.document, global.Math);
31101    } else {
31102        factory(jQuery, global, global.document, global.Math);
31103    }
31104})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
31105    'use strict';
31106
31107    // keeping central set of classnames and selectors
31108    var WRAPPER =               'fullpage-wrapper';
31109    var WRAPPER_SEL =           '.' + WRAPPER;
31110
31111    // slimscroll
31112    var SCROLLABLE =            'fp-scrollable';
31113    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
31114
31115    // util
31116    var RESPONSIVE =            'fp-responsive';
31117    var NO_TRANSITION =         'fp-notransition';
31118    var DESTROYED =             'fp-destroyed';
31119    var ENABLED =               'fp-enabled';
31120    var VIEWING_PREFIX =        'fp-viewing';
31121    var ACTIVE =                'active';
31122    var ACTIVE_SEL =            '.' + ACTIVE;
31123    var COMPLETELY =            'fp-completely';
31124    var COMPLETELY_SEL =        '.' + COMPLETELY;
31125
31126    // section
31127    var SECTION_DEFAULT_SEL =   '.section';
31128    var SECTION =               'fp-section';
31129    var SECTION_SEL =           '.' + SECTION;
31130    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
31131    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
31132    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
31133    var TABLE_CELL =            'fp-tableCell';
31134    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
31135    var AUTO_HEIGHT =           'fp-auto-height';
31136    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
31137    var NORMAL_SCROLL =         'fp-normal-scroll';
31138    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
31139
31140    // section nav
31141    var SECTION_NAV =           'fp-nav';
31142    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
31143    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
31144    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
31145    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
31146
31147    // slide
31148    var SLIDE_DEFAULT_SEL =     '.slide';
31149    var SLIDE =                 'fp-slide';
31150    var SLIDE_SEL =             '.' + SLIDE;
31151    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
31152    var SLIDES_WRAPPER =        'fp-slides';
31153    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
31154    var SLIDES_CONTAINER =      'fp-slidesContainer';
31155    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
31156    var TABLE =                 'fp-table';
31157
31158    // slide nav
31159    var SLIDES_NAV =            'fp-slidesNav';
31160    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
31161    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
31162    var SLIDES_ARROW =          'fp-controlArrow';
31163    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
31164    var SLIDES_PREV =           'fp-prev';
31165    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
31166    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
31167    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
31168    var SLIDES_NEXT =           'fp-next';
31169    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
31170    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
31171    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
31172
31173    var $window = $(window);
31174    var $document = $(document);
31175
31176    // Default options for iScroll.js used when using scrollOverflow
31177    var iscrollOptions = {
31178        scrollbars: true,
31179        mouseWheel: true,
31180        hideScrollbars: false,
31181        fadeScrollbars: false,
31182        disableMouse: true,
31183        interactiveScrollbars: true,
31184        bounce: false,
31185    };
31186
31187    $.fn.fullpage = function(options) {
31188        //only once my friend!
31189        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
31190
31191        // common jQuery objects
31192        var $htmlBody = $('html, body');
31193        var $body = $('body');
31194
31195        var FP = $.fn.fullpage;
31196
31197        // Creating some defaults, extending them with any options that were provided
31198        options = $.extend({
31199            //navigation
31200            menu: false,
31201            anchors:[],
31202            lockAnchors: false,
31203            navigation: false,
31204            navigationPosition: 'right',
31205            navigationTooltips: [],
31206            showActiveTooltip: false,
31207            slidesNavigation: false,
31208            slidesNavPosition: 'bottom',
31209            scrollBar: false,
31210            hybrid: false,
31211
31212            //scrolling
31213            css3: true,
31214            scrollingSpeed: 700,
31215            autoScrolling: true,
31216            fitToSection: true,
31217            fitToSectionDelay: 1000,
31218            easing: 'easeInOutCubic',
31219            easingcss3: 'ease',
31220            loopBottom: false,
31221            loopTop: false,
31222            loopHorizontal: true,
31223            continuousVertical: false,
31224            continuousHorizontal: false,
31225            scrollHorizontally: false,
31226            interlockedSlides: false,
31227            dragAndMove: false,
31228            offsetSections: false,
31229            resetSliders: false,
31230            fadingEffect: false,
31231            normalScrollElements: null,
31232            scrollOverflow: false,
31233            scrollOverflowReset: false,
31234            scrollOverflowHandler: iscrollHandler,
31235            scrollOverflowOptions: null,
31236            touchSensitivity: 5,
31237            normalScrollElementTouchThreshold: 5,
31238            bigSectionsDestination: null,
31239
31240            //Accessibility
31241            keyboardScrolling: true,
31242            animateAnchor: true,
31243            recordHistory: true,
31244
31245            //design
31246            controlArrows: true,
31247            controlArrowColor: '#fff',
31248            verticalCentered: true,
31249            sectionsColor : [],
31250            paddingTop: 0,
31251            paddingBottom: 0,
31252            fixedElements: null,
31253            responsive: 0, //backwards compabitility with responsiveWiddth
31254            responsiveWidth: 0,
31255            responsiveHeight: 0,
31256            responsiveSlides: false,
31257            parallax: false,
31258            parallaxOptions: {
31259                type: 'reveal',
31260                percentage: 62,
31261                property: 'translate'
31262            },
31263
31264            //Custom selectors
31265            sectionSelector: SECTION_DEFAULT_SEL,
31266            slideSelector: SLIDE_DEFAULT_SEL,
31267
31268            //events
31269            afterLoad: null,
31270            onLeave: null,
31271            afterRender: null,
31272            afterResize: null,
31273            afterReBuild: null,
31274            afterSlideLoad: null,
31275            onSlideLeave: null,
31276            afterResponsive: null,
31277
31278            lazyLoading: true
31279        }, options);
31280
31281        //flag to avoid very fast sliding for landscape sliders
31282        var slideMoving = false;
31283
31284        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
31285        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
31286        var container = $(this);
31287        var windowsHeight = $window.height();
31288        var isResizing = false;
31289        var isWindowFocused = true;
31290        var lastScrolledDestiny;
31291        var lastScrolledSlide;
31292        var canScroll = true;
31293        var scrollings = [];
31294        var controlPressed;
31295        var startingSection;
31296        var isScrollAllowed = {};
31297        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
31298        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
31299        var MSPointer = getMSPointer();
31300        var events = {
31301            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
31302            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
31303        };
31304
31305        //cheks for passive event support
31306        //added by Uncode from new fullPage updates
31307        var g_supportsPassive = false;
31308        try {
31309          var opts = Object.defineProperty({}, 'passive', {
31310            get: function() {
31311              g_supportsPassive = true;
31312            }
31313          });
31314          window.addEventListener("testPassive", null, opts);
31315          window.removeEventListener("testPassive", null, opts);
31316        } catch (e) {}
31317
31318        //timeouts
31319        var resizeId;
31320        var afterSectionLoadsId;
31321        var afterSlideLoadsId;
31322        var scrollId;
31323        var scrollId2;
31324        var keydownId;
31325        var originals = $.extend(true, {}, options); //deep copy
31326
31327        //Uncode addition
31328        var $masthead = $('#masthead');
31329        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
31330        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
31331        var bodyBorder = UNCODE.bodyBorder;
31332        var adminBarHeight = UNCODE.adminBarHeight;
31333
31334        displayWarnings();
31335
31336        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
31337        iscrollOptions.click = isTouch; // see #2035
31338
31339        //extending iScroll options with the user custom ones
31340        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
31341
31342        //easeInOutCubic animation included in the plugin
31343        $.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;}});
31344
31345        /**
31346        * Sets the autoScroll option.
31347        * It changes the scroll bar visibility and the history of the site as a result.
31348        */
31349        function setAutoScrolling(value, type){
31350            //removing the transformation
31351            if(!value){
31352                silentScroll(0);
31353            }
31354
31355            setVariableState('autoScrolling', value, type);
31356
31357            var element = $(SECTION_ACTIVE_SEL);
31358
31359            if(options.autoScrolling && !options.scrollBar){
31360                $htmlBody.css({
31361                    'overflow' : 'hidden !important',
31362                    'height' : '100%'
31363                });
31364
31365                //Uncode addition
31366                //setRecordHistory(originals.recordHistory, 'internal');
31367
31368                //for IE touch devices
31369                container.css({
31370                    '-ms-touch-action': 'none',
31371                    'touch-action': 'none'
31372                });
31373
31374                if(element.length){
31375                    //moving the container up
31376                    silentScroll(element.position().top);
31377                }
31378
31379            }else{
31380                $htmlBody.css({
31381                    'overflow' : 'visible !important',
31382                    'height' : 'initial'
31383                });
31384
31385                //Uncode addition
31386                //setRecordHistory(false, 'internal');
31387
31388                //for IE touch devices
31389                container.css({
31390                    '-ms-touch-action': '',
31391                    'touch-action': ''
31392                });
31393
31394                //scrolling the page to the section with no animation
31395                if (element.length) {
31396                    $htmlBody.scrollTop(element.position().top);
31397                }
31398            }
31399        }
31400
31401        /**
31402        * Defines wheter to record the history for each hash change in the URL.
31403        */
31404        function setRecordHistory(value, type){
31405            setVariableState('recordHistory', value, type);
31406        }
31407
31408        /**
31409        * Defines the scrolling speed
31410        */
31411        function setScrollingSpeed(value, type){
31412            setVariableState('scrollingSpeed', value, type);
31413        }
31414
31415        /**
31416        * Sets fitToSection
31417        */
31418        function setFitToSection(value, type){
31419            setVariableState('fitToSection', value, type);
31420        }
31421
31422        /**
31423        * Sets lockAnchors
31424        */
31425        function setLockAnchors(value){
31426            options.lockAnchors = value;
31427        }
31428
31429        /**
31430        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
31431        */
31432        function setMouseWheelScrolling(value){
31433            if(value){
31434                addMouseWheelHandler();
31435                addMiddleWheelHandler();
31436            }else{
31437                removeMouseWheelHandler();
31438                removeMiddleWheelHandler();
31439            }
31440        }
31441
31442        /**
31443        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
31444        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
31445        *
31446        * @param directions string containing the direction or directions separated by comma.
31447        */
31448        function setAllowScrolling(value, directions){
31449            if(typeof directions !== 'undefined'){
31450                directions = directions.replace(/ /g,'').split(',');
31451
31452                $.each(directions, function (index, direction){
31453                    setIsScrollAllowed(value, direction, 'm');
31454                });
31455            }
31456            else if(value){
31457                setMouseWheelScrolling(true);
31458                addTouchHandler();
31459            }else{
31460                setMouseWheelScrolling(false);
31461                removeTouchHandler();
31462            }
31463        }
31464
31465        /**
31466        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
31467        */
31468        function setKeyboardScrolling(value, directions){
31469            if(typeof directions !== 'undefined'){
31470                directions = directions.replace(/ /g,'').split(',');
31471
31472                $.each(directions, function (index, direction){
31473                    setIsScrollAllowed(value, direction, 'k');
31474                });
31475            }else{
31476                options.keyboardScrolling = value;
31477            }
31478        }
31479
31480        /**
31481        * Moves the page up one section.
31482        */
31483        function moveSectionUp(){
31484            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
31485
31486            //looping to the bottom if there's no more sections above
31487            if (!prev.length && (options.loopTop || options.continuousVertical)) {
31488                prev = $(SECTION_SEL).last();
31489            }
31490
31491            if (prev.length) {
31492                scrollPage(prev, null, true);
31493            }
31494        }
31495
31496        /**
31497        * Moves the page down one section.
31498        */
31499        function moveSectionDown(){
31500            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
31501
31502            //looping to the top if there's no more sections below
31503            if(!next.length &&
31504                (options.loopBottom || options.continuousVertical)){
31505                next = $(SECTION_SEL).first();
31506            }
31507
31508            if(next.length){
31509                scrollPage(next, null, false);
31510            }
31511        }
31512
31513        /**
31514        * Moves the page to the given section and slide with no animation.
31515        * Anchors or index positions can be used as params.
31516        */
31517        function silentMoveTo(sectionAnchor, slideAnchor){
31518            setScrollingSpeed (0, 'internal');
31519            moveTo(sectionAnchor, slideAnchor);
31520            setScrollingSpeed (originals.scrollingSpeed, 'internal');
31521        }
31522
31523        /**
31524        * Moves the page to the given section and slide.
31525        * Anchors or index positions can be used as params.
31526        */
31527        function moveTo(sectionAnchor, slideAnchor){
31528            var destiny = getSectionByAnchor(sectionAnchor);
31529
31530            if (typeof slideAnchor !== 'undefined'){
31531                scrollPageAndSlide(sectionAnchor, slideAnchor);
31532            }else if(destiny.length > 0){
31533                scrollPage(destiny);
31534            }
31535        }
31536
31537        /**
31538        * Slides right the slider of the active section.
31539        * Optional `section` param.
31540        */
31541        function moveSlideRight(section){
31542            moveSlide('right', section);
31543        }
31544
31545        /**
31546        * Slides left the slider of the active section.
31547        * Optional `section` param.
31548        */
31549        function moveSlideLeft(section){
31550            moveSlide('left', section);
31551        }
31552
31553        /**
31554         * When resizing is finished, we adjust the slides sizes and positions
31555         */
31556        function reBuild(resizing){
31557            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
31558
31559            isResizing = true;
31560
31561            windowsHeight = $window.height();  //updating global var
31562
31563            $(SECTION_SEL).each(function(){
31564                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
31565                var slides = $(this).find(SLIDE_SEL);
31566
31567                //adjusting the height of the table-cell for IE and Firefox
31568                if(options.verticalCentered){
31569                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
31570                }
31571
31572                $(this).css('height', windowsHeight + 'px');
31573
31574                //resizing the scrolling divs
31575                if(options.scrollOverflow){
31576                    if(slides.length){
31577                        slides.each(function(){
31578                            createScrollBar($(this));
31579                        });
31580                    }else{
31581                        createScrollBar($(this));
31582                    }
31583                }
31584
31585                //adjusting the position fo the FULL WIDTH slides...
31586                if (slides.length > 1) {
31587                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
31588                }
31589            });
31590
31591            var activeSection = $(SECTION_ACTIVE_SEL);
31592            var sectionIndex = activeSection.index(SECTION_SEL);
31593
31594            //isn't it the first section?
31595            if(sectionIndex){
31596                //adjusting the position for the current section
31597                silentMoveTo(sectionIndex + 1);
31598            }
31599
31600            isResizing = false;
31601            // Uncode change
31602            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
31603            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
31604            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
31605        }
31606
31607        /**
31608        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
31609        * are smaller than the set limit values.
31610        */
31611        function setResponsive(active){
31612            var isResponsive = $body.hasClass(RESPONSIVE);
31613
31614            if(active){
31615                if(!isResponsive){
31616                    setAutoScrolling(false, 'internal');
31617                    setFitToSection(false, 'internal');
31618                    $(SECTION_NAV_SEL).hide();
31619                    $body.addClass(RESPONSIVE);
31620                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31621                }
31622            }
31623            else if(isResponsive){
31624                setAutoScrolling(originals.autoScrolling, 'internal');
31625                setFitToSection(originals.autoScrolling, 'internal');
31626                $(SECTION_NAV_SEL).show();
31627                $body.removeClass(RESPONSIVE);
31628                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31629            }
31630        }
31631
31632        if($(this).length){
31633            //public functions
31634            FP.setAutoScrolling = setAutoScrolling;
31635            FP.setRecordHistory = setRecordHistory;
31636            FP.setScrollingSpeed = setScrollingSpeed;
31637            FP.setFitToSection = setFitToSection;
31638            FP.setLockAnchors = setLockAnchors;
31639            FP.setMouseWheelScrolling = setMouseWheelScrolling;
31640            FP.setAllowScrolling = setAllowScrolling;
31641            FP.setKeyboardScrolling = setKeyboardScrolling;
31642            FP.moveSectionUp = moveSectionUp;
31643            FP.moveSectionDown = moveSectionDown;
31644            FP.silentMoveTo = silentMoveTo;
31645            FP.moveTo = moveTo;
31646            FP.moveSlideRight = moveSlideRight;
31647            FP.moveSlideLeft = moveSlideLeft;
31648            FP.fitToSection = fitToSection;
31649            FP.reBuild = reBuild;
31650            FP.setResponsive = setResponsive;
31651            FP.destroy = destroy;
31652
31653            init();
31654
31655            bindEvents();
31656        }
31657
31658        function init(){
31659            //if css3 is not supported, it will use jQuery animations
31660            if(options.css3){
31661                options.css3 = support3d();
31662            }
31663
31664            options.scrollBar = options.scrollBar || options.hybrid;
31665
31666            setOptionsFromDOM();
31667            prepareDom();
31668            setAllowScrolling(true);
31669            setAutoScrolling(options.autoScrolling, 'internal');
31670            responsive();
31671
31672            //setting the class for the body element
31673            setBodyClass();
31674
31675            //Uncode addition
31676            // if(document.readyState === 'complete'){
31677            //     scrollToAnchor();
31678            // }
31679            // $window.on('load', scrollToAnchor);
31680        }
31681
31682        function bindEvents(){
31683            $window
31684                //when scrolling...
31685                //.on('scroll', scrollHandler)
31686
31687                //detecting any change on the URL to scroll to the given anchor link
31688                //(a way to detect back history button as we play with the hashes on the URL)
31689                .on('hashchange', hashChangeHandler)
31690
31691                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
31692                .blur(blurHandler)
31693
31694                //when resizing the site, we adjust the heights of the sections, slimScroll...
31695                .resize(resizeHandler);
31696
31697            $document
31698                //Sliding with arrow keys, both, vertical and horizontal
31699                .keydown(keydownHandler)
31700
31701                //to prevent scrolling while zooming
31702                .keyup(keyUpHandler)
31703
31704                //Scrolls to the section when clicking the navigation bullet
31705                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
31706
31707                //Scrolls the slider to the given slide destination for the given section
31708                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
31709
31710                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
31711
31712            //Scrolling horizontally when clicking on the slider controls.
31713            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
31714
31715            /**
31716            * Applying normalScroll elements.
31717            * Ignoring the scrolls over the specified selectors.
31718            */
31719            if(options.normalScrollElements){
31720                $document.on('mouseenter', options.normalScrollElements, function () {
31721                    setMouseWheelScrolling(false);
31722                });
31723
31724                $document.on('mouseleave', options.normalScrollElements, function(){
31725                    setMouseWheelScrolling(true);
31726                });
31727            }
31728        }
31729
31730        /**
31731        * Setting options from DOM elements if they are not provided.
31732        */
31733        function setOptionsFromDOM(){
31734            var sections = container.find(options.sectionSelector);
31735
31736            //no anchors option? Checking for them in the DOM attributes
31737            if(!options.anchors.length){
31738                options.anchors = sections.filter('[data-anchor]').map(function(){
31739                    return $(this).data('anchor').toString();
31740                }).get();
31741            }
31742
31743            //no tooltips option? Checking for them in the DOM attributes
31744            if(!options.navigationTooltips.length){
31745                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
31746                    return $(this).data('tooltip').toString();
31747                }).get();
31748            }
31749        }
31750
31751        /**
31752        * Works over the DOM structure to set it up for the current fullpage options.
31753        */
31754        function prepareDom(){
31755            container.css({
31756                'height': '100%',
31757                'position': 'relative'
31758            });
31759
31760            //adding a class to recognize the container internally in the code
31761            container.addClass(WRAPPER);
31762            $('html').addClass(ENABLED);
31763
31764            windowsHeight = $window.height();
31765
31766            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
31767
31768            addInternalSelectors();
31769
31770             //styling the sections / slides / menu
31771            $(SECTION_SEL).each(function(index){
31772                var section = $(this);
31773                var slides = section.find(SLIDE_SEL);
31774                var numSlides = slides.length;
31775
31776                styleSection(section, index);
31777                styleMenu(section, index);
31778
31779                // if there's any slide
31780                if (numSlides > 0) {
31781                    styleSlides(section, slides, numSlides);
31782                }else{
31783                    if(options.verticalCentered){
31784                        addTableClass(section);
31785                    }
31786                }
31787            });
31788
31789            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31790            if(options.fixedElements && options.css3){
31791                $(options.fixedElements).appendTo($body);
31792            }
31793
31794            //vertical centered of the navigation + active bullet
31795            if(options.navigation){
31796                addVerticalNavigation();
31797            }
31798
31799            enableYoutubeAPI();
31800
31801            if(options.scrollOverflow){
31802                if(document.readyState === 'complete'){
31803                    createScrollBarHandler();
31804                }
31805                //after DOM and images are loaded
31806                $window.on('load', createScrollBarHandler);
31807            }else{
31808                afterRenderActions();
31809            }
31810        }
31811
31812        /**
31813        * Styles the horizontal slides for a section.
31814        */
31815        function styleSlides(section, slides, numSlides){
31816            var sliderWidth = numSlides * 100;
31817            var slideWidth = 100 / numSlides;
31818
31819            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31820            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31821
31822            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31823
31824            if(numSlides > 1){
31825                if(options.controlArrows){
31826                    createSlideArrows(section);
31827                }
31828
31829                if(options.slidesNavigation){
31830                    addSlidesNavigation(section, numSlides);
31831                }
31832            }
31833
31834            slides.each(function(index) {
31835                $(this).css('width', slideWidth + '%');
31836
31837                if(options.verticalCentered){
31838                    addTableClass($(this));
31839                }
31840            });
31841
31842            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31843
31844            //if the slide won't be an starting point, the default will be the first one
31845            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31845ide by default.
31846            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31847                silentLandscapeScroll(startingSlide, 'internal');
31848            }else{
31849                slides.eq(0).addClass(ACTIVE);
31850            }
31851        }
31852
31853        /**
31854        * Styling vertical sections
31855        */
31856        function styleSection(section, index){
31857            //if no active section is defined, the 1st one will be the default one
31858            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31859                section.addClass(ACTIVE);
31860            }
31861            startingSection = $(SECTION_ACTIVE_SEL);
31862
31863            section.css('height', windowsHeight + 'px');
31864
31865            if(options.paddingTop){
31866                section.css('padding-top', options.paddingTop);
31867            }
31868
31869            if(options.paddingBottom){
31870                section.css('padding-bottom', options.paddingBottom);
31871            }
31872
31873            if (typeof options.sectionsColor[index] !==  'undefined') {
31874                section.css('background-color', options.sectionsColor[index]);
31875            }
31876
31877            if (typeof options.anchors[index] !== 'undefined') {
31878                section.attr('data-anchor', options.anchors[index]);
31879            }
31880        }
31881
31882        /**
31883        * Sets the data-anchor attributes to the menu elements and activates the current one.
31884        */
31885        function styleMenu(section, index){
31886            if (typeof options.anchors[index] !== 'undefined') {
31887                //activating the menu / nav element on load
31888                if(section.hasClass(ACTIVE)){
31889                    activateMenuAndNav(options.anchors[index], index);
31890                }
31891            }
31892
31893            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31894            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31895                $(options.menu).appendTo($body);
31896            }
31897        }
31898
31899        /**
31900        * Adds internal classes to be able to provide customizable selectors
31901        * keeping the link with the style sheet.
31902        */
31903        function addInternalSelectors(){
31904            container.find(options.sectionSelector).addClass(SECTION);
31905            container.find(options.slideSelector).addClass(SLIDE);
31906        }
31907
31908        /**
31909        * Creates the control arrows for the given section
31910        */
31911        function createSlideArrows(section){
31912            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31913
31914            if(options.controlArrowColor!='#fff'){
31915                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31916                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31917            }
31918
31919            if(!options.loopHorizontal){
31920                section.find(SLIDES_ARROW_PREV_SEL).hide();
31921            }
31922        }
31923
31924        /**
31925        * Creates a vertical navigation bar.
31926        */
31927        function addVerticalNavigation(){
31928            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31929            var nav = $(SECTION_NAV_SEL);
31930
31931            nav.addClass(function() {
31932                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31933            });
31934
31935            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31936                var link = '';
31937                if (options.anchors.length) {
31938                    link = options.anchors[i];
31939                }
31940
31941                var li = '<li><a href="#' + link + '"><span></span></a>';
31942
31943                // Only add tooltip if needed (defined by user)
31944                var tooltip = options.navigationTooltips[i];
31945
31946                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31947                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31948                }
31949
31950                li += '</li>';
31951
31952                nav.find('ul').append(li);
31953            }
31954
31955            //centering it vertically
31956            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
31957
31958            //activating the current active section
31959            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
31960        }
31961
31962        /**
31963        * Creates the slim scroll scrollbar for the sections and slides inside them.
31964        */
31965        function createScrollBarHandler(){
31966            $(SECTION_SEL).each(function(){
31967                var slides = $(this).find(SLIDE_SEL);
31968
31969                if(slides.length){
31970                    slides.each(function(){
31971                        createScrollBar($(this));
31972                    });
31973                }else{
31974                    createScrollBar($(this));
31975                }
31976
31977            });
31978            afterRenderActions();
31979        }
31980
31981        /*
31982        * Enables the Youtube videos API so we can control their flow if necessary.
31983        */
31984        function enableYoutubeAPI(){
31985            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
31986                addURLParam($(this), 'enablejsapi=1');
31987            });
31988        }
31989
31990        /**
31991        * Adds a new parameter and its value to the `src` of a given element
31992        */
31993        function addURLParam(element, newParam){
31994            var originalSrc = element.attr('src');
31995            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
31996        }
31997
31998        /*
31999        * Returns the prefix sign to use for a new parameter in an existen URL.
32000        *
32001        * @return {String}  ? | &
32002        */
32003        function getUrlParamSign(url){
32004            return ( !/\?/.test( url ) ) ? '?' : '&';
32005        }
32006
32007        /**
32008        * Actions and callbacks to fire afterRender
32009        */
32010        function afterRenderActions(){
32011            var section = $(SECTION_ACTIVE_SEL);
32012
32013            section.addClass(COMPLETELY);
32014
32015            if(options.scrollOverflowHandler.afterRender){
32016                options.scrollOverflowHandler.afterRender(section);
32017            }
32018            lazyLoad(section);
32019            playMedia(section);
32020            options.scrollOverflowHandler.afterLoad();
32021
32022            if(isDestinyTheStartingSection()){
32023                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32024            }
32025
32026            // Uncode change
32027            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32028            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32029        }
32030
32031        /**
32032        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32033        */
32034        function isDestinyTheStartingSection(){
32035            var anchors =  window.location.hash.replace('#', '').split('/');
32036            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32037
32038            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32039        }
32040
32041
32042        var isScrolling = false;
32043        var lastScroll = 0;
32044
32045        //when scrolling...
32046        function scrollHandler(){
32047            var currentSection;
32048
32049            if(!options.autoScrolling || options.scrollBar){
32050                var currentScroll = $window.scrollTop();
32051                var scrollDirection = getScrollDirection(currentScroll);
32052                var visibleSectionIndex = 0;
32053                var screen_mid = currentScroll + ($window.height() / 2.0);
32054                var isAtBottom = $body.height() - $window.height() === currentScroll;
32055                var sections =  document.querySelectorAll(SECTION_SEL);
32056
32057                //when using `auto-height` for a small last section it won't be centered in the viewport
32058                if(isAtBottom){
32059                    visibleSectionIndex = sections.length - 1;
32060                }
32061                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32062                else if(!currentScroll){
32063                    visibleSectionIndex = 0;
32064                }
32065
32066                //taking the section which is showing more content in the viewport
32067                else{
32068                    for (var i = 0; i < sections.length; ++i) {
32069                        var section = sections[i];
32070
32071                        // Pick the the last section which passes the middle line of the screen.
32072                        if (section.offsetTop <= screen_mid)
32073                        {
32074                            visibleSectionIndex = i;
32075                        }
32076                    }
32077                }
32078
32079                if(isCompletelyInViewPort(scrollDirection)){
32080                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
32081                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32082                    }
32083                }
32084
32085                //geting the last one, the current one on the screen
32086                currentSection = $(sections).eq(visibleSectionIndex);
32087
32088                //setting the visible section as active when manually scrolling
32089                //executing only once the first time we reach the section
32090                if(!currentSection.hasClass(ACTIVE)){
32091                    isScrolling = true;
32092                    var leavingSection = $(SECTION_ACTIVE_SEL);
32093                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
32094                    var yMovement = getYmovement(currentSection);
32095                    var anchorLink  = currentSection.data('anchor');
32096                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
32097                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
32098                    var slideIndex;
32099                    var slideAnchorLink;
32100
32101                    if(activeSlide.length){
32102                        slideAnchorLink = activeSlide.data('anchor');
32103                        slideIndex = activeSlide.index();
32104                    }
32105
32106                    if(canScroll){
32107                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32108
32109                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
32110                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
32111
32112                        stopMedia(leavingSection);
32113                        lazyLoad(currentSection);
32114                        playMedia(currentSection);
32115
32116                        activateMenuAndNav(anchorLink, sectionIndex - 1);
32117
32118                        if(options.anchors.length){
32119                            //needed to enter in hashChange event when using the menu with anchor links
32120                            lastScrolledDestiny = anchorLink;
32121                        }
32122                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
32123                    }
32124
32125                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
32126                    clearTimeout(scrollId);
32127                    scrollId = setTimeout(function(){
32128                        isScrolling = false;
32129                    }, 100);
32130                }
32131
32132                if(options.fitToSection){
32133                    //for the auto adjust of the viewport to fit a whole section
32134                    clearTimeout(scrollId2);
32135
32136                    scrollId2 = setTimeout(function(){
32137                        //checking it again in case it changed during the delay
32138                        if(options.fitToSection){
32139                            fitToSection();
32140                        }
32141                    }, options.fitToSectionDelay);
32142                }
32143            }
32144        }
32145
32146        /**
32147        * Fits the site to the nearest active section
32148        */
32149        function fitToSection(){
32150            //checking fitToSection again in case it was set to false before the timeout delay
32151            if(canScroll){
32152                //allows to scroll to an active section and
32153                //if the section is already active, we prevent firing callbacks
32154                isResizing = true;
32155
32156                scrollPage($(SECTION_ACTIVE_SEL));
32157                isResizing = false;
32158            }
32159        }
32160
32161        /**
32162        * Determines whether the active section has seen in its whole or not.
32163        */
32164        function isCompletelyInViewPort(movement){
32165            var top = $(SECTION_ACTIVE_SEL).position().top;
32166            var bottom = top + $window.height();
32167
32168            if(movement == 'up'){
32169                return bottom >= ($window.scrollTop() + $window.height());
32170            }
32171            return top <= $window.scrollTop();
32172        }
32173
32174        /**
32175        * Gets the directon of the the scrolling fired by the scroll event.
32176        */
32177        function getScrollDirection(currentScroll){
32178            var direction = currentScroll > lastScroll ? 'down' : 'up';
32179
32180            lastScroll = currentScroll;
32181
32182            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
32183            previousDestTop = currentScroll;
32184
32185            return direction;
32186        }
32187
32188        /**
32189        * Determines the way of scrolling up or down:
32190        * by 'automatically' scrolling a section or by using the default and normal scrolling.
32191        */
32192        function scrolling(type, scrollable){
32193            if (!isScrollAllowed.m[type]){
32194                return;
32195            }
32196            var check = (type === 'down') ? 'bottom' : 'top';
32197            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
32198
32199            if(scrollable.length > 0 ){
32200                //is the scrollbar at the start/end of the scroll?
32201                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
32202                    scrollSection();
32203                }else{
32204                    return true;
32205                }
32206            }else{
32207                // moved up/down
32208                scrollSection();
32209            }
32210        }
32211
32212        /*
32213        * Preventing bouncing in iOS #2285
32214        */
32215        function preventBouncing(event){
32216            var e = event.originalEvent;
32217            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
32218                //preventing the easing on iOS devices
32219                event.preventDefault();
32220            }
32221        }
32222
32223        var touchStartY = 0;
32224        var touchStartX = 0;
32225        var touchEndY = 0;
32226        var touchEndX = 0;
32227
32228        /* Detecting touch events
32229
32230        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
32231        * This way, the touchstart and the touch moves shows an small difference between them which is the
32232        * used one to determine the direction.
32233        */
32234        function touchMoveHandler(event){
32235            var e = event.originalEvent;
32236            var activeSection = $(e.target).closest(SECTION_SEL);
32237
32238            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
32239            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
32240
32241                if(options.autoScrolling){
32242                    //preventing the easing on iOS devices
32243                    event.preventDefault();
32244                }
32245
32246                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32247                var touchEvents = getEventsPage(e);
32248
32249                touchEndY = touchEvents.y;
32250                touchEndX = touchEvents.x;
32251
32252                //if movement in the X axys is greater than in the Y and the currect section has slides...
32253                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
32254
32255                    //is the movement greater than the minimum resistance to scroll?
32256                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
32257                        if (touchStartX > touchEndX) {
32258                            if(isScrollAllowed.m.right){
32259                                moveSlideRight(activeSection); //next
32260                            }
32261                        } else {
32262                            if(isScrollAllowed.m.left){
32263                                moveSlideLeft(activeSection); //prev
32264                            }
32265                        }
32266                    }
32267                }
32268
32269                //vertical scrolling (only when autoScrolling is enabled)
32270                else if(options.autoScrolling && canScroll){
32271
32272                    //is the movement greater than the minimum resistance to scroll?
32273                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
32274                        if (touchStartY > touchEndY) {
32275                            scrolling('down', scrollable);
32276                        } else if (touchEndY > touchStartY) {
32277                            scrolling('up', scrollable);
32278                        }
32279                    }
32280                }
32281            }
32282        }
32283
32284        /**
32285         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
32286         * Currently works well for iOS - Android might need some testing
32287         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
32288         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
32289         * @return {boolean} true if there is a match to options.normalScrollElements
32290         */
32291        function checkParentForNormalScrollElement (el, hop) {
32292            hop = hop || 0;
32293            var parent = $(el).parent();
32294
32295            if (hop < options.normalScrollElementTouchThreshold &&
32296                parent.is(options.normalScrollElements) ) {
32297                return true;
32298            } else if (hop == options.normalScrollElementTouchThreshold) {
32299                return false;
32300            } else {
32301                return checkParentForNormalScrollElement(parent, ++hop);
32302            }
32303        }
32304
32305        /**
32306        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
32307        * this way we make sure that is really a touch event what IE is detecting.
32308        */
32309        function isReallyTouch(e){
32310            //if is not IE   ||  IE is detecting `touch` or `pen`
32311            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
32312        }
32313
32314        /**
32315        * Handler for the touch start event.
32316        */
32317        function touchStartHandler(event){
32318            var e = event.originalEvent;
32319
32320            //stopping the auto scroll to adjust to a section
32321            if(options.fitToSection){
32322                $htmlBody.stop();
32323            }
32324
32325            if(isReallyTouch(e)){
32326                var touchEvents = getEventsPage(e);
32327                touchStartY = touchEvents.y;
32328                touchStartX = touchEvents.x;
32329            }
32330        }
32331
32332        /**
32333        * Gets the average of the last `number` elements of the given array.
32334        */
32335        function getAverage(elements, number){
32336            var sum = 0;
32337
32338            //taking `number` elements from the end to make the average, if there are not enought, 1
32339            var lastElements = elements.slice(Math.max(elements.length - number, 1));
32340
32341            for(var i = 0; i < lastElements.length; i++){
32342                sum = sum + lastElements[i];
32343            }
32344
32345            return Math.ceil(sum/number);
32346        }
32347
32348        /**
32349         * Detecting mousewheel scrolling
32350         *
32351         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
32352         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
32353         */
32354        var prevTime = new Date().getTime();
32355
32356        function MouseWheelHandler(e) {
32357            var curTime = new Date().getTime();
32358            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
32359
32360            //autoscrolling and not zooming?
32361            if(options.autoScrolling && !controlPressed && !isNormalScroll){
32362                // cross-browser wheel delta
32363                e = e || window.event;
32364                var value = e.wheelDelta || -e.deltaY || -e.detail;
32365                var delta = Math.max(-1, Math.min(1, value));
32366
32367                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
32368                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
32369
32370                //Limiting the array to 150 (lets not waste memory!)
32371                if(scrollings.length > 149){
32372                    scrollings.shift();
32373                }
32374
32375                //keeping record of the previous scrollings
32376                scrollings.push(Math.abs(value));
32377
32378                //preventing to scroll the site on mouse wheel when scrollbar is present
32379                if(options.scrollBar){
32380                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
32381                }
32382
32383                var activeSection = $(SECTION_ACTIVE_SEL);
32384                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32385
32386                //time difference between the last scroll and the current one
32387                var timeDiff = curTime-prevTime;
32388                prevTime = curTime;
32389
32390                //haven't they scrolled in a while?
32391                //(enough to be consider a different scrolling action to scroll another section)
32392                if(timeDiff > 200){
32393                    //emptying the array, we dont care about old scrollings for our averages
32394                    scrollings = [];
32395                }
32396
32397                if(canScroll){
32398                    var averageEnd = getAverage(scrollings, 10);
32399                    var averageMiddle = getAverage(scrollings, 70);
32400                    var isAccelerating = averageEnd >= averageMiddle;
32401
32402                    //to avoid double swipes...
32403                    if(isAccelerating && isScrollingVertically){
32404                        //scrolling down?
32405                        if (delta < 0) {
32406                            scrolling('down', scrollable);
32407
32408                        //scrolling up?
32409                        }else {
32410                            scrolling('up', scrollable);
32411                        }
32412                    }
32413                }
32414
32415                return false;
32416            }
32417
32418            if(options.fitToSection){
32419                //stopping the auto scroll to adjust to a section
32420                $htmlBody.stop();
32421            }
32422        }
32423
32424        /**
32425        * Slides a slider to the given direction.
32426        * Optional `section` param.
32427        */
32428        function moveSlide(direction, section){
32429            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
32430            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
32431            var numSlides = slides.find(SLIDE_SEL).length;
32432
32433            // more than one slide needed and nothing should be sliding
32434            if (!slides.length || slideMoving || numSlides < 2) {
32435                return;
32436            }
32437
32438            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
32439            var destiny = null;
32440
32441            if(direction === 'left'){
32442                destiny = currentSlide.prev(SLIDE_SEL);
32443            }else{
32444                destiny = currentSlide.next(SLIDE_SEL);
32445            }
32446
32447            //isn't there a next slide in the secuence?
32448            if(!destiny.length){
32449                //respect loopHorizontal settin
32450                if (!options.loopHorizontal) return;
32451
32452                if(direction === 'left'){
32453                    destiny = currentSlide.siblings(':last');
32454                }else{
32455                    destiny = currentSlide.siblings(':first');
32456                }
32457            }
32458
32459            slideMoving = true;
32460
32461            landscapeScroll(slides, destiny, direction);
32462        }
32463
32464        /**
32465        * Maintains the active slides in the viewport
32466        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
32467        */
32468        function keepSlidesPosition(){
32469            $(SLIDE_ACTIVE_SEL).each(function(){
32470                silentLandscapeScroll($(this), 'internal');
32471            });
32472        }
32473
32474        var previousDestTop = 0;
32475        /**
32476        * Returns the destination Y position based on the scrolling direction and
32477        * the height of the section.
32478        */
32479        function getDestinationPosition(element){
32480            var elemPosition = element.position();
32481
32482            //top of the desination will be at the top of the viewport
32483            var position = elemPosition.top;
32484            var isScrollingDown =  elemPosition.top > previousDestTop;
32485            var sectionBottom = position - windowsHeight + element.outerHeight();
32486            var bigSectionsDestination = options.bigSectionsDestination;
32487
32488            //Uncode addition
32489            var containerH = container.outerHeight();
32490            var containerPosition = container.offset();
32491
32492            //########### Commented by Uncode - START ###########
32493            //is the destination element bigger than the viewport?
32494            // if(element.outerHeight() > windowsHeight){
32495            //     //scrolling up?
32496            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
32497            //         position = sectionBottom;
32498            //     }
32499            // }
32500
32501            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
32502            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
32503            //     //The bottom of the destination will be at the bottom of the viewport
32504            //     position = sectionBottom;
32505            // }
32506            //########### Commented by Uncode - END ###########
32507
32508            //Uncode addition
32509            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
32510                position += 18;
32511            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
32512                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
32513            }
32514
32515            /*
32516            Keeping record of the last scrolled position to determine the scrolling direction.
32517            No conventional methods can be used as the scroll bar might not be present
32518            AND the section might not be active if it is auto-height and didnt reach the middle
32519            of the viewport.
32520            */
32521            previousDestTop = position;
32522            return position;
32523        }
32524
32525        /**
32526        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
32527        */
32528        function scrollPage(element, callback, isMovementUp){
32529            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
32530
32531            var dtop = getDestinationPosition(element);
32532            var slideAnchorLink;
32533            var slideIndex;
32534
32535            //local variables
32536            var v = {
32537                element: element,
32538                callback: callback,
32539                isMovementUp: isMovementUp,
32540                dtop: dtop,
32541                yMovement: getYmovement(element),
32542                anchorLink: element.data('anchor'),
32543                sectionIndex: element.index(SECTION_SEL),
32544                activeSlide: element.find(SLIDE_ACTIVE_SEL),
32545                activeSection: $(SECTION_ACTIVE_SEL),
32546                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
32547
32548                //caching the value of isResizing at the momment the function is called
32549                //because it will be checked later inside a setTimeout and the value might change
32550                localIsResizing: isResizing
32551            };
32552
32553            //quiting when destination scroll is the same as the current one
32554            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
32555
32556            if(v.activeSlide.length){
32557                slideAnchorLink = v.activeSlide.data('anchor');
32558                slideIndex = v.activeSlide.index();
32559            }
32560
32561            // If continuousVertical && we need to wrap around
32562            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
32563                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
32564                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
32565
32566                v = createInfiniteSections(v);
32567            }
32568
32569            //callback (onLeave) if the site is not just resizing and readjusting the slides
32570            if($.isFunction(options.onLeave) && !v.localIsResizing){
32571                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
32572                    return;
32573                }
32574            }
32575
32576            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
32577            if(!v.localIsResizing){
32578                stopMedia(v.activeSection);
32579            }
32580
32581            options.scrollOverflowHandler.beforeLeave();
32582            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32583            lazyLoad(element);
32584            options.scrollOverflowHandler.onLeave();
32585
32586
32587            //preventing from activating the MouseWheelHandler event
32588            //more than once if the page is scrolling
32589            canScroll = false;
32590
32591            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
32592
32593            performMovement(v);
32594
32595            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
32596            lastScrolledDestiny = v.anchorLink;
32597
32598            //avoid firing it twice (as it does also on scroll)
32599            activateMenuAndNav(v.anchorLink, v.sectionIndex);
32600        }
32601
32602        /**
32603        * Performs the vertical movement (by CSS3 or by jQuery)
32604        */
32605        function performMovement(v){
32606            // using CSS3 translate functionality
32607            if (options.css3 && options.autoScrolling && !options.scrollBar) {
32608
32609                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32610                // that's why we round it to 0.
32611                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
32612                transformContainer(translate3d, true);
32613
32614                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
32615                //scrollingSpeed to change in case of using silentMoveTo();
32616                if(options.scrollingSpeed){
32617                    clearTimeout(afterSectionLoadsId);
32618                    afterSectionLoadsId = setTimeout(function () {
32619                        afterSectionLoads(v);
32620                    }, options.scrollingSpeed);
32621                }else{
32622                    afterSectionLoads(v);
32623                }
32624            }
32625
32626            // using jQuery animate
32627            else{
32628                var scrollSettings = getScrollSettings(v);
32629
32630                $(scrollSettings.element).animate(
32631                    scrollSettings.options,
32632                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
32633                    if(options.scrollBar){
32634
32635                        /* Hack!
32636                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
32637                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
32638
32639                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
32640                        */
32641                        setTimeout(function(){
32642                            afterSectionLoads(v);
32643                        },30);
32644                    }else{
32645                        afterSectionLoads(v);
32646                    }
32647                });
32648            }
32649        }
32650
32651        /**
32652        * Gets the scrolling settings depending on the plugin autoScrolling option
32653        */
32654        function getScrollSettings(v){
32655            var scroll = {};
32656
32657            if(options.autoScrolling && !options.scrollBar){
32658                scroll.options = { 'top': -v.dtop};
32659                scroll.element = WRAPPER_SEL;
32660            }else{
32661                scroll.options = { 'scrollTop': v.dtop};
32662                scroll.element = 'html, body';
32663            }
32664
32665            return scroll;
32666        }
32667
32668        /**
32669        * Adds sections before or after the current one to create the infinite effect.
32670        */
32671        function createInfiniteSections(v){
32672            // Scrolling down
32673            if (!v.isMovementUp) {
32674                // Move all previous sections to after the active section
32675                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
32676            }
32677            else { // Scrolling up
32678                // Move all next sections to before the active section
32679                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
32680            }
32681
32682            // Maintain the displayed position (now that we changed the element order)
32683            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32684
32685            // Maintain the active slides visible in the viewport
32686            keepSlidesPosition();
32687
32688            // save for later the elements that still need to be reordered
32689            v.wrapAroundElements = v.activeSection;
32690
32691            // Recalculate animation variables
32692            v.dtop = v.element.position().top;
32693            v.yMovement = getYmovement(v.element);
32694
32695            return v;
32696        }
32697
32698        /**
32699        * Fix section order after continuousVertical changes have been animated
32700        */
32701        function continuousVerticalFixSectionOrder (v) {
32702            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
32703            // finish moving the elements around so the direct navigation will function more simply
32704            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
32705                return;
32706            }
32707
32708            if (v.isMovementUp) {
32709                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
32710            }
32711            else {
32712                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
32713            }
32714
32715            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32716
32717            // Maintain the active slides visible in the viewport
32718            keepSlidesPosition();
32719        }
32720
32721
32722        /**
32723        * Actions to do once the section is loaded.
32724        */
32725        function afterSectionLoads (v){
32726            continuousVerticalFixSectionOrder(v);
32727
32728            //callback (afterLoad) if the site is not just resizing and readjusting the slides
32729            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
32730            options.scrollOverflowHandler.afterLoad();
32731
32732            if(!v.localIsResizing){
32733                playMedia(v.element);
32734            }
32735
32736            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32737
32738            canScroll = true;
32739
32740            $.isFunction(v.callback) && v.callback.call(this);
32741        }
32742
32743        /**
32744        * Sets the value for the given attribute from the `data-` attribute with the same suffix
32745        * ie: data-srcset ==> srcset  |  data-src ==> src
32746        */
32747        function setSrc(element, attribute){
32748            element
32749                .attr(attribute, element.data(attribute))
32750                .removeAttr('data-' + attribute);
32751        }
32752
32753        /**
32754        * Lazy loads image, video and audio elements.
32755        */
32756        function lazyLoad(destiny){
32757            if (!options.lazyLoading){
32758                return;
32759            }
32760
32761            var panel = getSlideOrSection(destiny);
32762            var element;
32763
32764            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
32765                element = $(this);
32766
32767                $.each(['src', 'srcset'], function(index, type){
32768                    var attribute = element.attr('data-' + type);
32769                    if(typeof attribute !== 'undefined' && attribute){
32770                        setSrc(element, type);
32771                    }
32772                });
32773
32774                if(element.is('source')){
32775                    element.closest('video').get(0).load();
32776                }
32777            });
32778        }
32779
32780        /**
32781        * Plays video and audio elements.
32782        */
32783        function playMedia(destiny){
32784            var panel = getSlideOrSection(destiny);
32785
32786            //playing HTML5 media elements
32787            panel.find('video, audio').each(function(){
32788                var element = $(this).get(0);
32789
32790                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32791                    element.play();
32792                }
32793            });
32794
32795            //youtube videos
32796            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32797                var element = $(this).get(0);
32798
32799                if ( element.hasAttribute('data-autoplay') ){
32800                    playYoutube(element);
32801                }
32802
32803                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32804                element.onload = function() {
32805                    if ( element.hasAttribute('data-autoplay') ){
32806                        playYoutube(element);
32807                    }
32808                };
32809            });
32810        }
32811
32812        /**
32813        * Plays a youtube video
32814        */
32815        function playYoutube(element){
32816            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32817        }
32818
32819        /**
32820        * Stops video and audio elements.
32821        */
32822        function stopMedia(destiny){
32823            var panel = getSlideOrSection(destiny);
32824
32825            //stopping HTML5 media elements
32826            panel.find('video, audio').each(function(){
32827                var element = $(this).get(0);
32828
32829                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32830                    element.pause();
32831                }
32832            });
32833
32834            //youtube videos
32835            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32836                var element = $(this).get(0);
32837
32838                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32839                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32840                }
32841            });
32842        }
32843
32844        /**
32845        * Gets the active slide (or section) for the given section
32846        */
32847        function getSlideOrSection(destiny){
32848            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32849            if( slide.length ) {
32850                destiny = $(slide);
32851            }
32852
32853            return destiny;
32854        }
32855
32856        /**
32857        * Scrolls to the anchor in the URL when loading the site
32858        */
32859        function scrollToAnchor(){
32860            //getting the anchor link in the URL and deleting the `#`
32861            var value =  window.location.hash.replace('#', '').split('/');
32862            var sectionAnchor = decodeURIComponent(value[0]);
32863            var slideAnchor = decodeURIComponent(value[1]);
32864
32865            if(sectionAnchor){  //if theres any #
32866                if(options.animateAnchor){
32867                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32868                }else{
32869                    silentMoveTo(sectionAnchor, slideAnchor);
32870                }
32871            }
32872        }
32873
32874        /**
32875        * Detecting any change on the URL to scroll to the given anchor link
32876        * (a way to detect back history button as we play with the hashes on the URL)
32877        */
32878        function hashChangeHandler(){
32879            if(!isScrolling && !options.lockAnchors){
32880                var value =  window.location.hash.replace('#', '').split('/');
32881                var sectionAnchor = decodeURIComponent(value[0]);
32882                var slideAnchor = decodeURIComponent(value[1]);
32883
32884                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32885                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32886                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32887
32888
32889                if(sectionAnchor.length){
32890                    /*in order to call scrollpage() only once for each destination at a time
32891                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32892                    event is fired on every scroll too.*/
32893                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32894                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32895                    }
32896                }
32897            }
32898        }
32899
32900        //Sliding with arrow keys, both, vertical and horizontal
32901        function keydownHandler(e) {
32902
32903            clearTimeout(keydownId);
32904
32905            var activeElement = $(':focus');
32906
32907            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32908                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32909                options.keyboardScrolling && options.autoScrolling){
32910                var keyCode = e.which;
32911
32912                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32913                var keyControls = [40, 38, 32, 33, 34];
32914                if($.inArray(keyCode, keyControls) > -1){
32915                    e.preventDefault();
32916                }
32917
32918                controlPressed = e.ctrlKey;
32919
32920                keydownId = setTimeout(function(){
32921                    onkeydown(e);
32922                },150);
32923            }
32924        }
32925
32926        function tooltipTextHandler(){
32927            $(this).prev().trigger('click');
32928        }
32929
32930        //to prevent scrolling while zooming
32931        function keyUpHandler(e){
32932            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32933                controlPressed = e.ctrlKey;
32934            }
32935        }
32936
32937        //binding the mousemove when the mouse's middle button is released
32938        function mouseDownHandler(e){
32939            //middle button
32940            if (e.which == 2){
32941                oldPageY = e.pageY;
32942                container.on('mousemove', mouseMoveHandler);
32943            }
32944        }
32945
32946        //unbinding the mousemove when the mouse's middle button is released
32947        function mouseUpHandler(e){
32948            //middle button
32949            if (e.which == 2){
32950                container.off('mousemove');
32951            }
32952        }
32953
32954        //Scrolling horizontally when clicking on the slider controls.
32955        function slideArrowHandler(){
32956            var section = $(this).closest(SECTION_SEL);
32957
32958            if ($(this).hasClass(SLIDES_PREV)) {
32959                if(isScrollAllowed.m.left){
32960                    moveSlideLeft(section);
32961                }
32962            } else {
32963                if(isScrollAllowed.m.right){
32964                    moveSlideRight(section);
32965                }
32966            }
32967        }
32968
32969        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32970        function blurHandler(){
32971            isWindowFocused = false;
32972            controlPressed = false;
32973        }
32974
32975        //Scrolls to the section when clicking the navigation bullet
32976        function sectionBulletHandler(e){
32977            e.preventDefault();
32978            var index = $(this).parent().index();
32979            scrollPage($(SECTION_SEL).eq(index));
32980        }
32981
32982        //Scrolls the slider to the given slide destination for the given section
32983        function slideBulletHandler(e){
32984            e.preventDefault();
32985            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
32986            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
32987
32988            landscapeScroll(slides, destiny);
32989        }
32990
32991        /**
32992        * Keydown event
32993        */
32994        function onkeydown(e){
32995            var shiftPressed = e.shiftKey;
32996
32997            //do nothing if we can not scroll or we are not using horizotnal key arrows.
32998            if(!canScroll && [37,39].indexOf(e.which) < 0){
32999                return;
33000            }
33001
33002            switch (e.which) {
33003                //up
33004                case 38:
33005                case 33:
33006                    if(isScrollAllowed.k.up){
33007                        moveSectionUp();
33008                    }
33009                    break;
33010
33011                //down
33012                case 32: //spacebar
33013                    if(shiftPressed && isScrollAllowed.k.up){
33014                        moveSectionUp();
33015                        break;
33016                    }
33017                /* falls through */
33018                case 40:
33019                case 34:
33020                    if(isScrollAllowed.k.down){
33021                        moveSectionDown();
33022                    }
33023                    break;
33024
33025                //Home
33026                case 36:
33027                    if(isScrollAllowed.k.up){
33028                        moveTo(1);
33029                    }
33030                    break;
33031
33032                //End
33033                case 35:
33034                     if(isScrollAllowed.k.down){
33035                        moveTo( $(SECTION_SEL).length );
33036                    }
33037                    break;
33038
33039                //left
33040                case 37:
33041                    if(isScrollAllowed.k.left){
33042                        moveSlideLeft();
33043                    }
33044                    break;
33045
33046                //right
33047                case 39:
33048                    if(isScrollAllowed.k.right){
33049                        moveSlideRight();
33050                    }
33051                    break;
33052
33053                default:
33054                    return; // exit this handler for other keys
33055            }
33056        }
33057
33058        /**
33059        * Detecting the direction of the mouse movement.
33060        * Used only for the middle button of the mouse.
33061        */
33062        var oldPageY = 0;
33063        function mouseMoveHandler(e){
33064            if(canScroll){
33065                // moving up
33066                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33067                    moveSectionUp();
33068                }
33069
33070                // moving down
33071                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
33072                    moveSectionDown();
33073                }
33074            }
33075            oldPageY = e.pageY;
33076        }
33077
33078        /**
33079        * Scrolls horizontal sliders.
33080        */
33081        function landscapeScroll(slides, destiny, direction){
33082            var section = slides.closest(SECTION_SEL);
33083            var v = {
33084                slides: slides,
33085                destiny: destiny,
33086                direction: direction,
33087                destinyPos: destiny.position(),
33088                slideIndex: destiny.index(),
33089                section: section,
33090                sectionIndex: section.index(SECTION_SEL),
33091                anchorLink: section.data('anchor'),
33092                slidesNav: section.find(SLIDES_NAV_SEL),
33093                slideAnchor:  getAnchor(destiny),
33094                prevSlide: section.find(SLIDE_ACTIVE_SEL),
33095                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
33096
33097                //caching the value of isResizing at the momment the function is called
33098                //because it will be checked later inside a setTimeout and the value might change
33099                localIsResizing: isResizing
33100            };
33101            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
33102            v.direction = v.direction ? v.direction : v.xMovement;
33103
33104            //important!! Only do it when not resizing
33105            if(!v.localIsResizing){
33106                //preventing from scrolling to the next/prev section when using scrollHorizontally
33107                canScroll = false;
33108            }
33109
33110            if(options.onSlideLeave){
33111
33112                //if the site is not just resizing and readjusting the slides
33113                if(!v.localIsResizing && v.xMovement!=='none'){
33114                    if($.isFunction( options.onSlideLeave )){
33115                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
33116                            slideMoving = false;
33117                            return;
33118                        }
33119                    }
33120                }
33121            }
33122
33123            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33124
33125            if(!v.localIsResizing){
33126                stopMedia(v.prevSlide);
33127                lazyLoad(destiny);
33128            }
33129
33130            if(!options.loopHorizontal && options.controlArrows){
33131                //hidding it for the fist slide, showing for the rest
33132                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
33133
33134                //hidding it for the last slide, showing for the rest
33135                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
33136            }
33137
33138            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
33139            if(section.hasClass(ACTIVE) && !v.localIsResizing){
33140                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
33141            }
33142
33143            performHorizontalMove(slides, v, true);
33144        }
33145
33146
33147        function afterSlideLoads(v){
33148            activeSlidesNavigation(v.slidesNav, v.slideIndex);
33149
33150            //if the site is not just resizing and readjusting the slides
33151            if(!v.localIsResizing){
33152                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
33153
33154                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
33155                //and to prevent double scroll right after a windows resize
33156                canScroll = true;
33157
33158                playMedia(v.destiny);
33159            }
33160
33161            //letting them slide again
33162            slideMoving = false;
33163        }
33164
33165        /**
33166        * Performs the horizontal movement. (CSS3 or jQuery)
33167        *
33168        * @param fireCallback {Bool} - determines whether or not to fire the callback
33169        */
33170        function performHorizontalMove(slides, v, fireCallback){
33171            var destinyPos = v.destinyPos;
33172
33173            if(options.css3){
33174                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
33175
33176                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
33177
33178                afterSlideLoadsId = setTimeout(function(){
33179                    fireCallback && afterSlideLoads(v);
33180                }, options.scrollingSpeed, options.easing);
33181            }else{
33182                slides.animate({
33183                    scrollLeft : Math.round(destinyPos.left)
33184                }, options.scrollingSpeed, options.easing, function() {
33185
33186                    fireCallback && afterSlideLoads(v);
33187                });
33188            }
33189        }
33190
33191        /**
33192        * Sets the state for the horizontal bullet navigations.
33193        */
33194        function activeSlidesNavigation(slidesNav, slideIndex){
33195            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
33196            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
33197        }
33198
33199        var previousHeight = windowsHeight;
33200
33201        //when resizing the site, we adjust the heights of the sections, slimScroll...
33202        function resizeHandler(){
33203            //checking if it needs to get responsive
33204            responsive();
33205
33206            // rebuild immediately on touch devices
33207            if (isTouchDevice) {
33208                var activeElement = $(document.activeElement);
33209
33210                //if the keyboard is NOT visible
33211                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
33212                    var currentHeight = $window.height();
33213
33214                    //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)
33215                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
33216                        reBuild(true);
33217                        previousHeight = currentHeight;
33218                    }
33219                }
33220            }else{
33221                //in order to call the functions only when the resize is finished
33222                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
33223                clearTimeout(resizeId);
33224
33225                resizeId = setTimeout(function(){
33226                    reBuild(true);
33227                }, 350);
33228            }
33229        }
33230
33231        /**
33232        * Checks if the site needs to get responsive and disables autoScrolling if so.
33233        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
33234        */
33235        function responsive(){
33236            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
33237            var heightLimit = options.responsiveHeight;
33238
33239            //only calculating what we need. Remember its called on the resize event.
33240            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
33241            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
33242
33243            if(widthLimit && heightLimit){
33244                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
33245            }
33246            else if(widthLimit){
33247                setResponsive(isBreakingPointWidth);
33248            }
33249            else if(heightLimit){
33250                setResponsive(isBreakingPointHeight);
33251            }
33252        }
33253
33254        /**
33255        * Adds transition animations for the given element
33256        */
33257        function addAnimation(container, element){
33258            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
33259
33260            container.removeClass(NO_TRANSITION);
33261            return container.css({
33262                '-webkit-transition': transition,
33263                'transition': transition
33264            });
33265        }
33266
33267        /**
33268        * Remove transition animations for the given element
33269        */
33270        function removeAnimation(element){
33271            return element.addClass(NO_TRANSITION);
33272        }
33273
33274        /**
33275        * Activating the vertical navigation bullets according to the given slide name.
33276        */
33277        function activateNavDots(name, sectionIndex){
33278            if(options.navigation){
33279                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
33280                if(name){
33281                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
33282                }else{
33283                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
33284                }
33285            }
33286        }
33287
33288        /**
33289        * Activating the website main menu elements according to the given slide name.
33290        */
33291        function activateMenuElement(name){
33292            if(options.menu){
33293                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
33294                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
33295            }
33296        }
33297
33298        /**
33299        * Sets to active the current menu and vertical nav items.
33300        */
33301        function activateMenuAndNav(anchor, index){
33302            activateMenuElement(anchor);
33303            activateNavDots(anchor, index);
33304        }
33305
33306        /**
33307        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
33308        * from the current section.
33309        */
33310        function getYmovement(destiny){
33311            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
33312            var toIndex = destiny.index(SECTION_SEL);
33313            if( fromIndex == toIndex){
33314                return 'none';
33315            }
33316            if(fromIndex > toIndex){
33317                return 'up';
33318            }
33319            return 'down';
33320        }
33321
33322        /**
33323        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
33324        * from the current slide.
33325        */
33326        function getXmovement(fromIndex, toIndex){
33327            if( fromIndex == toIndex){
33328                return 'none';
33329            }
33330            if(fromIndex > toIndex){
33331                return 'left';
33332            }
33333            return 'right';
33334        }
33335
33336        /**
33337        * Checks if the element needs scrollbar and if the user wants to apply it.
33338        * If so it creates it.
33339        *
33340        * @param {Object} element   jQuery object of the section or slide
33341        */
33342        function createScrollBar(element){
33343            //User doesn't want scrollbar here? Sayonara baby!
33344            if(element.hasClass('fp-noscroll')) return;
33345
33346            //needed to make `scrollHeight` work under Opera 12
33347            element.css('overflow', 'hidden');
33348
33349            var scrollOverflowHandler = options.scrollOverflowHandler;
33350            var wrap = scrollOverflowHandler.wrapContent();
33351            //in case element is a slide
33352            var section = element.closest(SECTION_SEL);
33353            var scrollable = scrollOverflowHandler.scrollable(element);
33354            var contentHeight;
33355
33356            //if there was scroll, the contentHeight will be the one in the scrollable section
33357            if(scrollable.length){
33358                contentHeight = scrollOverflowHandler.scrollHeight(element);
33359            }else{
33360                contentHeight = element.get(0).scrollHeight;
33361                if(options.verticalCentered){
33362                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
33363                }
33364            }
33365
33366            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
33367
33368            //needs scroll?
33369            if ( contentHeight > scrollHeight) {
33370                //did we already have an scrollbar ? Updating it
33371                if(scrollable.length){
33372                    scrollOverflowHandler.update(element, scrollHeight);
33373                }
33374                //creating the scrolling
33375                else{
33376                    if(options.verticalCentered){
33377                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
33378                    }else{
33379                        element.wrapInner(wrap);
33380                    }
33381                    scrollOverflowHandler.create(element, scrollHeight);
33382                }
33383            }
33384            //removing the scrolling when it is not necessary anymore
33385            else{
33386                scrollOverflowHandler.remove(element);
33387            }
33388
33389            //undo
33390            element.css('overflow', '');
33391        }
33392
33393        function addTableClass(element){
33394            //In case we are styling for the 2nd time as in with reponsiveSlides
33395            if(!element.hasClass(TABLE)){
33396                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
33397            }
33398        }
33399
33400        function getTableHeight(element){
33401            var sectionHeight = windowsHeight;
33402
33403            if(options.paddingTop || options.paddingBottom){
33404                var section = element;
33405                if(!section.hasClass(SECTION)){
33406                    section = element.closest(SECTION_SEL);
33407                }
33408
33409                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
33410                sectionHeight = (windowsHeight - paddings);
33411            }
33412
33413            return sectionHeight;
33414        }
33415
33416        /**
33417        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
33418        */
33419        function transformContainer(translate3d, animated){
33420            if(animated){
33421                addAnimation(container);
33422            }else{
33423                removeAnimation(container);
33424            }
33425
33426            container.css(getTransforms(translate3d));
33427
33428            //syncronously removing the class after the animation has been applied.
33429            setTimeout(function(){
33430                container.removeClass(NO_TRANSITION);
33431            },10);
33432        }
33433
33434        /**
33435        * Gets a section by its anchor / index
33436        */
33437        function getSectionByAnchor(sectionAnchor){
33438            if(!sectionAnchor) return [];
33439
33440            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
33441            if(!section.length){
33442                section = $(SECTION_SEL).eq( sectionAnchor -1);
33443            }
33444
33445            return section;
33446        }
33447
33448        /**
33449        * Gets a slide inside a given section by its anchor / index
33450        */
33451        function getSlideByAnchor(slideAnchor, section){
33452            var slides = section.find(SLIDES_WRAPPER_SEL);
33453            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
33454
33455            if(!slide.length){
33456                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
33457            }
33458
33459            return slide;
33460        }
33461
33462        /**
33463        * Scrolls to the given section and slide anchors
33464        */
33465        function scrollPageAndSlide(destiny, slide){
33466            var section = getSectionByAnchor(destiny);
33467
33468            //do nothing if there's no section with the given anchor name
33469            if(!section.length) return;
33470
33471            //default slide
33472            if (typeof slide === 'undefined') {
33473                slide = 0;
33474            }
33475
33476            //we need to scroll to the section and then to the slide
33477            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
33478                scrollPage(section, function(){
33479                    scrollSlider(section, slide);
33480                });
33481            }
33482            //if we were already in the section
33483            else{
33484                scrollSlider(section, slide);
33485            }
33486        }
33487
33488        /**
33489        * Scrolls the slider to the given slide destination for the given section
33490        */
33491        function scrollSlider(section, slideAnchor){
33492            if(typeof slideAnchor !== 'undefined'){
33493                var slides = section.find(SLIDES_WRAPPER_SEL);
33494                var destiny =  getSlideByAnchor(slideAnchor, section);
33495
33496                if(destiny.length){
33497                    landscapeScroll(slides, destiny);
33498                }
33499            }
33500        }
33501
33502        /**
33503        * Creates a landscape navigation bar with dots for horizontal sliders.
33504        */
33505        function addSlidesNavigation(section, numSlides){
33506            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
33507            var nav = section.find(SLIDES_NAV_SEL);
33508
33509            //top or bottom
33510            nav.addClass(options.slidesNavPosition);
33511
33512            for(var i=0; i< numSlides; i++){
33513                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
33514            }
33515
33516            //centering it
33517            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
33518
33519            nav.find('li').first().find('a').addClass(ACTIVE);
33520        }
33521
33522
33523        /**
33524        * Sets the state of the website depending on the active section/slide.
33525        * It changes the URL hash when needed and updates the body class.
33526        */
33527        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
33528            var sectionHash = '';
33529
33530            if(options.anchors.length && !options.lockAnchors){
33531
33532                //isn't it the first slide?
33533                if(slideIndex){
33534                    if(typeof anchorLink !== 'undefined'){
33535                        sectionHash = anchorLink;
33536                    }
33537
33538                    //slide without anchor link? We take the index instead.
33539                    if(typeof slideAnchor === 'undefined'){
33540                        slideAnchor = slideIndex;
33541                    }
33542
33543                    lastScrolledSlide = slideAnchor;
33544                    setUrlHash(sectionHash + '/' + slideAnchor);
33545
33546                //first slide won't have slide anchor, just the section one
33547                }else if(typeof slideIndex !== 'undefined'){
33548                    lastScrolledSlide = slideAnchor;
33549                    setUrlHash(anchorLink);
33550                }
33551
33552                //section without slides
33553                else{
33554                    setUrlHash(anchorLink);
33555                }
33556            }
33557
33558            setBodyClass();
33559        }
33560
33561        /**
33562        * Sets the URL hash.
33563        */
33564        function setUrlHash(url){
33565            //Uncode addition
33566            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
33567                return false;
33568
33569            if(options.recordHistory){
33570                location.hash = url;
33571            }else{
33572                //Uncode addition
33573                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
33574                // if(isTouchDevice || isTouch){
33575                //     window.history.replaceState(undefined, undefined, '#' + url);
33576                // }else{
33577                //     var baseUrl = window.location.href.split('#')[0];
33578                //     window.location.replace( baseUrl + '#' + url );
33579                // }
33580                return false;
33581            }
33582        }
33583
33584        /**
33585        * Gets the anchor for the given slide / section. Its index will be used if there's none.
33586        */
33587        function getAnchor(element){
33588            var anchor = element.data('anchor');
33589            var index = element.index();
33590
33591            //Slide without anchor link? We take the index instead.
33592            if(typeof anchor === 'undefined'){
33593                anchor = index;
33594            }
33595
33596            return anchor;
33597        }
33598
33599        /**
33600        * Sets a class for the body of the page depending on the active section / slide
33601        */
33602        function setBodyClass(){
33603            var section = $(SECTION_ACTIVE_SEL);
33604            var slide = section.find(SLIDE_ACTIVE_SEL);
33605
33606            var sectionAnchor = getAnchor(section);
33607            var slideAnchor = getAnchor(slide);
33608
33609            var text = String(sectionAnchor);
33610
33611            if(slide.length){
33612                text = text + '-' + slideAnchor;
33613            }
33614
33615            //changing slash for dash to make it a valid CSS style
33616            text = text.replace('/', '-').replace('#','');
33617
33618            //removing previous anchor classes
33619            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
33620            $body[0].className = $body[0].className.replace(classRe, '');
33621
33622            //adding the current anchor
33623            $body.addClass(VIEWING_PREFIX + '-' + text);
33624        }
33625
33626        /**
33627        * Checks for translate3d support
33628        * @return boolean
33629        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
33630        */
33631        function support3d() {
33632            var el = document.createElement('p'),
33633                has3d,
33634                transforms = {
33635                    'webkitTransform':'-webkit-transform',
33636                    'OTransform':'-o-transform',
33637                    'msTransform':'-ms-transform',
33638                    'MozTransform':'-moz-transform',
33639                    'transform':'transform'
33640                };
33641
33642            // Add it to the body to get the computed style.
33643            document.body.insertBefore(el, null);
33644
33645            for (var t in transforms) {
33646                if (el.style[t] !== undefined) {
33647                    el.style[t] = 'translate3d(1px,1px,1px)';
33648                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
33649                }
33650            }
33651
33652            document.body.removeChild(el);
33653
33654            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
33655        }
33656
33657        /**
33658        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
33659        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
33660        */
33661        function removeMouseWheelHandler(){
33662            if (document.addEventListener) {
33663                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
33664                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
33665                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
33666            } else {
33667                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
33668            }
33669        }
33670
33671        /**
33672        * Adds the auto scrolling action for the mouse wheel and trackpad.
33673        * After this function is called, the mousewheel and trackpad movements will scroll through sections
33674        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
33675        */
33676        function addMouseWheelHandler(){
33677            var prefix = '';
33678            var _addEventListener;
33679
33680            if (window.addEventListener){
33681                _addEventListener = "addEventListener";
33682            }else{
33683                _addEventListener = "attachEvent";
33684                prefix = 'on';
33685            }
33686
33687             // detect available wheel event
33688            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
33689                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
33690                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
33691            var passiveEvent = g_supportsPassive ? {passive: false }
33691: false;
33692
33693
33694            if(support == 'DOMMouseScroll'){
33695                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
33696            }
33697
33698            //handle MozMousePixelScroll in older Firefox
33699            else{
33700                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
33701            }
33702        }
33703
33704        /**
33705        * Binding the mousemove when the mouse's middle button is pressed
33706        */
33707        function addMiddleWheelHandler(){
33708            container
33709                .on('mousedown', mouseDownHandler)
33710                .on('mouseup', mouseUpHandler);
33711        }
33712
33713        /**
33714        * Unbinding the mousemove when the mouse's middle button is released
33715        */
33716        function removeMiddleWheelHandler(){
33717            container
33718                .off('mousedown', mouseDownHandler)
33719                .off('mouseup', mouseUpHandler);
33720        }
33721
33722        /**
33723        * Adds the possibility to auto scroll through sections on touch devices.
33724        */
33725        function addTouchHandler(){
33726            if(isTouchDevice || isTouch){
33727                if(options.autoScrolling){
33728                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
33729                }
33730
33731                $(WRAPPER_SEL)
33732                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
33733                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
33734            }
33735        }
33736
33737        /**
33738        * Removes the auto scrolling for touch devices.
33739        */
33740        function removeTouchHandler(){
33741            if(isTouchDevice || isTouch){
33742                $(WRAPPER_SEL)
33743                    .off(events.touchstart)
33744                    .off(events.touchmove);
33745            }
33746        }
33747
33748        /*
33749        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
33750        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
33751        */
33752        function getMSPointer(){
33753            var pointer;
33754
33755            //IE >= 11 & rest of browsers
33756            if(window.PointerEvent){
33757                pointer = { down: 'pointerdown', move: 'pointermove'};
33758            }
33759
33760            //IE < 11
33761            else{
33762                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
33763            }
33764
33765            return pointer;
33766        }
33767
33768        /**
33769        * Gets the pageX and pageY properties depending on the browser.
33770        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
33771        */
33772        function getEventsPage(e){
33773            var events = [];
33774
33775            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
33776            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33777
33778            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33779            if(isTouch && isReallyTouch(e) && options.scrollBar){
33780                events.y = e.touches[0].pageY;
33781                events.x = e.touches[0].pageX;
33782            }
33783
33784            return events;
33785        }
33786
33787        /**
33788        * Slides silently (with no animation) the active slider to the given slide.
33789        * @param noCallback {bool} true or defined -> no callbacks
33790        */
33791        function silentLandscapeScroll(activeSlide, noCallbacks){
33792            setScrollingSpeed (0, 'internal');
33793
33794            if(typeof noCallbacks !== 'undefined'){
33795                //preventing firing callbacks afterSlideLoad etc.
33796                isResizing = true;
33797            }
33798
33799            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33800
33801            if(typeof noCallbacks !== 'undefined'){
33802                isResizing = false;
33803            }
33804
33805            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33806        }
33807
33808        /**
33809        * Scrolls silently (with no animation) the page to the given Y position.
33810        */
33811        function silentScroll(top){
33812            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33813            // that's why we round it to 0.
33814            var roundedTop = Math.round(top);
33815
33816            if (options.css3 && options.autoScrolling && !options.scrollBar){
33817                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33818                transformContainer(translate3d, false);
33819            }
33820            else if(options.autoScrolling && !options.scrollBar){
33821                container.css('top', -roundedTop);
33822            }
33823            else{
33824                $htmlBody.scrollTop(roundedTop);
33825            }
33826        }
33827
33828        /**
33829        * Returns the cross-browser transform string.
33830        */
33831        function getTransforms(translate3d){
33832            return {
33833                '-webkit-transform': translate3d,
33834                '-moz-transform': translate3d,
33835                '-ms-transform':translate3d,
33836                'transform': translate3d
33837            };
33838        }
33839
33840        /**
33841        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33842        * @type  m (mouse) or k (keyboard)
33843        */
33844        function setIsScrollAllowed(value, direction, type){
33845            switch (direction){
33846                case 'up': isScrollAllowed[type].up = value; break;
33847                case 'down': isScrollAllowed[type].down = value; break;
33848                case 'left': isScrollAllowed[type].left = value; break;
33849                case 'right': isScrollAllowed[type].right = value; break;
33850                case 'all':
33851                    if(type == 'm'){
33852                        setAllowScrolling(value);
33853                    }else{
33854                        setKeyboardScrolling(value);
33855                    }
33856            }
33857        }
33858
33859        /*
33860        * Destroys fullpage.js plugin events and optinally its html markup and styles
33861        */
33862        function destroy(all){
33863            setAutoScrolling(false, 'internal');
33864            setAllowScrolling(false);
33865            setKeyboardScrolling(false);
33866            container.addClass(DESTROYED);
33867
33868            clearTimeout(afterSlideLoadsId);
33869            clearTimeout(afterSectionLoadsId);
33870            clearTimeout(resizeId);
33871            clearTimeout(scrollId);
33872            clearTimeout(scrollId2);
33873
33874            $window
33875                .off('scroll', scrollHandler)
33876                .off('hashchange', hashChangeHandler)
33877                .off('resize', resizeHandler);
33878
33879            $document
33880                .off('click touchstart', SECTION_NAV_SEL + ' a')
33881                .off('mouseenter', SECTION_NAV_SEL + ' li')
33882                .off('mouseleave', SECTION_NAV_SEL + ' li')
33883                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33884                .off('mouseover', options.normalScrollElements)
33885                .off('mouseout', options.normalScrollElements);
33886
33887            $(SECTION_SEL)
33888                .off('click touchstart', SLIDES_ARROW_SEL);
33889
33890            clearTimeout(afterSlideLoadsId);
33891            clearTimeout(afterSectionLoadsId);
33892
33893            //lets make a mess!
33894            if(all){
33895                destroyStructure();
33896            }
33897        }
33898
33899        /*
33900        * Removes inline styles added by fullpage.js
33901        */
33902        function destroyStructure(){
33903            //reseting the `top` or `translate` properties to 0
33904            silentScroll(0);
33905
33906            //loading all the lazy load content
33907            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33908                setSrc($(this), 'src');
33909            });
33910
33911            container.find('img[data-srcset]').each(function(){
33912                setSrc($(this), 'srcset');
33913            });
33914
33915            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33916
33917            //removing inline styles
33918            $(SECTION_SEL).css( {
33919                'height': '',
33920                'background-color' : '',
33921                'padding': ''
33922            });
33923
33924            $(SLIDE_SEL).css( {
33925                'width': ''
33926            });
33927
33928            container.css({
33929                'height': '',
33930                'position': '',
33931                '-ms-touch-action': '',
33932                'touch-action': ''
33933            });
33934
33935            $htmlBody.css({
33936                'overflow': '',
33937                'height': ''
33938            });
33939
33940            // remove .fp-enabled class
33941            $('html').removeClass(ENABLED);
33942
33943            // remove .fp-responsive class
33944            $body.removeClass(RESPONSIVE);
33945
33946            // remove all of the .fp-viewing- classes
33947            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33948                if (className.indexOf(VIEWING_PREFIX) === 0) {
33949                    $body.removeClass(className);
33950                }
33951            });
33952
33953            //removing added classes
33954            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
33955                options.scrollOverflowHandler.remove($(this));
33956                $(this).removeClass(TABLE + ' ' + ACTIVE);
33957            });
33958
33959            removeAnimation(container);
33960
33961            //Unwrapping content
33962            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
33963                //unwrap not being use in case there's no child element inside and its just text
33964                $(this).replaceWith(this.childNodes);
33965            });
33966
33967            //removing the applied transition from the fullpage wrapper
33968            container.css({
33969                '-webkit-transition': 'none',
33970                'transition': 'none'
33971            });
33972
33973            //scrolling the page to the top with no animation
33974            $htmlBody.scrollTop(0);
33975
33976            //removing selectors
33977            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
33978            $.each(usedSelectors, function(index, value){
33979                $('.' + value).removeClass(value);
33980            });
33981        }
33982
33983        /*
33984        * Sets the state for a variable with multiple states (original, and temporal)
33985        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
33986        * This function is used to keep track of both states, the original and the temporal one.
33987        * If type is not 'internal', then we assume the user is globally changing the variable.
33988        */
33989        function setVariableState(variable, value, type){
33990            options[variable] = value;
33991            if(type !== 'internal'){
33992                originals[variable] = value;
33993            }
33994        }
33995
33996        /**
33997        * Displays warnings
33998        */
33999        function displayWarnings(){
34000            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
34001            //UNCODE.addition
34002            // if($('html').hasClass(ENABLED)){
34003            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
34004            //     return;
34005            // }
34006
34007            // Disable mutually exclusive settings
34008            //UNCODE.addition
34009            // if (options.continuousVertical &&
34010            //     (options.loopTop || options.loopBottom)) {
34011            //     options.continuousVertical = false;
34012            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34013            // }
34014
34015            // if(options.scrollBar && options.scrollOverflow){
34016            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34017            // }
34018
34019            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34020            //     options.continuousVertical = false;
34021            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34022            // }
34023
34024            //using extensions? Wrong file!
34025            $.each(extensions, function(index, extension){
34026                //is the option set to true?
34027                if(options[extension]){
34028                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34029                }
34030            });
34031
34032            //anchors can not have the same value as any element ID or NAME
34033            $.each(options.anchors, function(index, name){
34034
34035                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34036                var nameAttr = $document.find('[name]').filter(function() {
34037                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34038                });
34039
34040                var idAttr = $document.find('[id]').filter(function() {
34041                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34042                });
34043
34044                if(idAttr.length || nameAttr.length ){
34045                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34046                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34047                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34048                }
34049            });
34050        }
34051
34052        /**
34053        * Shows a message in the console of the given type.
34054        */
34055        function showError(type, text){
34056            console && console[type] && console[type]('fullPage: ' + text);
34057        }
34058
34059    }; //end of $.fn.fullpage
34060
34061    if(typeof IScroll !== 'undefined'){
34062        /*
34063        * Turns iScroll `mousewheel` option off dynamically
34064        * https://github.com/cubiq/iscroll/issues/1036
34065        */
34066        IScroll.prototype.wheelOn = function () {
34067            this.wrapper.addEventListener('wheel', this);
34068            this.wrapper.addEventListener('mousewheel', this);
34069            this.wrapper.addEventListener('DOMMouseScroll', this);
34070        };
34071
34072        /*
34073        * Turns iScroll `mousewheel` option on dynamically
34074        * https://github.com/cubiq/iscroll/issues/1036
34075        */
34076        IScroll.prototype.wheelOff = function () {
34077            this.wrapper.removeEventListener('wheel', this);
34078            this.wrapper.removeEventListener('mousewheel', this);
34079            this.wrapper.removeEventListener('DOMMouseScroll', this);
34080        };
34081    }
34082
34083    /**
34084     * An object to handle overflow scrolling.
34085     * This uses jquery.slimScroll to accomplish overflow scrolling.
34086     * It is possible to pass in an alternate scrollOverflowHandler
34087     * to the fullpage.js option that implements the same functions
34088     * as this handler.
34089     *
34090     * @type {Object}
34091     */
34092    var iscrollHandler = {
34093        refreshId: null,
34094        iScrollInstances: [],
34095
34096        // Enables or disables the mouse wheel for the active section or all slides in it
34097        toggleWheel: function(value){
34098            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
34099            scrollable.each(function(){
34100                var iScrollInstance = $(this).data('iscrollInstance');
34101                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
34102                    if(value){
34103                        iScrollInstance.wheelOn();
34104                    }
34105                    else{
34106                        iScrollInstance.wheelOff();
34107                    }
34108                }
34109            });
34110        },
34111
34112        /**
34113        * Turns off iScroll for the destination section.
34114        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
34115        * scroll the destination section/slide before the sections animations ends.
34116        */
34117        onLeave: function(){
34118            iscrollHandler.toggleWheel(false);
34119        },
34120
34121        // Turns off iScroll for the leaving section
34122        beforeLeave: function(){
34123            iscrollHandler.onLeave()
34124        },
34125
34126        // Turns on iScroll on section load
34127        afterLoad: function(){
34128            iscrollHandler.toggleWheel(true);
34129        },
34130
34131        /**
34132         * Called when overflow scrolling is needed for a section.
34133         *
34134         * @param  {Object} element      jQuery object containing current section
34135         * @param  {Number} scrollHeight Current window height in pixels
34136         */
34137        create: function(element, scrollHeight) {
34138            var scrollable = element.find(SCROLLABLE_SEL);
34139
34140            scrollable.height(scrollHeight);
34141            scrollable.each(function() {
34142                var $this = $(this);
34143                var iScrollInstance = $this.data('iscrollInstance');
34144                if (iScrollInstance) {
34145                    $.each(iscrollHandler.iScrollInstances, function(){
34146                        $(this).destroy();
34147                    });
34148                }
34149
34150                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
34151                iscrollHandler.iScrollInstances.push(iScrollInstance);
34152
34153                //off by default until the section gets active
34154                iScrollInstance.wheelOff();
34155
34156                $this.data('iscrollInstance', iScrollInstance);
34157            });
34158        },
34159
34160        /**
34161         * Return a boolean depending on whether the scrollable element is a
34162         * the end or at the start of the scrolling depending on the given type.
34163         *
34164         * @param  {String}  type       Either 'top' or 'bottom'
34165         * @param  {Object}  scrollable jQuery object for the scrollable element
34166         * @return {Boolean}
34167         */
34168        isScrolled: function(type, scrollable) {
34169            var scroller = scrollable.data('iscrollInstance');
34170
34171            //no scroller?
34172            if (!scroller) {
34173                return true;
34174            }
34175
34176            //Uncode addition
34177            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
34178            //End Uncode addition
34179
34180            if (type === 'top') {
34181                return scroller.y >= 0 && !scrollable.scrollTop();
34182            } else if (type === 'bottom') {
34183                //Uncode change
34184                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34185                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34186                //End Uncode change
34187            }
34188        },
34189
34190        /**
34191         * Returns the scrollable element for the given section.
34192         * If there are landscape slides, will only return a scrollable element
34193         * if it is in the active slide.
34194         *
34195         * @param  {Object}  activeSection jQuery object containing current section
34196         * @return {Boolean}
34197         */
34198        scrollable: function(activeSection){
34199            // if there are landscape slides, we check if the scrolling bar is in the current one or not
34200            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
34201                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
34202            }
34203            return activeSection.find(SCROLLABLE_SEL);
34204        },
34205
34206        /**
34207         * Returns the scroll height of the wrapped content.
34208         * If this is larger than the window height minus section padding,
34209         * overflow scrolling is needed.
34210         *
34211         * @param  {Object} element jQuery object containing current section
34212         * @return {Number}
34213         */
34214        scrollHeight: function(element) {
34215            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
34216        },
34217
34218        /**
34219         * Called when overflow scrolling is no longer needed for a section.
34220         *
34221         * @param  {Object}
34221 element      jQuery object containing current section
34222         */
34223        remove: function(element) {
34224            var scrollable = element.find(SCROLLABLE_SEL);
34225            if (scrollable.length) {
34226                var iScrollInstance = scrollable.data('iscrollInstance');
34227                iScrollInstance.destroy();
34228
34229                scrollable.data('iscrollInstance', null);
34230            }
34231            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
34232        },
34233
34234        /**
34235         * Called when overflow scrolling has already been setup but the
34236         * window height has potentially changed.
34237         *
34238         * @param  {Object} element      jQuery object containing current section
34239         * @param  {Number} scrollHeight Current window height in pixels
34240         */
34241        update: function(element, scrollHeight) {
34242            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
34243            //short period of time.
34244            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
34245            clearTimeout(iscrollHandler.refreshId);
34246            iscrollHandler.refreshId = setTimeout(function(){
34247                $.each(iscrollHandler.iScrollInstances, function(){
34248                    $(this).get(0).refresh();
34249                });
34250            }, 150);
34251
34252            //updating the wrappers height
34253            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
34254        },
34255
34256        /**
34257         * Called to get any additional elements needed to wrap the section
34258         * content in order to facilitate overflow scrolling.
34259         *
34260         * @return {String|Object} Can be a string containing HTML,
34261         *                         a DOM element, or jQuery object.
34262         */
34263        wrapContent: function() {
34264            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
34265        }
34266    };
34267});
34268
34269(function (global, factory) {
34270	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
34271	typeof define === 'function' && define.amd ? define(['exports'], factory) :
34272	(global = global || self, factory(global.window = global.window || {}));
34273}(this, (function (exports) { 'use strict';
34274
34275	/*!
34276	 * ScrollTrigger 3.8.0
34277	 * https://greensock.com
34278	 *
34279	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
34280	 * Subject to the terms at https://greensock.com/standard-license or for
34281	 * Club GreenSock members, the agreement issued with that membership.
34282	 * @author: Jack Doyle, [email protected]
34283	*/
34284	var gsap,
34285	    _coreInitted,
34286	    _win,
34287	    _doc,
34288	    _docEl,
34289	    _body,
34290	    _root,
34291	    _resizeDelay,
34292	    _raf,
34293	    _request,
34294	    _toArray,
34295	    _clamp,
34296	    _time2,
34297	    _syncInterval,
34298	    _refreshing,
34299	    _pointerIsDown,
34300	    _transformProp,
34301	    _i,
34302	    _prevWidth,
34303	    _prevHeight,
34304	    _autoRefresh,
34305	    _sort,
34306	    _suppressOverwrites,
34307	    _ignoreResize,
34308	    _limitCallbacks,
34309	    _startup = 1,
34310	    _proxies = [],
34311	    _scrollers = [],
34312	    _getTime = Date.now,
34313	    _time1 = _getTime(),
34314	    _lastScrollTime = 0,
34315	    _enabled = 1,
34316	    _passThrough = function _passThrough(v) {
34317	  return v;
34318	},
34319	    _getTarget = function _getTarget(t) {
34320	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
34321	},
34322	    _round = function _round(value) {
34323	  return Math.round(value * 100000) / 100000 || 0;
34324	},
34325	    _windowExists = function _windowExists() {
34326	  return typeof window !== "undefined";
34327	},
34328	    _getGSAP = function _getGSAP() {
34329	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
34330	},
34331	    _isViewport = function _isViewport(e) {
34332	  return !!~_root.indexOf(e);
34333	},
34334	    _getProxyProp = function _getProxyProp(element, property) {
34335	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
34336	},
34337	    _getScrollFunc = function _getScrollFunc(element, _ref) {
34338	  var s = _ref.s,
34339	      sc = _ref.sc;
34340
34341	  var i = _scrollers.indexOf(element),
34342	      offset = sc === _vertical.sc ? 1 : 2;
34343
34344	  !~i && (i = _scrollers.push(element) - 1);
34345	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
34346	    return arguments.length ? element[s] = value : element[s];
34347	  }));
34348	},
34349	    _getBoundsFunc = function _getBoundsFunc(element) {
34350	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
34351	    _winOffsets.width = _win.innerWidth;
34352	    _winOffsets.height = _win.innerHeight;
34353	    return _winOffsets;
34354	  } : function () {
34355	    return _getBounds(element);
34356	  });
34357	},
34358	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
34359	  var d = _ref2.d,
34360	      d2 = _ref2.d2,
34361	      a = _ref2.a;
34362	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
34363	    return a()[d];
34364	  } : function () {
34365	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
34366	  };
34367	},
34368	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
34369	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
34370	    return _winOffsets;
34371	  };
34372	},
34373	    _maxScroll = function _maxScroll(element, _ref3) {
34374	  var s = _ref3.s,
34375	      d2 = _ref3.d2,
34376	      d = _ref3.d,
34377	      a = _ref3.a;
34378	  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];
34379	},
34380	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
34381	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 34382-34586
34382	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
34383	  }
34384	},
34385	    _isString = function _isString(value) {
34386	  return typeof value === "string";
34387	},
34388	    _isFunction = function _isFunction(value) {
34389	  return typeof value === "function";
34390	},
34391	    _isNumber = function _isNumber(value) {
34392	  return typeof value === "number";
34393	},
34394	    _isObject = function _isObject(value) {
34395	  return typeof value === "object";
34396	},
34397	    _callIfFunc = function _callIfFunc(value) {
34398	  return _isFunction(value) && value();
34399	},
34400	    _combineFunc = function _combineFunc(f1, f2) {
34401	  return function () {
34402	    var result1 = _callIfFunc(f1),
34403	        result2 = _callIfFunc(f2);
34404
34405	    return function () {
34406	      _callIfFunc(result1);
34407
34408	      _callIfFunc(result2);
34409	    };
34410	  };
34411	},
34412	    _endAnimation = function _endAnimation(animation, reversed, pause) {
34413	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
34414	},
34415	    _callback = function _callback(self, func) {
34416	  var result = func(self);
34417	  result && result.totalTime && (self.callbackAnimation = result);
34418	},
34419	    _abs = Math.abs,
34420	    _scrollLeft = "scrollLeft",
34421	    _scrollTop = "scrollTop",
34422	    _left = "left",
34423	    _top = "top",
34424	    _right = "right",
34425	    _bottom = "bottom",
34426	    _width = "width",
34427	    _height = "height",
34428	    _Right = "Right",
34429	    _Left = "Left",
34430	    _Top = "Top",
34431	    _Bottom = "Bottom",
34432	    _padding = "padding",
34433	    _margin = "margin",
34434	    _Width = "Width",
34435	    _Height = "Height",
34436	    _px = "px",
34437	    _horizontal = {
34438	  s: _scrollLeft,
34439	  p: _left,
34440	  p2: _Left,
34441	  os: _right,
34442	  os2: _Right,
34443	  d: _width,
34444	  d2: _Width,
34445	  a: "x",
34446	  sc: function sc(value) {
34447	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
34448	  }
34449	},
34450	    _vertical = {
34451	  s: _scrollTop,
34452	  p: _top,
34453	  p2: _Top,
34454	  os: _bottom,
34455	  os2: _Bottom,
34456	  d: _height,
34457	  d2: _Height,
34458	  a: "y",
34459	  op: _horizontal,
34460	  sc: function sc(value) {
34461	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
34462	  }
34463	},
34464	    _getComputedStyle = function _getComputedStyle(element) {
34465	  return _win.getComputedStyle(element);
34466	},
34467	    _makePositionable = function _makePositionable(element) {
34468	  var position = _getComputedStyle(element).position;
34469
34470	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
34471	},
34472	    _setDefaults = function _setDefaults(obj, defaults) {
34473	  for (var p in defaults) {
34474	    p in obj || (obj[p] = defaults[p]);
34475	  }
34476
34477	  return obj;
34478	},
34479	    _getBounds = function _getBounds(element, withoutTransforms) {
34480	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
34481	    x: 0,
34482	    y: 0,
34483	    xPercent: 0,
34484	    yPercent: 0,
34485	    rotation: 0,
34486	    rotationX: 0,
34487	    rotationY: 0,
34488	    scale: 1,
34489	    skewX: 0,
34490	    skewY: 0
34491	  }).progress(1),
34492	      bounds = element.getBoundingClientRect();
34493	  tween && tween.progress(0).kill();
34494	  return bounds;
34495	},
34496	    _getSize = function _getSize(element, _ref4) {
34497	  var d2 = _ref4.d2;
34498	  return element["offset" + d2] || element["client" + d2] || 0;
34499	},
34500	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
34501	  var a = [],
34502	      labels = timeline.labels,
34503	      duration = timeline.duration(),
34504	      p;
34505
34506	  for (p in labels) {
34507	    a.push(labels[p] / duration);
34508	  }
34509
34510	  return a;
34511	},
34512	    _getClosestLabel = function _getClosestLabel(animation) {
34513	  return function (value) {
34514	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
34515	  };
34516	},
34517	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
34518	  var snap = gsap.utils.snap(snapIncrementOrArray),
34519	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
34520	    return a - b;
34521	  });
34522	  return a ? function (value, direction) {
34523	    var i;
34524
34525	    if (!direction) {
34526	      return snap(value);
34527	    }
34528
34529	    if (direction > 0) {
34530	      value -= 1e-4;
34531
34532	      for (i = 0; i < a.length; i++) {
34533	        if (a[i] >= value) {
34534	          return a[i];
34535	        }
34536	      }
34537
34538	      return a[i - 1];
34539	    } else {
34540	      i = a.length;
34541	      value += 1e-4;
34542
34543	      while (i--) {
34544	        if (a[i] <= value) {
34545	          return a[i];
34546	        }
34547	      }
34548	    }
34549
34550	    return a[0];
34551	  } : function (value, direction) {
34552	    var snapped = snap(value);
34553	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
34554	  };
34555	},
34556	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
34557	  return function (value, st) {
34558	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
34559	  };
34560	},
34561	    _multiListener = function _multiListener(func, element, types, callback) {
34562	  return types.split(",").forEach(function (type) {
34563	    return func(element, type, callback);
34564	  });
34565	},
34566	    _addListener = function _addListener(element, type, func) {
34567	  return element.addEventListener(type, func, {
34568	    passive: true
34569	  });
34570	},
34571	    _removeListener = function _removeListener(element, type, func) {
34572	  return element.removeEventListener(type, func);
34573	},
34574	    _markerDefaults = {
34575	  startColor: "green",
34576	  endColor: "red",
34577	  indent: 0,
34578	  fontSize: "16px",
34579	  fontWeight: "normal"
34580	},
34581	    _defaults = {
34582	  toggleActions: "play",
34583	  anticipatePin: 0
34584	},
34585	    _keywords = {
34586	  top: 0,
34587	  left: 0,
34588	  center: 0.5,
34589	  bottom: 1,
34590	  right: 1
34591	},
34592	    _offsetToPx = function _offsetToPx(value, size) {
34593	  if (_isString(value)) {
34594	    var eqIndex = value.indexOf("="),
34595	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
34596
34597	    if (~eqIndex) {
34598	      value.indexOf("%") > eqIndex && (relative *= size / 100);
34599	      value = value.substr(0, eqIndex - 1);
34600	    }
34601
34602	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
34603	  }
34604
34605	  return value;
34606	},
34607	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
34608	  var startColor = _ref5.startColor,
34609	      endColor = _ref5.endColor,
34610	      fontSize = _ref5.fontSize,
34611	      indent = _ref5.indent,
34612	      fontWeight = _ref5.fontWeight;
34613
34614	  var e = _doc.createElement("div"),
34615	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
34616	      isScroller = type.indexOf("scroller") !== -1,
34617	      parent = useFixedPosition ? _body : container,
34618	      isStart = type.indexOf("start") !== -1,
34619	      color = isStart ? startColor : endColor,
34620	      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;";
34621
34622	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
34623	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
34624	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
34625	  e._isStart = isStart;
34626	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
34627	  e.style.cssText = css;
34628	  e.innerText = name || name === 0 ? type + "-" + name : type;
34629	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
34630	  e._offset = e["offset" + direction.op.d2];
34631
34632	  _positionMarker(e, 0, direction, isStart);
34633
34634	  return e;
34635	},
34636	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
34637	  var vars = {
34638	    display: "block"
34639	  },
34640	      side = direction[flipped ? "os2" : "p2"],
34641	      oppositeSide = direction[flipped ? "p2" : "os2"];
34642	  marker._isFlipped = flipped;
34643	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
34644	  vars[direction.a] = flipped ? "1px" : 0;
34645	  vars["border" + side + _Width] = 1;
34646	  vars["border" + oppositeSide + _Width] = 0;
34647	  vars[direction.p] = start + "px";
34648	  gsap.set(marker, vars);
34649	},
34650	    _triggers = [],
34651	    _ids = {},
34652	    _sync = function _sync() {
34653	  return _getTime() - _lastScrollTime > 20 && _updateAll();
34654	},
34655	    _onScroll = function _onScroll() {
34656	  var time = _getTime();
34657
34658	  if (_lastScrollTime !== time) {
34659	    _updateAll();
34660
34661	    _lastScrollTime || _dispatch("scrollStart");
34662	    _lastScrollTime = time;
34663	  } else if (!_request) {
34664	    _request = _raf(_updateAll);
34665	  }
34666	},
34667	    _onResize = function _onResize() {
34668	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
34669	},
34670	    _listeners = {},
34671	    _emptyArray = [],
34672	    _media = [],
34673	    _creatingMedia,
34674	    _lastMediaTick,
34675	    _onMediaChange = function _onMediaChange(e) {
34676	  var tick = gsap.ticker.frame,
34677	      matches = [],
34678	      i = 0,
34679	      index;
34680
34681	  if (_lastMediaTick !== tick || _startup) {
34682	    _revertAll();
34683
34684	    for (; i < _media.length; i += 4) {
34685	      index = _win.matchMedia(_media[i]).matches;
34686
34687	      if (index !== _media[i + 3]) {
34688	        _media[i + 3] = index;
34689	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
34690	      }
34691	    }
34692
34693	    _revertRecorded();
34694
34695	    for (i = 0; i < matches.length; i++) {
34696	      index = matches[i];
34697	      _creatingMedia = _media[index];
34698	      _media[index + 2] = _media[index + 1](e);
34699	    }
34700
34701	    _creatingMedia = 0;
34702	    _coreInitted && _refreshAll(0, 1);
34703	    _lastMediaTick = tick;
34704
34705	    _dispatch("matchMedia");
34706	  }
34707	},
34708	    _softRefresh = function _softRefresh() {
34709	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
34710	},
34711	    _dispatch = function _dispatch(type) {
34712	  return _listeners[type] && _listeners[type].map(function (f) {
34713	    return f();
34714	  }) || _emptyArray;
34715	},
34716	    _savedStyles = [],
34717	    _revertRecorded = function _revertRecorded(media) {
34718	  for (var i = 0; i < _savedStyles.length; i += 5) {
34719	    if (!media || _savedStyles[i + 4] === media) {
34720	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
34721	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
34722	      _savedStyles[i + 3].uncache = 1;
34723	    }
34724	  }
34725	},
34726	    _revertAll = function _revertAll(kill, media) {
34727	  var trigger;
34728
34729	  for (_i = 0; _i < _triggers.length; _i++) {
34730	    trigger = _triggers[_i];
34731
34732	    if (!media || trigger.media === media) {
34733	      if (kill) {
34734	        trigger.kill(1);
34735	      } else {
34736	        trigger.revert();
34737	      }
34738	    }
34739	  }
34740
34741	  media && _revertRecorded(media);
34742	  media || _dispatch("revert");
34743	},
34744	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 34745-35079
34745	  return _scrollers.forEach(function (obj) {
34746	    return typeof obj === "function" && (obj.rec = 0);
34747	  });
34748	},
34749	    _refreshingAll,
34750	    _refreshAll = function _refreshAll(force, skipRevert) {
34751	  if (_lastScrollTime && !force) {
34752	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34753
34754	    return;
34755	  }
34756
34757	  _refreshingAll = true;
34758
34759	  var refreshInits = _dispatch("refreshInit");
34760
34761	  _sort && ScrollTrigger.sort();
34762	  skipRevert || _revertAll();
34763
34764	  _triggers.forEach(function (t) {
34765	    return t.refresh();
34766	  });
34767
34768	  refreshInits.forEach(function (result) {
34769	    return result && result.render && result.render(-1);
34770	  });
34771
34772	  _clearScrollMemory();
34773
34774	  _resizeDelay.pause();
34775
34776	  _refreshingAll = false;
34777
34778	  _dispatch("refresh");
34779	},
34780	    _lastScroll = 0,
34781	    _direction = 1,
34782	    _updateAll = function _updateAll() {
34783	  if (!_refreshingAll) {
34784	    var l = _triggers.length,
34785	        time = _getTime(),
34786	        recordVelocity = time - _time1 >= 50,
34787	        scroll = l && _triggers[0].scroll();
34788
34789	    _direction = _lastScroll > scroll ? -1 : 1;
34790	    _lastScroll = scroll;
34791
34792	    if (recordVelocity) {
34793	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34794	        _lastScrollTime = 0;
34795
34796	        _dispatch("scrollEnd");
34797	      }
34798
34799	      _time2 = _time1;
34800	      _time1 = time;
34801	    }
34802
34803	    if (_direction < 0) {
34804	      _i = l;
34805
34806	      while (_i-- > 0) {
34807	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34808	      }
34809
34810	      _direction = 1;
34811	    } else {
34812	      for (_i = 0; _i < l; _i++) {
34813	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34814	      }
34815	    }
34816
34817	    _request = 0;
34818	  }
34819	},
34820	    _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"],
34821	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34822	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34823	  _setState(state);
34824
34825	  var cache = pin._gsap;
34826
34827	  if (cache.spacerIsNative) {
34828	    _setState(cache.spacerState);
34829	  } else if (pin.parentNode === spacer) {
34830	    var parent = spacer.parentNode;
34831
34832	    if (parent) {
34833	      parent.insertBefore(pin, spacer);
34834	      parent.removeChild(spacer);
34835	    }
34836	  }
34837	},
34838	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34839	  if (pin.parentNode !== spacer) {
34840	    var i = _propNamesToCopy.length,
34841	        spacerStyle = spacer.style,
34842	        pinStyle = pin.style,
34843	        p;
34844
34845	    while (i--) {
34846	      p = _propNamesToCopy[i];
34847	      spacerStyle[p] = cs[p];
34848	    }
34849
34850	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34851	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34852	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34853	    spacerStyle.overflow = "visible";
34854	    spacerStyle.boxSizing = "border-box";
34855	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34856	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34857	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34858
34859	    _setState(spacerState);
34860
34861	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34862	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34863	    pinStyle[_padding] = cs[_padding];
34864	    pin.parentNode.insertBefore(spacer, pin);
34865	    spacer.appendChild(pin);
34866	  }
34867	},
34868	    _capsExp = /([A-Z])/g,
34869	    _setState = function _setState(state) {
34870	  if (state) {
34871	    var style = state.t.style,
34872	        l = state.length,
34873	        i = 0,
34874	        p,
34875	        value;
34876	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34877
34878	    for (; i < l; i += 2) {
34879	      value = state[i + 1];
34880	      p = state[i];
34881
34882	      if (value) {
34883	        style[p] = value;
34884	      } else if (style[p]) {
34885	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34886	      }
34887	    }
34888	  }
34889	},
34890	    _getState = function _getState(element) {
34891	  var l = _stateProps.length,
34892	      style = element.style,
34893	      state = [],
34894	      i = 0;
34895
34896	  for (; i < l; i++) {
34897	    state.push(_stateProps[i], style[_stateProps[i]]);
34898	  }
34899
34900	  state.t = element;
34901	  return state;
34902	},
34903	    _copyState = function _copyState(state, override, omitOffsets) {
34904	  var result = [],
34905	      l = state.length,
34906	      i = omitOffsets ? 8 : 0,
34907	      p;
34908
34909	  for (; i < l; i += 2) {
34910	    p = state[i];
34911	    result.push(p, p in override ? override[p] : state[i + 1]);
34912	  }
34913
34914	  result.t = state.t;
34915	  return result;
34916	},
34917	    _winOffsets = {
34918	  left: 0,
34919	  top: 0
34920	},
34921	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34922	  _isFunction(value) && (value = value(self));
34923
34924	  if (_isString(value) && value.substr(0, 3) === "max") {
34925	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34926	  }
34927
34928	  var time = containerAnimation ? containerAnimation.time() : 0,
34929	      p1,
34930	      p2,
34931	      element;
34932	  containerAnimation && containerAnimation.seek(0);
34933
34934	  if (!_isNumber(value)) {
34935	    _isFunction(trigger) && (trigger = trigger(self));
34936	    var offsets = value.split(" "),
34937	        bounds,
34938	        localOffset,
34939	        globalOffset,
34940	        display;
34941	    element = _getTarget(trigger) || _body;
34942	    bounds = _getBounds(element) || {};
34943
34944	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34945	      display = element.style.display;
34946	      element.style.display = "block";
34947	      bounds = _getBounds(element);
34948	      display ? element.style.display = display : element.style.removeProperty("display");
34949	    }
34950
34951	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
34952	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
34953	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
34954	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
34955	    scrollerSize -= scrollerSize - globalOffset;
34956	  } else if (markerScroller) {
34957	    _positionMarker(markerScroller, scrollerSize, direction, true);
34958	  }
34959
34960	  if (marker) {
34961	    var position = value + scrollerSize,
34962	        isStart = marker._isStart;
34963	    p1 = "scroll" + direction.d2;
34964
34965	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
34966
34967	    if (useFixedPosition) {
34968	      scrollerBounds = _getBounds(markerScroller);
34969	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
34970	    }
34971	  }
34972
34973	  if (containerAnimation && element) {
34974	    p1 = _getBounds(element);
34975	    containerAnimation.seek(scrollerMax);
34976	    p2 = _getBounds(element);
34977	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
34978	    value = value / containerAnimation._caScrollDist * scrollerMax;
34979	  }
34980
34981	  containerAnimation && containerAnimation.seek(time);
34982	  return containerAnimation ? value : Math.round(value);
34983	},
34984	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
34985	    _reparent = function _reparent(element, parent, top, left) {
34986	  if (element.parentNode !== parent) {
34987	    var style = element.style,
34988	        p,
34989	        cs;
34990
34991	    if (parent === _body) {
34992	      element._stOrig = style.cssText;
34993	      cs = _getComputedStyle(element);
34994
34995	      for (p in cs) {
34996	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
34997	          style[p] = cs[p];
34998	        }
34999	      }
35000
35001	      style.top = top;
35002	      style.left = left;
35003	    } else {
35004	      style.cssText = element._stOrig;
35005	    }
35006
35007	    gsap.core.getCache(element).uncache = 1;
35008	    parent.appendChild(element);
35009	  }
35010	},
35011	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
35012	  var getScroll = _getScrollFunc(scroller, direction),
35013	      prop = "_scroll" + direction.p2,
35014	      lastScroll1,
35015	      lastScroll2,
35016	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
35017	    var tween = getTween.tween,
35018	        onComplete = vars.onComplete,
35019	        modifiers = {};
35020	    tween && tween.kill();
35021	    lastScroll1 = Math.round(initialValue);
35022	    vars[prop] = scrollTo;
35023	    vars.modifiers = modifiers;
35024
35025	    modifiers[prop] = function (value) {
35026	      value = _round(getScroll());
35027
35028	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
35029	        tween.kill();
35030	        getTween.tween = 0;
35031	      } else {
35032	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
35033	      }
35034
35035	      lastScroll2 = lastScroll1;
35036	      return lastScroll1 = _round(value);
35037	    };
35038
35039	    vars.onComplete = function () {
35040	      getTween.tween = 0;
35041	      onComplete && onComplete.call(tween);
35042	    };
35043
35044	    tween = getTween.tween = gsap.to(scroller, vars);
35045	    return tween;
35046	  };
35047
35048	  scroller[prop] = getScroll;
35049	  scroller.addEventListener("wheel", function () {
35050	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
35051	  }, {
35052	    passive: true
35053	  });
35054	  return getTween;
35055	};
35056
35057	_horizontal.op = _vertical;
35058	var ScrollTrigger = function () {
35059	  function ScrollTrigger(vars, animation) {
35060	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
35061	    this.init(vars, animation);
35062	  }
35063
35064	  var _proto = ScrollTrigger.prototype;
35065
35066	  _proto.init = function init(vars, animation) {
35067	    this.progress = this.start = 0;
35068	    this.vars && this.kill(1);
35069
35070	    if (!_enabled) {
35071	      this.update = this.refresh = this.kill = _passThrough;
35072	      return;
35073	    }
35074
35075	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
35076	      trigger: vars
35077	    } : vars, _defaults);
35078
35079	    var _vars = vars,
35080	        onUpdate = _vars.onUpdate,
35081	        toggleClass = _vars.toggleClass,
35082	        id = _vars.id,
35083	        onToggle = _vars.onToggle,
35084	        onRefresh = _vars.onRefresh,
35085	        scrub = _vars.scrub,
35086	        trigger = _vars.trigger,
35087	        pin = _vars.pin,
35088	        pinSpacing = _vars.pinSpacing,
35089	        invalidateOnRefresh = _vars.invalidateOnRefresh,
35090	        anticipatePin = _vars.anticipatePin,
35091	        onScrubComplete = _vars.onScrubComplete,
35092	        onSnapComplete = _vars.onSnapComplete,
35093	        once = _vars.once,
35094	        snap = _vars.snap,
35095	        pinReparent = _vars.pinReparent,
35096	        pinSpacer = _vars.pinSpacer,
35097	        containerAnimation = _vars.containerAnimation,
35098	        fastScrollEnd = _vars.fastScrollEnd,
35099	        preventOverlaps = _vars.preventOverlaps,
35100	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
35101	        isToggle = !scrub && scrub !== 0,
35102	        scroller = _getTarget(vars.scroller || _win),
35103	        scrollerCache = gsap.core.getCache(scroller),
35104	        isViewport = _isViewport(scroller),
35105	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
35106	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
35107	        toggleActions = isToggle && vars.toggleActions.split(" "),
35108	        markers = "markers" in vars ? vars.markers : _defaults.markers,
35109	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
35110	        self = this,
35111	        onRefreshInit = vars.onRefreshInit && function () {
35112	      return vars.onRefreshInit(self);
35113	    },
35114	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
35115	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
35116	        lastSnap = 0,
35117	        scrollFunc = _getScrollFunc(scroller, direction),
35118	        tweenTo,
35119	        pinCache,
35120	        snapFunc,
35121	        scroll1,
35122	        scroll2,
35123	        start,
35124	        end,
35125	        markerStart,
35126	        markerEnd,
35127	        markerStartTrigger,
35128	        markerEndTrigger,
35129	        markerVars,
35130	        change,
35131	        pinOriginalState,
35132	        pinActiveState,
35133	        pinState,
35134	        spacer,
35135	        offset,
35136	        pinGetter,
35137	        pinSetter,
35138	        pinStart,
35139	        pinChange,
35140	        spacingStart,
35141	        spacerState,
35142	        markerStartSetter,
35143	        markerEndSetter,
35144	        cs,
35145	        snap1,
35146	        snap2,
35147	        scrubTween,
35148	        scrubSmooth,
35149	        snapDurClamp,
35150	        snapDelayedCall,
35151	        prevProgress,
35152	        prevScroll,
35153	        prevAnimProgress,
35154	        caMarkerSetter;
35155
35156	    self.media = _creatingMedia;
35157	    anticipatePin *= 45;
35158	    self.scroller = scroller;
35159	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
35160	    scroll1 = scrollFunc();
35161	    self.vars = vars;
35162	    animation = animation || vars.animation;
35163	    "refreshPriority" in vars && (_sort = 1);
35164	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
35165	      top: _getTweenCreator(scroller, _vertical),
35166	      left: _getTweenCreator(scroller, _horizontal)
35167	    };
35168	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
35169
35170	    if (animation) {
35171	      animation.vars.lazy = false;
35172	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
35173	      self.animation = animation.pause();
35174	      animation.scrollTrigger = self;
35175	      scrubSmooth = _isNumber(scrub) && scrub;
35176	      scrubSmooth && (scrubTween = gsap.to(animation, {
35177	        ease: "power3",
35178	        duration: scrubSmooth,
35179	        onComplete: function onComplete() {
35180	          return onScrubComplete && onScrubComplete(self);
35181	        }
35182	      }));
35183	      snap1 = 0;
35184	      id || (id = animation.vars.id);
35185	    }
35186
35187	    _triggers.push(self);
35188
35189	    if (snap) {
35190	      if (!_isObject(snap) || snap.push) {
35191	        snap = {
35192	          snapTo: snap
35193	        };
35194	      }
35195
35196	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
35197	        scrollBehavior: "auto"
35198	      });
35199	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
35200	        return _snapDirectional(snap.snapTo)(value, st.direction);
35201	      } : gsap.utils.snap(snap.snapTo);
35202	      snapDurClamp = snap.duration || {
35203	        min: 0.1,
35204	        max: 2
35205	      };
35206	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
35207	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
35208	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
35209	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
35210	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
35211	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
35212	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
35213	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
35214	              scroll = scrollFunc(),
35215	              endScroll = Math.round(start + endValue * change),
35216	              _snap = snap,
35217	              onStart = _snap.onStart,
35218	              _onInterrupt = _snap.onInterrupt,
35219	              _onComplete = _snap.onComplete,
35220	              tween = tweenTo.tween;
35221
35222	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
35223	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
35224	              return;
35225	            }
35226
35227	            if (snap.inertia === false) {
35228	              change1 = endValue - self.progress;
35229	            }
35230
35231	            tweenTo(endScroll, {
35232	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
35233	              ease: snap.ease || "power3",
35234	              data: _abs(endScroll - scroll),
35235	              onInterrupt: function onInterrupt() {
35236	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
35237	              },
35238	              onComplete: function onComplete() {
35239	                lastSnap = scrollFunc();
35240	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
35241	                onSnapComplete && onSnapComplete(self);
35242	                _onComplete && _onComplete(self);
35243	              }
35244	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
35245	            onStart && onStart(self, tweenTo.tween);
35246	          }
35247	        } else if (self.isActive) {
35248	          snapDelayedCall.restart(true);
35249	        }
35250	      }).pause();
35251	    }
35252
35253	    id && (_ids[id] = self);
35254	    trigger = self.trigger = _getTarget(trigger || pin);
35255	    pin = pin === true ? trigger : _getTarget(pin);
35256	    _isString(toggleClass) && (toggleClass = {
35257	      targets: trigger,
35258	      className: toggleClass
35259	    });
35260
35261	    if (pin) {
35262	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
35263	      self.pin = pin;
35264	      vars.force3D !== false && gsap.set(pin, {
35265	        force3D: true
35266	      });
35267	      pinCache = gsap.core.getCache(pin);
35268
35269	      if (!pinCache.spacer) {
35270	        if (pinSpacer) {
35271	          pinSpacer = _getTarget(pinSpacer);
35272	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
35273	          pinCache.spacerIsNative = !!pinSpacer;
35274	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
35275	        }
35276
35277	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
35278	        spacer.classList.add("pin-spacer");
35279	        id && spacer.classList.add("pin-spacer-" + id);
35280	        pinCache.pinState = pinOriginalState = _getState(pin);
35281	      } else {
35282	        pinOriginalState = pinCache.pinState;
35283	      }
35284
35285	      self.spacer = spacer = pinCache.spacer;
35286	      cs = _getComputedStyle(pin);
35287	      spacingStart = cs[pinSpacing + direction.os2];
35288	      pinGetter = gsap.getProperty(pin);
35289	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
35290
35291	      _swapPinIn(pin, spacer, cs);
35292
35293	      pinState = _getState(pin);
35294	    }
35295
35296	    if (markers) {
35297	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
35298	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
35299	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
35300	      offset = markerStartTrigger["offset" + direction.op.d2];
35301	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35302	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35303	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
35304
35305	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
35306	        _makePositionable(isViewport ? _body : scroller);
35307
35308	        gsap.set([markerStartTrigger, markerEndTrigger], {
35309	          force3D: true
35310	        });
35311	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
35312	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
35313	      }
35314	    }
35315
35316	    if (containerAnimation) {
35317	      var oldOnUpdate = containerAnimation.vars.onUpdate,
35318	          oldParams = containerAnimation.vars.onUpdateParams;
35319	      containerAnimation.eventCallback("onUpdate", function () {
35320	        self.update(0, 0, 1);
35321	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
35322	      });
35323	    }
35324
35325	    self.previous = function () {
35326	      return _triggers[_triggers.indexOf(self) - 1];
35327	    };
35328
35329	    self.next = function () {
35330	      return _triggers[_triggers.indexOf(self) + 1];
35331	    };
35332
35333	    self.revert = function (revert) {
35334	      var r = revert !== false || !self.enabled,
35335	          prevRefreshing = _refreshing;
35336
35337	      if (r !== self.isReverted) {
35338	        if (r) {
35339	          self.scroll.rec || (self.scroll.rec = scrollFunc());
35340	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
35341	          prevProgress = self.progress;
35342	          prevAnimProgress = animation && animation.progress();
35343	        }
35344
35345	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35346	          return m.style.display = r ? "none" : "block";
35347	        });
35348	        r && (_refreshing = 1);
35349	        self.update(r);
35350	        _refreshing = prevRefreshing;
35351	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
35352	        self.isReverted = r;
35353	      }
35354	    };
35355
35356	    self.refresh = function (soft, force) {
35357	      if ((_refreshing || !self.enabled) && !force) {
35358	        return;
35359	      }
35360
35361	      if (pin && soft && _lastScrollTime) {
35362	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
35363
35364	        return;
35365	      }
35366
35367	      _refreshing = 1;
35368	      scrubTween && scrubTween.pause();
35369	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
35370	      self.isReverted || self.revert();
35371
35372	      var size = getScrollerSize(),
35373	          scrollerBounds = getScrollerOffsets(),
35374	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
35375	          offset = 0,
35376	          otherPinOffset = 0,
35377	          parsedEnd = vars.end,
35378	          parsedEndTrigger = vars.endTrigger || trigger,
35379	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
35380	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
35381	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
35382	          i = triggerIndex,
35383	          cs,
35384	          bounds,
35385	          scroll,
35386	          isVertical,
35387	          override,
35388	          curTrigger,
35389	          curPin,
35390	          oppositeScroll,
35391	          initted,
35392	          revertedPins;
35393
35394	      while (i--) {
35395	        curTrigger = _triggers[i];
35396	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
35397	        curPin = curTrigger.pin;
35398
35399	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
35400	          revertedPins || (revertedPins = []);
35401	          revertedPins.unshift(curTrigger);
35402	          curTrigger.revert();
35403	        }
35404	      }
35405
35406	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
35407	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
35408	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
35409
35410	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
35411	        if (~parsedEnd.indexOf(" ")) {
35412	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
35413	        } else {
35414	          offset = _offsetToPx(parsedEnd.substr(2), size);
35415	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
35416	          parsedEndTrigger = trigger;
35417	        }
35418	      }
35419
35420	      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;
35421	      change = end - start || (start -= 0.01) && 0.001;
35422	      offset = 0;
35423	      i = triggerIndex;
35424
35425	      while (i--) {
35426	        curTrigger = _triggers[i];
35427	        curPin = curTrigger.pin;
35428
35429	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
35430	          cs = curTrigger.end - curTrigger.start;
35431	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
35432	          curPin === pin && (otherPinOffset += cs);
35433	        }
35434	      }
35435
35436	      start += offset;
35437	      end += offset;
35438	      self._pinPush = otherPinOffset;
35439
35440	      if (markerStart && offset) {
35441	        cs = {};
35442	        cs[direction.a] = "+=" + offset;
35443	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
35444	        gsap.set([markerStart, markerEnd], cs);
35445	      }
35446
35447	      if (pin) {
35448	        cs = _getComputedStyle(pin);
35449	        isVertical = direction === _vertical;
35450	        scroll = scrollFunc();
35451	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
35452	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
35453
35454	        _swapPinIn(pin, spacer, cs);
35455
35456	        pinState = _getState(pin);
35457	        bounds = _getBounds(pin, true);
35458	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
35459
35460	        if (pinSpacing) {
35461	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
35462	          spacerState.t = spacer;
35463	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
35464	          i && spacerState.push(direction.d, i + _px);
35465
35466	          _setState(spacerState);
35467
35468	          useFixedPosition && scrollFunc(prevScroll);
35469	        }
35470
35471	        if (useFixedPosition) {
35472	          override = {
35473	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
35474	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
35475	            boxSizing: "border-box",
35476	            position: "fixed"
35477	          };
35478	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
35479	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
35480	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
35481	          override[_padding] = cs[_padding];
35482	          override[_padding + _Top] = cs[_padding + _Top];
35483	          override[_padding + _Right] = cs[_padding + _Right];
35484	          override[_padding + _Bottom] = cs[_padding + _Bottom];
35485	          override[_padding + _Left] = cs[_padding + _Left];
35486	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
35487	        }
35488
35489	        if (animation) {
35490	          initted = animation._initted;
35491
35492	          _suppressOverwrites(1);
35493
35494	          animation.render(animation.duration(), true, true);
35495	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
35496	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
35497	          animation.render(0, true, true);
35498	          initted || animation.invalidate();
35499
35500	          _suppressOverwrites(0);
35501	        } else {
35502	          pinChange = change;
35503	        }
35504	      } else if (trigger && scrollFunc() && !containerAnimation) {
35505	        bounds = trigger.parentNode;
35506
35507	        while (bounds && bounds !== _body) {
35508	          if (bounds._pinOffset) {
35509	            start -= bounds._pinOffset;
35510	            end -= bounds._pinOffset;
35511	          }
35512
35513	          bounds = bounds.parentNode;
35514	        }
35515	      }
35516
35517	      revertedPins && revertedPins.forEach(function (t) {
35518	        return t.revert(false);
35519	      });
35520	      self.start = start;
35521	      self.end = end;
35522	      scroll1 = scroll2 = scrollFunc();
35523
35524	      if (!containerAnimation) {
35525	        scroll1 < prevScroll && scrollFunc(prevScroll);
35526	        self.scroll.rec = 0;
35527	      }
35528
35529	      self.revert(false);
35530	      _refreshing = 0;
35531	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
35532
35533	      if (prevProgress !== self.progress) {
35534	        animation && !isToggle && animation.totalProgress(prevProgress, true);
35535	        self.progress = prevProgress;
35536	        self.update(0, 0, 1);
35537	      }
35538
35539	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
35540	      onRefresh && onRefresh(self);
35541	    };
35542
35543	    self.getVelocity = function () {
35544	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
35545	    };
35546
35547	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 35548-35786
35548	      _endAnimation(self.callbackAnimation);
35549
35550	      if (animation) {
35551	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
35552	      }
35553	    };
35554
35555	    self.getTrailing = function (name) {
35556	      var i = _triggers.indexOf(self),
35557	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
35558
35559	      return _isString(name) ? a.filter(function (t) {
35560	        return t.vars.preventOverlaps === name;
35561	      }) : a;
35562	    };
35563
35564	    self.update = function (reset, recordVelocity, forceFake) {
35565	      if (containerAnimation && !forceFake && !reset) {
35566	        return;
35567	      }
35568
35569	      var scroll = self.scroll(),
35570	          p = reset ? 0 : (scroll - start) / change,
35571	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
35572	          prevProgress = self.progress,
35573	          isActive,
35574	          wasActive,
35575	          toggleState,
35576	          action,
35577	          stateChanged,
35578	          toggled,
35579	          isAtMax,
35580	          isTakingAction;
35581
35582	      if (recordVelocity) {
35583	        scroll2 = scroll1;
35584	        scroll1 = containerAnimation ? scrollFunc() : scroll;
35585
35586	        if (snap) {
35587	          snap2 = snap1;
35588	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
35589	        }
35590	      }
35591
35592	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
35593
35594	      if (clipped !== prevProgress && self.enabled) {
35595	        isActive = self.isActive = !!clipped && clipped < 1;
35596	        wasActive = !!prevProgress && prevProgress < 1;
35597	        toggled = isActive !== wasActive;
35598	        stateChanged = toggled || !!clipped !== !!prevProgress;
35599	        self.direction = clipped > prevProgress ? 1 : -1;
35600	        self.progress = clipped;
35601
35602	        if (stateChanged && !_refreshing) {
35603	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
35604
35605	          if (isToggle) {
35606	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
35607	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
35608	          }
35609	        }
35610
35611	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
35612	          return t.endAnimation();
35613	        }));
35614
35615	        if (!isToggle) {
35616	          if (scrubTween && !_refreshing && !_startup) {
35617	            scrubTween.vars.totalProgress = clipped;
35618	            scrubTween.invalidate().restart();
35619	          } else if (animation) {
35620	            animation.totalProgress(clipped, !!_refreshing);
35621	          }
35622	        }
35623
35624	        if (pin) {
35625	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
35626
35627	          if (!useFixedPosition) {
35628	            pinSetter(pinStart + pinChange * clipped);
35629	          } else if (stateChanged) {
35630	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
35631
35632	            if (pinReparent) {
35633	              if (!reset && (isActive || isAtMax)) {
35634	                var bounds = _getBounds(pin, true),
35635	                    _offset = scroll - start;
35636
35637	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
35638	              } else {
35639	                _reparent(pin, spacer);
35640	              }
35641	            }
35642
35643	            _setState(isActive || isAtMax ? pinActiveState : pinState);
35644
35645	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
35646	          }
35647	        }
35648
35649	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
35650	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
35651	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
35652	        });
35653	        onUpdate && !isToggle && !reset && onUpdate(self);
35654
35655	        if (stateChanged && !_refreshing) {
35656	          if (isToggle) {
35657	            if (isTakingAction) {
35658	              if (action === "complete") {
35659	                animation.pause().totalProgress(1);
35660	              } else if (action === "reset") {
35661	                animation.restart(true).pause();
35662	              } else if (action === "restart") {
35663	                animation.restart(true);
35664	              } else {
35665	                animation[action]();
35666	              }
35667	            }
35668
35669	            onUpdate && onUpdate(self);
35670	          }
35671
35672	          if (toggled || !_limitCallbacks) {
35673	            onToggle && toggled && _callback(self, onToggle);
35674	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35675	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
35676
35677	            if (!toggled) {
35678	              toggleState = clipped === 1 ? 1 : 3;
35679	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35680	            }
35681	          }
35682
35683	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
35684	            _endAnimation(self.callbackAnimation);
35685
35686	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
35687	          }
35688	        } else if (isToggle && onUpdate && !_refreshing) {
35689	          onUpdate(self);
35690	        }
35691	      }
35692
35693	      if (markerEndSetter) {
35694	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
35695	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
35696	        markerEndSetter(n);
35697	      }
35698
35699	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
35700	    };
35701
35702	    self.enable = function (reset, refresh) {
35703	      if (!self.enabled) {
35704	        self.enabled = true;
35705
35706	        _addListener(scroller, "resize", _onResize);
35707
35708	        _addListener(scroller, "scroll", _onScroll);
35709
35710	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
35711
35712	        if (reset !== false) {
35713	          self.progress = prevProgress = 0;
35714	          scroll1 = scroll2 = lastSnap = scrollFunc();
35715	        }
35716
35717	        refresh !== false && self.refresh();
35718	      }
35719	    };
35720
35721	    self.getTween = function (snap) {
35722	      return snap && tweenTo ? tweenTo.tween : scrubTween;
35723	    };
35724
35725	    self.disable = function (reset, allowAnimation) {
35726	      if (self.enabled) {
35727	        reset !== false && self.revert();
35728	        self.enabled = self.isActive = false;
35729	        allowAnimation || scrubTween && scrubTween.pause();
35730	        prevScroll = 0;
35731	        pinCache && (pinCache.uncache = 1);
35732	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
35733
35734	        if (snapDelayedCall) {
35735	          snapDelayedCall.pause();
35736	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
35737	        }
35738
35739	        if (!isViewport) {
35740	          var i = _triggers.length;
35741
35742	          while (i--) {
35743	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
35744	              return;
35745	            }
35746	          }
35747
35748	          _removeListener(scroller, "resize", _onResize);
35749
35750	          _removeListener(scroller, "scroll", _onScroll);
35751	        }
35752	      }
35753	    };
35754
35755	    self.kill = function (revert, allowAnimation) {
35756	      self.disable(revert, allowAnimation);
35757	      scrubTween && scrubTween.kill();
35758	      id && delete _ids[id];
35759
35760	      var i = _triggers.indexOf(self);
35761
35762	      _triggers.splice(i, 1);
35763
35764	      i === _i && _direction > 0 && _i--;
35765	      i = 0;
35766
35767	      _triggers.forEach(function (t) {
35768	        return t.scroller === self.scroller && (i = 1);
35769	      });
35770
35771	      i || (self.scroll.rec = 0);
35772
35773	      if (animation) {
35774	        animation.scrollTrigger = null;
35775	        revert && animation.render(-1);
35776	        allowAnimation || animation.kill();
35777	      }
35778
35779	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35780	        return m.parentNode && m.parentNode.removeChild(m);
35781	      });
35782
35783	      if (pin) {
35784	        pinCache && (pinCache.uncache = 1);
35785	        i = 0;
35786
35787	        _triggers.forEach(function (t) {
35788	          return t.pin === pin && i++;
35789	        });
35790
35791	        i || (pinCache.spacer = 0);
35792	      }
35793	    };
35794
35795	    self.enable(false, false);
35796	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35797	      return start || end || self.refresh();
35798	    }) && (change = 0.01) && (start = end = 0);
35799	  };
35800
35801	  ScrollTrigger.register = function register(core) {
35802	    if (!_coreInitted) {
35803	      gsap = core || _getGSAP();
35804
35805	      if (_windowExists() && window.document) {
35806	        _win = window;
35807	        _doc = document;
35808	        _docEl = _doc.documentElement;
35809	        _body = _doc.body;
35810	      }
35811
35812	      if (gsap) {
35813	        _toArray = gsap.utils.toArray;
35814	        _clamp = gsap.utils.clamp;
35815	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35816	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35817
35818	        if (_body) {
35819	          _raf = _win.requestAnimationFrame || function (f) {
35820	            return setTimeout(f, 16);
35821	          };
35822
35823	          _addListener(_win, "wheel", _onScroll);
35824
35825	          _root = [_win, _doc, _docEl, _body];
35826
35827	          _addListener(_doc, "scroll", _onScroll);
35828
35829	          var bodyStyle = _body.style,
35830	              border = bodyStyle.borderTopStyle,
35831	              bounds;
35832	          bodyStyle.borderTopStyle = "solid";
35833	          bounds = _getBounds(_body);
35834	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35835	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35836	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35837	          _syncInterval = setInterval(_sync, 200);
35838	          gsap.delayedCall(0.5, function () {
35839	            return _startup = 0;
35840	          });
35841
35842	          _addListener(_doc, "touchcancel", _passThrough);
35843
35844	          _addListener(_body, "touchstart", _passThrough);
35845
35846	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35847	            return _pointerIsDown = 1;
35848	          });
35849
35850	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35851	            return _pointerIsDown = 0;
35852	          });
35853
35854	          _transformProp = gsap.utils.checkPrefix("transform");
35855
35856	          _stateProps.push(_transformProp);
35857
35858	          _coreInitted = _getTime();
35859	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35860	          _autoRefresh = [_doc, "visibilitychange", function () {
35861	            var w = _win.innerWidth,
35862	                h = _win.innerHeight;
35863
35864	            if (_doc.hidden) {
35865	              _prevWidth = w;
35866	              _prevHeight = h;
35867	            } else if (_prevWidth !== w || _prevHeight !== h) {
35868	              _onResize();
35869	            }
35870	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35871	            return _lastScrollTime || _refreshAll();
35872	          }, _win, "resize", _onResize];
35873
35874	          _iterateAutoRefresh(_addListener);
35875	        }
35876	      }
35877	    }
35878
35879	    return _coreInitted;
35880	  };
35881
35882	  ScrollTrigger.defaults = function defaults(config) {
35883	    for (var p in config) {
35884	      _defaults[p] = config[p];
35885	    }
35886	  };
35887
35888	  ScrollTrigger.kill = function kill() {
35889	    _enabled = 0;
35890
35891	    _triggers.slice(0).forEach(function (trigger) {
35892	      return trigger.kill(1);
35893	    });
35894	  };
35895
35896	  ScrollTrigger.config = function config(vars) {
35897	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35898	    var ms = vars.syncInterval;
35899	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35900
35901	    if ("autoRefreshEvents" in vars) {
35902	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35903	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35904	    }
35905	  };
35906
35907	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35908	    var t = _getTarget(target),
35909	        i = _scrollers.indexOf(t),
35910	        isViewport = _isViewport(t);
35911
35912	    if (~i) {
35913	      _scrollers.splice(i, isViewport ? 6 : 2);
35914	    }
35915
35916	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35917	  };
35918
35919	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35920	    var mq, p, i, func, result;
35921
35922	    for (p in vars) {
35923	      i = _media.indexOf(p);
35924	      func = vars[p];
35925	      _creatingMedia = p;
35926
35927	      if (p === "all") {
35928	        func();
35929	      } else {
35930	        mq = _win.matchMedia(p);
35931
35932	        if (mq) {
35933	          mq.matches && (result = func());
35934
35935	          if (~i) {
35936	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35937	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35938	          } else {
35939	            i = _media.length;
35940
35941	            _media.push(p, func, result);
35942
35943	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35944	          }
35945
35946	          _media[i + 3] = mq.matches;
35947	        }
35948	      }
35949
35950	      _creatingMedia = 0;
35951	    }
35952
35953	    return _media;
35954	  };
35955
35956	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
35957	    query || (_media.length = 0);
35958	    query = _media.indexOf(query);
35959	    query >= 0 && _media.splice(query, 4);
35960	  };
35961
35962	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
35963	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
35964	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
35965	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
35966	  };
35967
35968	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
35969	    _isString(element) && (element = _getTarget(element));
35970	    var bounds = element.getBoundingClientRect(),
35971	        size = bounds[horizontal ? _width : _height],
35972	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
35973	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
35974	  };
35975
35976	  return ScrollTrigger;
35977	}();
35978	ScrollTrigger.version = "3.8.0";
35979
35980	ScrollTrigger.saveStyles = function (targets) {
35981	  return targets ? _toArray(targets).forEach(function (target) {
35982	    if (target && target.style) {
35983	      var i = _savedStyles.indexOf(target);
35984
35985	      i >= 0 && _savedStyles.splice(i, 5);
35986
35987	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
35988	    }
35989	  }) : _savedStyles;
35990	};
35991
35992	ScrollTrigger.revert = function (soft, media) {
35993	  return _revertAll(!soft, media);
35994	};
35995
35996	ScrollTrigger.create = function (vars, animation) {
35997	  return new ScrollTrigger(vars, animation);
35998	};
35999
36000	ScrollTrigger.refresh = function (safe) {
36001	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
36002	};
36003
36004	ScrollTrigger.update = _updateAll;
36005	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
36006
36007	ScrollTrigger.maxScroll = function (element, horizontal) {
36008	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
36009	};
36010
36011	ScrollTrigger.getScrollFunc = function (element, horizontal) {
36012	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
36013	};
36014
36015	ScrollTrigger.getById = function (id) {
36016	  return _ids[id];
36017	};
36018
36019	ScrollTrigger.getAll = function () {
36020	  return _triggers.slice(0);
36021	};
36022
36023	ScrollTrigger.isScrolling = function () {
36024	  return !!_lastScrollTime;
36025	};
36026
36027	ScrollTrigger.snapDirectional = _snapDirectional;
36028
36029	ScrollTrigger.addEventListener = function (type, callback) {
36030	  var a = _listeners[type] || (_listeners[type] = []);
36031	  ~a.indexOf(callback) || a.push(callback);
36032	};
36033
36034	ScrollTrigger.removeEventListener = function (type, callback) {
36035	  var a = _listeners[type],
36036	      i = a && a.indexOf(callback);
36037	  i >= 0 && a.splice(i, 1);
36038	};
36039
36040	ScrollTrigger.batch = function (targets, vars) {
36041	  var result = [],
36042	      varsCopy = {},
36043	      interval = vars.interval || 0.016,
36044	      batchMax = vars.batchMax || 1e9,
36045	      proxyCallback = function proxyCallback(type, callback) {
36046	    var elements = [],
36047	        triggers = [],
36048	        delay = gsap.delayedCall(interval, function () {
36049	      callback(elements, triggers);
36050	      elements = [];
36051	      triggers = [];
36052	    }).pause();
36053	    return function (self) {
36054	      elements.length || delay.restart(true);
36055	      elements.push(self.trigger);
36056	      triggers.push(self);
36057	      batchMax <= elements.length && delay.progress(1);
36058	    };
36059	  },
36060	      p;
36061
36062	  for (p in vars) {
36063	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
36064	  }
36065
36066	  if (_isFunction(batchMax)) {
36067	    batchMax = batchMax();
36068
36069	    _addListener(ScrollTrigger, "refresh", function () {
36070	      return batchMax = vars.batchMax();
36071	    });
36072	  }
36073
36074	  _toArray(targets).forEach(function (target) {
36075	    var config = {};
36076
36077	    for (p in varsCopy) {
36078	      config[p] = varsCopy[p];
36079	    }
36080
36081	    config.trigger = target;
36082	    result.push(ScrollTrigger.create(config));
36083	  });
36084
36085	  return result;
36086	};
36087
36088	ScrollTrigger.sort = function (func) {
36089	  return _triggers.sort(func || function (a, b) {
36090	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
36091	  });
36092	};
36093
36094	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
36095
36096	exports.ScrollTrigger = ScrollTrigger;
36097	exports.default = ScrollTrigger;
36098
36099	Object.defineProperty(exports, '__esModule', { value: true });
36100
36101})));
36102
36103/* ========================================================================
36104 * Bootstrap: collapse.js v3.1.1
36105 * http://getbootstrap.com/javascript/#collapse
36106 * ========================================================================
36107 * Copyright 2011-2014 Twitter, Inc.
36108 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36109 * ======================================================================== */
36110
36111
36112+function ($) {
36113	'use strict';
36114
36115	// COLLAPSE PUBLIC CLASS DEFINITION
36116	// ================================
36117
36118	var Collapse = function (element, options) {
36119		this.$element      = $(element)
36120		this.options       = $.extend({}, Collapse.DEFAULTS, options)
36121		this.transitioning = null
36122
36123		if (this.options.parent) this.$parent = $(this.options.parent)
36124		if (this.options.toggle) this.toggle()
36125	}
36126
36127	Collapse.DEFAULTS = {
36128		toggle: true
36129	}
36130
36131	Collapse.prototype.dimension = function () {
36132		var hasWidth = this.$element.hasClass('width')
36133		return hasWidth ? 'width' : 'height'
36134	}
36135
36136	Collapse.prototype.show = function () {
36137		if (this.transitioning || this.$element.hasClass('in')) return
36138
36139		var startEvent = $.Event('show.bs.collapse')
36140		this.$element.trigger(startEvent)
36141		if (startEvent.isDefaultPrevented()) return
36142
36143		var actives = this.$parent && this.$parent.find('> .panel > .in')
36144
36145		if (actives && actives.length) {
36146			var hasData = actives.data('bs.collapse')
36147			if (hasData && hasData.transitioning) return
36148			//START UNCODE EDIT
36149			var parentNoToggle = this.$parent.data('no-toggle')
36150			if (!parentNoToggle) {
36151				actives.collapse('hide')
36152			}
36153			//END UNCODE EDIT
36154			hasData || actives.data('bs.collapse', null)
36155		}
36156
36157		var dimension = this.dimension()
36158
36159		this.$element
36160			.removeClass('collapse')
36161			.addClass('collapsing')[dimension](0)
36162
36163		this.transitioning = 1
36164
36165		var complete = function (e) {
36166			if (e && e.target != this.$element[0]) return
36167			this.$element
36168				.removeClass('collapsing')
36169				.addClass('collapse in')[dimension]('auto')
36170			this.transitioning = 0
36171			this.$element.trigger('shown.bs.collapse')
36172		}
36173
36174		if (!$.support.transition) return complete.call(this)
36175
36176		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
36177
36178		this.$element
36179			.one($.support.transition.end, $.proxy(complete, this))
36180			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
36181	}
36182
36183	Collapse.prototype.hide = function () {
36184		if (this.transitioning || !this.$element.hasClass('in')) return
36185
36186		var startEvent = $.Event('hide.bs.collapse')
36187		this.$element.trigger(startEvent)
36188		if (startEvent.isDefaultPrevented()) return
36189
36190		var dimension = this.dimension()
36191
36192		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
36193
36194		this.$element
36195			.addClass('collapsing')
36196			.removeClass('collapse')
36197			.removeClass('in')
36198
36199		this.transitioning = 1
36200
36201		var complete = function (e) {
36202			if (e && e.target != this.$element[0]) return
36203			this.transitioning = 0
36204			this.$element
36205				.trigger('hidden.bs.collapse')
36206				.removeClass('collapsing')
36207				.addClass('collapse')
36208		}
36209
36210		if (!$.support.transition) return complete.call(this)
36211
36212		this.$element
36213			[dimension](0)
36214			.one($.support.transition.end, $.proxy(complete, this))
36215			.emulateTransitionEnd(350)
36216	}
36217
36218	Collapse.prototype.toggle = function () {
36219		this[this.$element.hasClass('in') ? 'hide' : 'show']()
36220	}
36221
36222
36223	// COLLAPSE PLUGIN DEFINITION
36224	// ==========================
36225
36226	var old = $.fn.collapse
36227
36228	$.fn.collapse = function (option) {
36229		return this.each(function () {
36230			var $this   = $(this)
36231			var data    = $this.data('bs.collapse')
36232			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
36233
36234			if (!data && options.toggle && option == 'show') option = !option
36235			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
36236			if (typeof option == 'string') data[option]()
36237		})
36238	}
36239
36240	$.fn.collapse.Constructor = Collapse
36241
36242
36243	// COLLAPSE NO CONFLICT
36244	// ====================
36245
36246	$.fn.collapse.noConflict = function () {
36247		$.fn.collapse = old
36248		return this
36249	}
36250
36251
36252	// COLLAPSE DATA-API
36253	// =================
36254
36255	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
36256		var $this   = $(this), href
36257		var target  = $this.attr('data-target')
36258				|| e.preventDefault()
36259				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
36260		//Edited by Uncode to replace ID in panel [START]
36261		var _target = href.replace(/^#/, "");
36262		if ( $('[data-id="' + _target + '"]').length ) {
36263			var $target = $('[data-id="' + _target + '"]')
36264		} else {
36265			var $target = $(target)
36266		}
36267		//Edited by Uncode to replace ID in panel [END]
36268		var data    = $target.data('bs.collapse')
36269		var option  = data ? 'toggle' : $this.data()
36270		var parent  = $this.attr('data-parent')
36271		var $parent = parent && $(parent)
36272
36273		if (!data || !data.transitioning) {
36274			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
36275			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
36276		}
36277
36278		$target.collapse(option)
36279	})
36280
36281}(jQuery);
36282
36283/* ========================================================================
36284 * Bootstrap: tab.js v3.1.1
36285 * http://getbootstrap.com/javascript/#tabs
36286 * ========================================================================
36287 * Copyright 2011-2014 Twitter, Inc.
36288 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36289 * ======================================================================== */
36290
36291
36292+function ($) {
36293  'use strict';
36294
36295  // TAB CLASS DEFINITION
36296  // ====================
36297
36298  var Tab = function (element) {
36299    this.element = $(element)
36300  }
36301
36302  Tab.prototype.show = function () {
36303    var $this    = this.element
36304    var $ul      = $this.closest('ul:not(.dropdown-menu)')
36305    var selector = $this.data('target')
36306
36307    if (!selector) {
36308      selector = $this.attr('href')
36309      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
36310    }
36311
36312    if ($this.parent('li').hasClass('active')) return
36313
36314    var previous = $ul.find('.active:last a')[0]
36315    var e        = $.Event('show.bs.tab', {
36316      relatedTarget: previous
36317    })
36318
36319    $this.trigger(e)
36320
36321    if (e.isDefaultPrevented()) return
36322
36323    //Edited by Uncode to replace ID in panel [START]
36324    var _target = selector.replace(/^#/, "");
36325    if ( $('[data-id="' + _target + '"]').length )
36326      var $target = $('[data-id="' + _target + '"]')
36327    else
36328      var $target = $(selector)
36329    //Edited by Uncode to replace ID in panel [END]
36330
36331    this.activate($this.parent('li'), $ul)
36332    this.activate($target, $target.parent(), function () {
36333      $this.trigger({
36334        type: 'shown.bs.tab',
36335        relatedTarget: previous
36336      })
36337    })
36338  }
36339
36340  Tab.prototype.activate = function (element, container, callback) {
36341    var $active    = container.find('> .active').add(container.find('> .active > .active'))
36342    var transition = callback
36343      && $.support.transition
36344      && $active.hasClass('fade')
36345
36346    function next() {
36347      $active
36348        .removeClass('active')
36349        .find('> .dropdown-menu > .active')
36350        .removeClass('active')
36351
36352      $active
36353        .find('.tab-excerpt').slideUp();
36354
36355      element.addClass('active')
36356      $('.tab-excerpt', element).slideDown();
36357
36358      //if (transition) {
36359        element[0].offsetWidth // reflow for transition
36360        element.add($active).addClass('in')
36361      /*} else {
36362        element.removeClass('fade')
36363      }*/
36364
36365      if (element.parent('.dropdown-menu')) {
36366        element.closest('li.dropdown').addClass('active')
36367      }
36368
36369      callback && callback()
36370    }
36371
36372    transition ?
36373      $active
36374        .one($.support.transition.end, next)
36375        .emulateTransitionEnd(150) :
36376      next()
36377
36378    $active.removeClass('in')
36379  }
36380
36381
36382  // TAB PLUGIN DEFINITION
36383  // =====================
36384
36385  var old = $.fn.tab
36386
36387  $.fn.tab = function ( option ) {
36388    return this.each(function () {
36389      var $this = $(this)
36390      var data  = $this.data('bs.tab')
36391
36392      if (!data) $this.data('bs.tab', (data = new Tab(this)))
36393      if (typeof option == 'string') data[option]()
36394    })
36395  }
36396
36397  $.fn.tab.Constructor = Tab
36398
36399
36400  // TAB NO CONFLICT
36401  // ===============
36402
36403  $.fn.tab.noConflict = function () {
36404    $.fn.tab = old
36405    return this
36406  }
36407
36408
36409  // TAB DATA-API
36410  // ============
36411
36412  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
36413    e.preventDefault()
36414    $(this).tab('show')
36415  })
36416
36417}(jQuery);
36418
36419/* ========================================================================
36420 * Bootstrap: tooltip.js v3.1.1
36421 * http://getbootstrap.com/javascript/#tooltip
36422 * Inspired by the original jQuery.tipsy by Jason Frame
36423 * ========================================================================
36424 * Copyright 2011-2014 Twitter, Inc.
36425 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36426 * ======================================================================== */
36427
36428
36429+function ($) {
36430  'use strict';
36431
36432  // TOOLTIP PUBLIC CLASS DEFINITION
36433  // ===============================
36434
36435  var Tooltip = function (element, options) {
36436    this.type       =
36437    this.options    =
36438    this.enabled    =
36439    this.timeout    =
36440    this.hoverState =
36441    this.$element   = null
36442
36443    this.init('tooltip', element, options)
36444  }
36445
36446  Tooltip.DEFAULTS = {
36447    animation: true,
36448    placement: 'top',
36449    selector: false,
36450    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
36451    trigger: 'hover focus',
36452    title: '',
36453    delay: 0,
36454    html: false,
36455    container: false,
36456    viewport: {
36457      selector: 'body',
36458      padding: 0
36459    }
36460  }
36461
36462  Tooltip.prototype.init = function (type, element, options) {
36463    this.enabled   = true
36464    this.type      = type
36465    this.$element  = $(element)
36466    this.options   = this.getOptions(options)
36467    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
36468
36469    var triggers = this.options.trigger.split(' ')
36470
36471    for (var i = triggers.length; i--;) {
36472      var trigger = triggers[i]
36473
36474      if (trigger == 'click') {
36475        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
36476      } else if (trigger != 'manual') {
36477        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
36478        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
36479
36480        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
36481        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
36482      }
36483    }
36484
36485    this.options.selector ?
36486      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
36487      this.fixTitle()
36488  }
36489
36490  Tooltip.prototype.getDefaults = function () {
36491    return Tooltip.DEFAULTS
36492  }
36493
36494  Tooltip.prototype.getOptions = function (options) {
36495    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
36496
36497    if (options.delay && typeof options.delay == 'number') {
36498      options.delay = {
36499        show: options.delay,
36500        hide: options.delay
36501      }
36502    }
36503
36504    return options
36505  }
36506
36507  Tooltip.prototype.getDelegateOptions = function () {
36508    var options  = {}
36509    var defaults = this.getDefaults()
36510
36511    this._options && $.each(this._options, function (key, value) {
36512      if (defaults[key] != value) options[key] = value
36513    })
36514
36515    return options
36516  }
36517
36518  Tooltip.prototype.enter = function (obj) {
36519    var self = obj instanceof this.constructor ?
36520      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36521
36522    clearTimeout(self.timeout)
36523
36524    self.hoverState = 'in'
36525
36526    if (!self.options.delay || !self.options.delay.show) return self.show()
36527
36528    self.timeout = setTimeout(function () {
36529      if (self.hoverState == 'in') self.show()
36530    }, self.options.delay.show)
36531  }
36532
36533  Tooltip.prototype.leave = function (obj) {
36534    var self = obj instanceof this.constructor ?
36535      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36536
36537    clearTimeout(self.timeout)
36538
36539    self.hoverState = 'out'
36540
36541    if (!self.options.delay || !self.options.delay.hide) return self.hide()
36542
36543    self.timeout = setTimeout(function () {
36544      if (self.hoverState == 'out') self.hide()
36545    }, self.options.delay.hide)
36546  }
36547
36548  Tooltip.prototype.show = function () {
36549    var e = $.Event('show.bs.' + this.type)
36550
36551    if (this.hasContent() && this.enabled) {
36552      this.$element.trigger(e)
36553
36554      if (e.isDefaultPrevented()) return
36555      var that = this;
36556
36557      var $tip = this.tip()
36558
36559      this.setContent()
36560
36561      if (this.options.animation) $tip.addClass('fade')
36562
36563      var placement = typeof this.options.placement == 'function' ?
36564        this.options.placement.call(this, $tip[0], this.$element[0]) :
36565        this.options.placement
36566
36567      var autoToken = /\s?auto?\s?/i
36568      var autoPlace = autoToken.test(placement)
36569      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
36570
36571      $tip
36572        .detach()
36573        .cs
36573s({ top: 0, left: 0, display: 'block' })
36574        .addClass(placement)
36575
36576      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
36577
36578      var pos          = this.getPosition()
36579      var actualWidth  = $tip[0].offsetWidth
36580      var actualHeight = $tip[0].offsetHeight
36581
36582      if (autoPlace) {
36583        var orgPlacement = placement
36584        var $parent      = this.$element.parent()
36585        var parentDim    = this.getPosition($parent)
36586
36587        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
36588                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
36589                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
36590                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
36591                    placement
36592
36593        $tip
36594          .removeClass(orgPlacement)
36595          .addClass(placement)
36596      }
36597
36598      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
36599
36600      this.applyPlacement(calculatedOffset, placement)
36601      this.hoverState = null
36602
36603      var complete = function() {
36604        that.$element.trigger('shown.bs.' + that.type)
36605      }
36606
36607      $.support.transition && this.$tip.hasClass('fade') ?
36608        $tip
36609          .one($.support.transition.end, complete)
36610          .emulateTransitionEnd(150) :
36611        complete()
36612    }
36613  }
36614
36615  Tooltip.prototype.applyPlacement = function (offset, placement) {
36616    var $tip   = this.tip()
36617    var width  = $tip[0].offsetWidth
36618    var height = $tip[0].offsetHeight
36619
36620    // manually read margins because getBoundingClientRect includes difference
36621    var marginTop = parseInt($tip.css('margin-top'), 10)
36622    var marginLeft = parseInt($tip.css('margin-left'), 10)
36623
36624    // we must check for NaN for ie 8/9
36625    if (isNaN(marginTop))  marginTop  = 0
36626    if (isNaN(marginLeft)) marginLeft = 0
36627
36628    offset.top  = offset.top  + marginTop
36629    offset.left = offset.left + marginLeft
36630
36631    // $.fn.offset doesn't round pixel values
36632    // so we use setOffset directly with our own function B-0
36633    $.offset.setOffset($tip[0], $.extend({
36634      using: function (props) {
36635        $tip.css({
36636          top: Math.round(props.top),
36637          left: Math.round(props.left)
36638        })
36639      }
36640    }, offset), 0)
36641
36642    $tip.addClass('in')
36643
36644    // check to see if placing tip in new offset caused the tip to resize itself
36645    var actualWidth  = $tip[0].offsetWidth
36646    var actualHeight = $tip[0].offsetHeight
36647
36648    if (placement == 'top' && actualHeight != height) {
36649      offset.top = offset.top + height - actualHeight
36650    }
36651
36652    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
36653
36654    if (delta.left) offset.left += delta.left
36655    else offset.top += delta.top
36656
36657    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
36658    var arrowPosition       = delta.left ? 'left'        : 'top'
36659    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
36660
36661    $tip.offset(offset)
36662    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
36663  }
36664
36665  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
36666    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
36667  }
36668
36669  Tooltip.prototype.setContent = function () {
36670    var $tip  = this.tip()
36671    var title = this.getTitle()
36672
36673    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
36674    $tip.removeClass('fade in top bottom left right')
36675  }
36676
36677  Tooltip.prototype.hide = function () {
36678    var that = this
36679    var $tip = this.tip()
36680    var e    = $.Event('hide.bs.' + this.type)
36681
36682    function complete() {
36683      if (that.hoverState != 'in') $tip.detach()
36684      that.$element.trigger('hidden.bs.' + that.type)
36685    }
36686
36687    this.$element.trigger(e)
36688
36689    if (e.isDefaultPrevented()) return
36690
36691    $tip.removeClass('in')
36692
36693    $.support.transition && this.$tip.hasClass('fade') ?
36694      $tip
36695        .one($.support.transition.end, complete)
36696        .emulateTransitionEnd(150) :
36697      complete()
36698
36699    this.hoverState = null
36700
36701    return this
36702  }
36703
36704  Tooltip.prototype.fixTitle = function () {
36705    var $e = this.$element
36706    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
36707      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
36708    }
36709  }
36710
36711  Tooltip.prototype.hasContent = function () {
36712    return this.getTitle()
36713  }
36714
36715  Tooltip.prototype.getPosition = function ($element) {
36716    $element   = $element || this.$element
36717    var el     = $element[0]
36718    var isBody = el.tagName == 'BODY'
36719    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
36720      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
36721      width:  isBody ? $(window).width()  : $element.outerWidth(),
36722      height: isBody ? $(window).height() : $element.outerHeight()
36723    }, isBody ? {top: 0, left: 0} : $element.offset())
36724  }
36725
36726  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
36727    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
36728           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
36729           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
36730        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
36731
36732  }
36733
36734  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
36735    var delta = { top: 0, left: 0 }
36736    if (!this.$viewport) return delta
36737
36738    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
36739    var viewportDimensions = this.getPosition(this.$viewport)
36740
36741    if (/right|left/.test(placement)) {
36742      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
36743      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
36744      if (topEdgeOffset < viewportDimensions.top) { // top overflow
36745        delta.top = viewportDimensions.top - topEdgeOffset
36746      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
36747        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
36747EdgeOffset
36748      }
36749    } else {
36750      var leftEdgeOffset  = pos.left - viewportPadding
36751      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
36752      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
36753        delta.left = viewportDimensions.left - leftEdgeOffset
36754      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
36755        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
36756      }
36757    }
36758
36759    return delta
36760  }
36761
36762  Tooltip.prototype.getTitle = function () {
36763    var title
36764    var $e = this.$element
36765    var o  = this.options
36766
36767    title = $e.attr('data-original-title')
36768      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
36769
36770    return title
36771  }
36772
36773  Tooltip.prototype.tip = function () {
36774    return this.$tip = this.$tip || $(this.options.template)
36775  }
36776
36777  Tooltip.prototype.arrow = function () {
36778    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
36779  }
36780
36781  Tooltip.prototype.validate = function () {
36782    if (!this.$element[0].parentNode) {
36783      this.hide()
36784      this.$element = null
36785      this.options  = null
36786    }
36787  }
36788
36789  Tooltip.prototype.enable = function () {
36790    this.enabled = true
36791  }
36792
36793  Tooltip.prototype.disable = function () {
36794    this.enabled = false
36795  }
36796
36797  Tooltip.prototype.toggleEnabled = function () {
36798    this.enabled = !this.enabled
36799  }
36800
36801  Tooltip.prototype.toggle = function (e) {
36802    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36803    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36804  }
36805
36806  Tooltip.prototype.destroy = function () {
36807    clearTimeout(this.timeout)
36808    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36809  }
36810
36811
36812  // TOOLTIP PLUGIN DEFINITION
36813  // =========================
36814
36815  var old = $.fn.tooltip
36816
36817  $.fn.tooltip = function (option) {
36818    return this.each(function () {
36819      var $this   = $(this)
36820      var data    = $this.data('bs.tooltip')
36821      var options = typeof option == 'object' && option
36822
36823      if (!data && option == 'destroy') return
36824      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36825      if (typeof option == 'string') data[option]()
36826    })
36827  }
36828
36829  $.fn.tooltip.Constructor = Tooltip
36830
36831
36832  // TOOLTIP NO CONFLICT
36833  // ===================
36834
36835  $.fn.tooltip.noConflict = function () {
36836    $.fn.tooltip = old
36837    return this
36838  }
36839
36840}(jQuery);
36841
36842/* ========================================================================
36843 * Bootstrap: transition.js v3.1.1
36844 * http://getbootstrap.com/javascript/#transitions
36845 * ========================================================================
36846 * Copyright 2011-2014 Twitter, Inc.
36847 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36848 * ======================================================================== */
36849
36850
36851+function ($) {
36852  'use strict';
36853
36854  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36855  // ============================================================
36856
36857  function transitionEnd() {
36858    var el = document.createElement('bootstrap')
36859
36860    var transEndEventNames = {
36861      WebkitTransition : 'webkitTransitionEnd',
36862      MozTransition    : 'transitionend',
36863      OTransition      : 'oTransitionEnd otransitionend',
36864      transition       : 'transitionend'
36865    }
36866
36867    for (var name in transEndEventNames) {
36868      if (el.style[name] !== undefined) {
36869        return { end: transEndEventNames[name] }
36870      }
36871    }
36872
36873    return false // explicit for ie8 (  ._.)
36874  }
36875
36876  // http://blog.alexmaccaw.com/css-transitions
36877  $.fn.emulateTransitionEnd = function (duration) {
36878    var called = false, $el = this
36879    $(this).one($.support.transition.end, function () { called = true })
36880    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36881    setTimeout(callback, duration)
36882    return this
36883  }
36884
36885  $(function () {
36886    $.support.transition = transitionEnd()
36887  })
36888
36889}(jQuery);
36890
36891
36892// ------------------------------------------
36893// Rellax.js
36894// Buttery smooth parallax library
36895// Copyright (c) 2016 Moe Amaya (@moeamaya)
36896// MIT license
36897//
36898// Thanks to Paraxify.js and Jaime Cabllero
36899// for parallax concepts
36900// ------------------------------------------
36901
36902(function (root, factory) {
36903	if (typeof define === 'function' && define.amd) {
36904		// AMD. Register as an anonymous module.
36905		define([], factory);
36906	} else if (typeof module === 'object' && module.exports) {
36907		// Node. Does not work with strict CommonJS, but
36908		// only CommonJS-like environments that support module.exports,
36909		// like Node.
36910		module.exports = factory();
36911	} else {
36912		// Browser globals (root is window)
36913		root.Rellax = factory();
36914	}
36915}(typeof window !== "undefined" ? window : global, function () {
36916	var Rellax = function(el, options){
36917		"use strict";
36918
36919		var self = Object.create(Rellax.prototype);
36920
36921		var posY = 0;
36922		var screenY = 0;
36923		var posX = 0;
36924		var screenX = 0;
36925		var blocks = [];
36926		var pause = true;
36927
36928		// check what requestAnimationFrame to use, and if
36929		// it's not supported, use the onscroll event
36930		var loop = window.requestAnimationFrame ||
36931			window.webkitRequestAnimationFrame ||
36932			window.mozRequestAnimationFrame ||
36933			window.msRequestAnimationFrame ||
36934			window.oRequestAnimationFrame ||
36935			function(callback){ return setTimeout(callback, 1000 / 60); };
36936
36937		// store the id for later use
36938		var loopId = null;
36939
36940		// Test via a getter in the options object to see if the passive property is accessed
36941		var supportsPassive = false;
vendor: 10,724 bytes, lines 36942-37243
36942		try {
36943			var opts = Object.defineProperty({}, 'passive', {
36944				get: function() {
36945					supportsPassive = true;
36946				}
36947			});
36948			window.addEventListener("testPassive", null, opts);
36949			window.removeEventListener("testPassive", null, opts);
36950		} catch (e) {}
36951
36952		// check what cancelAnimation method to use
36953		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
36954
36955		// check which transform property to use
36956		var transformProp = window.transformProp || (function(){
36957				var testEl = document.createElement('div');
36958				if (testEl.style.transform === null) {
36959					var vendors = ['Webkit', 'Moz', 'ms'];
36960					for (var vendor in vendors) {
36961						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
36962							return vendors[vendor] + 'Transform';
36963						}
36964					}
36965				}
36966				return 'transform';
36967			})();
36968
36969		// Default Settings
36970		self.options = {
36971			speed: -2,
36972			verticalSpeed: null,
36973			horizontalSpeed: null,
36974			breakpoints: [576, 768, 1201],
36975			center: false,
36976			wrapper: null,
36977			relativeToWrapper: false,
36978			round: true,
36979			vertical: true,
36980			horizontal: false,
36981			verticalScrollAxis: "y",
36982			horizontalScrollAxis: "x",
36983			callback: function() {},
36984		};
36985
36986		// User defined options (might have more in the future)
36987		if (options){
36988			Object.keys(options).forEach(function(key){
36989				self.options[key] = options[key];
36990			});
36991		}
36992
36993		function validateCustomBreakpoints () {
36994			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
36995				var isAscending = true;
36996				var isNumerical = true;
36997				var lastVal;
36998				self.options.breakpoints.forEach(function (i) {
36999					if (typeof i !== 'number') isNumerical = false;
37000					if (lastVal !== null) {
37001						if (i < lastVal) isAscending = false;
37002					}
37003					lastVal = i;
37004				});
37005				if (isAscending && isNumerical) return;
37006			}
37007			// revert defaults if set incorrectly
37008			self.options.breakpoints = [576, 768, 1201];
37009			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
37010		}
37011
37012		if (options && options.breakpoints) {
37013			validateCustomBreakpoints();
37014		}
37015
37016		// By default, rellax class
37017		if (!el) {
37018			el = '.rellax';
37019		}
37020
37021		// check if el is a className or a node
37022		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
37023
37024		// Now query selector
37025		if (elements.length > 0) {
37026			self.elems = elements;
37027		}
37028
37029		// The elements don't exist
37030		else {
37031			console.warn("Rellax: The elements you're trying to select don't exist.");
37032			return;
37033		}
37034
37035		// Has a wrapper and it exists
37036		if (self.options.wrapper) {
37037			if (!self.options.wrapper.nodeType) {
37038				var wrapper = document.querySelector(self.options.wrapper);
37039
37040				if (wrapper) {
37041					self.options.wrapper = wrapper;
37042				} else {
37043					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
37044					return;
37045				}
37046			}
37047		}
37048
37049		// set a placeholder for the current breakpoint
37050		var currentBreakpoint;
37051
37052		// helper to determine current breakpoint
37053		var getCurrentBreakpoint = function (w) {
37054			var bp = self.options.breakpoints;
37055			if (w < bp[0]) return 'xs';
37056			if (w >= bp[0] && w < bp[1]) return 'sm';
37057			if (w >= bp[1] && w < bp[2]) return 'md';
37058			return 'lg';
37059		};
37060
37061		// Get and cache initial position of all elements
37062		var cacheBlocks = function() {
37063			for (var i = 0; i < self.elems.length; i++){
37064				var block = createBlock(self.elems[i]);
37065				blocks.push(block);
37066			}
37067		};
37068
37069
37070		// Let's kick this script off
37071		// Build array for cached element values
37072		var init = function() {
37073			for (var i = 0; i < blocks.length; i++){
37074				self.elems[i].style.cssText = blocks[i].style;
37075			}
37076
37077			blocks = [];
37078
37079			screenY = window.innerHeight;
37080			screenX = window.innerWidth;
37081			currentBreakpoint = getCurrentBreakpoint(screenX);
37082
37083			setPosition();
37084
37085			cacheBlocks();
37086
37087			animate();
37088
37089			// If paused, unpause and set listener for window resizing events
37090			if (pause) {
37091				window.addEventListener('resize', init);
37092				pause = false;
37093				// Start the loop
37094				update();
37095			}
37096		};
37097
37098		// We want to cache the parallax blocks'
37099		// values: base, top, height, speed
37100		// el: is dom object, return: el cache values
37101		var createBlock = function(el) {
37102			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
37103			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
37104			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
37105			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
37106			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
37107			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
37108			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
37109			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
37110			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
37111			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
37112			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
37113			var dataMin = el.getAttribute( 'data-rellax-min' );
37114			var dataMax = el.getAttribute( 'data-rellax-max' );
37115			var dataMinX = el.getAttribute('data-rellax-min-x');
37116			var dataMaxX = el.getAttribute('data-rellax-max-x');
37117			var dataMinY = el.getAttribute('data-rellax-min-y');
37118			var dataMaxY = el.getAttribute('data-rellax-max-y');
37119			var mapBreakpoints;
37120			var breakpoints = true;
37121
37122			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
37123				breakpoints = false;
37124			} else {
37125				mapBreakpoints = {
37126					'xs': dataXsSpeed,
37127					'sm': dataMobileSpeed,
37128					'md': dataTabletSpeed,
37129					'lg': dataDesktopSpeed
37130				};
37131			}
37132
37133			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
37134			// ensures elements are positioned based on HTML layout.
37135			//
37136			// If the element has the percentage attribute, the posY and posX needs to be
37137			// the current scroll position's value, so that the elements are still positioned based on HTML layout
37138			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37139			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
37140			if (self.options.relativeToWrapper) {
37141				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37142				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
37143			}
37144			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
37145			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;
37146
37147			var blockTop = posY + el.getBoundingClientRect().top;
37148			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
37149
37150			var blockLeft = posX + el.getBoundingClientRect().left;
37151			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
37152
37153			// apparently parallax equation everyone uses
37154			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
37155			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
37156			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
37157
37158			// Optional individual block speed as data attr, otherwise global speed
37159			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
37160			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
37161			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
37162
37163			// Optional individual block movement axis direction as data attr, otherwise global movement direction
37164			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
37165			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
37166
37167			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
37168
37169			// ~~Store non-translate3d transforms~~
37170			// Store inline styles and extract transforms
37171			var style = el.style.cssText;
37172			var transform = '';
37173
37174			// Check if there's an inline styled transform
37175			var searchResult = /transform\s*:/i.exec(style);
37176			if (searchResult) {
37177				// Get the index of the transform
37178				var index = searchResult.index;
37179
37180				// Trim the style to the transform point and get the following semi-colon index
37181				var trimmedStyle = style.slice(index);
37182				var delimiter = trimmedStyle.indexOf(';');
37183
37184				// Remove "transform" string and save the attribute
37185				if (delimiter) {
37186					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
37187				} else {
37188					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
37189				}
37190			}
37191
37192			return {
37193				baseX: bases.x,
37194				baseY: bases.y,
37195				top: blockTop,
37196				left: blockLeft,
37197				height: blockHeight,
37198				width: blockWidth,
37199				speed: speed,
37200				verticalSpeed: verticalSpeed,
37201				horizontalSpeed: horizontalSpeed,
37202				verticalScrollAxis: verticalScrollAxis,
37203				horizontalScrollAxis: horizontalScrollAxis,
37204				style: style,
37205				transform: transform,
37206				zindex: dataZindex,
37207				min: dataMin,
37208				max: dataMax,
37209				minX: dataMinX,
37210				maxX: dataMaxX,
37211				minY: dataMinY,
37212				maxY: dataMaxY
37213			};
37214		};
37215
37216		// set scroll position (posY, posX)
37217		// side effect method is not ideal, but okay for now
37218		// returns true if the scroll changed, false if nothing happened
37219		var setPosition = function() {
37220			var oldY = posY;
37221			var oldX = posX;
37222
37223			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37224			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
37225			// If option relativeToWrapper is true, use relative wrapper value instead.
37226			if (self.options.relativeToWrapper) {
37227				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37228				posY = scrollPosY - self.options.wrapper.offsetTop;
37229			}
37230
37231
37232			if (oldY != posY && self.options.vertical) {
37233				// scroll changed, return true
37234				return true;
37235			}
37236
37237			if (oldX != posX && self.options.horizontal) {
37238				// scroll changed, return true
37239				return true;
37240			}
37241
37242			// scroll did not change
37243			return false;
37244		};
37245
37246		// Ahh a pure function, gets new transform value
37247		// based on scrollPosition and speed
37248		// Allow for decimal pixel values
37249		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
37250			var result = {};
37251			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
37252			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
37253
37254			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
37255			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
37256
37257			return result;
37258		};
37259
37260		// Remove event listeners and loop again
37261		var deferredUpdate = function() {
37262			window.removeEventListener('resize', deferredUpdate);
37263			window.removeEventListener('orientationchange', deferredUpdate);
37264			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
37265			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
37266
37267			// loop again
37268			loopId = loop(update);
37269		};
37270
37271		// Loop
37272		var update = function() {
37273			if (setPosition() && pause === false) {
37274				animate();
37275
37276				// loop again
37277				loopId = loop(update);
37278			} else {
37279				loopId = null;
37280
37281				// Don't animate until we get a position updating event
37282				window.addEventListener('resize', deferredUpdate);
37283				window.addEventListener('orientationchange', deferredUpdate);
37284				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
37285				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
37286			}
37287		};
37288
37289		// Transform3d on parallax element
37290		var animate = function() {
37291			var positions;
37292			for (var i = 0; i < self.elems.length; i++){
37293				// Determine relevant movement directions
37294				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
37295				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
37296				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
37297				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
37298				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
37299				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
37300
37301				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
37302				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
37303
37304				// Subtracting initialize value, so element stays in same spot as HTML
37305				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
37306				var positionY = positions.y - blocks[i].baseY;
37307				var positionX = positions.x - blocks[i].baseX;
37308
37309				// The next two "if" blocks go like this:
37310				// Check if a limit is defined (first "min", then "max");
37311				// Check if we need to change the Y or the X
37312				// (Currently working only if just one of the axes is enabled)
37313				// Then, check if the new position is inside the allowed limit
37314				// If so, use new position. If not, set position to limit.
37315
37316				// Check if a min limit is defined
37317				if (blocks[i].min !== null) {
37318					if (self.options.vertical && !self.options.horizontal) {
37319						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
37320					}
37321					if (self.options.horizontal && !self.options.vertical) {
37322						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
37323					}
37324				}
37325
37326				// Check if directional min limits are defined
37327				if (blocks[i].minY != null) {
37328						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
37329				}
37330				if (blocks[i].minX != null) {
37331						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
37332				}
37333
37334				// Check if a max limit is defined
37335				if (blocks[i].max !== null) {
37336					if (self.options.vertical && !self.options.horizontal) {
37337						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
37338					}
37339					if (self.options.horizontal && !self.options.vertical) {
37340						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
37341					}
37342				}
37343
37344				// Check if directional max limits are defined
37345				if (blocks[i].maxY != null) {
37346						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
37347				}
37348				if (blocks[i].maxX != null) {
37349						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
37350				}
37351
37352				var zindex = blocks[i].zindex;
37353
37354				// Move that element
37355				// (Set the new translation and append initial inline transforms.)
37356				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
37357				self.elems[i].style[transformProp] = translate;
37358			}
37359			self.options.callback(positions);
37360		};
37361
37362		self.destroy = function() {
37363			for (var i = 0; i < self.elems.length; i++){
37364				self.elems[i].style.cssText = blocks[i].style;
37365			}
37366
37367			// Remove resize event listener if not pause, and pause
37368			if (!pause) {
37369				window.removeEventListener('resize', init);
37370				pause = true;
37371			}
37372
37373			// Clear the animation loop to prevent possible memory leak
37374			clearLoop(loopId);
37375			loopId = null;
37376		};
37377
37378		// Init
37379		init();
37380
37381		// Allow to recalculate the initial values whenever we want
37382		self.refresh = init;
37383
37384		return self;
37385	};
37386	return Rellax;
37387}));
37388
37389/*
37390 * OKVideo by OKFocus v2.3.2
37391 * http://okfoc.us
37392 *
37393 * Copyright 2014, OKFocus
37394 * Licensed under the MIT license.
37395 *
37396 */
37397var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
37398// youtube player ready
37399function onYouTubeIframeAPIReady() {
37400	YTplayers = new Array();
37401	jQuery('.uncode-video-container.video').each(function() {
37402		var playerY;
37403		if (jQuery(this).attr('data-provider') == 'youtube') {
37404			var id = jQuery(this).attr('data-id'),
37405				start = jQuery(this).attr('data-start'),
37406				end = jQuery(this).attr('data-end');
37407			start = typeof start && start !== null ? start : 0;
37408			end = typeof end && end !== null ? end : 0;
37409			options = jQuery(window).data('okoptions-' + id);
37410			if ( typeof options === 'undefined' ) {
37411				return true;
37412			}
37413			options.time = jQuery(this).attr('data-t');
37414			playerY = new YT.Player('okplayer-' + id, {
37415				videoId: options.video ? options.video.id : null,
37416				playerVars: {
37417					'autohide': 1,
37418					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
37419					'disablekb': 1,
37420					'cc_load_policy': options.captions,
37421					'controls': 0,
37422					'enablejsapi': 1,
37423					'fs': 0,
37424					'modestbranding': 1,
37425					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
37426					'iv_load_policy': options.annotations,
37427					'loop': options.loop,
37428					'showinfo': 0,
37429					'rel': 0,
37430					'wmode': 'opaque',
37431					'hd': options.hd,
37432					'mute': 1,
37433					'start': start,
37434					'end': end
37435				},
37436				events: {
37437					'onReady': OKEvents.yt.ready,
37438					'onStateChange': OKEvents.yt.onStateChange,
37439					'onError': OKEvents.yt.error
37440				}
37441			});
37442			YTplayers[id] = playerY;
37443			playerY.videoId = id;
37444		}
37445
37446	});
37447}
37448// vimeo player ready
37449function vimeoPlayerReady(id) {
37450	options = jQuery(window).data('okoptions-' + id);
37451	if ( typeof options === 'undefined' ) {
37452		return true;
37453	}
37454	var jIframe = options.jobject,
37455		iframe = jIframe[0];
37456
37457	jIframe.attr('src', jIframe.data('src'));
37458	var playerV = new Vimeo.Player(iframe);
37459	// hide player until Vimeo hides controls...
37460	playerV.on('loaded', function(e) {
37461		OKEvents.v.onReady(iframe);
37462		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
37463		if (carouselContainer.length) {
37464			UNCODE.owlPlayVideo(carouselContainer);
37465		}
37466		// "Do not try to add listeners or call functions before receiving this event."
37467		if (OKEvents.utils.isMobile()) {
37468			// mobile devices cannot listen for play event
37469			OKEvents.v.onPlay(playerV);
37470		} else {
37471			playerV.on('play', function(){
37472				OKEvents.v.onPlay(playerV);
37473				jQuery(window).trigger('okevents.v.play', [playerV]);
37474			});
37475			playerV.on('pause', function(){
37476				OKEvents.v.onPause;
37477				jQuery(window).trigger('okevents.v.pause', [playerV]);
37478			});
37479			playerV.on('ended', function(){
37480				OKEvents.v.onFinish
37481				jQuery(window).trigger('okevents.v.ended', [playerV]);
37482			});
37483		}
37484		if (options.time != null) {
37485			var optsTimeStr = (options.time).replace('t=', ''),
37486				timeV = '';
37487
37488			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
37489				var timeArr = optsTimeStr.split(/([^\d.-])/);
37490				for ( var i = 0; i < timeArr.length; i++ ) {
37491					if ( timeArr[i] === 'h' ) {
37492						timeV += parseFloat(timeArr[i-1]) * 3600;
37493					} else if ( timeArr[i] === 'm' ) {
37494						timeV += parseFloat(timeArr[i-1]) * 60;
37495					} else if ( timeArr[i] === 's' ) {
37496						timeV += parseFloat(timeArr[i-1]);
37497					}
37498				}
37499			} else {
37500				timeV = optsTimeStr;
37501			}
37502
37503			playerV.setCurrentTime(timeV);
37504		}
37505
37506		playerV.setVolume(0);
37507		playerV.play();
37508		jQuery(iframe).css({
37509			visibility: 'visible',
37510			opacity: 1
37511		});
37512		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37513		jQuery(iframe).closest('#page-header').addClass('video-started');
37514		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37515
37516		jQuery(window).trigger('okevents.v.loaded', [playerV]);
37517	});
37518}
37519OKEvents = {
37520	yt: {
37521		ready: function(event) {
37522			var id = event.target.videoId,
37523				$video = jQuery('#okplayer-' + id),
37524				options = jQuery(window).data('okoptions-' + id);
37525			if ( typeof options === 'undefined' ) {
37526				return true;
37527			}
37528			youtubePlayers[id] = event.target;
37529			event.target.setVolume(options.volume);
37530			if (options.autoplay === 1) {
37531				if (options.playlist.list) {
37532					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
37533				} else {
37534					var inCarousel = $video.closest('.owl-item');
37535					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
37536						if (options.time != null) {
37537							event.target.seekTo(parseInt(options.time));
37538						}
37539						event.target.playVideo();
37540					} else {
37541						event.target.pauseVideo();
37542					}
37543				}
37544			}
37545			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
37546
37547			$video.closest('[data-provider]').on('uncode-resume', function(){
37548				if (options.time != null) {
37549					event.target.seekTo(parseInt(options.time)).playVideo();
37550				} else {
37551					event.target.seekTo(0).playVideo();
37552				}
37553			});
37554
37555			$video.closest('[data-provider]').on('uncode-pause', function(){
37556				if (options.time != null) {
37557					event.target.seekTo(parseInt(options.time)).pauseVideo();
37558				} else {
37559					event.target.seekTo(0).pauseVideo();
37560				}
37561			});
37562			jQuery(window).trigger('okevents.y.loaded', [event]);
37563		},
37564		onStateChange: function(event) {
37565			var id = event.target.videoId,
37566				$video = jQuery('#okplayer-' + id),
37567				options = jQuery(window).data('okoptions-' + id);
37568			if ( typeof options === 'undefined' ) {
37569				return true;
37570			}
37571			youtubePlayers[id] = event.target;
37572			event.target.setVolume(options.volume);
37573			var $fluid = $video.closest('.fluid-object'),
37574				$tmb = $video.closest('.tmb'),
37575				setTime;
37576			switch (event.data) {
37577				case -1:
37578					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
37579					break;
37580				case 0:
37581					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
37582					options.loop && event.target.playVideo();
37583					break;
37584				case 1:
37585					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37586					setTimeout(function() {
37587						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
37588						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37589						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
37590						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37591					}, 300);
37592				break;
37593				case 2:
37594					OKEvents.utils.isFunction(options.onPause) && options.onPause();
37595					break;
37596				case 3:
37597					OKEvents.utils.isFunction(options.buffering) && options.buffering();
37598					break;
37599				case 5:
37600					OKEvents.utils.isFunction(options.cued) && options.cued();
37601					break;
37602				default:
37603					throw "OKVideo: received invalid data from YT player.";
37604			}
37605
37606			jQuery(window).trigger('okevents.y.change', [event]);
37607		},
37608		error: function(event) {
37609			throw event;
37610		}
37611	},
37612	v: {
37613		onReady: function(target) {
37614			if ( typeof options === 'undefined' ) {
37615				return true;
37616			}
37617			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
37618		},
37619		onPlay: function(player) {
37620			if ( typeof options === 'undefined' ) {
37621				return true;
37622			}
37623			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
37624			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37625			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37626			jQuery(player.element).closest('#page-header').addClass('video-started');
37627			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37628		},
37629		onPause: function() {
37630			if ( typeof options === 'undefined' ) {
37631				return true;
37632			}
37633			OKEvents.utils.isFunction(options.onPause) && options.onPause();
37634		},
37635		onFinish: function() {
37636			if ( typeof options === 'undefined' ) {
37637				return true;
37638			}
37639			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
37640		}
37641	},
37642	utils: {
37643		isFunction: function(func) {
37644			if (typeof func === 'function') {
37645				return true;
37646			} else {
37647				return false;
37648			}
37649		},
37650		isMobile: function() {
37651			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
37652				return true;
37653			} else {
37654				return false;
37655			}
37656		}
37657	}
37658};
37659
37660/**
37661 * vivus - JavaScript library to make drawing animation on SVG
37662 * @version v0.4.4
37663 * @link https://github.com/maxwellito/vivus
37664 * @license MIT
37665 */
37666
37667'use strict';
37668
37669(function () {
37670
37671  'use strict';
37672
37673/**
37674 * Pathformer
37675 * Beta version
37676 *
37677 * Take any SVG version 1.1 and transform
37678 * child elements to 'path' elements
37679 *
37680 * This code is purely forked from
37681 * https://github.com/Waest/SVGPathConverter
37682 */
37683
37684/**
37685 * Class constructor
37686 *
37687 * @param {DOM|String} element Dom element of the SVG or id of it
37688 */
37689function Pathformer(element) {
37690  // Test params
37691  if (typeof element === 'undefined') {
37692	throw new Error('Pathformer [constructor]: "element" parameter is required');
37693  }
37694
37695  // Set the element
37696  if (element.constructor === String) {
37697	element = document.getElementById(element);
37698	if (!element) {
37699	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
37700	}
37701  }
37702  if (element instanceof window.SVGElement ||
37703	  element instanceof window.SVGGElement ||
37704	  /^svg$/i.test(element.nodeName)) {
37705	this.el = element;
37706  } else {
37707	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
37708  }
37709
37710  // Start
37711  this.scan(element);
37712}
37713
37714/**
37715 * List of tags which can be transformed
37716 * to path elements
37717 *
37718 * @type {Array}
37719 */
37720Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
37721
37722/**
37723 * List of attribute names which contain
37724 * data. This array list them to check if
37725 * they contain bad values, like percentage.
37726 *
37727 * @type {Array}
37728 */
37729Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 37729-38527
37729y1', 'y2'];
37730
37731/**
37732 * Finds the elements compatible for transform
37733 * and apply the liked method
37734 *
37735 * @param  {object} options Object from the constructor
37736 */
37737Pathformer.prototype.scan = function (svg) {
37738  var fn, element, pathData, pathDom,
37739	  elements = svg.querySelectorAll(this.TYPES.join(','));
37740
37741  for (var i = 0; i < elements.length; i++) {
37742	element = elements[i];
37743	fn = this[element.tagName.toLowerCase() + 'ToPath'];
37744	pathData = fn(this.parseAttr(element.attributes));
37745	pathDom = this.pathMaker(element, pathData);
37746	element.parentNode.replaceChild(pathDom, element);
37747  }
37748};
37749
37750
37751/**
37752 * Read `line` element to extract and transform
37753 * data, to make it ready for a `path` object.
37754 *
37755 * @param  {DOMelement} element Line element to transform
37756 * @return {object}			 Data for a `path` element
37757 */
37758Pathformer.prototype.lineToPath = function (element) {
37759  var newElement = {},
37760	  x1 = element.x1 || 0,
37761	  y1 = element.y1 || 0,
37762	  x2 = element.x2 || 0,
37763	  y2 = element.y2 || 0;
37764
37765  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
37766  return newElement;
37767};
37768
37769/**
37770 * Read `rect` element to extract and transform
37771 * data, to make it ready for a `path` object.
37772 * The radius-border is not taken in charge yet.
37773 * (your help is more than welcomed)
37774 *
37775 * @param  {DOMelement} element Rect element to transform
37776 * @return {object}             Data for a `path` element
37777 */
37778Pathformer.prototype.rectToPath = function (element) {
37779  var newElement = {},
37780      x      = parseFloat(element.x)      || 0,
37781      y      = parseFloat(element.y)      || 0,
37782      width  = parseFloat(element.width)  || 0,
37783      height = parseFloat(element.height) || 0;
37784
37785  if (element.rx || element.ry) {
37786    var rx = parseInt(element.rx, 10) || -1,
37787        ry = parseInt(element.ry, 10) || -1;
37788    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
37789    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
37790
37791    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
37792                   'L ' + (x + width - rx) + ',' + y + ' ' +
37793                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
37794                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
37795                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
37796                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
37797                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
37798                   'L ' + x + ',' + (y + ry) + ' ' +
37799                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
37800  }
37801  else {
37802    newElement.d = 'M' + x + ' ' + y + ' ' +
37803                   'L' + (x + width) + ' ' + y + ' ' +
37804                   'L' + (x + width) + ' ' + (y + height) + ' ' +
37805                   'L' + x + ' ' + (y + height) + ' Z';
37806  }
37807  return newElement;
37808};
37809
37810/**
37811 * Read `polyline` element to extract and transform
37812 * data, to make it ready for a `path` object.
37813 *
37814 * @param  {DOMelement} element Polyline element to transform
37815 * @return {object}             Data for a `path` element
37816 */
37817Pathformer.prototype.polylineToPath = function (element) {
37818  var newElement = {},
37819      points = element.points.trim().split(' '),
37820      i, path;
37821
37822  // Reformatting if points are defined without commas
37823  if (element.points.indexOf(',') === -1) {
37824    var formattedPoints = [];
37825    for (i = 0; i < points.length; i+=2) {
37826      formattedPoints.push(points[i] + ',' + points[i+1]);
37827    }
37828    points = formattedPoints;
37829  }
37830
37831  // Generate the path.d value
37832  path = 'M' + points[0];
37833  for(i = 1; i < points.length; i++) {
37834    if (points[i].indexOf(',') !== -1) {
37835      path += 'L' + points[i];
37836    }
37837  }
37838  newElement.d = path;
37839  return newElement;
37840};
37841
37842/**
37843 * Read `polygon` element to extract and transform
37844 * data, to make it ready for a `path` object.
37845 * This method rely on polylineToPath, because the
37846 * logic is similar. The path created is just closed,
37847 * so it needs an 'Z' at the end.
37848 *
37849 * @param  {DOMelement} element Polygon element to transform
37850 * @return {object}             Data for a `path` element
37851 */
37852Pathformer.prototype.polygonToPath = function (element) {
37853  var newElement = Pathformer.prototype.polylineToPath(element);
37854
37855  newElement.d += 'Z';
37856  return newElement;
37857};
37858
37859/**
37860 * Read `ellipse` element to extract and transform
37861 * data, to make it ready for a `path` object.
37862 *
37863 * @param  {DOMelement} element ellipse element to transform
37864 * @return {object}             Data for a `path` element
37865 */
37866Pathformer.prototype.ellipseToPath = function (element) {
37867  var newElement = {},
37868      rx = parseFloat(element.rx) || 0,
37869      ry = parseFloat(element.ry) || 0,
37870      cx = parseFloat(element.cx) || 0,
37871      cy = parseFloat(element.cy) || 0,
37872      startX = cx - rx,
37873      startY = cy,
37874      endX = parseFloat(cx) + parseFloat(rx),
37875      endY = cy;
37876
37877  newElement.d = 'M' + startX + ',' + startY +
37878                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37879                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37880  return newElement;
37881};
37882
37883/**
37884 * Read `circle` element to extract and transform
37885 * data, to make it ready for a `path` object.
37886 *
37887 * @param  {DOMelement} element Circle element to transform
37888 * @return {object}             Data for a `path` element
37889 */
37890Pathformer.prototype.circleToPath = function (element) {
37891  var newElement = {},
37892      r  = parseFloat(element.r)  || 0,
37893      cx = parseFloat(element.cx) || 0,
37894      cy = parseFloat(element.cy) || 0,
37895      startX = cx - r,
37896      startY = cy,
37897      endX = parseFloat(cx) + parseFloat(r),
37898      endY = cy;
37899
37900  newElement.d =  'M' + startX + ',' + startY +
37901                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37902                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37903  return newElement;
37904};
37905
37906/**
37907 * Create `path` elements form original element
37908 * and prepared objects
37909 *
37910 * @param  {DOMelement} element  Original element to transform
37911 * @param  {object} pathData     Path data (from `toPath` methods)
37912 * @return {DOMelement}          Path element
37913 */
37914Pathformer.prototype.pathMaker = function (element, pathData) {
37915  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37916  for(i = 0; i < element.attributes.length; i++) {
37917    attr = element.attributes[i];
37918    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37919      pathTag.setAttribute(attr.name, attr.value);
37920    }
37921  }
37922  for(i in pathData) {
37923    pathTag.setAttribute(i, pathData[i]);
37924  }
37925  return pathTag;
37926};
37927
37928/**
37929 * Parse attributes of a DOM element to
37930 * get an object of attribute => value
37931 *
37932 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37933 * @return {object}                  Object of attributes
37934 */
37935Pathformer.prototype.parseAttr = function (element) {
37936  var attr, output = {};
37937  for (var i = 0; i < element.length; i++) {
37938    attr = element[i];
37939    // Check if no data attribute contains '%', or the transformation is impossible
37940    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37941      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37942    }
37943    output[attr.name] = attr.value;
37944  }
37945  return output;
37946};
37947
37948  'use strict';
37949
37950var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37951
37952/**
37953 * Vivus
37954 * Beta version
37955 *
37956 * Take any SVG and make the animation
37957 * to give give the impression of live drawing
37958 *
37959 * This in more than just inspired from codrops
37960 * At that point, it's a pure fork.
37961 */
37962
37963/**
37964 * Class constructor
37965 * option structure
37966 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
37967 *   duration: <int> (in frames)
37968 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
37969 *   delay: <int> (delay between the drawing of first and last path)
37970 *   dashGap <integer> whitespace extra margin between dashes
37971 *   pathTimingFunction <function> timing animation function for each path element of the SVG
37972 *   animTimingFunction <function> timing animation function for the complete SVG
37973 *   forceRender <boolean> force the browser to re-render all updated path items
37974 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
37975 *
37976 * The attribute 'type' is by default on 'delayed'.
37977 *  - 'delayed'
37978 *    all paths are draw at the same time but with a
37979 *    little delay between them before start
37980 *  - 'sync'
37981 *    all path are start and finish at the same time
37982 *  - 'oneByOne'
37983 *    only one path is draw at the time
37984 *    the end of the first one will trigger the draw
37985 *    of the next one
37986 *
37987 * All these values can be overwritten individually
37988 * for each path item in the SVG
37989 * The value of frames will always take the advantage of
37990 * the duration value.
37991 * If you fail somewhere, an error will be thrown.
37992 * Good luck.
37993 *
37994 * @constructor
37995 * @this {Vivus}
37996 * @param {DOM|String}   element  Dom element of the SVG or id of it
37997 * @param {Object}       options  Options about the animation
37998 * @param {Function}     callback Callback for the end of the animation
37999 */
38000function Vivus (element, options, callback) {
38001
38002  setupEnv();
38003
38004  // Setup
38005  this.isReady = false;
38006  this.setElement(element, options);
38007  this.setOptions(options);
38008  this.setCallback(callback);
38009
38010  if (this.isReady) {
38011    this.init();
38012  }
38013}
38014
38015/**
38016 * Timing functions
38017 **************************************
38018 *
38019 * Default functions to help developers.
38020 * It always take a number as parameter (between 0 to 1) then
38021 * return a number (between 0 and 1)
38022 */
38023Vivus.LINEAR          = function (x) {return x;};
38024Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
38025Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
38026Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
38027Vivus.EASE_OUT_BOUNCE = function (x) {
38028  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
38029    rate = Math.pow(base,1.5),
38030    rateR = Math.pow(1 - x, 2),
38031    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
38032  return (1- rateR) + (progress * rateR);
38033};
38034
38035
38036/**
38037 * Setters
38038 **************************************
38039 */
38040
38041/**
38042 * Check and set the element in the instance
38043 * The method will not return anything, but will throw an
38044 * error if the parameter is invalid
38045 *
38046 * @param {DOM|String}   element  SVG Dom element or id of it
38047 */
38048Vivus.prototype.setElement = function (element, options) {
38049  var onLoad, self;
38050
38051  // Basic check
38052  if (typeof element === 'undefined') {
38053    throw new Error('Vivus [constructor]: "element" parameter is required');
38054  }
38055
38056  // Set the element
38057  if (element.constructor === String) {
38058    element = document.getElementById(element);
38059    if (!element) {
38060      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
38061    }
38062  }
38063  this.parentEl = element;
38064
38065  // Load the SVG with XMLHttpRequest and extract the SVG
38066  if (options && options.file) {
38067    var self = this;
38068    onLoad = function (e) {
38069      var domSandbox = document.createElement('div');
38070      domSandbox.innerHTML = this.responseText;
38071
38072      var svgTag = domSandbox.querySelector('svg');
38073      if (!svgTag) {
38074        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
38075      }
38076
38077      self.el = svgTag
38078      self.el.setAttribute('width', '100%');
38079      self.el.setAttribute('height', '100%');
38080      self.parentEl.appendChild(self.el)
38081      self.isReady = true;
38082      self.init();
38083      self = null;
38084    }
38085
38086    var oReq = new window.XMLHttpRequest();
38087    oReq.addEventListener('load', onLoad);
38088    oReq.open('GET', options.file);
38089    oReq.send();
38090    return;
38091  }
38092
38093  switch (element.constructor) {
38094  case window.SVGSVGElement:
38095  case window.SVGElement:
38096  case window.SVGGElement:
38097    this.el = element;
38098    this.isReady = true;
38099    break;
38100
38101  case window.HTMLObjectElement:
38102    self = this;
38103    onLoad = function (e) {
38104      if (self.isReady) {
38105        return;
38106      }
38107      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
38108      if (!self.el && e) {
38109        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
38110      }
38111      else if (self.el) {
38112        if (element.getAttribute('built-by-vivus')) {
38113          self.parentEl.insertBefore(self.el, element);
38114          self.parentEl.removeChild(element);
38115          self.el.setAttribute('width', '100%');
38116          self.el.setAttribute('height', '100%');
38117        }
38118        self.isReady = true;
38119        self.init();
38120        self = null;
38121      }
38122    };
38123
38124    if (!onLoad()) {
38125      element.addEventListener('load', onLoad);
38126    }
38127    break;
38128
38129  default:
38130    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
38131  }
38132};
38133
38134/**
38135 * Set up user option to the instance
38136 * The method will not return anything, but will throw an
38137 * error if the parameter is invalid
38138 *
38139 * @param  {object} options Object from the constructor
38140 */
38141Vivus.prototype.setOptions = function (options) {
38142  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
38143  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
38144
38145  // Basic check
38146  if (options !== undefined && options.constructor !== Object) {
38147    throw new Error('Vivus [constructor]: "options" parameter must be an object');
38148  }
38149  else {
38150    options = options || {};
38151  }
38152
38153  // Set the animation type
38154  if (options.type && allowedTypes.indexOf(options.type) === -1) {
38155    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
38156  }
38157  else {
38158    this.type = options.type || allowedTypes[0];
38159  }
38160
38161  // Set the start type
38162  if (options.start && allowedStarts.indexOf(options.start) === -1) {
38163    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
38164  }
38165  else {
38166    this.start = options.start || allowedStarts[0];
38167  }
38168
38169  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
38170  this.duration     = parsePositiveInt(options.duration, 120);
38171  this.delay        = parsePositiveInt(options.delay, null);
38172  //Uncode addition
38173  this.delayStart   = parsePositiveInt(options.delayStart, null);
38174  //#END
38175  this.dashGap      = parsePositiveInt(options.dashGap, 1);
38176  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
38177  this.reverseStack = !!options.reverseStack;
38178  this.selfDestroy  = !!options.selfDestroy;
38179  this.onReady      = options.onReady;
38180  this.map          = [];
38181  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
38182
38183  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
38184
38185  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
38186  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
38187
38188  if (this.delay >= this.duration) {
38189    throw new Error('Vivus [constructor]: delay must be shorter than duration');
38190  }
38191};
38192
38193/**
38194 * Set up callback to the instance
38195 * The method will not return enything, but will throw an
38196 * error if the parameter is invalid
38197 *
38198 * @param  {Function} callback Callback for the animation end
38199 */
38200Vivus.prototype.setCallback = function (callback) {
38201  // Basic check
38202  if (!!callback && callback.constructor !== Function) {
38203    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
38204  }
38205  this.callback = callback || function () {};
38206};
38207
38208
38209/**
38210 * Core
38211 **************************************
38212 */
38213
38214/**
38215 * Map the svg, path by path.
38216 * The method return nothing, it just fill the
38217 * `map` array. Each item in this array represent
38218 * a path element from the SVG, with informations for
38219 * the animation.
38220 *
38221 * ```
38222 * [
38223 *   {
38224 *     el: <DOMobj> the path element
38225 *     length: <number> length of the path line
38226 *     startAt: <number> time start of the path animation (in frames)
38227 *     duration: <number> path animation duration (in frames)
38228 *   },
38229 *   ...
38230 * ]
38231 * ```
38232 *
38233 */
38234Vivus.prototype.mapping = function () {
38235  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
38236  timePoint = totalLength = lengthMeter = 0;
38237  paths = this.el.querySelectorAll('path');
38238
38239  for (i = 0; i < paths.length; i++) {
38240    path = paths[i];
38241    if (this.isInvisible(path)) {
38242      continue;
38243    }
38244    pathObj = {
38245      el: path,
38246      length: Math.ceil(path.getTotalLength())
38247    };
38248    // Test if the path length is correct
38249    if (isNaN(pathObj.length)) {
38250      if (window.console && console.warn) {
38251        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
38252      }
38253      continue;
38254    }
38255    this.map.push(pathObj);
38256    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
38257    path.style.strokeDashoffset = pathObj.length + this.dashGap;
38258    pathObj.length += this.dashGap;
38259    totalLength += pathObj.length;
38260
38261    this.renderPath(i);
38262  }
38263
38264  totalLength = totalLength === 0 ? 1 : totalLength;
38265  this.delay = this.delay === null ? this.duration / 3 : this.delay;
38266  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
38267
38268  // Reverse stack if asked
38269  if (this.reverseStack) {
38270    this.map.reverse();
38271  }
38272
38273  for (i = 0; i < this.map.length; i++) {
38274    pathObj = this.map[i];
38275
38276    switch (this.type) {
38277    case 'delayed':
38278      pathObj.startAt = this.delayUnit * i;
38279      pathObj.duration = this.duration - this.delay;
38280      break;
38281
38282    case 'oneByOne':
38283      pathObj.startAt = lengthMeter / totalLength * this.duration;
38284      pathObj.duration = pathObj.length / totalLength * this.duration;
38285      break;
38286
38287    case 'sync':
38288    case 'async':
38289    case 'nsync':
38290      pathObj.startAt = 0;
38291      pathObj.duration = this.duration;
38292      break;
38293
38294    case 'scenario-sync':
38295      path = pathObj.el;
38296      pAttrs = this.parseAttr(path);
38297      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
38298      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38299      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
38300      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38301      break;
38302
38303    case 'scenario':
38304      path = pathObj.el;
38305      pAttrs = this.parseAttr(path);
38306      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
38307      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38308      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38309      break;
38310    }
38311    lengthMeter += pathObj.length;
38312    this.frameLength = this.frameLength || this.duration;
38313  }
38314};
38315
38316/**
38317 * Interval method to draw the SVG from current
38318 * position of the animation. It update the value of
38319 * `currentFrame` and re-trace the SVG.
38320 *
38321 * It use this.handle to store the requestAnimationFrame
38322 * and clear it one the animation is stopped. So this
38323 * attribute can be used to know if the animation is
38324 * playing.
38325 *
38326 * Once the animation at the end, this method will
38327 * trigger the Vivus callback.
38328 *
38329 */
38330Vivus.prototype.drawer = function () {
38331  var self = this;
38332  this.currentFrame += this.speed;
38333
38334  if (this.currentFrame <= 0) {
38335    this.stop();
38336    this.reset();
38337  } else if (this.currentFrame >= this.frameLength) {
38338    this.stop();
38339    this.currentFrame = this.frameLength;
38340    this.trace();
38341    if (this.selfDestroy) {
38342      this.destroy();
38343    }
38344  } else {
38345    this.trace();
38346    this.handle = requestAnimFrame(function () {
38347      self.drawer();
38348    });
38349    return;
38350  }
38351
38352  this.callback(this);
38353  if (this.instanceCallback) {
38354    this.instanceCallback(this);
38355    this.instanceCallback = null;
38356  }
38357};
38358
38359/**
38360 * Draw the SVG at the current instant from the
38361 * `currentFrame` value. Here is where most of the magic is.
38362 * The trick is to use the `strokeDashoffset` style property.
38363 *
38364 * For optimisation reasons, a new property called `progress`
38365 * is added in each item of `map`. This one contain the current
38366 * progress of the path element. Only if the new value is different
38367 * the new value will be applied to the DOM element. This
38368 * method save a lot of resources to re-render the SVG. And could
38369 * be improved if the animation couldn't be played forward.
38370 *
38371 */
38372Vivus.prototype.trace = function () {
38373  var i, progress, path, currentFrame;
38374  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
38375  for (i = 0; i < this.map.length; i++) {
38376    path = this.map[i];
38377    progress = (currentFrame - path.startAt) / path.duration;
38378    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
38379    if (path.progress !== progress) {
38380      path.progress = progress;
38381      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
38382      this.renderPath(i);
38383    }
38384  }
38385};
38386
38387/**
38388 * Method forcing the browser to re-render a path element
38389 * from it's index in the map. Depending on the `forceRender`
38390 * value.
38391 * The trick is to replace the path element by it's clone.
38392 * This practice is not recommended because it's asking more
38393 * ressources, too much DOM manupulation..
38394 * but it's the only way to let the magic happen on IE.
38395 * By default, this fallback is only applied on IE.
38396 *
38397 * @param  {Number} index Path index
38398 */
38399Vivus.prototype.renderPath = function (index) {
38400  if (this.forceRender && this.map && this.map[index]) {
38401    var pathObj = this.map[index],
38402        newPath = pathObj.el.cloneNode(true);
38403    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
38404    pathObj.el = newPath;
38405  }
38406};
38407
38408/**
38409 * When the SVG object is loaded and ready,
38410 * this method will continue the initialisation.
38411 *
38412 * This this mainly due to the case of passing an
38413 * object tag in the constructor. It will wait
38414 * the end of the loading to initialise.
38415 *
38416 */
38417Vivus.prototype.init = function () {
38418  // Set object variables
38419  this.frameLength = 0;
38420  this.currentFrame = 0;
38421  this.map = [];
38422
38423  // Start
38424  new Pathformer(this.el);
38425  this.mapping();
38426  this.starter();
38427
38428  if (this.onReady) {
38429    this.onReady(this);
38430  }
38431};
38432
38433/**
38434 * Trigger to start of the animation.
38435 * Depending on the `start` value, a different script
38436 * will be applied.
38437 *
38438 * If the `start` value is not valid, an error will be thrown.
38439 * Even if technically, this is impossible.
38440 *
38441 */
38442Vivus.prototype.starter = function () {
38443  switch (this.start) {
38444  case 'manual':
38445    return;
38446
38447  case 'autostart':
38448    this.play();
38449    break;
38450
38451  case 'inViewport':
38452    var self = this,
38453    listener = function () {
38454      if (self.isInViewport(self.parentEl, 1)) {
38455        self.play();
38456        window.removeEventListener('scroll', listener);
38457        //Uncode addition
38458        window.removeEventListener('fp-slide-changed', listener);
38459        window.removeEventListener('fp-slide-scroll', listener);
38460        //#END
38461      }
38462    };
38463    window.addEventListener('scroll', listener);
38464    //Uncode addition
38465    window.addEventListener('fp-slide-changed', listener);
38466    window.addEventListener('fp-slide-scroll', listener);
38467    //#END
38468    listener();
38469    break;
38470  }
38471};
38472
38473
38474/**
38475 * Controls
38476 **************************************
38477 */
38478
38479/**
38480 * Get the current status of the animation between
38481 * three different states: 'start', 'progress', 'end'.
38482 * @return {string} Instance status
38483 */
38484Vivus.prototype.getStatus = function () {
38485  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
38486};
38487
38488/**
38489 * Reset the instance to the initial state : undraw
38490 * Be careful, it just reset the animation, if you're
38491 * playing the animation, this won't stop it. But just
38492 * make it start from start.
38493 *
38494 */
38495Vivus.prototype.reset = function () {
38496  return this.setFrameProgress(0);
38497};
38498
38499/**
38500 * Set the instance to the final state : drawn
38501 * Be careful, it just set the animation, if you're
38502 * playing the animation on rewind, this won't stop it.
38503 * But just make it start from the end.
38504 *
38505 */
38506Vivus.prototype.finish = function () {
38507  return this.setFrameProgress(1);
38508};
38509
38510/**
38511 * Set the level of progress of the drawing.
38512 *
38513 * @param {number} progress Level of progress to set
38514 */
38515Vivus.prototype.setFrameProgress = function (progress) {
38516  progress = Math.min(1, Math.max(0, progress));
38517  this.currentFrame = Math.round(this.frameLength * progress);
38518  this.trace();
38519  return this;
38520};
38521
38522/**
38523 * Play the animation at the desired speed.
38524 * Speed must be a valid number (no zero).
38525 * By default, the speed value is 1.
38526 * But a negative value is accepted to go forward.
38527 *
38528 * And works with float too.
38529 * But don't forget we are in JavaScript, se be nice
38530 * with him and give him a 1/2^x value.
38531 *
38532 * @param  {number} speed Animation speed [optional]
38533 */
38534Vivus.prototype.play = function (speed, callback) {
38535  this.instanceCallback = null;
38536
38537  if (speed && typeof speed === 'function') {
38538    this.instanceCallback = speed; // first parameter is actually the callback function
38539    speed = null;
38540  }
38541  else if (speed && typeof speed !== 'number') {
38542    throw new Error('Vivus [play]: invalid speed');
38543  }
38544  // if the first parameter wasn't the callback, check if the seconds was
38545  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
38546    this.instanceCallback = callback;
38547  }
38548
38549
38550  this.speed = speed || 1;
38551  //Uncode addition
38552  if (!this.handle) {
38553    var $this = this,
38554    delay = (this.delayStart != null) ? this.delayStart : 0;
38555    setTimeout(function() {
38556      $this.drawer();
38557    }, delay);
38558  }
38559  //#END
38560  return this;
38561};
38562
38563/**
38564 * Stop the current animation, if on progress.
38565 * Should not trigger any error.
38566 *
38567 */
38568Vivus.prototype.stop = function () {
38569  if (this.handle) {
38570    cancelAnimFrame(this.handle);
38571    this.handle = null;
38572  }
38573  return this;
38574};
38575
38576/**
38577 * Destroy the instance.
38578 * Remove all bad styling attributes on all
38579 * path tags
38580 *
38581 */
38582Vivus.prototype.destroy = function () {
38583  this.stop();
38584  var i, path;
38585  for (i = 0; i < this.map.length; i++) {
38586    path = this.map[i];
38587    path.el.style.strokeDashoffset = null;
38588    path.el.style.strokeDasharray = null;
38589    this.renderPath(i);
38590  }
38591};
38592
38593
38594/**
38595 * Utils methods
38596 * include methods from Codrops
38597 **************************************
38598 */
38599
38600/**
38601 * Method to best guess if a path should added into
38602 * the animation or not.
38603 *
38604 * 1. Use the `data-vivus-ignore` attribute if set
38605 * 2. Check if the instance must ignore invisible paths
38606 * 3. Check if the path is visible
38607 *
38608 * For now the visibility checking is unstable.
38609 * It will be used for a beta phase.
38610 *
38611 * Other improvments are planned. Like detecting
38612 * is the path got a stroke or a valid opacity.
38613 */
38614Vivus.prototype.isInvisible = function (el) {
38615  var rect,
38616    ignoreAttr = el.getAttribute('data-ignore');
38617
38618  if (ignoreAttr !== null) {
38619    return ignoreAttr !== 'false';
38620  }
38621
38622  if (this.ignoreInvisible) {
38623    rect = el.getBoundingClientRect();
38624    return !rect.width && !rect.height;
38625  }
38626  else {
38627    return false;
38628  }
38629};
38630
38631/**
38632 * Parse attributes of a DOM element to
38633 * get an object of {attributeName => attributeValue}
38634 *
38635 * @param  {object} element DOM element to parse
38636 * @return {object}         Object of attributes
38637 */
38638Vivus.prototype.parseAttr = function (element) {
38639  var attr, output = {};
38640  if (element && element.attributes) {
38641    for (var i = 0; i < element.attributes.length; i++) {
38642      attr = element.attributes[i];
38643      output[attr.name] = attr.value;
38644    }
38645  }
38646  return output;
38647};
38648
38649/**
38650 * Reply if an element is in the page viewport
38651 *
38652 * @param  {object} el Element to observe
38653 * @param  {number} h  Percentage of height
38654 * @return {boolean}
38655 */
38656Vivus.prototype.isInViewport = function (el, h) {
38657  var scrolled   = this.scrollY(),
38658    viewed       = scrolled + this.getViewportH(),
38659    elBCR        = el.getBoundingClientRect(),
38660    elHeight     = elBCR.height,
38661    elTop        = scrolled + elBCR.top,
38662    elBottom     = elTop + elHeight;
38663
38664  // if 0, the element is considered in the viewport as soon as it enters.
38665  // if 1, the element is considered in the viewport only when it's fully inside
38666  // value in percentage (1 >= h >= 0)
38667  h = h || 0;
38668
38669  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
38670};
38671
38672
38673/**
38674 * Get the viewport height in pixels
38675 *
38676 * @return {integer} Viewport height
38677 */
38678Vivus.prototype.getViewportH = function () {
38679  var client = this.docElem.clientHeight,
38680    inner = window.innerHeight;
38681
38682  if (client < inner) {
38683    return inner;
38684  }
38685  else {
38686    return client;
38687  }
38688};
38689
38690/**
38691 * Get the page Y offset
38692 *
38693 * @return {integer} Page Y offset
38694 */
38695Vivus.prototype.scrollY = function () {
38696  return window.pageYOffset || this.docElem.scrollTop;
38697};
38698
38699setupEnv = function () {
38700
38701  if (Vivus.prototype.docElem) {
38702    return;
38703  }
38704
38705  /**
38706   * Alias for document element
38707   *
38708   * @type {DOMelement}
38709   */
38710  Vivus.prototype.docElem = window.document.documentElement;
38711
38712  /**
38713   * Alias for `requestAnimationFrame` or
38714   * `setTimeout` function for deprecated browsers.
38715   *
38716   */
38717  requestAnimFrame = (function () {
38718    return (
38719      window.requestAnimationFrame       ||
38720      window.webkitRequestAnimationFrame ||
38721      window.mozRequestAnimationFrame    ||
38722      window.oRequestAnimationFrame      ||
38723      window.msRequestAnimationFrame     ||
38724      function(/* function */ callback){
38725        return window.setTimeout(callback, 1000 / 60);
38726      }
38727    );
38728  })();
38729
38730  /**
38731   * Alias for `cancelAnimationFrame` or
38732   * `cancelTimeout` function for deprecated browsers.
38733   *
38734   */
38735  cancelAnimFrame = (function () {
38736    return (
38737      window.cancelAnimationFrame       ||
38738      window.webkitCancelAnimationFrame ||
38739      window.mozCancelAnimationFrame    ||
38740      window.oCancelAnimationFrame      ||
38741      window.msCancelAnimationFrame     ||
38742      function(id){
38743        return window.clearTimeout(id);
38744      }
38745    );
38746  })();
38747};
38748
38749/**
38750 * Parse string to integer.
38751 * If the number is not positive or null
38752 * the method will return the default value
38753 * or 0 if undefined
38754 *
38755 * @param {string} value String to parse
38756 * @param {*}
38756 defaultValue Value to return if the result parsed is invalid
38757 * @return {number}
38758 *
38759 */
38760parsePositiveInt = function (value, defaultValue) {
38761  var output = parseInt(value, 10);
38762  return (output >= 0) ? output : defaultValue;
38763};
38764
38765
38766  if (typeof define === 'function' && define.amd) {
38767    // AMD. Register as an anonymous module.
38768    define([], function() {
38769      return Vivus;
38770    });
38771  } else if (typeof exports === 'object') {
38772    // Node. Does not work with strict CommonJS, but
38773    // only CommonJS-like environments that support module.exports,
38774    // like Node.
38775    module.exports = Vivus;
38776  } else {
38777    // Browser globals
38778    window.Vivus = Vivus;
38779  }
38780
38781}());

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.