PageSourceSearch

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

js theparlour.net collected 2026-09-26 09:00:38 UTC 1,290,438 bytes, 38,829 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					var $vmenu = $('body.vmenu .vmenu-container');
12471					if ( ! $vmenu.length && UNCODE.wwidth > UNCODE.mediaQuery ) {
12472						$(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12473					}
12474
12475					if (this.opts.subIndicators) {
12476						this.$subArrow = $('<span/>').addClass('sub-arrow');
12477						if (this.opts.subIndicatorsText) {
12478							this.$subArrow.html(this.opts.subIndicatorsText);
12479						}
12480					}
12481
12482					// make sure mouse detection is enabled
12483					initMouseDetection();
12484				}
12485
12486				// init sub menus
12487				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
12488
12489				this.$firstLink = this.$root.find('a').eq(0);
12490
12491				// find current item
12492				if (this.opts.markCurrentItem) {
12493					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
12494						reHash = /#.*/,
12495						locHref = window.location.href.replace(reDefaultDoc, ''),
12496						locHrefNoHash = locHref.replace(reHash, '');
12497					this.$root.find('a').each(function() {
12498						var href = this.href.replace(reDefaultDoc, ''),
12499							$this = $(this);
12500						if (href == locHref || href == locHrefNoHash) {
12501							$this.addClass('current');
12502							if (self.opts.markCurrentTree) {
12503								$this.parents('li').each(function() {
12504									var $this = $(this);
12505									if ($this.dataSM('sub')) {
12506										$this.children('a').addClass('current');
12507									}
12508								});
12509							}
12510						}
12511					});
12512				}
12513			},
12514			destroy: function() {
12515				this.menuHideAll();
12516				this.$root
12517					.removeData('smartmenus')
12518					.removeAttr('data-smartmenus-id')
12519					.removeDataSM('level')
12520					.unbind('.smartmenus')
12521					.undelegate('.smartmenus');
12522				var eNamespace = '.smartmenus' + this.rootId;
12523				$(document).unbind(eNamespace);
12524				$(window).unbind(eNamespace);
12525				if (this.opts.subIndicators) {
12526					this.$subArrow = null;
12527				}
12528				var self = this;
12529				$.each(this.subMenus, function() {
12530					if (this.hasClass('mega-menu')) {
12531						this.find('ul').removeDataSM('in-mega');
12532					}
12533					if (this.dataSM('shown-before')) {
12534						if (IElt8) {
12535							this.children().css({ styleFloat: '', width: '' });
12536						}
12537						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
12538							if (!IE6) {
12539								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
12540							} else {
12541								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
12542							}
12543						}
12544						if (this.dataSM('scroll-arrows')) {
12545							this.dataSM('scroll-arrows').remove();
12546						}
12547						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
12548					}
12549					if (self.opts.subIndicators) {
12550						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
12551					}
12552					this.removeDataSM('shown-before')
12553						.removeDataSM('ie-shim')
12554						.removeDataSM('scroll-arrows')
12555						.removeDataSM('parent-a')
12556						.removeDataSM('level')
12557						.removeDataSM('beforefirstshowfired')
12558						.parent().removeDataSM('sub');
12559				});
12560				if (this.opts.markCurrentItem) {
12561					this.$root.find('a.current').removeClass('current');
12562				}
12563				this.$root = null;
12564				this.$firstLink = null;
12565				this.$firstSub = null;
12566				if (this.$disableOverlay) {
12567					this.$disableOverlay.remove();
12568					this.$disableOverlay = null;
12569				}
12570				menuTrees.splice($.inArray(this, menuTrees), 1);
12571			},
12572			disable: function(noOverlay) {
12573				if (!this.disabled) {
12574					this.menuHideAll();
12575					// display overlay over the menu to prevent interaction
12576					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
12577						var pos = this.$root.offset();
12578						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
12579							position: 'absolute',
12580							top: pos.top,
12581							left: pos.left,
12582							width: this.$root.outerWidth(),
12583							height: this.$root.outerHeight(),
12584							zIndex: this.getStartZIndex() + 1,
12585							opacity: 0
12586						}).appendTo(document.body);
12587					}
12588					this.disabled = true;
12589				}
12590			},
12591			docClick: function(e) {
12592				// hide on any click outside the menu or on a menu link
12593				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
12594					this.menuHideAll($(e.target));
12595				}
12596			},
12597			docTouchEnd: function(e) {
12598				if (!this.lastTouch) {
12599					return;
12600				}
12601				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))) {
12602					if (this.hideTimeout) {
12603						clearTimeout(this.hideTimeout);
12604						this.hideTimeout = 0;
12605					}
12606					// hide with a delay to prevent triggering accidental unwanted click on some page element
12607					var self = this;
12608					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
12609				}
12610				this.lastTouch = null;
12611			},
12612			docTouchMove: function(e) {
12613				if (!this.lastTouch) {
12614					return;
12615				}
12616				var touchPoint = e.originalEvent.touches[0];
12617				this.lastTouch.x2 = touchPoint.pageX;
12618				this.lastTouch.y2 = touchPoint.pageY;
12619			},
12620			docTouchStart: function(e) {
12621				var touchPoint = e.originalEvent.touches[0];
12622				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
12623			},
12624			enable: function() {
12625				if (this.disabled) {
12626					if (this.$disableOverlay) {
12627						this.$disableOverlay.remove();
12628						this.$disableOverlay = null;
12629					}
12630					this.disabled = false;
12631				}
12632			},
12633			getHeight: function($elm) {
12634				return this.getOffset($elm, true);
12635			},
12636			// returns precise width/height float values in IE9+, FF4+, recent WebKit
12637			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
12638			getOffset: function($elm, height) {
12639				var old,
12640					$win = $(window),
12641					winW = $win.width();
12642				if ($elm.css('display') == 'none') {
12643					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
12644					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
12645					if ( 
12646						($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length)
12647						||
12648						($('body').hasClass('vmenu-offcanvas-overlay') && winW >= 960 && $elm.closest('.main-menu-container').length && !$elm.closest('.menu-horizontal-inner').length)
12649					) {
12650						$elm.closest('li').addClass('smartmenu-open-item');
12651					}
12652				}
12653				var defaultView = $elm[0].ownerDocument.defaultView,
12654					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
12655					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
12656				if (val) {
12657					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
12658	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
12659	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
12660	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
12661				} else {
12662					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
12663				}
12664				if (old) {
12665					$elm.hide().css(old);
12666				}
12667				return val;
12668			},
12669			getWidth: function($elm) {
12670				return this.getOffset($elm);
12671			},
12672			getStartZIndex: function() {
12673				var zIndex = parseInt(this.$root.css('z-index'));
12674				return !isNaN(zIndex) ? zIndex : 1;
12675			},
12676			handleEvents: function() {
12677				return !this.disabled && this.isCSSOn();
12678			},
12679			handleItemEvents: function($a) {
12680				return this.handleEvents() && !this.isLinkInMegaMenu($a);
12681			},
12682			isCollapsible: function() {
12683				return this.$firstSub.css('position') == 'static';
12684			},
12685			isCSSOn: function() {
12686				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';
12687			},
12688			isFixed: function() {
12689				return this.$root.css('position') == 'fixed';
12690			},
12691			isLinkInMegaMenu: function($a) {
12692				return !$a.parent().parent().dataSM('level');
12693			},
12694			isTouchMode: function() {
12695				return !mouse || this.isCollapsible();
12696			},
12697			itemActivate: function($a) {
12698				var $li = $a.parent(),
12699					$ul = $li.parent(),
12700					level = $ul.dataSM('level');
12701				// 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
12702				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
12703					var self = this;
12704					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
12705						self.itemActivate($(this).dataSM('parent-a'));
12706					});
12707				}
12708				// hide any visible deeper level sub menus
12709				if (this.visibleSubMenus.length > level) {
12710					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--) {
12711						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12712							this.menuHide(this.visibleSubMenus[i]);
12713						//}
12714					}
12715				}
12716				// save new active item and sub menu for this level
12717				this.activatedItems[level - 1] = $a;
12718				this.visibleSubMenus[level - 1] = $ul;
12719				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
12720					return;
12721				}
12722				// show the sub menu if this item has one
12723				var $sub = $li.dataSM('sub');
12724				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
12725					this.menuShow($sub);
12726				}
12727			},
12728			itemBlur: function(e) {
12729				var $a = $(e.currentTarget);
12730				if (!this.handleItemEvents($a)) {
12731					return;
12732				}
12733				this.$root.triggerHandler('blur.smapi', $a[0]);
12734			},
12735			itemClick: function(e) {
12736				var $a = $(e.currentTarget);
12737
12738				if (!this.handleItemEvents($a)) {
12739					return;
12740				}
12741				$a.removeDataSM('mousedown');
12742				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
12743					return false;
12744				}
12745				var $sub = $a.parent().dataSM('sub');
12746				if (this.isTouchMode()) {
12747					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
12748					if ($a.dataSM('href')) {
12749						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
12750					}
12751					// if the sub is not visible
12752					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12753						// try to activate the item and show the sub
12754						this.itemActivate($a);
12755						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
12756						// 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
12757						if ($sub.is(':visible')) {
12758							return false;
12759						}
12760					}
12761				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
12762					this.clickActivated = true;
12763					this.menuShow($sub);
12764					return false;
12765				}
12766				if ($a.hasClass('disabled')) {
12767					return false;
12768				}
12769				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
12770					return false;
12771				}
12772			},
12773			itemDown: function(e) {
12774				var $a = $(e.currentTarget);
12775				if (!this.handleItemEvents($a)) {
12776					return;
12777				}
12778				$a.dataSM('mousedown', true);
12779			},
12780			itemEnter: function(e) {
12781				var $a = $(e.currentTarget);
12782				if (!this.handleItemEvents($a)) {
12783					return;
12784				}
12785				if (!this.isTouchMode()) {
12786					if (this.showTimeout) {
12787						clearTimeout(this.showTimeout);
12788						this.showTimeout = 0;
12789					}
12790					var self = this;
12791					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
12792				}
12793				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
12794			},
12795			itemFocus: function(e) {
12796				var $a = $(e.currentTarget);
12797				if (!this.handleItemEvents($a)) {
12798					return;
12799				}
12800				// 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
12801				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
12802					this.itemActivate($a);
12803				}
12804				this.$root.triggerHandler('focus.smapi', $a[0]);
12805			},
12806			itemLeave: function(e) {
12807				var $a = $(e.currentTarget);
12808				if (!this.handleItemEvents($a)) {
12809					return;
12810				}
12811				if (!this.isTouchMode()) {
12812					if ($a[0].blur) {
12813						$a[0].blur();
12814					}
12815					if (this.showTimeout) {
12816						clearTimeout(this.showTimeout);
12817						this.showTimeout = 0;
12818					}
12819				}
12820				$a.removeDataSM('mousedown');
12821				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
12822			},
12823			itemTouchEnd: function(e) {
12824				var $a = $(e.currentTarget);
12825				if (!this.handleItemEvents($a)) {
12826					return;
12827				}
12828				// prevent the address bar on iPhone from sliding down when expanding a sub menu
12829				var $sub = $a.parent().dataSM('sub');
12830				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12831					$a.dataSM('href', $a.attr('href'));
12832					$a.attr('href', '#');
12833				}
12834			},
12835			menuFixLayout: function($ul) {
12836				// fixes a menu that is being shown for the first time
12837				if (!$ul.dataSM('shown-before')) {
12838					$ul.hide().dataSM('shown-before', true);
12839					// fix the layout of the items in IE<8
12840					if (IElt8) {
12841						$ul.children().css({ styleFloat: 'left', width: '100%' });
12842					}
12843				}
12844			},
12845			menuHide: function($sub) {
12846				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
12847					return;
12848				}
12849				$sub.stop(true, true);
12850				if ($sub.is(':visible')) {
12851					var complete = function() {
12852						// unset z-index
12853						if (IElt9) {
12854							$sub.parent().css('z-index', '');
12855						} else {
12856							$sub.css('z-index', '');
12857						}
12858					};
12859					// if sub is collapsible (mobile view)
12860					if (this.isCollapsible()) {
12861						if (this.opts.collapsibleHideFunction) {
12862							this.opts.collapsibleHideFunction.call(this, $sub, complete);
12863						} else {
12864							$sub.hide(this.opts.collapsibleHideDuration, complete);
12865						}
12866					} else {
12867						if (this.opts.hideFunction) {
12868							this.opts.hideFunction.call(this, $sub, complete);
12869						} else {
12870							$sub.hide(this.opts.hideDuration, complete);
12871						}
12872					}
12873					// remove IE iframe shim
12874					if ($sub.dataSM('ie-shim')) {
12875						$sub.dataSM('ie-shim').remove();
12876					}
12877					// deactivate scrolling if it is activated for this sub
12878					if ($sub.dataSM('scroll')) {
12879						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
12880					}
12881					// unhighlight parent item
12882					$sub.dataSM('parent-a').removeClass('highlighted');
12883					var level = $sub.dataSM('level');
12884					this.activatedItems.splice(level - 1, 1);
12885					this.visibleSubMenus.splice(level - 1, 1);
12886					this.$root.triggerHandler('hide.smapi', $sub[0]);
12887				}
12888			},
12889			menuHideAll: function($item) {
12890				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
12891				var $win = $(window),
12892					winW = $win.width();
12893				if (this.showTimeout) {
12894					clearTimeout(this.showTimeout);
12895					this.showTimeout = 0;
12896				}
12897				// hide all subs
12898				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
12899					if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) {
12900						if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) {
12901							this.menuHide(this.visibleSubMenus[i]);
12902							$(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item');
12903						} else {
12904							return;
12905						}
12906					} else {
12907						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12908							this.menuHide(this.visibleSubMenus[i]);
12909						//}
12910					}
12911				}
12912				// hide root if it's popup
12913				if (this.opts.isPopup) {
12914					this.$root.stop(true, true);
12915					if (this.$root.is(':visible')) {
12916						if (this.opts.hideFunction) {
12917							this.opts.hideFunction.call(this, this.$root);
12918						} else {
12919							this.$root.hide(this.opts.hideDuration);
12920						}
12921						// remove IE iframe shim
12922						if (this.$root.dataSM('ie-shim')) {
12923							this.$root.dataSM('ie-shim').remove();
12924						}
12925					}
12926				}
12927				this.activatedItems = [];
12928				this.visibleSubMenus = [];
12929				this.clickActivated = false;
12930				// reset z-index increment
12931				this.zIndexInc = 0;
12932			},
12933			menuIframeShim: function($ul) {
12934				// create iframe shim for the menu
12935				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
12936					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
12937						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
12938					);
12939				}
12940			},
12941			menuInit: function($ul) {
12942				if (!$ul.dataSM('in-mega')) {
12943					this.subMenus.push($ul);
12944					// mark UL's in mega drop downs (if any) so we can neglect them
12945					if ($ul.hasClass('mega-menu')) {
12946						$ul.find('ul').dataSM('in-mega', true);
12947					}
12948					// get level (much faster than, for example, using parentsUntil)
12949					var level = 2,
12950						par = $ul[0];
12951					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
12952						level++;
12953					}
12954					// cache stuff
12955					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
12956						.dataSM('level', level)
12957						.parent().dataSM('sub', $ul);
12958					// add sub indicator to parent item
12959					if (this.opts.subIndicators) {
12960						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
12961					}
12962				}
12963			},
12964			menuPosition: function($sub) {
12965				var fixIE = $('html.ie').length;
12966				// if (fixIE) {
12967				// 	var $rowParent = $($sub).closest('.main-menu-container');
12968				// 	$rowParent.height($rowParent.height());
12969				// }
12970				var $a = $sub.dataSM('parent-a'),
12971					$li = $sub.parent(),
12972					$ul = $sub.parent().parent(),
12973					// $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'),
12974					$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'),
12975					level = $sub.dataSM('level'),
12976					subW = this.getWidth($sub),
12977					subH = this.getHeight($sub),
12978					itemOffset = $a.offset(),
12979					itemX = itemOffset.left,
12980					itemY = itemOffset.top,
12981					itemW = this.getWidth($a),
12982					itemH = this.getHeight($a),
12983					$win = $(window),
12984					winX = $win.scrollLeft(),
12985					winY = $win.scrollTop(),
12986					winW = $win.width(),
12987					winH = $win.height(),
12988					containerW = $container.width(),
12989					containerOffsetX = containerW + ((winW - containerW) / 2),
12990					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
12991					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
12992					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
12993					x, y, leftPos;
12994
12995				if (horizontalParent) {
12996					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
12997					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
12998				} else {
12999					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
13000					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
13001				}
13002				if (this.opts.keepInViewport && !this.isCollapsible()) {
13003					if (this.isFixed()) {
13004						itemX -= winX;
13005						itemY -= winY;
13006						winX = winY = 0;
13007					}
13008					var absX = itemX + x,
13009						absY = itemY + y;
13010					if (this.opts.rightToLeftSubMenus && absX < winX) {
13011						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
13012					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
13013						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
13014					}
13015					if (!horizontalParent) {
13016						if (subH < winH && absY + subH > winY + winH) {
13017							y += winY + winH - subH - absY;
13018						} else if (subH >= winH || absY < winY) {
13019							y += winY - absY;
13020						}
13021					}
13022					// do we need scrolling?
13023					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
13024					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
13025						var self = this;
13026						if (!$sub.dataSM('scroll-arrows')) {
13027							$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]])
13028								.bind({
13029									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
13030									mouseleave: function(e) {
13031										self.menuScrollStop($sub);
13032										self.menuScrollOut($sub, e);
13033									},
13034									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
13035								})
13036								.insertAfter($sub)
13037							);
13038						}
13039						// bind events to show/hide arrows on hover and save scrolling data for this sub
13040						var vportY = winY - (itemY + itemH);
13041						$sub.dataSM('scroll', {
13042								vportY: vportY,
13043								subH: subH,
13044								winH: winH,
13045								step: 1
13046							})
13047							.bind({
13048								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
13049								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
13050								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
13051							})
13052							.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
13052StartZIndex() + this.zIndexInc })
13053							.eq(0).css('margin-top', vportY).end()
13054							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
13055							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
13056					}
13057				}
13058				if ( !$sub.closest('.menu-accordion').length ) {
13059					var rightPos = 'auto';
13060					if ( $sub.closest('.grid-filters').length ) {
13061						if ( $sub.closest('.text-right').length ) {
13062							leftPos = '0px';
13063							rightPos = 'auto';
13064						} else {
13065							leftPos = 'auto';
13066							rightPos = '0px';
13067						}
13068						x = 0;
13069					} else {
13070						if ( $sub.hasClass('mega-menu-inner') ) {
13071							$sub.css({ width: containerW});
13072							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
13073							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
13074								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
13075							}
13076							x = 0;
13077						} else {
13078							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
13079							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
13080						}
13081					}
13082				}
13083
13084				// $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) });
13085				$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) });
13086				// IE iframe shim
13087				this.menuIframeShim($sub);
13088				if ($sub.dataSM('ie-shim')) {
13089					$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) });
13090				}
13091			},
13092			menuScroll: function($sub, up, wheel) {
13093				var y = parseFloat($sub.css('margin-top')),
13094					scroll = $sub.dataSM('scroll'),
13095					navH = $('.navbar-main').outerHeight(),
13096					end = scroll.vportY + (up ? navH + 54 : scroll.winH - scroll.subH),
13097					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
13098				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
13099				y = parseFloat($sub.css('margin-top'));
13100				// show opposite arrow if appropriate
13101				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
13102					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
13103				}
13104				// accelerate when not using mousewheel to scroll
13105				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
13106					$sub.dataSM('scroll').step += 0.5;
13107				}
13108				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
13109				if (Math.abs(y - end) < 1) {
13110					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
13111					$sub.dataSM('scroll').step = 1;
13112				} else if (!wheel) {
13113					var self = this;
13114					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
13115				}
13116			},
13117			menuScrollMousewheel: function($sub, e) {
13118				var $closestSub = $(e.target).closest('ul');
13119				while ($closestSub.dataSM('in-mega')) {
13120					$closestSub = $closestSub.parent().closest('ul');
13121				}
13122				if ($closestSub[0] == $sub[0]) {
13123					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
13124					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
13125						this.menuScroll($sub, up, true);
13126					}
13127				}
13128				if ( ! $sub.hasClass('mega-menu-inner') ) {
13129					e.preventDefault();
13130				}
13131			},
13132			menuScrollOut: function($sub, e) {
13133				var reClass = /^scroll-(up|down)/,
13134					$closestSub = $(e.relatedTarget).closest('ul');
13135				while ($closestSub.dataSM('in-mega')) {
13136					$closestSub = $closestSub.parent().closest('ul');
13137				}
13138				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
13139					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
13140				}
13141			},
13142			menuScrollOver: function($sub, e) {
13143				var reClass = /^scroll-(up|down)/,
13144					$closestSub = $(e.target).closest('ul');
13145				while ($closestSub.dataSM('in-mega')) {
13146					$closestSub = $closestSub.parent().closest('ul');
13147				}
13148				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
13149					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
13150				}
13151			},
13152			menuScrollStop: function($sub) {
13153				if (this.scrollTimeout) {
13154					clearTimeout(this.scrollTimeout);
13155					this.scrollTimeout = 0;
13156					$sub.dataSM('scroll').step = 1;
13157				}
13158			},
13159			menuShow: function($sub) {
13160				if (!$sub.dataSM('beforefirstshowfired')) {
13161					$sub.dataSM('beforefirstshowfired', true);
13162					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
13163						return;
13164					}
13165				}
13166				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
13167					return;
13168				}
13169				this.menuFixLayout($sub);
13170				$sub.stop(true, true);
13171				if (!$sub.is(':visible')) {
13172					$sub.css({
13173						'visibility': 'visible',
13174						'pointer-events': 'auto',
13175					});
13176					// set z-index - for IE < 9 set it to the parent LI
13177					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
13178					if (IElt9) {
13179						$sub.parent().css('z-index', zIndex);
13180					} else {
13181						$sub.css('z-index', zIndex);
13182					}
13183					// highlight parent item
13184					if (this.opts.keepHighlighted || this.isCollapsible()) {
13185						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
13186							$sub.dataSM('parent-a').addClass('highlighted');
13187					}
13188					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
13189					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
13190						if (!IElt8) {
13191							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13192							if (this.opts.subMenusMinWidth) {
13193							 	$sub.css('min-width', this.opts.subMenusMinWidth);
13194							}
13195							if (this.opts.subMenusMaxWidth) {
13196							 	var noMaxWidth = this.getWidth($sub);
13197							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13198								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13199							 	}
13200								if (noMaxWidth > this.getWidth($sub)) {
13201									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13202								}
13203							}
13204						// IE6,7
13205 						} else {
13206							$sub.children().css('styleFloat', 'none');
13207							if (IE6) {
13208								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
13209									.children().children('a').css('white-space', 'nowrap');
13210							} else { // IE7
13211								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13212								if (this.opts.subMenusMinWidth) {
13213									$sub.css('min-width', this.opts.subMenusMinWidth);
13214								}
13215							}
13216							if (this.opts.subMenusMaxWidth) {
13217								var noMaxWidth = $sub.width();
13218								if (IE6) {
13219							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
13220									if (noMaxWidth > maxWidth) {
13221										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
13222									} else {
13223										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
13224									}
13225								} else { // IE7
13226								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13227									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13228								 	}
13229									if (noMaxWidth > $sub.width()) {
13230										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13231									} else {
13232										$sub.width(noMaxWidth);
13233									}
13234								}
13235							} else {
13236							 	$sub.width($sub.width());
13237							}
13238							$sub.children().css('styleFloat', 'left');
13239						}
13240					}
13241					if ( $sub.hasClass('mega-menu-inner') && $('body').hasClass('scrollable-megamenu') && UNCODE.wwidth > UNCODE.mediaQuery ) {
13242						var $nav = $('.navbar-main'),
13243							navH = 0,
13244							navTop = 0,
13245							$vmenu = $('body.vmenu .vmenu-container, body.menu-overlay .vmenu-container'),
13246							$offcanvas = $('body.menu-offcanvas .vmenu-container');
13247						if ( $nav.length && typeof $nav[0] !== 'undefined' ) {
13248							var navRect = $nav[0].getBoundingClientRect();
13249							navH = navRect.height;
13250							navTop = navRect.top;
13251						}
13252						if ( ! $vmenu.length && ! $offcanvas.length ) {
13253							$sub.css({ maxHeight: UNCODE.wheight - navH });
13254						}
13255					}
13256					this.menuPosition($sub);
13257					// insert IE iframe shim
13258					if ($sub.dataSM('ie-shim')) {
13259						$sub.dataSM('ie-shim').insertBefore($sub);
13260					}
13261					var complete = function() {
13262						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
13263						$sub.css('overflow', '');
13264					};
13265					// if sub is collapsible (mobile view)
13266					if (this.isCollapsible()) {
13267						if (this.opts.collapsibleShowFunction) {
13268							this.opts.collapsibleShowFunction.call(this, $sub, complete);
13269						} else {
13270							$sub.show(this.opts.collapsibleShowDuration, complete);
13271						}
13272					} else {
13273						if (this.opts.showFunction) {
13274							this.opts.showFunction.call(this, $sub, complete);
13275						} else {
13276							$sub.show(this.opts.showDuration, complete);
13277						}
13278					}
13279					// save new sub menu for this level
13280					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
13281					this.$root.triggerHandler('show.smapi', $sub[0]);
13282				}
13283			},
13284			popupHide: function(noHideTimeout) {
13285				if (this.hideTimeout) {
13286					clearTimeout(this.hideTimeout);
13287					this.hideTimeout = 0;
13288				}
13289				var self = this;
13290				this.hideTimeout = setTimeout(function() {
13291					self.menuHideAll();
13292				}, noHideTimeout ? 1 : this.opts.hideTimeout);
13293			},
13294			popupShow: function(left, top) {
13295				if (!this.opts.isPopup) {
13296					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
13297					return;
13298				}
13299				if (this.hideTimeout) {
13300					clearTimeout(this.hideTimeout);
13301					this.hideTimeout = 0;
13302				}
13303				this.menuFixLayout(this.$root);
13304				this.$root.stop(true, true);
13305				if (!this.$root.is(':visible')) {
13306					this.$root.css({ left: left, top: top });
13307					// IE iframe shim
13308					this.menuIframeShim(this.$root);
13309					if (this.$root.dataSM('ie-shim')) {
13310						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
13310: left, top: top }).insertBefore(this.$root);
13311					}
13312					// show menu
13313					if (this.opts.showFunction) {
13314						this.opts.showFunction.call(this, this.$root);
13315					} else {
13316						this.$root.show(this.opts.showDuration);
13317					}
13318					this.visibleSubMenus[0] = this.$root;
13319				}
13320			},
13321			refresh: function() {
13322				this.menuHideAll();
13323				this.$root.find('ul').each(function() {
13324						var $this = $(this);
13325						if ($this.dataSM('scroll-arrows')) {
13326							$this.dataSM('scroll-arrows').remove();
13327						}
13328					})
13329					.removeDataSM('in-mega')
13330					.removeDataSM('shown-before')
13331					.removeDataSM('ie-shim')
13332					.removeDataSM('scroll-arrows')
13333					.removeDataSM('parent-a')
13334					.removeDataSM('level')
13335					.removeDataSM('beforefirstshowfired');
13336				this.$root.find('a.has-submenu').removeClass('has-submenu')
13337					.parent().removeDataSM('sub');
13338				if (this.opts.subIndicators) {
13339					this.$root.find('span.sub-arrow').remove();
13340				}
13341				if (this.opts.markCurrentItem) {
13342					this.$root.find('a.current').removeClass('current');
13343				}
13344				this.subMenus = [];
13345				this.init(true);
13346			},
13347			rootOut: function(e) {
13348				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13349					return;
13350				}
13351				if (this.hideTimeout) {
13352					clearTimeout(this.hideTimeout);
13353					this.hideTimeout = 0;
13354				}
13355				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
13356					var self = this;
13357					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
13358				}
13359			},
13360			rootOver: function(e) {
13361				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13362					return;
13363				}
13364				if (this.hideTimeout) {
13365					clearTimeout(this.hideTimeout);
13366					this.hideTimeout = 0;
13367				}
13368			},
13369			winResize: function(e) {
13370				if (!this.handleEvents()) {
13371					// we still need to resize the disable overlay if it's visible
13372					if (this.$disableOverlay) {
13373						var pos = this.$root.offset();
13374	 					this.$disableOverlay.css({
13375							top: pos.top,
13376							left: pos.left,
13377							width: this.$root.outerWidth(),
13378							height: this.$root.outerHeight()
13379						});
13380					}
13381					return;
13382				}
13383				// hide sub menus on resize - on mobile do it only on orientation change
13384				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
13385					if (this.activatedItems.length) {
13386						this.activatedItems[this.activatedItems.length - 1][0].blur();
13387					}
13388					this.menuHideAll();
13389				}
13390			}
13391		}
13392	});
13393
13394	$.fn.dataSM = function(key, val) {
13395		if (val) {
13396			return this.data(key + '_smartmenus', val);
13397		}
13398		return this.data(key + '_smartmenus');
13399	}
13400
13401	$.fn.removeDataSM = function(key) {
13402		return this.removeData(key + '_smartmenus');
13403	}
13404
13405	$.fn.smartmenus = function(options) {
13406		if (typeof options == 'string') {
13407			var args = arguments,
13408				method = options;
13409			Array.prototype.shift.call(args);
13410			return this.each(function() {
13411				var smartmenus = $(this).data('smartmenus');
13412				if (smartmenus && smartmenus[method]) {
13413					smartmenus[method].apply(smartmenus, args);
13414				}
13415			});
13416		}
13417		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
13418		return this.each(function() {
13419			new $.SmartMenus(this, opts);
13420		});
13421	}
13422
13423	// default settings
13424	$.fn.smartmenus.defaults = {
13425		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
13426		mainMenuSubOffsetX:	0,		// pixels offset from default position
13427		mainMenuSubOffsetY:	0,		// pixels offset from default position
13428		subMenusSubOffsetX:	0,		// pixels offset from default position
13429		subMenusSubOffsetY:	0,		// pixels offset from default position
13430		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13431		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13432		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
13433		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
13434		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
13435		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
13436		scrollInterval:		30,		// interval between each scrolling step
13437		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
13438		showTimeout:		250,		// timeout before showing the sub menus
13439		hideTimeout:		500,		// timeout before hiding the sub menus
13440		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
13441		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
13442							// don't forget to call complete() at the end of whatever you do
13443							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
13444		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
13445		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
13446							// don't forget to call complete() at the end of whatever you do
13447							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
13448		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
13449		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
13450							// (i.e. when mobile styles are used to make the sub menus collapsible)
13451		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
13452		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
13453							// (i.e. when mobile styles are used to make the sub menus collapsible)
13454		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
13455		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
13456		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
13457		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
13458		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
13459		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
13460		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
13461		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
13462		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
13463	};
13464
13465})(jQuery);
13466/*
13467 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
13468 * Open source under the BSD License.
13469 * Copyright © 2008 George McGinley Smith
13470 * All rights reserved.
13471 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
13472*/
13473
13474/* globals jQuery, define, module, require */
13475(function (factory) {
13476	if (typeof define === "function" && define.amd) {
13477		define(['jquery'], function ($) {
13478			return factory($);
13479		});
13480	} else if (typeof module === "object" && typeof module.exports === "object") {
13481		module.exports = factory(require('jquery'));
13482	} else {
13483		factory(jQuery);
13484	}
13485})(function($){
13486
13487	// Preserve the original jQuery "swing" easing as "jswing"
13488	if (typeof $.easing !== 'undefined') {
13489		$.easing['jswing'] = $.easing['swing'];
13490	}
13491
13492	var pow = Math.pow,
13493		sqrt = Math.sqrt,
13494		sin = Math.sin,
13495		cos = Math.cos,
13496		PI = Math.PI,
13497		c1 = 1.70158,
13498		c2 = c1 * 1.525,
13499		c3 = c1 + 1,
13500		c4 = ( 2 * PI ) / 3,
13501		c5 = ( 2 * PI ) / 4.5;
13502
13503	// x is the fraction of animation progress, in the range 0..1
13504	function bounceOut(x) {
13505		var n1 = 7.5625,
13506			d1 = 2.75;
13507		if ( x < 1/d1 ) {
13508			return n1*x*x;
13509		} else if ( x < 2/d1 ) {
13510			return n1*(x-=(1.5/d1))*x + .75;
13511		} else if ( x < 2.5/d1 ) {
13512			return n1*(x-=(2.25/d1))*x + .9375;
13513		} else {
13514			return n1*(x-=(2.625/d1))*x + .984375;
13515		}
13516	}
13517
13518	$.extend( $.easing, {
13519		def: 'easeOutQuad',
13520		swing: function (x) {
13521			return $.easing[$.easing.def](x);
13522		},
13523		easeInQuad: function (x) {
13524			return x * x;
13525		},
13526		easeOutQuad: function (x) {
13527			return 1 - ( 1 - x ) * ( 1 - x );
13528		},
13529		easeInOutQuad: function (x) {
13530			return x < 0.5 ?
13531				2 * x * x :
13532				1 - pow( -2 * x + 2, 2 ) / 2;
13533		},
13534		easeInCubic: function (x) {
13535			return x * x * x;
13536		},
13537		easeOutCubic: function (x) {
13538			return 1 - pow( 1 - x, 3 );
13539		},
13540		easeInOutCubic: function (x) {
13541			return x < 0.5 ?
13542				4 * x * x * x :
13543				1 - pow( -2 * x + 2, 3 ) / 2;
13544		},
13545		easeInQuart: function (x) {
13546			return x * x * x * x;
13547		},
13548		easeOutQuart: function (x) {
13549			return 1 - pow( 1 - x, 4 );
13550		},
13551		easeInOutQuart: function (x) {
13552			return x < 0.5 ?
13553				8 * x * x * x * x :
13554				1 - pow( -2 * x + 2, 4 ) / 2;
13555		},
13556		easeInQuint: function (x) {
13557			return x * x * x * x * x;
13558		},
13559		easeOutQuint: function (x) {
13560			return 1 - pow( 1 - x, 5 );
13561		},
13562		easeInOutQuint: function (x) {
13563			return x < 0.5 ?
13564				16 * x * x * x * x * x :
13565				1 - pow( -2 * x + 2, 5 ) / 2;
13566		},
13567		easeInSine: function (x) {
13568			return 1 - cos( x * PI/2 );
13569		},
13570		easeOutSine: function (x) {
13571			return sin( x * PI/2 );
13572		},
13573		easeInOutSine: function (x) {
13574			return -( cos( PI * x ) - 1 ) / 2;
13575		},
13576		easeInExpo: function (x) {
13577			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
13578		},
13579		easeOutExpo: function (x) {
13580			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
13581		},
13582		easeInOutExpo: function (x) {
13583			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13584				pow( 2, 20 * x - 10 ) / 2 :
13585				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
13586		},
13587		easeInCirc: function (x) {
13588			return 1 - sqrt( 1 - pow( x, 2 ) );
13589		},
13590		easeOutCirc: function (x) {
13591			return sqrt( 1 - pow( x - 1, 2 ) );
13592		},
13593		easeInOutCirc: function (x) {
13594			return x < 0.5 ?
13595				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
13596				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
13597		},
13598		easeInElastic: function (x) {
13599			return x === 0 ? 0 : x === 1 ? 1 :
13600				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
13601		},
13602		easeOutElastic: function (x) {
13603			return x === 0 ? 0 : x === 1 ? 1 :
13604				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
13605		},
13606		easeInOutElastic: function (x) {
13607			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13608				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
13609				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
13610		},
13611		easeInBack: function (x) {
13612			return c3 * x * x * x - c1 * x * x;
13613		},
13614		easeOutBack: function (x) {
13615			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
13616		},
13617		easeInOutBack: function (x) {
13618			return x < 0.5 ?
13619				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
13620				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
13621		},
13622		easeInBounce: function (x) {
13623			return 1 - bounceOut( 1 - x );
13624		},
13625		easeOutBounce: bounceOut,
13626		easeInOutBounce: function (x) {
13627			return x < 0.5 ?
13628				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
13629				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
13630		}
13631	});
13632	return $;
13633});
13634
13635/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
13636 * Licensed under the MIT License (LICENSE.txt).
13637 *
13638 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
13639 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
13640 * Thanks to: Seamus Leahy for adding deltaX and deltaY
13641 *
13642 * Version: 3.0.6
13643 *
13644 * Requires: 1.2.2+
13645 */
13646(function($) {
13647    var types = ['DOMMouseScroll', 'mousewheel'];
13648    if ($.event.fixHooks) {
13649        for (var i = types.length; i;) {
13650            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
13651        }
13652    }
13653    $.event.special.mousewheel = {
13654        setup: function() {
13655            if (this.addEventListener) {
13656                for (var i = types.length; i;) {
13657                    this.addEventListener(types[--i], handler, false);
13658                }
13659            } else {
13660                this.onmousewheel = handler;
13661            }
13662        },
13663        teardown: function() {
13664            if (this.removeEventListener) {
13665                for (var i = types.length; i;) {
13666                    this.removeEventListener(types[--i], handler, false);
13667                }
13668            } else {
13669                this.onmousewheel = null;
13670            }
13671        }
13672    };
13673    $.fn.extend({
13674        mousewheel: function(fn) {
13675            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
13676        },
13677        unmousewheel: function(fn) {
13678            return this.unbind("mousewheel", fn);
13679        }
13680    });
13681
13682    function handler(event) {
13683        var orgEvent = event || window.event,
13684            args = [].slice.call(arguments, 1),
13685            delta = 0,
13686            returnValue = true,
13687            deltaX = 0,
13688            deltaY = 0;
13689        event = $.event.fix(orgEvent);
13690        event.type = "mousewheel";
13691        // Old school scrollwheel delta
13692        if (orgEvent.wheelDelta) {
13693            delta = orgEvent.wheelDelta / 120;
13694        }
13695        if (orgEvent.detail) {
13696            delta = -orgEvent.detail / 3;
13697        }
13698        // New school multidimensional scroll (touchpads) deltas
13699        deltaY = delta;
13700        // Gecko
13701        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
13702            deltaY = 0;
13703            deltaX = -1 * delta;
13704        }
13705        // Webkit
13706        if (orgEvent.wheelDeltaY !== undefined) {
13707            deltaY = orgEvent.wheelDeltaY / 120;
13708        }
13709        if (orgEvent.wheelDeltaX !== undefined) {
13710            deltaX = -1 * orgEvent.wheelDeltaX / 120;
13711        }
13712        // Add event and delta to the front of the arguments
13713        args.unshift(event, delta, deltaX, deltaY);
13714        return ($.event.dispatch || $.event.handle).apply(this, args);
13715    }
13716})(jQuery);
13717/**
13718 * jQuery iLightBox - Revolutionary Lightbox Plugin
13719 * http://www.ilightbox.net/
13720 *
13721 * @version: 2.2.4 - October 14, 2017
13722 *
13723 * @author: iProDev (Hemn Chawroka)
13724 *          http://www.iprodev.com/
13725 *
13726 */
13727(function($, window, undefined) {
13728
13729	var extensions = {
13730			flash: ['swf'],
13731			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
13732			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
13733			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
13734		},
13735
13736		// Global DOM elements
13737		$win = $(window),
13738		$doc = $(document),
13739
13740		// Support indicators
13741		browser,
13742		transform,
13743		gpuAcceleration,
13744		fullScreenApi = '',
13745		userAgent = navigator.userAgent || navigator.vendor || window.opera,
13746        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
13747        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
13748        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)),
13749
13750		// Events
13751		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
13752		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
13753		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
13754		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
13755
13756		// Math shorthands
13757		abs = Math.abs,
13758		sqrt = Math.sqrt,
13759		round = Math.round,
13760		max = Math.max,
13761		min = Math.min,
13762		floor = Math.floor,
13763		random = Math.random,
13764
13765		pluginspages = {
13766			quicktime: 'http://www.apple.com/quicktime/download',
13767			flash: 'http://www.adobe.com/go/getflash'
13768		},
13769
13770		iLightBox = function(el, options, items, instant) {
13771			var iL = this;
13772
13773			iL.options = options,
13774				iL.selector = options.selector || el,
13775				iL.context = document,
13776				iL.instant = instant;
13777
13778			if (items.length < 1) iL.attachItems();
13779			else iL.items = items;
13780
13781			iL.vars = {
13782				total: iL.items.length,
13783				start: 0,
13784				current: null,
13785				next: null,
13786				prev: null,
13787				BODY: $('body'),
13788				loadRequests: 0,
13789				overlay: $('<div class="ilightbox-overlay"></div>'),
13790				loader: $('<div class="ilightbox-loader"><div></div></div>'),
13791				toolbar: $('<div class="ilightbox-toolbar"></div>'),
13792				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
13793				title: $('<div class="ilightbox-title"></div>'),
13794				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
13795				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
13796				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
13797				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
13798				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
13799				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13800				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13801				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13802				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
13803				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13804				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>'),
13805				thumbs: false,
13806				nextLock: false,
13807				prevLock: false,
13808				hashLock: false,
13809				isMobile: false,
13810				mobileMaxWidth: 980,
13811				isInFullScreen: false,
13812				isSwipe: false,
13813				mouseID: 0,
13814				cycleID: 0,
13815				isPaused: 0,
13816				captionHeight: 39,
13817			};
13818
13819			// Hideable elements with mousemove event
13820			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
13821
13822			iL.normalizeItems();
13823
13824			//Check necessary plugins
13825			iL.availPlugins();
13826
13827			//Set startFrom
13828			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
13829
13830			//If randomStart
13831			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
13832			iL.vars.start = iL.options.startFrom;
13833
13834			if (instant) iL.instantCall();
13835			else iL.patchItemsEvents();
13836
13837			if (iL.options.linkId) {
13838				iL.hashChangeHandler();
13839				$win.iLightBoxHashChange(function() {
13840					iL.hashChangeHandler();
13841				});
13842			}
13843
13844			if (supportTouch) {
13845				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
13846					replace = "itap";
13847				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
13848					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
13849					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
13850					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
13851			}
13852
13853			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
13854				$.extend(iL.options.styles, {
13855					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13856					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13857					nextOpacity: 0,
13858					prevOpacity: 0
13859				});
13860			}
13861		};
13862
13863	//iLightBox helpers
13864	iLightBox.prototype = {
13865		showLoader: function() {
13866			var iL = this;
13867			iL.vars.loadRequests += 1;
13868			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
13869				//top: '-30px'
13870				opacity: '1'
13871			}, iL.options.show.speed, 'easeOutCirc');
13872			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
13873				//left: '-30px'
13874				opacity: '1'
13875			}, iL.options.show.speed, 'easeOutCirc');
13876		},
13877
13878		hideLoader: function() {
13879			var iL = this;
13880			iL.vars.loadRequests -= 1;
13881			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
13882			if (iL.options.path.toLowerCase() == "horizontal") {
13883				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13884					//top: '-192px'
13885					opacity: '0'
13886				}, iL.options.show.speed, 'easeInCirc');
13887			} else {
13888				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13889					//left: '-192px'
13890					opacity: '0'
13891				}, iL.options.show.speed, 'easeInCirc');
13892			}
13893		},
13894
13895		createUI: function() {
13896			var iL = this;
13897
13898			iL.ui = {
13899				currentElement: iL.vars.holder,
13900				nextElement: iL.vars.nextPhoto,
13901				prevElement: iL.vars.prevPhoto,
13902				currentItem: iL.vars.current,
13903				nextItem: iL.vars.next,
13904				prevItem: iL.vars.prev,
13905				hide: function() {
13906					iL.closeAction();
13907				},
13908				refresh: function() {
13909					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13910				},
13911				fullscreen: function() {
13912					iL.fullScreenAction();
13913				}
13914			};
13915		},
13916
13917		attachItems: function() {
13918			var iL = this,
13919				itemsObject = new Array(),
13920				items = new Array();
13921
13922			$(iL.selector, iL.context).each(function() {
13923				var t = $(this),
13924					URL = t.attr(iL.options.attr) || null,
13925					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
13926					caption = t.data('caption'),
13927					title = t.data('title'),
13928					type = t.data('type') || getTypeByExtension(URL),
13929					clone = t.data('lbox-clone') || false;
13930
13931				//Uncode addition ##START##
13932				if (type === false) {
13933					return;
13934				}
13935				//Uncode addition ##END##
13936
13937				if (t.data('lbox-clone') != undefined) return;
13938
13939				//Uncode addition ##START##
13940				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
13941					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
13942						URL_i,
13943						URLS_LENGHT = ALBUM_URLS.length;
13944
13945					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
13946						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
13947							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
13948							item_opts = item_opts && eval("({" + item_opts + "})") || {},
13949							items.push({
13950								URL: ALBUM_URLS[URL_i].url,
13951								caption: ALBUM_URLS[URL_i].caption,
13952								title: ALBUM_URLS[URL_i].title,
13953								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
13954								options: item_opts,
13955								clone: clone
13956							});
13957							var newT = t;
13958							newT.attr('href',ALBUM_URLS[URL_i].url);
13959							if (!iL.instant) itemsObject.push(newT);
13960						}
13961					}
13962				} else {
13963				//Uncode addition ##END##
13964					items.push({
13965						URL: URL,
13966						caption: caption,
13967						title: title,
13968						type: type,
13969						options: options,
13970						clone: clone
13971					});
13972				}
13973
13974
13975				if (iL.vars != undefined) iL.vars.total = items.length;
13976
13977				if (!iL.instant) itemsObject.push(t);
13978			});
13979
13980			iL.items = items,
13981				iL.itemsObject = itemsObject;
13982
13983		},
13984
13985		normalizeItems: function() {
13986			var iL = this,
13987				newItems = new Array();
13988
13989			$.each(iL.items, function(key, val) {
13990
13991				if (typeof val == "string") val = {
13992					url: val
13993				};
13994
13995				var URL = val.url || val.URL || null,
13996					options = val.options || {},
13997					caption = val.caption || null,
13998					title = val.title || null,
13999					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
14000					ext = (typeof URL != 'object') ? getExtension(URL) : '';
14001
14002				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
14003				options.videoType = options.videoType || null,
14004				options.skin = options.skin || iL.options.skin,
14005				options.width = options.width || null,
14006				options.height = options.height || null,
14007				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
14008				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
14009				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
14010
14011				if (type == "video") {
14012					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
14013
14014					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
14015					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
14016					options.html5video.preload = options.html5video.preload || "metadata";
14017					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
14018					//UNCODE addition
14019					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
14020				}
14021
14022				if (!options.width || !options.height) {
14023					if (type == "video") options.width = 1280, options.height = 720;
14024					else if (type == "iframe") options.width = '100%', options.height = '90%';
14025					else if (type == "flash") options.width = 1280, options.height = 720;
14026				}
14027
14028				delete val.url;
14029				val.index = key;
14030				val.URL = URL;
14031				val.caption = caption;
14032				val.title = title;
14033				val.type = type;
14034				val.options = options;
14035				val.ext = ext;
14036
14037				newItems.push(val);
14038			});
14039
14040			iL.items = newItems;
14041		},
14042
14043		instantCall: function() {
14044			var iL = this,
14045				key = iL.vars.start;
14046
14047			iL.vars.current = key;
14048			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
14049			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
14050
14051			iL.addContents();
14052			iL.patchEvents();
14053		},
14054
14055		addContents: function() {
14056			var iL = this,
14057				vars = iL.vars,
14058				opts = iL.options,
14059				viewport = getViewport(),
14060				path = opts.path.toLowerCase(),
14061				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
14062					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
14063				}),
14064				needRecognition = recognizingItems.length > 0;
14065
14066			if (opts.mobileOptimizer && !opts.innerToolbar)
14067				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14068
14069			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
14070
14071			if (opts.linkId)
14072				vars.overlay[0].setAttribute('linkid', opts.linkId);
14073
14074			//Add Toolbar Buttons
14075			if (opts.controls.toolbar) {
14076				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
14077				if (opts.controls.fullscreen)
14078					vars.toolbar.append(vars.fullScreenButton);
14079				if (opts.controls.slideshow)
14080					vars.toolbar.append(vars.innerPlayButton);
14081				if (vars.total > 1)
14082					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
14083			}
14084
14085			//Append elements to body
14086			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
14087
14088			if (!opts.innerToolbar)
14089				vars.BODY.append(vars.toolbar);
14090			if (opts.controls.arrows)
14091				vars.BODY.append(vars.nextButton).append(vars.prevButton);
14092
14093			if (opts.controls.thumbnail && vars.total > 1) {
14094				vars.BODY.append(vars.thumbnails);
14095				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
14096				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
14097				vars.thumbs = true;
14098			}
14099
14100			//Configure loader and arrows
14101			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
14102				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
14103			} : {
14104				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
14105			};
14106			vars.loader.addClass(opts.skin).css(loaderCss);
14107			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
14108			if (path == "horizontal")
14109				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
14110
14111			// Configure arrow buttons
14112			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14113
14114			if (!opts.infinite) {
14115				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14116
14117				if (vars.current == 0)
14118					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14119				if (vars.current >= vars.total - 1)
14120					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14121			}
14122
14123			if (opts.show.effect) {
14124				vars.overlay.stop().fadeIn(opts.show.speed);
14125				vars.toolbar.stop().fadeIn(opts.show.speed);
14126			} else {
14127				vars.overlay.show();
14128				vars.toolbar.show();
14129			}
14130
14131			var length = recognizingItems.length;
14132			if (needRecognition) {
14133				iL.showLoader();
14134
14135				$.each(recognizingItems, function(key, val) {
14136					var resultFnc = function(result) {
14137							var key = -1,
14138								filter = iL.items.filter(function(e, i, arr) {
14139									if (e.URL == result.url)
14140										key = i;
14141
14142									return e.URL == result.url;
14143								}),
14144								self = iL.items[key];
14145
14146							if (result)
14147								$.extend(true, self, {
14148									URL: result.source,
14149									type: result.type,
14150									recognized: true,
14151									options: {
14152										html5video: result.html5video,
14153										width: (result.type == "image") ? 0 : (result.width || self.width),
14154										height: (result.type == "image") ? 0 : (result.height || self.height),
14155										thumbnail: self.options.thumbnail || result.thumbnail
14156									}
14157								});
14158
14159							length--;
14160
14161							if (length == 0) {
14162								iL.hideLoader();
14163
14164								vars.dontGenerateThumbs = false;
14165								iL.generateThumbnails();
14166
14167								if (opts.show.effect)
14168									setTimeout(function() {
14169										iL.generateBoxes();
14170									}, opts.show.speed);
14171								else
14172									iL.generateBoxes();
14173							}
14174						};
14175
14176					iL.ogpRecognition(this, resultFnc);
14177				});
14178			}
14179			else {
14180				if (opts.show.effect)
14181					setTimeout(function() {
14182						iL.generateBoxes();
14183					}, opts.show.speed);
14184				else
14185					iL.generateBoxes();
14186			}
14187
14188			iL.createUI();
14189
14190			window.iLightBox = {
14191				close: function() {
14192					iL.closeAction();
14193				},
14194				fullscreen: function() {
14195					iL.fullScreenAction();
14196				},
14197				moveNext: function() {
14198					iL.moveTo('next');
14199				},
14200				movePrev: function() {
14201					iL.moveTo('prev');
14202				},
14203				goTo: function(index) {
14204					iL.goTo(index);
14205				},
14206				refresh: function() {
14207					iL.refresh();
14208				},
14209				reposition: function() {
14210					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
14211				},
14212				setOption: function(options) {
14213					iL.setOption(options);
14214				},
14215				destroy: function() {
14216					iL.closeAction();
14217					iL.dispatchItemsEvents();
14218				}
14219			};
14220
14221			if (opts.linkId) {
14222				vars.hashLock = true;
14223				window.location.hash = opts.linkId + '/' + vars.current;
14224				setTimeout(function() {
14225					vars.hashLock = false;
14226				}, 55);
14227			}
14228
14229			if (!opts.slideshow.startPaused) {
14230				iL.resume();
14231				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
14232			}
14233
14234			//Trigger the onOpen callback
14235			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
14236		},
14237
14238		loadContent: function(obj, opt, speed) {
14239			var iL = this,
14240				holder, item;
14241
14242			iL.createUI();
14243
14244			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
14245
14246			if (opt == 'current') {
14247				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
14248				else iL.vars.lockWheel = false;
14249
14250				if (!obj.options.swipe) iL.vars.lockSwipe = true;
14251				else iL.vars.lockSwipe = false;
14252			}
14253
14254			switch (opt) {
14255				case 'current':
14256					holder = iL.vars.holder, item = iL.vars.current;
14257					break;
14258				case 'next':
14259					holder = iL.vars.nextPhoto, item = iL.vars.next;
14260					break;
14261				case 'prev':
14262					holder = iL.vars.prevPhoto, item = iL.vars.prev;
14263					break;
14264			}
14265
14266			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
14267			$('div.ilightbox-inner-toolbar', holder).remove();
14268
14269			if (obj.title || iL.options.innerToolbar) {
14270				var innerToolbar = iL.vars.innerToolbar.clone();
14271				if (obj.title && iL.options.show.title) {
14272					var title = iL.vars.title.clone();
14273					title.empty().html(obj.title);
14274					innerToolbar.append(title);
14275				}
14276				if (iL.options.innerToolbar) {
14277					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
14278				}
14279				holder.prepend(innerToolbar);
14280			}
14281
14282			//console.warn('loadContent', arguments);
14283
14284			iL.loadSwitcher(obj, holder, item, opt);
14285		},
14286
14287		loadSwitcher: function(obj, holder, item, opt) {
14288			var iL = this,
14289				opts = iL.options,
14290				api = {
14291					element: holder,
14292					position: item
14293				};
14294
14295			switch (obj.type) {
14296				case 'image':
14297					//Trigger the onBeforeLoad callback
14298					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14299					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14300
14301					iL.loadImage(obj.URL, function(img) {
14302						//Trigger the onAfterLoad callback
14303						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14304						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14305
14306						var width = (img) ? img.width : 400,
14307							height = (img) ? img.height : 200;
14308
14309						holder.data({
14310							naturalWidth: width,
14311							naturalHeight: height
14312						});
14313
14314						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
14315
14316						//Trigger the onRender callback
14317						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14318						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14319
14320						iL.configureHolder(obj, opt, holder);
14321					});
14322
14323					break;
14324
14325				case 'video':
14326					holder.data({
14327						naturalWidth: obj.options.width,
14328						naturalHeight: obj.options.height
14329					});
14330
14331					if (opt === 'current') {
14332						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					} else {
14338						$('div.ilightbox-container', holder).empty();
14339					}
14340
14341					iL.configureHolder(obj, opt, holder);
14342
14343					break;
14344
14345				case 'iframe':
14346					//iL.showLoader();
14347					holder.data({
14348						naturalWidth: obj.options.width,
14349						naturalHeight: obj.options.height
14350					});
14351
14352					iL.configureHolder(obj, opt, holder);
14353
14354					if (opt === 'current') {
14355						var el = iL.addContent(holder, obj);
14356
14357						//Trigger the onRender callback
14358						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14359						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14360
14361						//Trigger the onBeforeLoad callback
14362						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14363						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14364
14365						el.bind('load', function() {
14366							//Trigger the onAfterLoad callback
14367							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14368							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14369
14370							//iL.hideLoader();
14371							el.unbind('load');
14372						});
14373					} else {
14374						$('div.ilightbox-container', holder).empty();
14375					}
14376
14377					break;
14378
14379				case 'inline':
14380					var el = $(obj.URL),
14381						content = iL.addContent(holder, obj),
14382						images = findImageInElement(holder);
14383
14384					holder.data({
14385						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14386						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14387					});
14388					content.children().eq(0).show();
14389
14390					//Trigger the onRender callback
14391					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14392					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14393
14394					//Trigger the onBeforeLoad callback
14395					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14396					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14397
14398					iL.loadImage(images, function() {
14399						//Trigger the onAfterLoad callback
14400						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14401						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14402
14403						iL.configureHolder(obj, opt, holder);
14404					});
14405
14406					break;
14407
14408				case 'flash':
14409					var el = iL.addContent(holder, obj);
14410
14411					holder.data({
14412						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14413						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14414					});
14415
14416					//Trigger the onRender callback
14417					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14418					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14419
14420					iL.configureHolder(obj, opt, holder);
14421
14422					break;
14423
14424				case 'ajax':
14425					var ajax = obj.options.ajax || {};
14426					//Trigger the onBeforeLoad callback
14427					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14428					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14429
14430					iL.showLoader();
14431					$.ajax({
14432						url: obj.URL || opts.ajaxSetup.url,
14433						data: ajax.data || null,
14434						dataType: ajax.dataType || "html",
14435						type: ajax.type || opts.ajaxSetup.type,
14436						cache: ajax.cache || opts.ajaxSetup.cache,
14437						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
14438						global: ajax.global || opts.ajaxSetup.global,
14439						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
14440						username: ajax.username || opts.ajaxSetup.username,
14441						password: ajax.password || opts.ajaxSetup.password,
14442						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
14443						complete: ajax.complete || opts.ajaxSetup.complete,
14444						success: function(data, textStatus, jqXHR) {
14445							iL.hideLoader();
14446
14447							var el = $(data),
14448								container = $('div.ilightbox-container', holder),
14449								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
14450								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
14451								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
14452									'overflow': 'hidden'
14453								} : {};
14454
14455							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
14456							holder.show().data({
14457								naturalWidth: (elWidth || container.outerWidth()),
14458								naturalHeight: (elHeight || container.outerHeight())
14459							}).hide();
14460
14461							//Trigger the onRender callback
14462							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14463							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14464
14465							var images = findImageInElement(holder);
14466							iL.loadImage(images, function() {
14467								//Trigger the onAfterLoad callback
14468								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14469								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14470
14471								iL.configureHolder(obj, opt, holder);
14472							});
14473
14474							opts.ajaxSetup.success(data, textStatus, jqXHR);
14475							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
14476						},
14477						error: function(jqXHR, textStatus, errorThrown) {
14478							//Trigger the onAfterLoad callback
14479							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14480							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14481
14482							iL.hideLoader();
14483							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
14484							iL.configureHolder(obj, opt, holder);
14485
14486							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
14487							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
14488						}
14489					});
14490
14491					break;
14492
14493				case 'html':
14494					var object = obj.URL,
14495						el
14496					container = $('div.ilightbox-container', holder);
14497
14498					if (object[0].nodeName) el = object.clone();
14499					else {
14500						var dom = $(object);
14501						if (dom.selector) el = $('<div>' + dom + '</div>');
14502						else el = dom;
14503					}
14504
14505					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
14506						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
14507
14508					iL.addContent(holder, obj);
14509
14510					el.appendTo(document.documentElement).hide();
14511
14512					//Trigger the onRender callback
14513					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14514					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14515
14516					var images = findImageInElement(holder);
14517
14518					//Trigger the onBeforeLoad callback
14519					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14520					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14521
14522					iL.loadImage(images, function() {
14523						//Trigger the onAfterLoad callback
14524						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14525						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14526
14527						holder.show().data({
14528							naturalWidth: (elWidth || container.outerWidth()),
14529							naturalHeight: (elHeight || container.outerHeight())
14530						}).hide();
14531						el.remove();
14532
14533						iL.configureHolder(obj, opt, holder);
14534					});
14535
14536					break;
14537			}
14538		},
14539
14540		configureHolder: function(obj, opt, holder) {
14541			var iL = this,
14542				vars = iL.vars,
14543				opts = iL.options;
14544
14545			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
14546
14547			if (opt == "current")
14548				var item = vars.current;
14549			else if (opt == "next")
14550				var opacity = opts.styles.nextOpacity,
14551					item = vars.next;
14552			else
14553				var opacity = opts.styles.prevOpacity,
14554					item = vars.prev;
14555
14556			var api = {
14557				element: holder,
14558				position: item
14559			};
14560
14561			iL.items[item].options.width = iL.items[item].options.width || 0,
14562			iL.items[item].options.height = iL.items[item].options.height || 0;
14563
14564			if (opt == "current") {
14565				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
14566					holder.css(transform, '');
14567					if (obj.caption) {
14568						iL.setCaption(obj, holder);
14569						var caption = $('div.ilightbox-caption', holder),
14570							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
14571						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
14571Speed);
14572					}
14573
14574					var social = obj.options.social;
14575					if (social) {
14576						iL.setSocial(social, obj.URL, holder);
14577						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
14578					}
14579
14580					//Generate thumbnails
14581					iL.generateThumbnails();
14582
14583					//Trigger the onShow callback
14584					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14585					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14586				});
14587				else {
14588					holder.show();
14589
14590					//Generate thumbnails
14591					iL.generateThumbnails();
14592
14593					//Trigger the onShow callback
14594					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14595					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14596				}
14597			} else {
14598				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
14599					if (opt == "next") vars.nextLock = false;
14600					else vars.prevLock = false;
14601
14602					//Generate thumbnails
14603					iL.generateThumbnails();
14604
14605					//Trigger the onShow callback
14606					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14607					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14608				});
14609				else {
14610					holder.css({
14611						opacity: opacity
14612					}).show();
14613					if (opt == "next") vars.nextLock = false;
14614					else vars.prevLock = false;
14615
14616					//Generate thumbnails
14617					iL.generateThumbnails();
14618
14619					//Trigger the onShow callback
14620					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14621					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14622				}
14623			}
14624
14625			setTimeout(function() {
14626				iL.repositionPhoto();
14627			}, 0);
14628		},
14629
14630		generateBoxes: function() {
14631			var iL = this,
14632				vars = iL.vars,
14633				opts = iL.options;
14634
14635			if (opts.infinite && vars.total >= 3) {
14636				if (vars.current == vars.total - 1) vars.next = 0;
14637				if (vars.current == 0) vars.prev = vars.total - 1;
14638			} else opts.infinite = false;
14639
14640			//UNCODE addition
14641			if ( typeof iL.items[vars.current] == 'undefined' )
14642				vars.current = 0;
14643
14644			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
14645
14646			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
14647			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
14648		},
14649
14650		generateThumbnails: function() {
14651			var iL = this,
14652				vars = iL.vars,
14653				opts = iL.options,
14654				timeOut = null;
14655
14656			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
14657				var thumbnails = vars.thumbnails,
14658					container = $('div.ilightbox-thumbnails-container', thumbnails),
14659					grid = $('div.ilightbox-thumbnails-grid', container),
14660					i = 0;
14661
14662				grid.removeAttr('style').empty();
14663
14664				$.each(iL.items, function(key, val) {
14665					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
14666						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
14667						thumb = val.options.thumbnail,
14668						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
14669						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
14670
14671					thumbnail.css({
14672						opacity: 0
14673					}).addClass(isActive);
14674
14675					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
14676						icon.addClass('ilightbox-thumbnail-video');
14677						thumbnail.append(icon);
14678					} else if (val.options.icon) {
14679						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
14680						thumbnail.append(icon);
14681					}
14682
14683					if (thumb) iL.loadImage(thumb, function(img) {
14684						i++;
14685						if (img) thumbnail.data({
14686							naturalWidth: img.width,
14687							naturalHeight: img.height
14688						}).append('<img src="' + thumb + '" border="0" />');
14689						else thumbnail.data({
14690							naturalWidth: opts.thumbnails.maxWidth,
14691							naturalHeight: opts.thumbnails.maxHeight
14692						});
14693
14694						clearTimeout(timeOut);
14695						timeOut = setTimeout(function() {
14696							iL.positionThumbnails(thumbnails, container, grid);
14697						}, 20);
14698						setTimeout(function() {
14699							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
14700						}, i * 20);
14701					});
14702
14703					grid.append(thumbnail);
14704				});
14705				iL.vars.dontGenerateThumbs = true;
14706			}
14707		},
14708
14709		positionThumbnails: function(thumbnails, container, grid) {
14710			var iL = this,
14711				vars = iL.vars,
14712				opts = iL.options,
14713				viewport = getViewport(),
14714				path = opts.path.toLowerCase();
14715
14716			if (!thumbnails) thumbnails = vars.thumbnails;
14717			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
14718			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
14719
14720			var thumbs = $('.ilightbox-thumbnail', grid),
14721				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
14722				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
14723				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
14724				gridHeight = (path == 'horizontal') ? heightAvail : 0,
14725				active = $('.ilightbox-active', grid),
14726				gridCss = {},
14727				css = {};
14728
14729			if (arguments.length < 3) {
14730				thumbs.css({
14731					opacity: opts.thumbnails.normalOpacity
14732				});
14733				active.css({
14734					opacity: opts.thumbnails.activeOpacity
14735				});
14736			}
14737
14738			thumbs.each(function(i) {
14739				var t = $(this),
14740					data = t.data(),
14741					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
14742				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
14743				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
14744
14745				t.css({
14746					width: dims.width,
14747					height: dims.height
14748				});
14749				if (path == 'horizontal') t.css({
14750					'float': 'left'
14751				});
14752
14753				(path == 'horizontal') ? (
14754					gridWidth += t.outerWidth()
14755				) : (
14756					gridHeight += t.outerHeight()
14757				);
14758			});
14759
14760			gridCss = {
14761				width: gridWidth,
14762				height: gridHeight
14763			};
14764
14765			grid.css(gridCss);
14766
14767			gridCss = {};
14768
14769			var gridOffset = grid.offset(),
14770				activeOffset = (active.length) ? active.offset() : {
14771					top: parseInt(heightAvail / 2),
14772					left: parseInt(widthAvail / 2)
14773				};
14774
14775			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
14776				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
14777				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
14778				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
14779
14780			(path == 'horizontal') ? (
14781				gridCss.top = 0,
14782				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
14783			) : (
14784				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
14785				gridCss.left = 0
14786			);
14787
14788			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
14789			else grid.css(gridCss);
14790		},
14791
14792		loadImage: function(image, callback) {
14793			if (!$.isArray(image)) image = [image];
14794
14795			var iL = this,
14796				length = image.length;
14797
14798			if (length > 0) {
14799				iL.showLoader();
14800				$.each(image, function(index, value) {
14801					var img = new Image();
14802					img.onload = function() {
14803						length -= 1;
14804						if (length == 0) {
14805							iL.hideLoader();
14806							callback(img);
14807						}
14808					};
14809					img.onerror = img.onabort = function() {
14810						length -= 1;
14811						if (length == 0) {
14812							iL.hideLoader();
14813							callback(false);
14814						}
14815					};
14816					img.src = image[index];
14817				});
14818			} else callback(false);
14819		},
14820
14821		patchItemsEvents: function() {
14822			var iL = this,
14823				vars = iL.vars,
14824				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
14825				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
14826
14827			if (iL.context && iL.selector) {
14828				var $items = $(iL.selector, iL.context);
14829
14830				$(iL.context).on(clickEvent, iL.selector, function() {
14831					var $this = $(this),
14832						//UNCODE addition
14833						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
14834					if (UNCODE.isMobile) {
14835						var isCarousel = $this.closest('.owl-carousel');
14836						if (isCarousel.length) {
14837							if (isCarousel.hasClass('owl-translating')) return false;
14838						}
14839					}
14840
14841					vars.current = key;
14842					vars.next = iL.items[key + 1] ? key + 1 : null;
14843					vars.prev = iL.items[key - 1] ? key - 1 : null;
14844
14845					//UNCODE addition
14846					if ( vars.BODY.hasClass('fp-slide-scrolling') )
14847						return false;
14848
14849					iL.addContents();
14850					iL.patchEvents();
14851
14852					return false;
14853				}).on(vEvent, iL.selector, function() {
14854					return false;
14855				});
14856			} else
14857				$.each(iL.itemsObject, function(key, val) {
14858					val.on(clickEvent, function() {
14859						vars.current = key;
14860						vars.next = iL.items[key + 1] ? key + 1 : null;
14861						vars.prev = iL.items[key - 1] ? key - 1 : null;
14862
14863						iL.addContents();
14864						iL.patchEvents();
14865
14866						return false;
14867					}).on(vEvent, function() {
14868						return false;
14869					});
14870				});
14871		},
14872
14873		dispatchItemsEvents: function() {
14874			var iL = this,
14875				vars = iL.vars,
14876				opts = iL.options;
14877
14878			if (iL.context && iL.selector)
14879				$(iL.context).off('.iL', iL.selector);
14880			else
14881				$.each(iL.itemsObject, function(key, val) {
14882					val.off('.iL');
14883				});
14884		},
14885
14886		refresh: function() {
14887			var iL = this;
14888
14889			iL.dispatchItemsEvents();
14890			iL.attachItems();
14891			iL.normalizeItems();
14892			iL.patchItemsEvents();
14893		},
14894
14895		patchEvents: function() {
14896			var iL = this,
14897				vars = iL.vars,
14898				opts = iL.options,
14899				path = opts.path.toLowerCase(),
14900				holders = $('.ilightbox-holder'),
14901				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
14902				durationThreshold = 1000,
14903				horizontalDistanceThreshold =
14904				verticalDistanceThreshold = 100,
14905				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
14906
14907			$win.bind('resize.iLightBox', function() {
14908				var viewport = getViewport();
14909
14910				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14911				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14912
14913				iL.repositionPhoto(null);
14914				if (supportTouch) {
14915					clearTimeout(vars.setTime);
14916					vars.setTime = setTimeout(function() {
14917						var scrollTop = getScrollXY().y;
14918						window.scrollTo(0, scrollTop - 30);
14919						window.scrollTo(0, scrollTop + 30);
14920						window.scrollTo(0, scrollTop);
14921					}, 2000);
14922				}
14923				if (vars.thumbs) iL.positionThumbnails();
14924			}).bind('keydown.iLightBox', function(event) {
14925				if (opts.controls.keyboard) {
14926					switch (event.keyCode) {
14927						case 13:
14928							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
14929							break;
14930						case 27:
14931							if (opts.keyboard.esc) iL.closeAction();
14932							break;
14933						case 37:
14934							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
14935							break;
14936						case 38:
14937							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
14938							break;
14939						case 39:
14940							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
14941							break;
14942						case 40:
14943							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
14944							break;
14945					}
14946				}
14947			});
14948
14949			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
14950				iL.doFullscreen();
14951			});
14952
14953			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
14954					return arr.lastIndexOf(e) === i;
14955				}),
14956				holderEvents = "";
14957
14958			$.each(holderEventsArr, function(key, val) {
14959				if (key != 0) holderEvents += ' ';
14960				holderEvents += val;
14961			});
14962
14963			$doc.on(clickEvent, '.ilightbox-overlay', function() {
14964				if (opts.overlay.blur) iL.closeAction();
14965			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
14966				iL.moveTo('next');
14967			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
14968				iL.moveTo('prev');
14969			}).on(clickEvent, '.ilightbox-thumbnail', function() {
14970				var t = $(this),
14971					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
14972					index = thumbs.index(t);
14973
14974				if (index != vars.current) iL.goTo(index);
14975			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14976				var caption = $('div.ilightbox-caption', vars.holder),
14977					social = $('div.ilightbox-social', vars.holder),
14978					fadeSpeed = opts.effects.fadeSpeed;
14979
14980				if (vars.nextLock || vars.prevLock) {
14981					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
14982					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
14983
14984					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
14985					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
14986				} else {
14987					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
14988					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
14989
14990					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
14991					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
14992				}
14993			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
14994				if (e.type == 'mouseenter') vars.lockWheel = true;
14995				else vars.lockWheel = false;
14996			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
14997				var t = $(this);
14998
14999				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
15000				else if (t.hasClass('ilightbox-play')) {
15001					iL.resume();
15002					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
15003				} else if (t.hasClass('ilightbox-pause')) {
15004					iL.pause();
15005					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
15006				} else iL.closeAction();
15007			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
15008				// prevent scrolling
15009				e.preventDefault();
15010			});
15011
15012			function mouseMoveHandler(e) {
15013				if (!vars.isMobile) {
15014					if (!vars.mouseID) {
15015						vars.hideableElements.show();
15016					}
15017
15018					vars.mouseID = clearTimeout(vars.mouseID);
15019
15020					if (buttonsArray.indexOf(e.target) === -1)
15021						vars.mouseID = setTimeout(function() {
15022							vars.hideableElements.hide();
15023							vars.mouseID = clearTimeout(vars.mouseID);
15024						}, 3000);
15025				}
15026			}
15027
15028			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
15029
15030			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15031				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
15032				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
15033			});
15034
15035			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
15036				delay = false;
15037
15038			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
15039				event.preventDefault();
15040				if (delay) return;
15041				delay = true;
15042				if (!vars.lockWheel) {
15043					event.preventDefault();
15044					if (delta < 0) {
15045						iL.moveTo('next');
15046					} else if (delta > 0) {
15047						iL.moveTo('prev');
15048					}
15049				}
15050				setTimeout(function(){
15051					delay = false;
15052				}, 2000);
15053			});
15054
15055			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
15056				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
15057
15058				vars.BODY.addClass('ilightbox-closedhand');
15059
15060				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
15061					scrollTop = $doc.scrollTop(),
15062					scrollLeft = $doc.scrollLeft(),
15063					offsets = [
15064						holders.eq(0).offset(),
15065						holders.eq(1).offset(),
15066						holders.eq(2).offset()
15067					],
15068					offSet = [{
15069						top: offsets[0].top - scrollTop,
15070						left: offsets[0].left - scrollLeft
15071					}, {
15072						top: offsets[1].top - scrollTop,
15073						left: offsets[1].left - scrollLeft
15074					}, {
15075						top: offsets[2].top - scrollTop,
15076						left: offsets[2].left - scrollLeft
15077					}],
15078					start = {
15079						time: (new Date()).getTime(),
15080						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15081					},
15082					stop;
15083
15084				function moveEachHandler(i) {
15085					var t = $(this),
15086						offset = offSet[i],
15087						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
15088
15089					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
15090				}
15091
15092				function moveHandler(event) {
15093
15094					if (!start) return;
15095
15096					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
15097
15098					stop = {
15099						time: (new Date()).getTime(),
15100						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15101					};
15102
15103					holders.each(moveEachHandler);
15104
15105					// prevent scrolling
15106					event.preventDefault();
15107				}
15108
15109				function repositionHolders() {
15110					holders.each(function() {
15111						var t = $(this),
15112							offset = t.data('offset') || {
15113								top: t.offset().top - scrollTop,
15114								left: t.offset().left - scrollLeft
15115							},
15116							top = offset.top,
15117							left = offset.left;
15118
15119						t.css(transform, gpuAcceleration).stop().animate({
15120							top: top,
15121							left: left
15122						}, 500, 'easeOutCirc', function() {
15123							t.css(transform, '');
15124						});
15125					});
15126				}
15127
15128				holders.bind(touchMoveEvent, moveHandler);
15129				$doc.one(touchStopEvent, function(event) {
15130					holders.unbind(touchMoveEvent, moveHandler);
15131
15132					vars.BODY.removeClass('ilightbox-closedhand');
15133
15134					if (start && stop) {
15135						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
15136							if (start.coords[0] > stop.coords[0]) {
15137								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15138								else {
15139									vars.isSwipe = true;
15140									iL.moveTo('next');
15141								}
15142							} else {
15143								if (vars.current == 0 && !opts.infinite) repositionHolders();
15144								else {
15145									vars.isSwipe = true;
15146									iL.moveTo('prev');
15147								}
15148							}
15149						} 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) {
15150							if (start.coords[1] > stop.coords[1]) {
15151								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15152								else {
15153									vars.isSwipe = true;
15154									iL.moveTo('next');
15155								}
15156							} else {
15157								if (vars.current == 0 && !opts.infinite) repositionHolders();
15158								else {
15159									vars.isSwipe = true;
15160									iL.moveTo('prev');
15161								}
15162							}
15163						} else repositionHolders();
15164					}
15165					start = stop = undefined;
15166				});
15167			});
15168
15169		},
15170
15171		goTo: function(index) {
15172			var iL = this,
15173				vars = iL.vars,
15174				opts = iL.options,
15175				diff = (index - vars.current);
15176
15177			if (opts.infinite) {
15178				if (index == vars.total - 1 && vars.current == 0) diff = -1;
15179				if (vars.current == vars.total - 1 && index == 0) diff = 1;
15180			}
15181
15182			if (diff == 1) iL.moveTo('next');
15183			else if (diff == -1) iL.moveTo('prev');
15184			else {
15185
15186				if (vars.nextLock || vars.prevLock) return false;
15187
15188				//Trigger the onBeforeChange callback
15189				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
15190
15191				if (opts.linkId) {
15192					vars.hashLock = true;
15193					window.location.hash = opts.linkId + '/' + index;
15194				}
15195
15196				if (iL.items[index]) {
15197					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
15198					else iL.vars.lockWheel = false;
15199
15200					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
15201					else vars.lockSwipe = false;
15202				}
15203
15204				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
15205					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
15206				});
15207
15208				vars.current = index;
15209				vars.next = index + 1;
15210				vars.prev = index - 1;
15211
15212				iL.createUI();
15213
15214				setTimeout(function() {
15215					iL.generateBoxes();
15216				}, opts.effects.loadedFadeSpeed + 50);
15217
15218				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
15219				iL.positionThumbnails();
15220
15221				if (opts.linkId) setTimeout(function() {
15222					vars.hashLock = false;
15223				}, 55);
15224
15225				// Configure arrow buttons
15226				if (!opts.infinite) {
15227					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15228
15229					if (vars.current == 0) {
15230						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15231					}
15232					if (vars.current >= vars.total - 1) {
15233						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15234					}
15235				}
15236
15237				// Reset next cycle timeout
15238				iL.resetCycle();
15239
15240				//Trigger the onAfterChange callback
15241				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
15242			}
15243		},
15244
15245		moveTo: function(side) {
15246			var iL = this,
15247				vars = iL.vars,
15248				opts = iL.options,
15249				path = opts.path.toLowerCase(),
15250				viewport = getViewport(),
15251				switchSpeed = opts.effects.switchSpeed;
15252
15253			if (vars.nextLock || vars.prevLock) return false;
15254			else {
15255
15256				var item = (side == "next") ? vars.next : vars.prev;
15257
15258				if (opts.linkId) {
15259					vars.hashLock = true;
15260					window.location.hash = opts.linkId + '/' + item;
15261				}
15262
15263				if (side == "next") {
15264					if (!iL.items[item]) return false;
15265					var firstHolder = vars.nextPhoto,
15266						secondHolder = vars.holder,
15267						lastHolder = vars.prevPhoto,
15268						firstClass = 'ilightbox-prev',
15269						secondClass = 'ilightbox-next';
15270				} else if (side == "prev") {
15271					if (!iL.items[item]) return false;
15272					var firstHolder = vars.prevPhoto,
15273						secondHolder = vars.holder,
15274						lastHolder = vars.nextPhoto,
15275						firstClass = 'ilightbox-next',
15276						secondClass = 'ilightbox-prev';
15277				}
15278
15279				//Trigger the onBeforeChange callback
15280				if (typeof opts.callback.onBeforeChange == 'function')
15281					opts.callback.onBeforeChange.call(iL, iL.ui);
15282
15283				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
15284
15285				var captionFirst = $('div.ilightbox-caption', secondHolder),
15286					socialFirst = $('div.ilightbox-social', secondHolder);
15287
15288				if (captionFirst.length)
15289					captionFirst.stop().fadeOut(switchSpeed, function() {
15290						$(this).remove();
15291					});
15292				if (socialFirst.length)
15293					socialFirst.stop().fadeOut(switchSpeed, function() {
15294						$(this).remove();
15295					});
15296
15297				if (iL.items[item].caption) {
15298					iL.setCaption(iL.items[item], firstHolder);
15299					var caption = $('div.ilightbox-caption', firstHolder),
15300						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
15301					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
15302				}
15303
15304				var social = iL.items[item].options.social;
15305				if (social) {
15306					iL.setSocial(social, iL.items[item].URL, firstHolder);
15307					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
15308				}
15309
15310				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
15311					val.removeClass('ilightbox-next ilightbox-prev');
15312				});
15313
15314				var firstOffset = firstHolder.data('offset'),
15315					winW = (viewport.width - (opts.styles.pageOffsetX)),
15316					winH = (viewport.height - (opts.styles.pageOffsetY)),
15317					width = firstOffset.newDims.width,
15318					height = firstOffset.newDims.height,
15319					thumbsOffset = firstOffset.thumbsOffset,
15320					diff = firstOffset.diff,
15321					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
15322					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15323
15324				var secondOffset = secondHolder.data('offset'),
15325					object = secondOffset.object;
15326
15327				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15328					var objRatio = width / height;
15329					height = height - vars.captionHeight;
15330					width = height * objRatio;
15331					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
15332					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15333				}*/
15334
15335				firstHolder.show().css(transform, gpuAcceleration).animate({
15336					top: top,
15337					left: left,
15338					opacity: 1
15339				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15340					firstHolder.css(transform, '');
15341				});
15342
15343				$('div.ilightbox-container', firstHolder).animate({
15344					width: width,
15345					height: height
15346				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15347
15348				diff = secondOffset.diff;
15349
15350				width = secondOffset.newDims.width,
15351					height = secondOffset.newDims.height;
15352
15353				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15354					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15355					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
15356
15357				if (side == 'prev')
15358					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
15359				else {
15360					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
15361					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
15362				}
15363
15364				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15365					var objRatio = width / height;
15366					height = height - vars.captionHeight;
15367					width = height * objRatio;
15368					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
15369				}*/
15370
15371				$('div.ilightbox-container', secondHolder).animate({
15372					width: width,
15373					height: height
15374				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15375
15376				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
15377					top: top,
15378					left: left,
15379					opacity: opts.styles.prevOpacity,
15380				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15381					secondHolder.css(transform, '');
15382
15383					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
15384					iL.positionThumbnails();
15385
15386					if (iL.items[item]) {
15387						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
15388						else vars.lockWheel = false;
15389
15390						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
15391						else vars.lockSwipe = false;
15392					}
15393
15394					vars.isSwipe = false;
15395
15396					// Remove iframe & video from previous slide
15397					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15398						$('div.ilightbox-container', secondHolder).empty();
15399					}
15400
15401					if (side == "next") {
15402						vars.nextPhoto = lastHolder,
15403							vars.prevPhoto = secondHolder,
15404							vars.holder = firstHolder;
15405
15406						vars.nextPhoto.hide();
15407
15408						vars.next = vars.next + 1,
15409							vars.prev = vars.current,
15410							vars.current = vars.current + 1;
15411
15412						if (opts.infinite) {
15413							if (vars.current > vars.total - 1) vars.current = 0;
15414							if (vars.current == vars.total - 1) vars.next = 0;
15415							if (vars.current == 0) vars.prev = vars.total - 1;
15416						}
15417
15418						iL.createUI();
15419
15420						if (!iL.items[vars.next])
15421							vars.nextLock = false;
15422						else
15423							iL.loadContent(iL.items[vars.next], 'next');
15424					} else {
15425						vars.prevPhoto = lastHolder;
15426						vars.nextPhoto = secondHolder;
15427						vars.holder = firstHolder;
15428
15429						vars.prevPhoto.hide();
15430
15431						vars.next = vars.current;
15432						vars.current = vars.prev;
15433						vars.prev = vars.current - 1;
15434
15435						if (opts.infinite) {
15436							if (vars.current == vars.total - 1) vars.next = 0;
15437							if (vars.current == 0) vars.prev = vars.total - 1;
15438						}
15439
15440						iL.createUI();
15441
15442						if (!iL.items[vars.prev])
15443							vars.prevLock = false;
15444						else
15445							iL.loadContent(iL.items[vars.prev], 'prev');
15446					}
15447
15448					// Add iframe & video content for current slide
15449					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15450						iL.loadContent(iL.items[vars.current], 'current');
15451					}
15452
15453					if (opts.linkId) setTimeout(function() {
15454						vars.hashLock = false;
15455					}, 55);
15456
15457					// Configure arrow buttons
15458					if (!opts.infinite) {
15459						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15460
15461						if (vars.current == 0)
15462							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15463						if (vars.current >= vars.total - 1)
15464							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15465					}
15466
15467					iL.repositionPhoto();
15468
15469					// Reset next cycle timeout
15470					iL.resetCycle();
15471
15472					//Trigger the onAfterChange callback
15473					if (typeof opts.callback.onAfterChange == 'function')
15474						opts.callback.onAfterChange.call(iL, iL.ui);
15475				});
15476
15477				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
15478					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
15479
15480				lastHolder.css(transform, gpuAcceleration).animate({
15481					top: top,
15482					left: left,
15483					opacity: opts.styles.nextOpacity
15484				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15485					lastHolder.css(transform, '');
15486				}).addClass(secondClass);
15487			}
15488		},
15489
15490		setCaption: function(obj, target) {
15491			var iL = this,
15492				caption = $('<div class="ilightbox-caption"></div>');
15493
15494			if (obj.caption) {
15495				caption.html(obj.caption);
15496				$('div.ilightbox-container', target).append(caption);
15497			}
15498		},
15499
15500		normalizeSocial: function(obj, url) {
15501			var iL = this,
15502				vars = iL.vars,
15503				opts = iL.options,
15504				baseURL = window.location.href;
15505
15506			$.each(obj, function(key, value) {
15507				if (!value)
15508					return true;
15509
15510				var item = key.toLowerCase(),
15511					source, text;
15512
15513				switch (item) {
15514					case 'facebook':
15515						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
15516							text = "Share on Facebook";
15517						break;
15518					case 'twitter':
15519						source = "http://twitter.com/home?status={URL}",
15520							text = "Share on Twitter";
15521						break;
15522					case 'digg':
15523						source = "http://digg.com/submit?phase=2&url={URL}",
15524							text = "Share on Digg";
15525						break;
15526					case 'reddit':
15527						source = "http://reddit.com/submit?url={URL}",
15528							text = "Share on reddit";
15529						break;
15530				}
15531
15532				obj[key] = {
15533					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
15534					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
15535					text: value.text || text || "Share on " + key,
15536					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
15537					height: value.height || 360
15538				};
15539
15540			});
15541
15542			return obj;
15543		},
15544
15545		setSocial: function(obj, url, target) {
15546			var iL = this,
15547				socialBar = $('<div class="ilightbox-social"></div>'),
15548				buttons = '<ul>';
15549
15550			obj = iL.normalizeSocial(obj, url);
15551
15552			$.each(obj, function(key, value) {
15553				var item = key.toLowerCase(),
15554					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, '+'));
15555				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>';
15556			});
15557
15558			buttons += '</ul>';
15559
15560			socialBar.html(buttons);
15561			$('div.ilightbox-container', target).append(socialBar);
15562		},
15563
15564		fullScreenAction: function() {
15565			var iL = this,
15566				vars = iL.vars;
15567
15568			if (fullScreenApi.supportsFullScreen) {
15569				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
15570				else fullScreenApi.requestFullScreen(document.documentElement);
15571			} else {
15572				iL.doFullscreen();
15573			}
15574		},
15575
15576		doFullscreen: function() {
15577			var iL = this,
15578				vars = iL.vars,
15579				viewport = getViewport(),
15580				opts = iL.options;
15581
15582			if (opts.fullAlone) {
15583				var currentHolder = vars.holder,
15584					current = iL.items[vars.current],
15585					windowWidth = viewport.width,
15586					windowHeight = viewport.height,
15587					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
15588					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15589
15590				if (!vars.isInFullScreen) {
15591					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
15592					vars.overlay.css({
15593						opacity: 1
15594					});
15595
15596					$.each(hideElements, function(i, element) {
15597						element.hide();
15598					});
15599
15600					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
15601
15602					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
15603						naturalWidthOld: currentHolder.data('naturalWidth'),
15604						naturalHeightOld: currentHolder.data('naturalHeight'),
15605						naturalWidth: windowWidth,
15606						naturalHeight: windowHeight
15607					});
15608					else {
15609						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
15610							newWidth = windowWidth,
15611							newHeight = windowHeight,
15612							width = currentHolder.data('naturalWidth'),
15613							height = currentHolder.data('naturalHeight');
15614
15615						if (viewport.toLowerCase() == 'fill') {
15616							newHeight = (newWidth / width) * height;
15617
15618							if (newHeight < windowHeight) {
15619								newWidth = (windowHeight / height) * width,
15620									newHeight = windowHeight;
15621							}
15622						} else if (viewport.toLowerCase() == 'fit') {
15623							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
15624
15625							newWidth = dims.width,
15626								newHeight = dims.height;
15627						} else if (viewport.toLowerCase() == 'stretch') {
15628							newWidth = newWidth,
15629								newHeight = newHeight;
15630						} else {
15631							var scale = (width > newWidth || height > newHeight) ? true : false,
15632								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
15633							newWidth = dims.width,
15634								newHeight = dims.height;
15635						}
15636
15637						currentHolder.data({
15638							naturalWidthOld: currentHolder.data('naturalWidth'),
15639							naturalHeightOld: currentHolder.data('naturalHeight'),
15640							naturalWidth: newWidth,
15641							naturalHeight: newHeight
15642						});
15643					}
15644
15645					$.each(elements, function(key, val) {
15646						val.addClass('ilightbox-fullscreen');
15647					});
15648
15649					//Trigger the onEnterFullScreen callback
15650					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
15651				} else {
15652					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
15653					vars.overlay.css({
15654						opacity: iL.options.overlay.opacity
15655					});
15656
15657					$.each(hideElements, function(i, element) {
15658						element.show();
15659					});
15660
15661					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
15662
15663					currentHolder.data({
15664						naturalWidth: currentHolder.data('naturalWidthOld'),
15665						naturalHeight: currentHolder.data('naturalHeightOld'),
15666						naturalWidthOld: null,
15667						naturalHeightOld: null
15668					});
15669
15670					$.each(elements, function(key, val) {
15671						val.removeClass('ilightbox-fullscreen');
15672					});
15673
15674					//Trigger the onExitFullScreen callback
15675					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
15676				}
15677			} else {
15678				if (!vars.isInFullScreen) vars.isInFullScreen = true;
15679				else vars.isInFullScreen = false;
15680			}
15681			iL.repositionPhoto(true);
15682		},
15683
15684		closeAction: function() {
15685			var iL = this,
15686				vars = iL.vars,
15687				opts = iL.options;
15688
15689			$win.unbind('.iLightBox');
15690			$doc.off('.iLightBox');
15691
15692			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
15693
15694			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
15695
15696			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
15697				vars.overlay.remove();
15698				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15699			});
15700			else {
15701				vars.overlay.remove();
15702				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15703			}
15704
15705			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15706
15707			$.each(fadeOuts, function(i, element) {
15708				element.removeAttr('style').remove();
15709			});
15710
15711			vars.dontGenerateThumbs = vars.isInFullScreen = false;
15712
15713			window.iLightBox = null;
15714
15715			if (opts.linkId) {
15716				vars.hashLock = true;
15717				removeHash();
15718				setTimeout(function() {
15719					vars.hashLock = false;
15720				}, 55);
15721			}
15722
15723			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15724
15725			//Trigger the onHide callback
15726			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
15727		},
15728
15729		repositionPhoto: function() {
15730			var iL = this,
15731				vars = iL.vars,
15732				opts = iL.options,
15733				path = opts.path.toLowerCase(),
15734				viewport = getViewport(),
15735				winWidth = viewport.width,
15736				winHeight = viewport.height;
15737
15738			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
15739
15740			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
15741				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
15742				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
15743				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
15744				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,
15745				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)));
15746
15747			var elObject = {
15748				type: 'current',
15749				width: width,
15750				height: height,
15751				item: iL.items[vars.current],
15752				offsetW: offsetW,
15753				offsetH: offsetH,
15754				thumbsOffsetW: thumbsOffsetW,
15755				thumbsOffsetH: thumbsOffsetH,
15756				animate: arguments.length,
15757				holder: vars.holder
15758			};
15759
15760			iL.repositionEl(elObject);
15761
15762			if (iL.items[vars.next]) {
15763				elObject = $.extend(elObject, {
15764					type: 'next',
15765					item: iL.items[vars.next],
15766					offsetX: opts.styles.nextOffsetX,
15767					offsetY: opts.styles.nextOffsetY,
15768					holder: vars.nextPhoto
15769				});
15770
15771				iL.repositionEl(elObject);
15772			}
15773
15774			if (iL.items[vars.prev]) {
15775				elObject = $.extend(elObject, {
15776					type: 'prev',
15777					item: iL.items[vars.prev],
15778					offsetX: opts.styles.nextOffsetX,
15779					offsetY: opts.styles.prevOffsetY,
15780					holder: vars.prevPhoto
15781				});
15782
15783				iL.repositionEl(elObject);
15784			}
15785
15786			var loaderCss = (path == "horizontal") ? {
15787				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
15788			} : {
15789				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
15790			};
15791			vars.loader.css(loaderCss);
15792		},
15793
15794		repositionEl: function(obj) {
15795			var iL = this,
15796				vars = iL.vars,
15797				opts = iL.options,
15798				path = opts.path.toLowerCase(),
15799				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
15800				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
15801				itemParent = obj.item,
15802				item = obj.item.options,
15803				holder = obj.holder,
15804				offsetX = obj.offsetX || 0,
15805				offsetY = obj.offsetY || 0,
15806				//Uncode change ##START##
15807				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
15808				//Uncode change ##END##
15809				thumbsOffsetW = obj.thumbsOffsetW,
15810				thumbsOffsetH = obj.thumbsOffsetH;
15811
15812			if (obj.type == 'current') {
15813				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);
15814				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);
15815			} else {
15816				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
15817				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
15818			}
15819
15820
15821			//Uncode change ##START##
15822			heightAvail = parseInt(heightAvail - toolbarHeight);
15823			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
15824			//Uncode change ##END##
15825
15826			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
15827				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
15828
15829			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
15830					width: width,
15831					height: height
15832				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
15833				newDims = $.extend({}, dims, {});
15834
15835			if (obj.type == 'prev' || obj.type == 'next')
15836				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
15837				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
15838			else
15839				width = dims.width,
15840				height = dims.height;
15841
15842			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
15843				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);
15844
15845			switch (obj.type) {
15846				case 'current':
15847					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
15848						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15849					break;
15850
15851				case 'next':
15852					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
15853						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
15854					break;
15855
15856				case 'prev':
15857					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
15858						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15859					break;
15860			}
15861
15862			holder.data('offset', {
15863				top: top,
15864				left: left,
15865				newDims: newDims,
15866				diff: {
15867					W: widthDiff,
15868					H: heightDiff
15869				},
15870				thumbsOffset: {
15871					W: thumbsOffsetW,
15872					H: thumbsOffsetH
15873				},
15874				object: obj
15875			});
15876
15877			var opacityMobile;
15878			if ( isMobile ) {
15879				opacityMobile = {
15880					opacity: 1,
15881					top: top,
15882					left: left
15883				};
15884			} else {
15885				opacityMobile = {
15886					top: top,
15887					left: left
15888				};
15889			}
15890
15891			if (obj.animate > 0 && opts.effects.reposition) {
15892				holder.css(transform, gpuAcceleration).stop().animate(
15893					opacityMobile,
15894					opts.effects.repositionSpeed, 'easeOutCirc', function() {
15895					holder.css(transform, '');
15896				});
15897				$('div.ilightbox-container', holder).stop().animate({
15898					width: width,
15899					height: height
15900				}, opts.effects.repositionSpeed, 'easeOutCirc');
15901				$('div.ilightbox-inner-toolbar', holder).stop().animate({
15902					width: width
15903				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
15904					$(this).css('overflow', 'visible');
15905				});
15906			} else {
15907				holder.css(opacityMobile);
15908				$('div.ilightbox-container', holder).css({
15909					width: width,
15910					height: height
15911				});
15912				$('div.ilightbox-inner-toolbar', holder).css({
15913					width: width
15914				});
15915			}
15916		},
15917
15918
15919		resume: function(priority) {
15920			var iL = this,
15921				vars = iL.vars,
15922				opts = iL.options;
15923
15924			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
15925				return;
15926			}
15927
15928			vars.isPaused = 0;
15929
15930			if (vars.cycleID) {
15931				vars.cycleID = clearTimeout(vars.cycleID);
15932			}
15933
15934			vars.cycleID = setTimeout(function() {
15935				if (vars.current == vars.total - 1) iL.goTo(0);
15936				else iL.moveTo('next');
15937			}, opts.slideshow.pauseTime);
15938		},
15939
15940		pause: function(priority) {
15941			var iL = this,
15942				vars = iL.vars,
15943				opts = iL.options;
15944
15945			if (priority < vars.isPaused) {
15946				return;
15947			}
15948
15949			vars.isPaused = priority || 100;
15950
15951			if (vars.cycleID) {
15952				vars.cycleID = clearTimeout(vars.cycleID);
15953			}
15954		},
15955
15956		resetCycle: function() {
15957			var iL = this,
15958				vars = iL.vars,
15959				opts = iL.options;
15960
15961			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
15962				iL.resume();
15963			}
15964		},
15965
15966		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
15967			var iL = this;
15968
15969			if (!width) factor = height / height_old;
15970			else if (!height) factor = width / width_old;
15971			else factor = min(width / width_old, height / height_old);
15972
15973			if (!thumb) {
15974				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
15975				else if (factor < iL.options.minScale) factor = iL.options.minScale;
15976			}
15977
15978			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
15979				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
15980
15981			return {
15982				width: final_width,
15983				height: final_height,
15984				ratio: factor
15985			};
15986		},
15987
15988		setOption: function(options) {
15989			var iL = this;
15990
15991			iL.options = $.extend(true, iL.options, options || {});
15992			iL.refresh();
15993		},
15994
15995		availPlugins: function() {
15996			var iL = this,
15997				testEl = document.createElement("video");
15998
15999			iL.plugins = {
16000				flash: !isMobile,
16001				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
16002				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
16003				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
16004				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
16005				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
16006			};
16007		},
16008
16009		addContent: function(element, obj) {
16010			var iL = this,
16011				el;
16012
16013			switch (obj.type) {
16014				case 'video':
16015					var HTML5 = false,
16016						videoType = obj.videoType,
16017						html5video = obj.options.html5video;
16018
16019					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
16020						obj.ext = 'mp4',
16021						obj.URL = html5video.h264 || obj.URL;
16022					else if (html5video.webm && iL.plugins.html5WebM)
16023						obj.ext = 'webm',
16024						obj.URL = html5video.webm || obj.URL;
16025					else if (html5video.ogg && iL.plugins.html5Vorbis)
16026						obj.ext = 'ogv',
16027						obj.URL = html5video.ogg || obj.URL;
16028
16029					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
16030					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
16031					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
16032					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
16033
16034					if (HTML5) {
16035						el = $('<video />
16035', {
16036							"width": "100%",
16037							"height": "100%",
16038							"preload": html5video.preload,
16039							"autoplay": html5video.autoplay,
16040							"loop": html5video.loop,
16041							"poster": html5video.poster,
16042							"controls": html5video.controls,
16043							"controlslist": "nodownload"
16044						}).append($('<source />', {
16045							"src": obj.URL,
16046							"type": videoType
16047						}));
16048					} else {
16049						if (!iL.plugins.quicktime) el = $('<span />', {
16050							"class": "ilightbox-alert",
16051							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
16052						});
16053						else {
16054
16055							el = $('<object />', {
16056								"type": "video/quicktime",
16057								"pluginspage": pluginspages.quicktime
16058							}).attr({
16059								"data": obj.URL,
16060								"width": "100%",
16061								"height": "100%"
16062							}).append($('<param />', {
16063								"name": "src",
16064								"value": obj.URL
16065							})).append($('<param />', {
16066								"name": "autoplay",
16067								"value": "false"
16068							})).append($('<param />', {
16069								"name": "loop",
16070								"value": "false"
16071							})).append($('<param />', {
16072								"name": "scale",
16073								"value": "tofit"
16074							}));
16075
16076							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
16077						}
16078					}
16079
16080					break;
16081
16082				case 'flash':
16083					if (!iL.plugins.flash) el = $('<span />', {
16084						"class": "ilightbox-alert",
16085						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
16086					});
16087					else {
16088						var flashvars = "",
16089							i = 0;
16090
16091						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
16092							if (i != 0) flashvars += "&";
16093							flashvars += k + "=" + encodeURIComponent(v);
16094							i++;
16095						});
16096						else flashvars = null;
16097
16098						el = $('<embed />').attr({
16099							"type": "application/x-shockwave-flash",
16100							"src": obj.URL,
16101							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16102							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16103							"quality": "high",
16104							"bgcolor": "#000000",
16105							"play": "true",
16106							"loop": "true",
16107							"menu": "true",
16108							"wmode": "transparent",
16109							"scale": "showall",
16110							"allowScriptAccess": "always",
16111							"allowFullScreen": "true",
16112							"flashvars": flashvars,
16113							"fullscreen": "yes"
16114						});
16115					}
16116
16117					break;
16118
16119				case 'iframe':
16120					el = $('<iframe />').attr({
16121						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16122						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16123						src: obj.URL,
16124						frameborder: 0,
16125						'hspace': 0,
16126						'vspace': 0,
16127						'scrolling': supportTouch ? 'auto' : 'scroll',
16128						'webkitAllowFullScreen': '',
16129						'mozallowfullscreen': '',
16130						'allowFullScreen': ''
16131					});
16132
16133					break;
16134
16135				case 'inline':
16136					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
16137
16138					break;
16139
16140				case 'html':
16141					var object = obj.URL,
16142						el;
16143
16144					if (object[0].nodeName) {
16145						el = $('<div class="ilightbox-wrapper"></div>').html(object);
16146					} else {
16147						var dom = $(obj.URL),
16148							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
16149						el = $('<div class="ilightbox-wrapper"></div>').html(html);
16150					}
16151
16152					break;
16153			}
16154
16155			$('div.ilightbox-container', element).empty().html(el);
16156
16157			// For fixing Chrome about just playing the video for first time
16158			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
16159				var src = el[0].currentSrc + '?' + floor(random() * 30000);
16160				el[0].currentSrc = src;
16161				el[0].src = src;
16162			});
16163
16164			return el;
16165		},
16166
16167		ogpRecognition: function(obj, callback) {
16168			var iL = this,
16169				url = obj.URL;
16170
16171			iL.showLoader();
16172			doAjax(url, function(data) {
16173				iL.hideLoader();
16174				if (data) {
16175					var object = new Object();
16176
16177					object.length = false,
16178					object.url = data.url;
16179
16180					if (data.status == 200) {
16181						var result = data.results,
16182							type = result.type,
16183							source = result.source;
16184
16185						object.source = source.src,
16186						object.width = source.width && parseInt(source.width) || 0,
16187						object.height = source.height && parseInt(source.height) || 0,
16188						object.type = type,
16189						object.thumbnail = source.thumbnail || result.images && result.images[0],
16190						object.html5video = result.html5video || {},
16191						object.length = true;
16192
16193						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
16194						else if (source.type.indexOf("video/") != -1) object.type = "video";
16195						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
16196						else if (source.type.indexOf("image/") != -1) object.type = "image";
16197
16198					} else if (typeof data.response != 'undefined')
16199						throw data.response;
16200
16201					callback.call(this, object.length ? object : false);
16202				}
16203			});
16204		},
16205
16206		hashChangeHandler: function(url) {
16207			var iL = this,
16208				vars = iL.vars,
16209				opts = iL.options,
16210				URL = url || window.location.href,
16211				hash = parseURI(URL).hash,
16212				split = hash.split('/'),
16213				index = split[1];
16214
16215			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
16216
16217			if (index) {
16218				var target = split[1] || 0;
16219				if (iL.items[target]) {
16220					var overlay = $('.ilightbox-overlay');
16221					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
16222						iL.goTo(target);
16223					} else {
16224						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
16225						//iL.goTo(target);
16226					}
16227				} else {
16228					var overlay = $('.ilightbox-overlay');
16229					if (overlay.length) iL.closeAction();
16230				}
16231			} else {
16232				var overlay = $('.ilightbox-overlay');
16233				if (overlay.length) iL.closeAction();
16234			}
16235		}
16236	};
16237
16238	/**
16239	 * Parse style to pixels.
16240	 *
16241	 * @param {Object}   $element   jQuery object with element.
16242	 * @param {Property} property   CSS property to get the pixels from.
16243	 *
16244	 * @return {Int}
16245	 */
16246	function getPixel($element, property) {
16247		return parseInt($element.css(property), 10) || 0;
16248	}
16249
16250	/**
16251	 * Make sure that number is within the limits.
16252	 *
16253	 * @param {Number} number
16254	 * @param {Number} min
16255	 * @param {Number} max
16256	 *
16257	 * @return {Number}
16258	 */
16259	function within(number, min, max) {
16260		return number < min ? min : number > max ? max : number;
16261	}
16262
16263	/**
16264	 * Get viewport/window size (width and height).
16265	 *
16266	 * @return {Object}
16267	 */
16268	function getViewport() {
16269		var e = window,
16270			a = 'inner';
16271		if (!('innerWidth' in window)) {
16272			a = 'client';
16273			e = document.documentElement || document.body;
16274		}
16275		return {
16276			width: e[a + 'Width'],
16277			height: e[a + 'Height']
16278		}
16279	}
16280
16281	/**
16282	 * Remove hash tag from the URL
16283	 *
16284	 * @return {Void}
16285	 */
16286	function removeHash() {
16287		var scroll = getScrollXY();
16288
16289		//UNCODE change
16290		// window.location.hash = "";
16291		// history.pushState("", document.title, window.location.pathname + window.location.search);
16292		history.replaceState({}, document.title, window.location.pathname + window.location.search);
16293
16294		// Restore the scroll offset, should be flicker free
16295		window.scrollTo(scroll.x, scroll.y);
16296	}
16297
16298	/**
16299	 * Do the ajax requests with callback.
16300	 *
16301	 * @param {String}   url
16302	 * @param {Function} callback
16303	 *
16304	 * @return {Void}
16305	 */
16306	function doAjax(url, callback) {
16307		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');
16308		$.ajax({
16309			url: url,
16310			dataType: 'jsonp'
16311		});
16312
16313		iLCallback = function(data) {
16314			callback.call(this, data);
16315		};
16316	}
16317
16318	/**
16319	 * Find image from DOM elements
16320	 *
16321	 * @param {Element} element
16322	 *
16323	 * @return {Void}
16324	 */
16325	function findImageInElement(element) {
16326		var elements = $('*', element),
16327			imagesArr = new Array();
16328
16329		elements.each(function() {
16330			var url = "",
16331				element = this;
16332
16333			if ($(element).css("background-image") != "none") {
16334				url = $(element).css("background-image");
16335			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
16336				url = $(element).attr("src");
16337			}
16338
16339			if (url.indexOf("gradient") == -1) {
16340				url = url.replace(/url\(\"/g, "");
16341				url = url.replace(/url\(/g, "");
16342				url = url.replace(/\"\)/g, "");
16343				url = url.replace(/\)/g, "");
16344
16345				var urls = url.split(",");
16346
16347				for (var i = 0; i < urls.length; i++) {
16348					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
16349						var extra = "";
16350						if (browser.msie && browser.version < 9) {
16351							extra = "?" + floor(random() * 3000);
16352						}
16353						imagesArr.push(urls[i] + extra);
16354					}
16355				}
16356			}
16357		});
16358
16359		return imagesArr;
16360	}
16361
16362	/**
16363	 * Get file extension.
16364	 *
16365	 * @param {String} URL
16366	 *
16367	 * @return {String}
16368	 */
16369	function getExtension(URL) {
16370		if (URL !== null) {
16371			//UNCODE: fix issue to detect media type with query strings
16372			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
16373			ext = ext.split('.').pop().toLowerCase();
16374
16375			return ext;
16376		}
16377	}
16378
16379	/**
16380	 * Get type via extension.
16381	 *
16382	 * @param {String} URL
16383	 *
16384	 * @return {String}
16385	 */
16386	function getTypeByExtension(URL) {
16387		var type,
16388			ext = getExtension(URL);
16389
16390		//Uncode addition ##START##
16391		if (URL == undefined) {
16392			return false;
16393		}
16394		//Uncode addition ##END##
16395
16396		if (extensions.image.indexOf(ext) !== -1) type = 'image';
16397		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
16398		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
16399		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
16400		else type = 'iframe';
16401
16402		return type;
16403	}
16404
16405	/**
16406	 * Return value from percent of a number.
16407	 *
16408	 * @param {Number} percent
16409	 * @param {Number} total
16410	 *
16411	 * @return {Number}
16412	 */
16413	function percentToValue(percent, total) {
16414		return parseInt((total / 100) * percent);
16415	}
16416
16417	/**
16418	 * A JavaScript equivalent of PHP’s parse_url.
16419	 *
16420	 * @param {String} url           The URL to parse.
16421	 *
16422	 * @return {Mixed}
16423	 */
16424	function parseURI(url) {
16425		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
16426		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
16427		return (m ? {
16428			href: m[0] || '',
16429			protocol: m[1] || '',
16430			authority: m[2] || '',
16431			host: m[3] || '',
16432			hostname: m[4] || '',
16433			port: m[5] || '',
16434			pathname: m[6] || '',
16435			search: m[7] || '',
16436			hash: m[8] || ''
16437		} : null);
16438	}
16439
16440	/**
16441	 * Gets the absolute URI.
16442	 *
16443	 * @param {String} href     The relative URL.
16444	 * @param {String} base     The base URL.
16445	 *
16446	 * @return {String}         The absolute URL.
16447	 */
16448	function absolutizeURI(base, href) { // RFC 3986
16449		var iL = this;
16450
16451		function removeDotSegments(input) {
16452			var output = [];
16453			input.replace(/^(\.\.?(\/|$))+/, '')
16454				.replace(/\/(\.(\/|$))+/g, '/')
16455				.replace(/\/\.\.$/, '/../')
16456				.replace(/\/?[^\/]*/g, function(p) {
16457					if (p === '/..') {
16458						output.pop();
16459					} else {
16460						output.push(p);
16461					}
16462				});
16463			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
16464		}
16465
16466		href = parseURI(href || '');
16467		base = parseURI(base || '');
16468
16469		return !href || !base ? null : (href.protocol || base.protocol) +
16470			(href.protocol || href.authority ? href.authority : base.authority) +
16471			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)) +
16472			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
16473			href.hash;
16474	}
16475
16476	/**
16477	 * A JavaScript equivalent of PHP’s version_compare.
16478	 *
16479	 * @param {String} v1
16480	 * @param {String} v2
16481	 * @param {String} operator
16482	 *
16483	 * @return {Boolean}
16484	 */
16485	function version_compare(v1, v2, operator) {
16486		this.php_js = this.php_js || {};
16487		this.php_js.ENV = this.php_js.ENV || {};
16488		var i = 0,
16489			x = 0,
16490			compare = 0,
16491			vm = {
16492				'dev': -6,
16493				'alpha': -5,
16494				'a': -5,
16495				'beta': -4,
16496				'b': -4,
16497				'RC': -3,
16498				'rc': -3,
16499				'#': -2,
16500				'p': 1,
16501				'pl': 1
16502			},
16503			prepVersion = function(v) {
16504				v = ('' + v).replace(/[_\-+]/g, '.');
16505				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
16506				return (!v.length ? [-8] : v.split('.'));
16507			},
16508			numVersion = function(v) {
16509				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
16510			};
16511		v1 = prepVersion(v1);
16512		v2 = prepVersion(v2);
16513		x = max(v1.length, v2.length);
16514		for (i = 0; i < x; i++) {
16515			if (v1[i] == v2[i]) {
16516				continue;
16517			}
16518			v1[i] = numVersion(v1[i]);
16519			v2[i] = numVersion(v2[i]);
16520			if (v1[i] < v2[i]) {
16521				compare = -1;
16522				break;
16523			} else if (v1[i] > v2[i]) {
16524				compare = 1;
16525				break;
16526			}
16527		}
16528		if (!operator) {
16529			return compare;
16530		}
16531
16532		switch (operator) {
16533			case '>':
16534			case 'gt':
16535				return (compare > 0);
16536			case '>=':
16537			case 'ge':
16538				return (compare >= 0);
16539			case '<=':
16540			case 'le':
16541				return (compare <= 0);
16542			case '==':
16543			case '=':
16544			case 'eq':
16545				return (compare === 0);
16546			case '<>':
16547			case '!=':
16548			case 'ne':
16549				return (compare !== 0);
16550			case '':
16551			case '<':
16552			case 'lt':
16553				return (compare < 0);
16554			default:
16555				return null;
16556		}
16557	}
16558
16559
16560	// Begin the iLightBox plugin
16561	$.fn.iLightBox = function() {
16562
16563		var args = arguments,
16564			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
16565			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
16566
16567		if (!opt) opt = {};
16568
16569		// Default options. Play carefully.
16570		var options = $.extend(true, {
16571			attr: 'href',
16572			path: 'vertical',
16573			skin: 'dark',
16574			linkId: false,
16575			infinite: false,
16576			startFrom: 0,
16577			randomStart: false,
16578			keepAspectRatio: true,
16579			maxScale: 1,
16580			minScale: .2,
16581			innerToolbar: false,
16582			smartRecognition: false,
16583			mobileOptimizer: true,
16584			fullAlone: true,
16585			fullViewPort: null,
16586			fullStretchTypes: 'flash, video',
16587			overlay: {
16588				blur: true,
16589				opacity: .85
16590			},
16591			controls: {
16592				arrows: false,
16593				slideshow: false,
16594				toolbar: true,
16595				fullscreen: true,
16596				thumbnail: true,
16597				keyboard: true,
16598				mousewheel: true,
16599				swipe: true
16600			},
16601			keyboard: {
16602				left: true, // previous
16603				right: true, // next
16604				up: true, // previous
16605				down: true, // next
16606				esc: true, // close
16607				shift_enter: true // fullscreen
16608			},
16609			show: {
16610				effect: true,
16611				speed: 300,
16612				title: true
16613			},
16614			hide: {
16615				effect: true,
16616				speed: 300
16617			},
16618			caption: {
16619				start: true,
16620				show: 'mouseenter',
16621				hide: 'mouseleave'
16622			},
16623			social: {
16624				start: true,
16625				show: 'mouseenter',
16626				hide: 'mouseleave',
16627				buttons: false
16628			},
16629			styles: {
16630				pageOffsetX: 0,
16631				pageOffsetY: 0,
16632				nextOffsetX: 45,
16633				nextOffsetY: 0,
16634				nextOpacity: 1,
16635				nextScale: 1,
16636				prevOffsetX: 45,
16637				prevOffsetY: 0,
16638				prevOpacity: 1,
16639				prevScale: 1
16640			},
16641			thumbnails: {
16642				maxWidth: 120,
16643				maxHeight: 80,
16644				normalOpacity: 1,
16645				activeOpacity: .6
16646			},
16647			effects: {
16648				reposition: true,
16649				repositionSpeed: 200,
16650				switchSpeed: 500,
16651				loadedFadeSpeed: 180,
16652				fadeSpeed: 200
16653			},
16654			slideshow: {
16655				pauseTime: 5000,
16656				pauseOnHover: false,
16657				startPaused: true
16658			},
16659			text: {
16660				close: "Press Esc to close",
16661				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
16662				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
16663				slideShow: "Slideshow",
16664				next: "Next",
16665				previous: "Previous"
16666			},
16667			errors: {
16668				loadImage: "An error occurred when trying to load photo.",
16669				loadContents: "An error occurred when trying to load contents.",
16670				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
16671			},
16672			ajaxSetup: {
16673				url: '',
16674				beforeSend: function(jqXHR, settings) {},
16675				cache: false,
16676				complete: function(jqXHR, textStatus) {},
16677				crossDomain: false,
16678				error: function(jqXHR, textStatus, errorThrown) {},
16679				success: function(data, textStatus, jqXHR) {},
16680				global: true,
16681				ifModified: false,
16682				username: null,
16683				password: null,
16684				type: 'GET'
16685			},
16686			callback: {}
16687		}, opt);
16688
16689		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
16690
16691		items = $.isArray(items) ? items : new Array();
16692
16693		if (typeof args[0] == 'string') items[0] = args[0];
16694
16695		if (version_compare($.fn.jquery, '1.8', '>=')) {
16696			var iLB = new iLightBox($(this), options, items, instant);
16697			return {
16698				close: function() {
16699					iLB.closeAction();
16700				},
16701				fullscreen: function() {
16702					iLB.fullScreenAction();
16703				},
16704				moveNext: function() {
16705					iLB.moveTo('next');
16706				},
16707				movePrev: function() {
16708					iLB.moveTo('prev');
16709				},
16710				goTo: function(index) {
16711					iLB.goTo(index);
16712				},
16713				refresh: function() {
16714					iLB.refresh();
16715				},
16716				reposition: function() {
16717					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
16718				},
16719				setOption: function(options) {
16720					iLB.setOption(options);
16721				},
16722				destroy: function() {
16723					iLB.closeAction();
16724					iLB.dispatchItemsEvents();
16725				}
16726			};
16727		} else {
16728			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
16729		}
16730
16731	};
16732
16733
16734	$.iLightBox = function() {
16735		return $.fn.iLightBox(arguments[0], arguments[1]);
16736	};
16737
16738	function getScrollXY() {
16739		var scrOfX = 0,
16740			scrOfY = 0;
16741		if (typeof(window.pageYOffset) == 'number') {
16742			//Netscape compliant
16743			scrOfY = window.pageYOffset;
16744			scrOfX = window.pageXOffset;
16745		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
16746			//DOM compliant
16747			scrOfY = document.body.scrollTop;
16748			scrOfX = document.body.scrollLeft;
16749		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
16750			//IE6 standards compliant mode
16751			scrOfY = document.documentElement.scrollTop;
16752			scrOfX = document.documentElement.scrollLeft;
16753		}
16754		return {
16755			x: scrOfX,
16756			y: scrOfY
16757		};
16758	}
16759
16760	(function() {
16761		// add new event shortcuts
16762		$.each(("touchstart touchmove touchend " +
16763			"tap taphold " +
16764			"swipe swipeleft swiperight " +
16765			"scrollstart scrollstop").split(" "), function(i, name) {
16766
16767			$.fn[name] = function(fn) {
16768				return fn ? this.bind(name, fn) : this.trigger(name);
16769			};
16770
16771			// jQuery < 1.8
16772			// if ($.attrFn) {
16773			// 	$.attrFn[name] = true;
16774			// }
16775		});
16776
16777		var tapSettings = {
16778			startEvent: 'touchstart.iTap',
16779			endEvent: 'touchend.iTap'
16780		};
16781
16782		// tap Event:
16783		$.event.special.itap = {
16784			setup: function() {
16785
16786				var self = this,
16787					$self = $(this),
16788					start, stop;
16789
16790				$self.bind(tapSettings.startEvent, function(event) {
16791					start = getScrollXY();
16792
16793					$self.one(tapSettings.endEvent, function(event) {
16794						stop = getScrollXY();
16795
16796						var orgEvent = event || window.event;
16797						event = $.event.fix(orgEvent);
16798						event.type = "itap";
16799
16800						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
16801
16802						start = stop = undefined;
16803					});
16804				});
16805			},
16806
16807			teardown: function() {
16808				$(this).unbind(tapSettings.startEvent);
16809			}
16810		};
16811	}());
16812
16813
16814	//Fullscreen API
16815	(function() {
16816		fullScreenApi = {
16817				supportsFullScreen: false,
16818				isFullScreen: function() {
16819					return false;
16820				},
16821				requestFullScreen: function() {},
16822				cancelFullScreen: function() {},
16823				fullScreenEventName: '',
16824				prefix: ''
16825			},
16826			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
16827
16828		// check for native support
16829		if (typeof document.cancelFullScreen != 'undefined') {
16830			fullScreenApi.supportsFullScreen = true;
16831		} else {
16832			// check for fullscreen support by vendor prefix
16833			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
16834				fullScreenApi.prefix = browserPrefixes[i];
16835
16836				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
16837					fullScreenApi.supportsFullScreen = true;
16838
16839					break;
16840				}
16841			}
16842		}
16843
16844		// update methods to do something useful
16845		if (fullScreenApi.supportsFullScreen) {
16846			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
16847
16848			fullScreenApi.isFullScreen = function() {
16849				switch (this.prefix) {
16850					case '':
16851						return document.fullScreen;
16852					case 'webkit':
16853						return document.webkitIsFullScreen;
16854					default:
16855						return document[this.prefix + 'FullScreen'];
16856				}
16857			}
16858			fullScreenApi.requestFullScreen = function(el) {
16859				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
16860			}
16861			fullScreenApi.cancelFullScreen = function(el) {
16862				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
16863			}
16864		}
16865	}());
16866
16867	// Browser detect
16868	(function() {
16869		function uaMatch(ua) {
16870			ua = ua.toLowerCase();
16871
16872			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
16873				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
16874				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
16875				/(msie) ([\w.]+)/.exec(ua) ||
16876				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
16877
16878			return {
16879				browser: match[1] || "",
16880				version: match[2] || "0"
16881			};
16882		}
16883
16884		var matched = uaMatch(navigator.userAgent);
16885		browser = {};
16886
16887		if (matched.browser) {
16888			browser[matched.browser] = true;
16889			browser.version = matched.version;
16890		}
16891
16892		// Chrome is Webkit, but Webkit is also Safari.
16893		if (browser.chrome) {
16894			browser.webkit = true;
16895		} else if (browser.webkit) {
16896			browser.safari = true;
16897		}
16898	}());
16899
16900	// Feature detects
16901	(function() {
16902		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
16903		var el = document.createElement('div');
16904
16905		function testProp(prop) {
16906			for (var p = 0, pl = prefixes.length; p < pl; p++) {
16907				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
16908				if (el.style[prefixedProp] !== undefined) {
16909					return prefixedProp;
16910				}
16911			}
16912		}
16913
16914		// Global support indicators
16915		transform = testProp('transform') || '';
16916		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
16917	}());
16918
16919
16920	/*
16921		PluginDetect v0.7.9
16922		www.pinlady.net/PluginDetect/license/
16923		[ getVersion onWindowLoaded BetterIE ]
16924		[ Flash QuickTime Shockwave ]
16925	*/
16926	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;
16926d++){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);
16926d.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)}
16926c.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;
16926if(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();
16927
16928	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)};
16929
16930
16931	/*
16932		jQuery hashchange event v1.3
16933		https://github.com/cowboy/jquery-hashchange
16934		Copyright (c) 2010 "Cowboy" Ben Alman
16935		Dual licensed under the MIT and GPL licenses.
16936	*/
16937	(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=
16938	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||
16939	"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;
16939a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
16940
16941	if (!Array.prototype.filter) {
16942		Array.prototype.filter = function(fun /*, thisp */ ) {
16943			"use strict";
16944
16945			if (this == null)
16946				throw new TypeError();
16947
16948			var t = Object(this);
16949			var len = t.length >>> 0;
16950			if (typeof fun != "function")
16951				throw new TypeError();
16952
16953			var res = [];
16954			var thisp = arguments[1];
16955			for (var i = 0; i < len; i++) {
16956				if (i in t) {
16957					var val = t[i]; // in case fun mutates this
16958					if (fun.call(thisp, val, i, t))
16959						res.push(val);
16960				}
16961			}
16962
16963			return res;
16964		};
16965	}
16966
16967	if (!Array.prototype.indexOf) {
16968		Array.prototype.indexOf = function(searchElement, fromIndex) {
16969			var k;
16970
16971			if (this == null) {
16972				throw new TypeError('"this" is null or not defined');
16973			}
16974
16975			var O = Object(this);
16976
16977			var len = O.length >>> 0;
16978
16979			if (len === 0) {
16980				return -1;
16981			}
16982
16983			var n = +fromIndex || 0;
16984
16985			if (abs(n) === Infinity) {
16986				n = 0;
16987			}
16988
16989			if (n >= len) {
16990				return -1;
16991			}
16992
16993			k = max(n >= 0 ? n : len - abs(n), 0);
16994
16995			while (k < len) {
16996				var kValue;
16997				if (k in O && O[k] === searchElement) {
16998					return k;
16999				}
17000				k++;
17001			}
17002			return -1;
17003		};
17004	}
17005
17006	if (!Array.prototype.lastIndexOf) {
17007		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
17008			"use strict";
17009
17010			if (this == null)
17011				throw new TypeError();
17012
17013			var t = Object(this);
17014			var len = t.length >>> 0;
17015			if (len === 0)
17016				return -1;
17017
17018			var n = len;
17019			if (arguments.length > 1) {
17020				n = Number(arguments[1]);
17021				if (n != n)
17022					n = 0;
17023				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
17024					n = (n > 0 || -1) * floor(abs(n));
17025			}
17026
17027			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
17028
17029			for (; k >= 0; k--) {
17030				if (k in t && t[k] === searchElement)
17031					return k;
17032			}
17033			return -1;
17034		};
17035	}
17036})(jQuery, this);
17037
17038/*!
17039 * lightgallery | 2.5.0 | June 13th 2022
17040 * http://www.lightgalleryjs.com/
17041 * Copyright (c) 2020 Sachin Neravath;
17042 * @license GPLv3
17043 */
17044
17045(function (global, factory) {
17046	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
17047	typeof define === 'function' && define.amd ? define(factory) :
17048	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
17049}(this, (function () { 'use strict';
17050
17051	/*! *****************************************************************************
17052	Copyright (c) Microsoft Corporation.
17053
17054	Permission to use, copy, modify, and/or distribute this software for any
17055	purpose with or without fee is hereby granted.
17056
17057	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17058	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17059	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17060	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17061	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17062	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17063	PERFORMANCE OF THIS SOFTWARE.
17064	***************************************************************************** */
17065
17066	var __assign = function() {
17067		__assign = Object.assign || function __assign(t) {
17068			for (var s, i = 1, n = arguments.length; i < n; i++) {
17069				s = arguments[i];
17070				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
17071			}
17072			return t;
17073		};
17074		return __assign.apply(this, arguments);
17075	};
17076
17077	function __spreadArrays() {
17078		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
17079		for (var r = Array(s), k = 0, i = 0; i < il; i++)
17080			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
17081				r[k] = a[j];
17082		return r;
17083	}
17084
17085	/**
17086	 * List of lightGallery events
17087	 * All events should be documented here
17088	 * Below interfaces are used to build the website documentations
17089	 * */
17090	var lGEvents = {
17091		afterAppendSlide: 'lgAfterAppendSlide',
17092		init: 'lgInit',
17093		hasVideo: 'lgHasVideo',
17094		containerResize: 'lgContainerResize',
17095		updateSlides: 'lgUpdateSlides',
17096		afterAppendSubHtml: 'lgAfterAppendSubHtml',
17097		beforeOpen: 'lgBeforeOpen',
17098		afterOpen: 'lgAfterOpen',
17099		slideItemLoad: 'lgSlideItemLoad',
17100		beforeSlide: 'lgBeforeSlide',
17101		afterSlide: 'lgAfterSlide',
17102		posterClick: 'lgPosterClick',
17103		dragStart: 'lgDragStart',
17104		dragMove: 'lgDragMove',
17105		dragEnd: 'lgDragEnd',
17106		beforeNextSlide: 'lgBeforeNextSlide',
17107		beforePrevSlide: 'lgBeforePrevSlide',
17108		beforeClose: 'lgBeforeClose',
17109		afterClose: 'lgAfterClose',
17110		rotateLeft: 'lgRotateLeft',
17111		rotateRight: 'lgRotateRight',
17112		flipHorizontal: 'lgFlipHorizontal',
17113		flipVertical: 'lgFlipVertical',
17114		autoplay: 'lgAutoplay',
17115		autoplayStart: 'lgAutoplayStart',
17116		autoplayStop: 'lgAutoplayStop',
17117	};
17118
17119	var lightGalleryCoreSettings = {
17120		mode: 'lg-slide',
17121		easing: 'ease',
17122		speed: 400,
17123		licenseKey: '0000-0000-000-0000',
17124		height: '100%',
17125		width: '100%',
17126		addClass: '',
17127		startClass: 'lg-start-zoom',
17128		backdropDuration: 300,
17129		container: '',
17130		startAnimationDuration: 400,
17131		zoomFromOrigin: true,
17132		hideBarsDelay: 0,
17133		showBarsAfter: 10000,
17134		slideDelay: 0,
17135		supportLegacyBrowser: true,
17136		allowMediaOverlap: false,
17137		videoMaxSize: '1280-720',
17138		loadYouTubePoster: true,
17139		defaultCaptionHeight: 0,
17140		ariaLabelledby: '',
17141		ariaDescribedby: '',
17142		resetScrollPosition: true,
17143		hideScrollbar: false,
17144		closable: true,
17145		swipeToClose: true,
17146		closeOnTap: true,
17147		showCloseIcon: true,
17148		showMaximizeIcon: false,
17149		loop: true,
17150		escKey: true,
17151		keyPress: true,
17152		trapFocus: true,
17153		controls: true,
17154		slideEndAnimation: true,
17155		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 17156-17703
17156		mousewheel: false,
17157		getCaptionFromTitleOrAlt: true,
17158		appendSubHtmlTo: '.lg-sub-html',
17159		subHtmlSelectorRelative: false,
17160		preload: 2,
17161		numberOfSlideItemsInDom: 10,
17162		selector: '',
17163		selectWithin: '',
17164		nextHtml: '',
17165		prevHtml: '',
17166		index: 0,
17167		iframeWidth: '100%',
17168		iframeHeight: '100%',
17169		iframeMaxWidth: '100%',
17170		iframeMaxHeight: '100%',
17171		download: true,
17172		counter: true,
17173		appendCounterTo: '.lg-toolbar',
17174		swipeThreshold: 50,
17175		enableSwipe: true,
17176		enableDrag: true,
17177		dynamic: false,
17178		dynamicEl: [],
17179		extraProps: [],
17180		exThumbImage: '',
17181		isMobile: undefined,
17182		mobileSettings: {
17183			controls: false,
17184			showCloseIcon: false,
17185			download: false,
17186		},
17187		plugins: [],
17188		strings: {
17189			closeGallery: 'Close gallery',
17190			toggleMaximize: 'Toggle maximize',
17191			previousSlide: 'Previous slide',
17192			nextSlide: 'Next slide',
17193			download: 'Download',
17194			playVideo: 'Play video',
17195		},
17196	};
17197
17198	function initLgPolyfills() {
17199		(function () {
17200			if (typeof window.CustomEvent === 'function')
17201				return false;
17202			function CustomEvent(event, params) {
17203				params = params || {
17204					bubbles: false,
17205					cancelable: false,
17206					detail: null,
17207				};
17208				var evt = document.createEvent('CustomEvent');
17209				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
17210				return evt;
17211			}
17212			window.CustomEvent = CustomEvent;
17213		})();
17214		(function () {
17215			if (!Element.prototype.matches) {
17216				Element.prototype.matches =
17217					Element.prototype.msMatchesSelector ||
17218						Element.prototype.webkitMatchesSelector;
17219			}
17220		})();
17221	}
17222	var lgQuery = /** @class */ (function () {
17223		function lgQuery(selector) {
17224			this.cssVenderPrefixes = [
17225				'TransitionDuration',
17226				'TransitionTimingFunction',
17227				'Transform',
17228				'Transition',
17229			];
17230			this.selector = this._getSelector(selector);
17231			this.firstElement = this._getFirstEl();
17232			return this;
17233		}
17234		lgQuery.generateUUID = function () {
17235			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
17236				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
17237				return v.toString(16);
17238			});
17239		};
17240		lgQuery.prototype._getSelector = function (selector, context) {
17241			if (context === void 0) { context = document; }
17242			if (typeof selector !== 'string') {
17243				return selector;
17244			}
17245			context = context || document;
17246			var fl = selector.substring(0, 1);
17247			if (fl === '#') {
17248				return context.querySelector(selector);
17249			}
17250			else {
17251				return context.querySelectorAll(selector);
17252			}
17253		};
17254		lgQuery.prototype._each = function (func) {
17255			if (!this.selector) {
17256				return this;
17257			}
17258			if (this.selector.length !== undefined) {
17259				[].forEach.call(this.selector, func);
17260			}
17261			else {
17262				func(this.selector, 0);
17263			}
17264			return this;
17265		};
17266		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
17267			// prettier-ignore
17268			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
17269				return group1.toUpperCase();
17270			});
17271			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
17272				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
17273				el.style['webkit' + property] = value;
17274				el.style['moz' + property] = value;
17275				el.style['ms' + property] = value;
17276				el.style['o' + property] = value;
17277			}
17278			else {
17279				el.style[property] = value;
17280			}
17281		};
17282		lgQuery.prototype._getFirstEl = function () {
17283			if (this.selector && this.selector.length !== undefined) {
17284				return this.selector[0];
17285			}
17286			else {
17287				return this.selector;
17288			}
17289		};
17290		lgQuery.prototype.isEventMatched = function (event, eventName) {
17291			var eventNamespace = eventName.split('.');
17292			return event
17293				.split('.')
17294				.filter(function (e) { return e; })
17295				.every(function (e) {
17296				return eventNamespace.indexOf(e) !== -1;
17297			});
17298		};
17299		lgQuery.prototype.attr = function (attr, value) {
17300			if (value === undefined) {
17301				if (!this.firstElement) {
17302					return '';
17303				}
17304				return this.firstElement.getAttribute(attr);
17305			}
17306			this._each(function (el) {
17307				el.setAttribute(attr, value);
17308			});
17309			return this;
17310		};
17311		lgQuery.prototype.find = function (selector) {
17312			return $LG(this._getSelector(selector, this.selector));
17313		};
17314		lgQuery.prototype.first = function () {
17315			if (this.selector && this.selector.length !== undefined) {
17316				return $LG(this.selector[0]);
17317			}
17318			else {
17319				return $LG(this.selector);
17320			}
17321		};
17322		lgQuery.prototype.eq = function (index) {
17323			return $LG(this.selector[index]);
17324		};
17325		lgQuery.prototype.parent = function () {
17326			return $LG(this.selector.parentElement);
17327		};
17328		lgQuery.prototype.get = function () {
17329			return this._getFirstEl();
17330		};
17331		lgQuery.prototype.removeAttr = function (attributes) {
17332			var attrs = attributes.split(' ');
17333			this._each(function (el) {
17334				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
17335			});
17336			return this;
17337		};
17338		lgQuery.prototype.wrap = function (className) {
17339			if (!this.firstElement) {
17340				return this;
17341			}
17342			var wrapper = document.createElement('div');
17343			wrapper.className = className;
17344			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
17345			this.firstElement.parentNode.removeChild(this.firstElement);
17346			wrapper.appendChild(this.firstElement);
17347			return this;
17348		};
17349		lgQuery.prototype.addClass = function (classNames) {
17350			if (classNames === void 0) { classNames = ''; }
17351			this._each(function (el) {
17352				// IE doesn't support multiple arguments
17353				classNames.split(' ').forEach(function (className) {
17354					if (className) {
17355						el.classList.add(className);
17356					}
17357				});
17358			});
17359			return this;
17360		};
17361		lgQuery.prototype.removeClass = function (classNames) {
17362			this._each(function (el) {
17363				// IE doesn't support multiple arguments
17364				classNames.split(' ').forEach(function (className) {
17365					if (className) {
17366						el.classList.remove(className);
17367					}
17368				});
17369			});
17370			return this;
17371		};
17372		lgQuery.prototype.hasClass = function (className) {
17373			if (!this.firstElement) {
17374				return false;
17375			}
17376			return this.firstElement.classList.contains(className);
17377		};
17378		lgQuery.prototype.hasAttribute = function (attribute) {
17379			if (!this.firstElement) {
17380				return false;
17381			}
17382			return this.firstElement.hasAttribute(attribute);
17383		};
17384		lgQuery.prototype.toggleClass = function (className) {
17385			if (!this.firstElement) {
17386				return this;
17387			}
17388			if (this.hasClass(className)) {
17389				this.removeClass(className);
17390			}
17391			else {
17392				this.addClass(className);
17393			}
17394			return this;
17395		};
17396		lgQuery.prototype.css = function (property, value) {
17397			var _this = this;
17398			this._each(function (el) {
17399				_this._setCssVendorPrefix(el, property, value);
17400			});
17401			return this;
17402		};
17403		// Need to pass separate namespaces for separate elements
17404		lgQuery.prototype.on = function (events, listener) {
17405			var _this = this;
17406			if (!this.selector) {
17407				return this;
17408			}
17409			events.split(' ').forEach(function (event) {
17410				if (!Array.isArray(lgQuery.eventListeners[event])) {
17411					lgQuery.eventListeners[event] = [];
17412				}
17413				lgQuery.eventListeners[event].push(listener);
17414				_this.selector.addEventListener(event.split('.')[0], listener);
17415			});
17416			return this;
17417		};
17418		// @todo - test this
17419		lgQuery.prototype.once = function (event, listener) {
17420			var _this = this;
17421			this.on(event, function () {
17422				_this.off(event);
17423				listener(event);
17424			});
17425			return this;
17426		};
17427		lgQuery.prototype.off = function (event) {
17428			var _this = this;
17429			if (!this.selector) {
17430				return this;
17431			}
17432			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
17433				if (_this.isEventMatched(event, eventName)) {
17434					lgQuery.eventListeners[eventName].forEach(function (listener) {
17435						_this.selector.removeEventListener(eventName.split('.')[0], listener);
17436					});
17437					lgQuery.eventListeners[eventName] = [];
17438				}
17439			});
17440			return this;
17441		};
17442		lgQuery.prototype.trigger = function (event, detail) {
17443			if (!this.firstElement) {
17444				return this;
17445			}
17446			var customEvent = new CustomEvent(event.split('.')[0], {
17447				detail: detail || null,
17448			});
17449			this.firstElement.dispatchEvent(customEvent);
17450			return this;
17451		};
17452		// Does not support IE
17453		lgQuery.prototype.load = function (url) {
17454			var _this = this;
17455			fetch(url)
17456				.then(function (res) { return res.text(); })
17457				.then(function (html) {
17458				_this.selector.innerHTML = html;
17459			});
17460			return this;
17461		};
17462		lgQuery.prototype.html = function (html) {
17463			if (html === undefined) {
17464				if (!this.firstElement) {
17465					return '';
17466				}
17467				return this.firstElement.innerHTML;
17468			}
17469			this._each(function (el) {
17470				el.innerHTML = html;
17471			});
17472			return this;
17473		};
17474		lgQuery.prototype.append = function (html) {
17475			this._each(function (el) {
17476				if (typeof html === 'string') {
17477					el.insertAdjacentHTML('beforeend', html);
17478				}
17479				else {
17480					el.appendChild(html);
17481				}
17482			});
17483			return this;
17484		};
17485		lgQuery.prototype.prepend = function (html) {
17486			this._each(function (el) {
17487				el.insertAdjacentHTML('afterbegin', html);
17488			});
17489			return this;
17490		};
17491		lgQuery.prototype.remove = function () {
17492			this._each(function (el) {
17493				el.parentNode.removeChild(el);
17494			});
17495			return this;
17496		};
17497		lgQuery.prototype.empty = function () {
17498			this._each(function (el) {
17499				el.innerHTML = '';
17500			});
17501			return this;
17502		};
17503		lgQuery.prototype.scrollTop = function (scrollTop) {
17504			if (scrollTop !== undefined) {
17505				document.body.scrollTop = scrollTop;
17506				document.documentElement.scrollTop = scrollTop;
17507				return this;
17508			}
17509			else {
17510				return (window.pageYOffset ||
17511					document.documentElement.scrollTop ||
17512					document.body.scrollTop ||
17513					0);
17514			}
17515		};
17516		lgQuery.prototype.scrollLeft = function (scrollLeft) {
17517			if (scrollLeft !== undefined) {
17518				document.body.scrollLeft = scrollLeft;
17519				document.documentElement.scrollLeft = scrollLeft;
17520				return this;
17521			}
17522			else {
17523				return (window.pageXOffset ||
17524					document.documentElement.scrollLeft ||
17525					document.body.scrollLeft ||
17526					0);
17527			}
17528		};
17529		lgQuery.prototype.offset = function () {
17530			if (!this.firstElement) {
17531				return {
17532					left: 0,
17533					top: 0,
17534				};
17535			}
17536			var rect = this.firstElement.getBoundingClientRect();
17537			var bodyMarginLeft = $LG('body').style().marginLeft;
17538			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
17539			return {
17540				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
17541				top: rect.top + this.scrollTop(),
17542			};
17543		};
17544		lgQuery.prototype.style = function () {
17545			if (!this.firstElement) {
17546				return {};
17547			}
17548			return (this.firstElement.currentStyle ||
17549				window.getComputedStyle(this.firstElement));
17550		};
17551		// Width without padding and border even if box-sizing is used.
17552		lgQuery.prototype.width = function () {
17553			var style = this.style();
17554			return (this.firstElement.clientWidth -
17555				parseFloat(style.paddingLeft) -
17556				parseFloat(style.paddingRight));
17557		};
17558		// Height without padding and border even if box-sizing is used.
17559		lgQuery.prototype.height = function () {
17560			var style = this.style();
17561			return (this.firstElement.clientHeight -
17562				parseFloat(style.paddingTop) -
17563				parseFloat(style.paddingBottom));
17564		};
17565		lgQuery.eventListeners = {};
17566		return lgQuery;
17567	}());
17568	function $LG(selector) {
17569		initLgPolyfills();
17570		return new lgQuery(selector);
17571	}
17572
17573	var defaultDynamicOptions = [
17574		'src',
17575		'sources',
17576		'subHtml',
17577		'subHtmlUrl',
17578		'html',
17579		'video',
17580		'poster',
17581		'slideName',
17582		'responsive',
17583		'srcset',
17584		'sizes',
17585		'iframe',
17586		'downloadUrl',
17587		'download',
17588		'width',
17589		'facebookShareUrl',
17590		'tweetText',
17591		'iframeTitle',
17592		'twitterShareUrl',
17593		'pinterestShareUrl',
17594		'pinterestText',
17595		'fbHtml',
17596		'disqusIdentifier',
17597		'disqusUrl',
17598	];
17599	// Convert html data-attribute to camalcase
17600	function convertToData(attr) {
17601		// FInd a way for lgsize
17602		if (attr === 'href') {
17603			return 'src';
17604		}
17605		attr = attr.replace('data-', '');
17606		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
17607		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
17608		return attr;
17609	}
17610	var utils = {
17611		/**
17612		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
17613		 */
17614		//Uncode edit ##START##
17615		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
17616		// getSize: function (el, container, spacing, defaultLgSize) {
17617		//Uncode edit ##END##
17618			if (spacing === void 0) { spacing = 0; }
17619			var LGel = $LG(el);
17620			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
17621			//Uncode edit ##START##
17622			if ( typeof galleryItem.size && galleryItem.size != null ) {
17623				lgSize = galleryItem.size;
17624			}
17625			//Uncode edit ##END##
17626			if (!lgSize) {
17627				return;
17628			}
17629			var isResponsiveSizes = lgSize.split(',');
17630			// if at-least two viewport sizes are available
17631			if (isResponsiveSizes[1]) {
17632				var wWidth = window.innerWidth;
17633				for (var i = 0; i < isResponsiveSizes.length; i++) {
17634					var size_1 = isResponsiveSizes[i];
17635					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
17636					if (responsiveWidth > wWidth) {
17637						lgSize = size_1;
17638						break;
17639					}
17640					// take last item as last option
17641					if (i === isResponsiveSizes.length - 1) {
17642						lgSize = size_1;
17643					}
17644				}
17645			}
17646			var size = lgSize.split('-');
17647			var width = parseInt(size[0], 10);
17648			var height = parseInt(size[1], 10);
17649			var cWidth = container.width();
17650			var cHeight = container.height() - spacing;
17651			var maxWidth = Math.min(cWidth, width);
17652			var maxHeight = Math.min(cHeight, height);
17653			var ratio = Math.min(maxWidth / width, maxHeight / height);
17654			return { width: width * ratio, height: height * ratio };
17655		},
17656		/**
17657		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
17658		 * @param {jQuery Element}
17659		 * @returns {String} Transform CSS string
17660		 */
17661		getTransform: function (el, container, top, bottom, imageSize) {
17662			if (!imageSize) {
17663				return;
17664			}
17665			var LGel = $LG(el).find('img').first();
17666			if (!LGel.get()) {
17667				return;
17668			}
17669			var containerRect = container.get().getBoundingClientRect();
17670			var wWidth = containerRect.width;
17671			// using innerWidth to include mobile safari bottom bar
17672			var wHeight = container.height() - (top + bottom);
17673			var elWidth = LGel.width();
17674			var elHeight = LGel.height();
17675			var elStyle = LGel.style();
17676			var x = (wWidth - elWidth) / 2 -
17677				LGel.offset().left +
17678				(parseFloat(elStyle.paddingLeft) || 0) +
17679				(parseFloat(elStyle.borderLeft) || 0) +
17680				$LG(window).scrollLeft() +
17681				containerRect.left;
17682			var y = (wHeight - elHeight) / 2 -
17683				LGel.offset().top +
17684				(parseFloat(elStyle.paddingTop) || 0) +
17685				(parseFloat(elStyle.borderTop) || 0) +
17686				$LG(window).scrollTop() +
17687				top;
17688			var scX = elWidth / imageSize.width;
17689			var scY = elHeight / imageSize.height;
17690			var transform = 'translate3d(' +
17691				(x *= -1) +
17692				'px, ' +
17693				(y *= -1) +
17694				'px, 0) scale3d(' +
17695				scX +
17696				', ' +
17697				scY +
17698				', 1)';
17699			return transform;
17700		},
17701		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
17702			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
17703			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 17703-17775
17703+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
17704		},
17705		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
17706			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
17707			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17708			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17709			var sourceTag = '';
17710			if (sources) {
17711				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17712				sourceTag = sourceObj.map(function (source) {
17713					var attrs = '';
17714					Object.keys(source).forEach(function (key) {
17715						// Do not remove the first space as it is required to separate the attributes
17716						attrs += " " + key + "=\"" + source[key] + "\"";
17717					});
17718					return "<source " + attrs + "></source>";
17719				});
17720			}
17721			return "" + sourceTag + imgMarkup;
17722		},
17723		// Get src from responsive src
17724		getResponsiveSrc: function (srcItms) {
17725			var rsWidth = [];
17726			var rsSrc = [];
17727			var src = '';
17728			for (var i = 0; i < srcItms.length; i++) {
17729				var _src = srcItms[i].split(' ');
17730				// Manage empty space
17731				if (_src[0] === '') {
17732					_src.splice(0, 1);
17733				}
17734				rsSrc.push(_src[0]);
17735				rsWidth.push(_src[1]);
17736			}
17737			var wWidth = window.innerWidth;
17738			for (var j = 0; j < rsWidth.length; j++) {
17739				if (parseInt(rsWidth[j], 10) > wWidth) {
17740					src = rsSrc[j];
17741					break;
17742				}
17743			}
17744			return src;
17745		},
17746		isImageLoaded: function (img) {
17747			if (!img)
17748				return false;
17749			// During the onload event, IE correctly identifies any images that
17750			// weren’t downloaded as not complete. Others should too. Gecko-based
17751			// browsers act like NS4 in that they report this incorrectly.
17752			if (!img.complete) {
17753				return false;
17754			}
17755			// However, they do have two very useful properties: naturalWidth and
17756			// naturalHeight. These give the true size of the image. If it failed
17757			// to load, either of these should be zero.
17758			if (img.naturalWidth === 0) {
17759				return false;
17760			}
17761			// No other way of checking: assume it’s ok.
17762			return true;
17763		},
17764		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17765			var videoClass = '';
17766			if (_isVideo && _isVideo.youtube) {
17767				videoClass = 'lg-has-youtube';
17768			}
17769			else if (_isVideo && _isVideo.vimeo) {
17770				videoClass = 'lg-has-vimeo';
17771			}
17772			else {
17773				videoClass = 'lg-has-html5';
17774			}
17775			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
vendor: 5,030 bytes, lines 17775-17886
17775\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>";
17776		},
17777		getFocusableElements: function (container) {
17778			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])');
17779			var visibleElements = [].filter.call(elements, function (element) {
17780				var style = window.getComputedStyle(element);
17781				return style.display !== 'none' && style.visibility !== 'hidden';
17782			});
17783			return visibleElements;
17784		},
17785		/**
17786		 * @desc Create dynamic elements array from gallery items when dynamic option is false
17787		 * It helps to avoid frequent DOM interaction
17788		 * and avoid multiple checks for dynamic elments
17789		 *
17790		 * @returns {Array} dynamicEl
17791		 */
17792		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17793			var dynamicElements = [];
17794			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17795			[].forEach.call(items, function (item) {
17796				var dynamicEl = {};
17797				for (var i = 0; i < item.attributes.length; i++) {
17798					var attr = item.attributes[i];
17799					if (attr.specified) {
17800						var dynamicAttr = convertToData(attr.name);
17801						var label = '';
17802						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17803							label = dynamicAttr;
17804						}
17805						if (label) {
17806							dynamicEl[label] = attr.value;
17807						}
17808					}
17809				}
17810				var currentItem = $LG(item);
17811				var alt = currentItem.find('img').first().attr('alt');
17812				var title = currentItem.attr('title');
17813				//Uncode edit ##START##
17814				// var thumb = exThumbImage
17815				var thumb = exThumbImage && currentItem.attr(exThumbImage)
17816				//Uncode edit ##END##
17817					? currentItem.attr(exThumbImage)
17818					: currentItem.find('img').first().attr('src');
17819				dynamicEl.thumb = thumb;
17820				//Uncode edit ##START##
17821				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17822					// dynamicEl.subHtml = title || alt || '';
17823					dynamicEl.subHtml = title || '';
17824				}
17825				// dynamicEl.alt = alt || title || '';
17826				dynamicEl.alt = title || '';
17827				var inlineType = currentItem.attr('data-type');
17828				dynamicEl.type = inlineType;
17829				//Uncode edit ##END##
17830				dynamicElements.push(dynamicEl);
17831			});
17832			return dynamicElements;
17833		},
17834		isMobile: function () {
17835			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17836		},
17837		/**
17838		 * @desc Check the given src is video
17839		 * @param {String} src
17840		 * @return {Object} video type
17841		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17842		 *
17843		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
17844		 */
17845		isVideo: function (src, isHTML5VIdeo, index) {
17846			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
17847				if (isHTML5VIdeo) {
17848					return {
17849						html5: true,
17850					};
17851				}
17852				else {
17853					console.warn('lightGallery :- data-src is not provided on slide item ' +
17854						(index + 1) +
17855						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17856					return;
17857				}
17858			}
17859			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17860			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17861			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17862			if (youtube) {
17863				return {
17864					youtube: youtube,
17865				};
17866			}
17867			else if (vimeo) {
17868				return {
17869					vimeo: vimeo,
17870				};
17871			}
17872			else if (wistia) {
17873				return {
17874					wistia: wistia,
17875				};
17876			}
17877		},
17878	};
17879
17880	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17881	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17882	// Unique id for each gallery
17883	var lgId = 0;
17884	var LightGallery = /** @class */ (function () {
17885		function LightGallery(element, options) {
17886			this.lgOpened = false;
vendor: 4,563 bytes, lines 17887-18021
17887			this.index = 0;
17888			// lightGallery modules
17889			this.plugins = [];
17890			// false when lightGallery load first slide content;
17891			this.lGalleryOn = false;
17892			// True when a slide animation is in progress
17893			this.lgBusy = false;
17894			this.currentItemsInDom = [];
17895			// Scroll top value before lightGallery is opened
17896			this.prevScrollTop = 0;
17897			this.bodyPaddingRight = 0;
17898			this.isDummyImageRemoved = false;
17899			this.dragOrSwipeEnabled = false;
17900			this.mediaContainerPosition = {
17901				top: 0,
17902				bottom: 0,
17903			};
17904			if (!element) {
17905				return this;
17906			}
17907			lgId++;
17908			this.lgId = lgId;
17909			this.el = element;
17910			this.LGel = $LG(element);
17911			this.generateSettings(options);
17912			this.buildModules();
17913			// When using dynamic mode, ensure dynamicEl is an array
17914			if (this.settings.dynamic &&
17915				this.settings.dynamicEl !== undefined &&
17916				!Array.isArray(this.settings.dynamicEl)) {
17917				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17918			}
17919			this.galleryItems = this.getItems();
17920			this.normalizeSettings();
17921			// Gallery items
17922			this.init();
17923			//Uncode edit ##START##
17924			// this.validateLicense();
17925			//Uncode edit ##END##
17926			return this;
17927		}
17928		LightGallery.prototype.generateSettings = function (options) {
17929			// lightGallery settings
17930			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17931			if (this.settings.isMobile &&
17932				typeof this.settings.isMobile === 'function'
17933				? this.settings.isMobile()
17934				: utils.isMobile()) {
17935				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17936				this.settings = __assign(__assign({}, this.settings), mobileSettings);
17937			}
17938		};
17939		LightGallery.prototype.normalizeSettings = function () {
17940			if (this.settings.slideEndAnimation) {
17941				this.settings.hideControlOnEnd = false;
17942			}
17943			if (!this.settings.closable) {
17944				this.settings.swipeToClose = false;
17945			}
17946			// And reset it on close to get the correct value next time
17947			this.zoomFromOrigin = this.settings.zoomFromOrigin;
17948			// At the moment, Zoom from image doesn't support dynamic options
17949			// @todo add zoomFromOrigin support for dynamic images
17950			if (this.settings.dynamic) {
17951				this.zoomFromOrigin = false;
17952			}
17953			if (!this.settings.container) {
17954				this.settings.container = document.body;
17955			}
17956			// settings.preload should not be grater than $item.length
17957			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17958		};
17959		LightGallery.prototype.init = function () {
17960			var _this = this;
17961			this.addSlideVideoInfo(this.galleryItems);
17962			this.buildStructure();
17963			this.LGel.trigger(lGEvents.init, {
17964				instance: this,
17965			});
17966			if (this.settings.keyPress) {
17967				this.keyPress();
17968			}
17969			setTimeout(function () {
17970				_this.enableDrag();
17971				_this.enableSwipe();
17972				_this.triggerPosterClick();
17973			}, 50);
17974			this.arrow();
17975			if (this.settings.mousewheel) {
17976				this.mousewheel();
17977			}
17978			if (!this.settings.dynamic) {
17979				this.openGalleryOnItemClick();
17980			}
17981		};
17982		LightGallery.prototype.openGalleryOnItemClick = function () {
17983			var _this = this;
17984			var _loop_1 = function (index) {
17985				var element = this_1.items[index];
17986				var $element = $LG(element);
17987				// Using different namespace for click because click event should not unbind if selector is same object('this')
17988				// @todo manage all event listners - should have namespace that represent element
17989				var uuid = lgQuery.generateUUID();
17990				$element
17991					.attr('data-lg-id', uuid)
17992					.on("click.lgcustom-item-" + uuid, function (e) {
17993					e.preventDefault();
17994					var currentItemIndex = _this.settings.index || index;
17995					_this.openGallery(currentItemIndex, element);
17996				});
17997			};
17998			var this_1 = this;
17999			// Using for loop instead of using bubbling as the items can be any html element.
18000			for (var index = 0; index < this.items.length; index++) {
18001				_loop_1(index);
18002			}
18003		};
18004		/**
18005		 * Module constructor
18006		 * Modules are build incrementally.
18007		 * Gallery should be opened only once all the modules are initialized.
18008		 * use moduleBuildTimeout to make sure this
18009		 */
18010		LightGallery.prototype.buildModules = function () {
18011			var _this = this;
18012			this.settings.plugins.forEach(function (plugin) {
18013				_this.plugins.push(new plugin(_this, $LG));
18014			});
18015		};
18016		LightGallery.prototype.validateLicense = function () {
18017			if (!this.settings.licenseKey) {
18018				console.warn('Please provide a valid license key');
18019			}
18020			else if (this.settings.licenseKey === '0000-0000-000-0000') {
18021				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 18021-18435
18021id for production use");
18022			}
18023		};
18024		LightGallery.prototype.getSlideItem = function (index) {
18025			return $LG(this.getSlideItemId(index));
18026		};
18027		LightGallery.prototype.getSlideItemId = function (index) {
18028			return "#lg-item-" + this.lgId + "-" + index;
18029		};
18030		LightGallery.prototype.getIdName = function (id) {
18031			return id + "-" + this.lgId;
18032		};
18033		LightGallery.prototype.getElementById = function (id) {
18034			return $LG("#" + this.getIdName(id));
18035		};
18036		LightGallery.prototype.manageSingleSlideClassName = function () {
18037			if (this.galleryItems.length < 2) {
18038				this.outer.addClass('lg-single-item');
18039			}
18040			else {
18041				this.outer.removeClass('lg-single-item');
18042			}
18043		};
18044		LightGallery.prototype.buildStructure = function () {
18045			var _this = this;
18046			var container = this.$container && this.$container.get();
18047			if (container) {
18048				return;
18049			}
18050			var controls = '';
18051			var subHtmlCont = '';
18052			// Create controls
18053			if (this.settings.controls) {
18054				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>";
18055			}
18056			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18057				subHtmlCont =
18058					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
18059			}
18060			var addClasses = '';
18061			if (this.settings.allowMediaOverlap) {
18062				// Do not remove space before last single quote
18063				addClasses += 'lg-media-overlap ';
18064			}
18065			var ariaLabelledby = this.settings.ariaLabelledby
18066				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
18067				: '';
18068			var ariaDescribedby = this.settings.ariaDescribedby
18069				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
18070				: '';
18071			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
18072			var closeIcon = this.settings.closable && this.settings.showCloseIcon
18073				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
18074				: '';
18075			var maximizeIcon = this.settings.showMaximizeIcon
18076				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
18077				: '';
18078			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'
18079				? subHtmlCont
18080				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
18081				? subHtmlCont
18082				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
18083			$LG(this.settings.container).append(template);
18084			if (document.body !== this.settings.container) {
18085				$LG(this.settings.container).css('position', 'relative');
18086			}
18087			this.outer = this.getElementById('lg-outer');
18088			this.$lgComponents = this.getElementById('lg-components');
18089			this.$backdrop = this.getElementById('lg-backdrop');
18090			this.$container = this.getElementById('lg-container');
18091			this.$inner = this.getElementById('lg-inner');
18092			this.$content = this.getElementById('lg-content');
18093			this.$toolbar = this.getElementById('lg-toolbar');
18094			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
18095			var outerClassNames = this.settings.mode + " ";
18096			this.manageSingleSlideClassName();
18097			if (this.settings.enableDrag) {
18098				outerClassNames += 'lg-grab ';
18099			}
18100			this.outer.addClass(outerClassNames);
18101			this.$inner.css('transition-timing-function', this.settings.easing);
18102			this.$inner.css('transition-duration', this.settings.speed + 'ms');
18103			if (this.settings.download) {
18104				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>");
18105			}
18106			this.counter();
18107			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
18108				_this.refreshOnResize();
18109			});
18110			this.hideBars();
18111			this.manageCloseGallery();
18112			this.toggleMaximize();
18113			this.initModules();
18114		};
18115		LightGallery.prototype.refreshOnResize = function () {
18116			if (this.lgOpened) {
18117				var currentGalleryItem = this.galleryItems[this.index];
18118				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
18119				this.mediaContainerPosition = this.getMediaContainerPosition();
18120				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
18121				//Uncode edit ##START##
18122				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18123				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18124				//Uncode edit ##END##
18125				if (__slideVideoInfo) {
18126					this.resizeVideoSlide(this.index, this.currentImageSize);
18127				}
18128				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
18129					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18130					this.outer
18131						.find('.lg-current .lg-dummy-img')
18132						.first()
18133						.attr('style', imgStyle);
18134				}
18135				this.LGel.trigger(lGEvents.containerResize);
18136			}
18137		};
18138		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
18139			var lgVideoStyle = this.getVideoContStyle(imageSize);
18140			var currentSlide = this.getSlideItem(index);
18141			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
18142		};
18143		/**
18144		 * Update slides dynamically.
18145		 * Add, edit or delete slides dynamically when lightGallery is opened.
18146		 * Modify the current gallery items and pass it via updateSlides method
18147		 * @note
18148		 * - Do not mutate existing lightGallery items directly.
18149		 * - Always pass new list of gallery items
18150		 * - You need to take care of thumbnails outside the gallery if any
18151		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
18152		 * @param items Gallery items
18153		 * @param index After the update operation, which slide gallery should navigate to
18154		 * @category lGPublicMethods
18155		 * @example
18156		 * const plugin = lightGallery();
18157		 *
18158		 * // Adding slides dynamically
18159		 * let galleryItems = [
18160		 * // Access existing lightGallery items
18161		 * // galleryItems are automatically generated internally from the gallery HTML markup
18162		 * // or directly from galleryItems when dynamic gallery is used
18163		 *   ...plugin.galleryItems,
18164		 *     ...[
18165		 *       {
18166		 *         src: 'img/img-1.png',
18167		 *           thumb: 'img/thumb1.png',
18168		 *         },
18169		 *     ],
18170		 *   ];
18171		 *   plugin.updateSlides(
18172		 *     galleryItems,
18173		 *     plugin.index,
18174		 *   );
18175		 *
18176		 *
18177		 * // Remove slides dynamically
18178		 * galleryItems = JSON.parse(
18179		 *   JSON.stringify(updateSlideInstance.galleryItems),
18180		 * );
18181		 * galleryItems.shift();
18182		 * updateSlideInstance.updateSlides(galleryItems, 1);
18183		 * @see <a href="/demos/update-slides/">Demo</a>
18184		 */
18185		LightGallery.prototype.updateSlides = function (items, index) {
18186			if (this.index > items.length - 1) {
18187				this.index = items.length - 1;
18188			}
18189			if (items.length === 1) {
18190				this.index = 0;
18191			}
18192			if (!items.length) {
18193				this.closeGallery();
18194				return;
18195			}
18196			var currentSrc = this.galleryItems[index].src;
18197			this.galleryItems = items;
18198			this.updateControls();
18199			this.$inner.empty();
18200			this.currentItemsInDom = [];
18201			var _index = 0;
18202			// Find the current index based on source value of the slide
18203			this.galleryItems.some(function (galleryItem, itemIndex) {
18204				if (galleryItem.src === currentSrc) {
18205					_index = itemIndex;
18206					return true;
18207				}
18208				return false;
18209			});
18210			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
18211			this.loadContent(_index, true);
18212			this.getSlideItem(_index).addClass('lg-current');
18213			this.index = _index;
18214			this.updateCurrentCounter(_index);
18215			this.LGel.trigger(lGEvents.updateSlides);
18216		};
18217		// Get gallery items based on multiple conditions
18218		LightGallery.prototype.getItems = function () {
18219			// Gallery items
18220			this.items = [];
18221			if (!this.settings.dynamic) {
18222				if (this.settings.selector === 'this') {
18223					this.items.push(this.el);
18224				}
18225				else if (this.settings.selector) {
18226					if (typeof this.settings.selector === 'string') {
18227						if (this.settings.selectWithin) {
18228							var selectWithin = $LG(this.settings.selectWithin);
18229							this.items = selectWithin
18230								.find(this.settings.selector)
18231								.get();
18232						}
18233						else {
18234							this.items = this.el.querySelectorAll(this.settings.selector);
18235						}
18236					}
18237					else {
18238						this.items = this.settings.selector;
18239					}
18240				}
18241				else {
18242					this.items = this.el.children;
18243				}
18244				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
18245			}
18246			else {
18247				return this.settings.dynamicEl || [];
18248			}
18249		};
18250		LightGallery.prototype.shouldHideScrollbar = function () {
18251			return (this.settings.hideScrollbar &&
18252				document.body === this.settings.container);
18253		};
18254		LightGallery.prototype.hideScrollbar = function () {
18255			if (!this.shouldHideScrollbar()) {
18256				return;
18257			}
18258			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
18259			var bodyRect = document.documentElement.getBoundingClientRect();
18260			var scrollbarWidth = window.innerWidth - bodyRect.width;
18261			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
18262			$LG(document.body).addClass('lg-overlay-open');
18263		};
18264		LightGallery.prototype.resetScrollBar = function () {
18265			if (!this.shouldHideScrollbar()) {
18266				return;
18267			}
18268			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
18269			$LG(document.body).removeClass('lg-overlay-open');
18270		};
18271		/**
18272		 * Open lightGallery.
18273		 * Open gallery with specific slide by passing index of the slide as parameter.
18274		 * @category lGPublicMethods
18275		 * @param {Number} index  - index of the slide
18276		 * @param {HTMLElement} element - Which image lightGallery should zoom from
18277		 *
18278		 * @example
18279		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
18280		 * const dynamicGallery = lightGallery($dynamicGallery, {
18281		 *     dynamic: true,
18282		 *     dynamicEl: [
18283		 *         {
18284		 *              src: 'img/1.jpg',
18285		 *              thumb: 'img/thumb-1.jpg',
18286		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
18287		 *         },
18288		 *         ...
18289		 *     ],
18290		 * });
18291		 * $dynamicGallery.addEventListener('click', function () {
18292		 *     // Starts with third item.(Optional).
18293		 *     // This is useful if you want use dynamic mode with
18294		 *     // custom thumbnails (thumbnails outside gallery),
18295		 *     dynamicGallery.openGallery(2);
18296		 * });
18297		 *
18298		 */
18299		LightGallery.prototype.openGallery = function (index, element) {
18300			var _this = this;
18301			if (index === void 0) { index = this.settings.index; }
18302			// prevent accidental double execution
18303			if (this.lgOpened)
18304				return;
18305			this.lgOpened = true;
18306			this.outer.removeClass('lg-hide-items');
18307			this.hideScrollbar();
18308			// Add display block, but still has opacity 0
18309			this.$container.addClass('lg-show');
18310			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
18311			this.currentItemsInDom = itemsToBeInsertedToDom;
18312			var items = '';
18313			itemsToBeInsertedToDom.forEach(function (item) {
18314				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18315			});
18316			this.$inner.append(items);
18317			this.addHtml(index);
18318			var transform = '';
18319			this.mediaContainerPosition = this.getMediaContainerPosition();
18320			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
18321			if (!this.settings.allowMediaOverlap) {
18322				this.setMediaContainerPosition(top, bottom);
18323			}
18324			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
18325			if (this.zoomFromOrigin && element) {
18326				//Uncode edit ##START##
18327				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18328				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18329				//Uncode edit ##END##
18330				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
18331			}
18332			if (!this.zoomFromOrigin || !transform) {
18333				this.outer.addClass(this.settings.startClass);
18334				this.getSlideItem(index).removeClass('lg-complete');
18335			}
18336			var timeout = this.settings.zoomFromOrigin
18337				? 100
18338				: this.settings.backdropDuration;
18339			setTimeout(function () {
18340				_this.outer.addClass('lg-components-open');
18341			}, timeout);
18342			this.index = index;
18343			//Uncode edit ##START##
18344			// this.LGel.trigger(lGEvents.beforeOpen);
18345			this.LGel.trigger(lGEvents.beforeOpen, {
18346				galleryItems: this.galleryItems,
18347				items: this.items,
18348				outer: this.outer,
18349			});
18350			//Uncode edit ##END##
18351			// add class lg-current to remove initial transition
18352			this.getSlideItem(index).addClass('lg-current');
18353			this.lGalleryOn = false;
18354			// Store the current scroll top value to scroll back after closing the gallery..
18355			this.prevScrollTop = $LG(window).scrollTop();
18356			setTimeout(function () {
18357				// Need to check both zoomFromOrigin and transform values as we need to set set the
18358				// default opening animation if user missed to add the lg-size attribute
18359				if (_this.zoomFromOrigin && transform) {
18360					var currentSlide_1 = _this.getSlideItem(index);
18361					currentSlide_1.css('transform', transform);
18362					setTimeout(function () {
18363						currentSlide_1
18364							.addClass('lg-start-progress lg-start-end-progress')
18365							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
18366						_this.outer.addClass('lg-zoom-from-image');
18367					});
18368					setTimeout(function () {
18369						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
18370					}, 100);
18371				}
18372				setTimeout(function () {
18373					_this.$backdrop.addClass('in');
18374					_this.$container.addClass('lg-show-in');
18375				}, 10);
18376				setTimeout(function () {
18377					if (_this.settings.trapFocus &&
18378						document.body === _this.settings.container) {
18379						_this.trapFocus();
18380					}
18381				}, _this.settings.backdropDuration + 50);
18382				// lg-visible class resets gallery opacity to 1
18383				if (!_this.zoomFromOrigin || !transform) {
18384					setTimeout(function () {
18385						_this.outer.addClass('lg-visible');
18386					}, _this.settings.backdropDuration);
18387				}
18388				// initiate slide function
18389				_this.slide(index, false, false, false);
18390				_this.LGel.trigger(lGEvents.afterOpen);
18391			});
18392			if (document.body === this.settings.container) {
18393				$LG('html').addClass('lg-on');
18394			}
18395		};
18396		/**
18397		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
18398		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
18399		 * if you have dynamic captions for each media,
18400		 * you can provide an appropriate height for the captions via allowMediaOverlap option
18401		 */
18402		LightGallery.prototype.getMediaContainerPosition = function () {
18403			if (this.settings.allowMediaOverlap) {
18404				return {
18405					top: 0,
18406					bottom: 0,
18407				};
18408			}
18409			var top = this.$toolbar.get().clientHeight || 0;
18410			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
18411			var captionHeight = this.settings.defaultCaptionHeight ||
18412				(subHtml && subHtml.clientHeight) ||
18413				0;
18414			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
18415			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
18416			var bottom = thumbHeight + captionHeight;
18417			//Uncode edit ##START##
18418			bottom = bottom < 55 ? 55 : bottom;
18419			//Uncode edit ##END##
18420			return {
18421				top: top,
18422				bottom: bottom,
18423			};
18424		};
18425		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
18426			if (top === void 0) { top = 0; }
18427			if (bottom === void 0) { bottom = 0; }
18428			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
18429		};
18430		LightGallery.prototype.hideBars = function () {
18431			var _this = this;
18432			// Hide controllers if mouse doesn't move for some period
18433			setTimeout(function () {
18434				_this.outer.removeClass('lg-hide-items');
18435				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 18436-18566
18436					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
18437						_this.outer.removeClass('lg-hide-items');
18438						clearTimeout(_this.hideBarTimeout);
18439						// Timeout will be cleared on each slide movement also
18440						_this.hideBarTimeout = setTimeout(function () {
18441							_this.outer.addClass('lg-hide-items');
18442						}, _this.settings.hideBarsDelay);
18443					});
18444					_this.outer.trigger('mousemove.lg');
18445				}
18446			}, this.settings.showBarsAfter);
18447		};
18448		LightGallery.prototype.initPictureFill = function ($img) {
18449			if (this.settings.supportLegacyBrowser) {
18450				try {
18451					picturefill({
18452						elements: [$img.get()],
18453					});
18454				}
18455				catch (e) {
18456					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
18457				}
18458			}
18459		};
18460		/**
18461		 *  @desc Create image counter
18462		 *  Ex: 1/10
18463		 */
18464		LightGallery.prototype.counter = function () {
18465			if (this.settings.counter) {
18466				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>";
18467				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
18468			}
18469		};
18470		/**
18471		 *  @desc add sub-html into the slide
18472		 *  @param {Number} index - index of the slide
18473		 */
18474		LightGallery.prototype.addHtml = function (index) {
18475			var subHtml;
18476			var subHtmlUrl;
18477			if (this.galleryItems[index].subHtmlUrl) {
18478				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
18479			}
18480			else {
18481				subHtml = this.galleryItems[index].subHtml;
18482			}
18483			if (!subHtmlUrl) {
18484				if (subHtml) {
18485					// get first letter of sub-html
18486					// if first letter starts with . or # get the html form the jQuery object
18487					var fL = subHtml.substring(0, 1);
18488					if (fL === '.' || fL === '#') {
18489						if (this.settings.subHtmlSelectorRelative &&
18490							!this.settings.dynamic) {
18491							subHtml = $LG(this.items)
18492								.eq(index)
18493								.find(subHtml)
18494								.first()
18495								.html();
18496						}
18497						else {
18498							subHtml = $LG(subHtml).first().html();
18499						}
18500					}
18501				}
18502				else {
18503					subHtml = '';
18504				}
18505			}
18506			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18507				if (subHtmlUrl) {
18508					this.outer.find('.lg-sub-html').load(subHtmlUrl);
18509				}
18510				else {
18511					this.outer.find('.lg-sub-html').html(subHtml);
18512				}
18513			}
18514			else {
18515				var currentSlide = $LG(this.getSlideItemId(index));
18516				if (subHtmlUrl) {
18517					currentSlide.load(subHtmlUrl);
18518				}
18519				else {
18520					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
18521				}
18522			}
18523			// Add lg-empty-html class if title doesn't exist
18524			if (typeof subHtml !== 'undefined' && subHtml !== null) {
18525				if (subHtml === '') {
18526					this.outer
18527						.find(this.settings.appendSubHtmlTo)
18528						.addClass('lg-empty-html');
18529				}
18530				else {
18531					this.outer
18532						.find(this.settings.appendSubHtmlTo)
18533						.removeClass('lg-empty-html');
18534				}
18535			}
18536			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
18537				index: index,
18538			});
18539		};
18540		/**
18541		 *  @desc Preload slides
18542		 *  @param {Number} index - index of the slide
18543		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
18544		 */
18545		LightGallery.prototype.preload = function (index) {
18546			for (var i = 1; i <= this.settings.preload; i++) {
18547				if (i >= this.galleryItems.length - index) {
18548					break;
18549				}
18550				this.loadContent(index + i, false);
18551			}
18552			for (var j = 1; j <= this.settings.preload; j++) {
18553				if (index - j < 0) {
18554					break;
18555				}
18556				this.loadContent(index - j, false);
18557			}
18558		};
18559		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
18560			if (!imageSize)
18561				return '';
18562			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
18563		};
18564		LightGallery.prototype.getVideoContStyle = function (imageSize) {
18565			if (!imageSize)
18566				return '';
18567			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
18568		};
18569		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
18570			var $currentItem;
18571			if (!this.settings.dynamic) {
18572				$currentItem = $LG(this.items).eq(index);
18573			}
18574			if ($currentItem) {
18575				var _dummyImgSrc = void 0;
18576				if (!this.settings.exThumbImage) {
18577					_dummyImgSrc = $currentItem.find('img').first().attr('src');
18578				}
18579				else {
18580					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
18581				}
18582				if (!_dummyImgSrc)
18583					return '';
18584				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18585				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
18586				$currentSlide.addClass('lg-first-slide');
18587				this.outer.addClass('lg-first-slide-loading');
18588				return dummyImgContent;
18589			}
18590			return '';
18591		};
18592		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
18593			var currentGalleryItem = this.galleryItems[index];
18594			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18595			// Use the thumbnail as dummy image which will be resized to actual image size and
18596			// displayed on top of actual image
18597			var imgContent = '';
18598			var altAttr = alt ? 'alt="' + alt + '"' : '';
18599			if (this.isFirstSlideWithZoomAnimation()) {
18600				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
18601			}
18602			else {
18603				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
18604			}
18605			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
18606			$currentSlide.prepend(imgMarkup);
18607		};
18608		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
18609			var mediaObject = $slide.find('.lg-object').first();
18610			if (utils.isImageLoaded(mediaObject.get()) ||
18611				isHTML5VideoWithoutPoster) {
18612				onLoad();
18613			}
18614			else {
18615				mediaObject.on('load.lg error.lg', function () {
18616					onLoad && onLoad();
18617				});
18618				mediaObject.on('error.lg', function () {
18619					onError && onError();
18620				});
18621			}
18622		};
18623		/**
18624		 *
18625		 * @param $el Current slide item
18626		 * @param index
18627		 * @param delay Delay is 0 except first time
18628		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
18629		 * @param isFirstSlide
18630		 */
18631		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
18632			var _this = this;
18633			//Uncode edit ##START##
18634			var $item = _this.galleryItems[index],
18635				type = $item.type;
18636
18637			if ( typeof $item.src !== 'undefined' ) {
18638				var inline_id = $item.src.replace('#', ''),
18639					$inline = document.getElementById(inline_id),
18640					inline_html;
18641
18642				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18643					inline_html = $inline.innerHTML;
18644				} else {
18645					inline_html = '';
18646				}
18647			}
18648			//Uncode edit ##END##
18649			this.onSlideObjectLoad(currentSlide, true, function () {
18650				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
18651			}, function () {
18652				currentSlide.addClass('lg-complete lg-complete_');
18653				//Uncode edit ##START##
18654				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18655				if ( inline_html !== '' ) {
18656					currentSlide.html(inline_html);
18657				} else {
18658					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18659				}
18660				//Uncode edit ##END##
18661			});
18662		};
18663		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
18664			var _this = this;
18665			var currentGalleryItem = this.galleryItems[index];
18666			// Adding delay for video slides without poster for better performance and user experience
18667			// Videos should start playing once once the gallery is completely loaded
18668			var _speed = isFirstSlide &&
vendor: 3,676 bytes, lines 18669-18757
18669				this.getSlideType(currentGalleryItem) === 'video' &&
18670				!currentGalleryItem.poster
18671				? speed
18672				: 0;
18673			setTimeout(function () {
18674				$currentSlide.addClass('lg-complete lg-complete_');
18675				_this.LGel.trigger(lGEvents.slideItemLoad, {
18676					index: index,
18677					delay: delay || 0,
18678					isFirstSlide: isFirstSlide,
18679				});
18680			}, _speed);
18681		};
18682		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
18683			return !!(!this.lGalleryOn &&
18684				this.zoomFromOrigin &&
18685				this.currentImageSize);
18686		};
18687		// Add video slideInfo
18688		LightGallery.prototype.addSlideVideoInfo = function (items) {
18689			var _this = this;
18690			items.forEach(function (element, index) {
18691				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
18692				if (element.__slideVideoInfo &&
18693					_this.settings.loadYouTubePoster &&
18694					!element.poster &&
18695					element.__slideVideoInfo.youtube) {
18696					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
18697				}
18698			});
18699		};
18700		/**
18701		 *  Load slide content into slide.
18702		 *  This is used to load content into slides that is not visible too
18703		 *  @param {Number} index - index of the slide.
18704		 *  @param {Boolean} rec - if true call loadcontent() function again.
18705		 */
18706		LightGallery.prototype.loadContent = function (index, rec) {
18707			var _this = this;
18708			var currentGalleryItem = this.galleryItems[index];
18709			var $currentSlide = $LG(this.getSlideItemId(index));
18710			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18711			var src = currentGalleryItem.src;
18712			var video = currentGalleryItem.video;
18713			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
18714			if (currentGalleryItem.responsive) {
18715				var srcDyItms = currentGalleryItem.responsive.split(',');
18716				src = utils.getResponsiveSrc(srcDyItms) || src;
18717			}
18718			var videoInfo = currentGalleryItem.__slideVideoInfo;
18719			var lgVideoStyle = '';
18720			var iframe = !!currentGalleryItem.iframe;
18721			var isFirstSlide = !this.lGalleryOn;
18722			// delay for adding complete class. it is 0 except first time.
18723			var delay = 0;
18724			if (isFirstSlide) {
18725				if (this.zoomFromOrigin && this.currentImageSize) {
18726					delay = this.settings.startAnimationDuration + 10;
18727				}
18728				else {
18729					delay = this.settings.backdropDuration + 10;
18730				}
18731			}
18732			if (!$currentSlide.hasClass('lg-loaded')) {
18733				if (videoInfo) {
18734					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
18735					//Uncode edit ##START##
18736					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18737					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
18738					//Uncode edit ##END##
18739					lgVideoStyle = this.getVideoContStyle(videoSize);
18740				}
18741				if (iframe) {
18742					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18743					$currentSlide.prepend(markup);
18744				}
18745				else if (poster) {
18746					var dummyImg = '';
18747					var hasStartAnimation = isFirstSlide &&
18748						this.zoomFromOrigin &&
18749						this.currentImageSize;
18750					if (hasStartAnimation) {
18751						dummyImg = this.getDummyImageContent($currentSlide, index, '');
18752					}
18753					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18754					$currentSlide.prepend(markup);
18755				}
18756				//Uncode edit ##START##
18757				// else if (videoInfo) {
18758				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18759					if (! _html5Video) {
18760						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18761					}
18762					//Uncode edit ##END##
18763					$currentSlide.prepend(markup);
18764				}
18765				else {
18766					//Uncode edit ##START##
18767					var $item = _this.galleryItems[index],
18768						type = $item.type;
18769
18770					if ( typeof $item.src !== 'undefined' ) {
18771						var inline_id = $item.src.replace('#', ''),
18772							$inline = document.getElementById(inline_id),
18773							inline_html;
18774
18775						if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18776							inline_html = $inline.innerHTML;
18777						} else {
18778							inline_html = '';
18779						}
18780					}
18781					if ( inline_html !== '' ) {
18782						$currentSlide.html(inline_html);
18783					} else {
18784						this.setImgMarkup(src, $currentSlide, index);
18785						if (srcset || sources) {
18786							var $img = $currentSlide.find('.lg-object');
18787							this.initPictureFill($img);
18788						}
18789					}
18790					/*this.setImgMarkup(src, $currentSlide, index);
18791					if (srcset || sources) {
18792						var $img = $currentSlide.find('.lg-object');
18793						this.initPictureFill($img);
18794					}*/
18795					//Uncode edit ##END##
18796				}
18797				if (poster || videoInfo) {
18798					this.LGel.trigger(lGEvents.hasVideo, {
18799						index: index,
18800						src: src,
18801						html5Video: _html5Video,
18802						hasPoster: !!poster,
18803					});
18804				}
18805				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18806				if (this.lGalleryOn &&
18807					this.settings.appendSubHtmlTo === '.lg-item') {
18808					this.addHtml(index);
18809				}
18810			}
18811			// For first time add some delay for displaying the start animation.
18812			var _speed = 0;
18813			// Do not change the delay value because it is required for zoom plugin.
18814			// If gallery opened from direct url (hash) speed value should be 0
18815			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18816				_speed = delay;
18817			}
18818			// Only for first slide and zoomFromOrigin is enabled
18819			if (this.isFirstSlideWithZoomAnimation()) {
18820				setTimeout(function () {
18821					$currentSlide
18822						.removeClass('lg-start-end-progress lg-start-progress')
18823						.removeAttr('style');
18824				}, this.settings.startAnimationDuration + 100);
18825				if (!$currentSlide.hasClass('lg-loaded')) {
18826					setTimeout(function () {
18827						if (_this.getSlideType(currentGalleryItem) === 'image') {
18828							var alt = currentGalleryItem.alt;
18829							var altAttr = alt ? 'alt="' + alt + '"' : '';
18830							$currentSlide
18831								.find('.lg-img-wrap')
18832								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
18833							if (srcset || sources) {
18834								var $img = $currentSlide.find('.lg-object');
18835								_this.initPictureFill($img);
18836							}
18837						}
18838						if (_this.getSlideType(currentGalleryItem) === 'image' ||
18839							(_this.getSlideType(currentGalleryItem) === 'video' &&
18840								poster)) {
18841							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18842							// load remaining slides once the slide is completely loaded
18843							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18844								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18845							}, function () {
18846								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18847							});
18848						}
18849					}, this.settings.startAnimationDuration + 100);
18850				}
18851			}
18852			// SLide content has been added to dom
18853			$currentSlide.addClass('lg-loaded');
18854			if (!this.isFirstSlideWithZoomAnimation() ||
18855				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18856				//Uncode edit ##START##
18857				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18858				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.get
vendor: 31,133 bytes, lines 18858-19782
18858SlideType(currentGalleryItem) === 'audio'));
18859				//Uncode edit ##END##
18860			}
18861			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18862			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18863				$currentSlide.hasClass('lg-complete_') &&
18864				!this.lGalleryOn) {
18865				setTimeout(function () {
18866					$currentSlide.addClass('lg-complete');
18867				}, this.settings.backdropDuration);
18868			}
18869			// Content loaded
18870			// Need to set lGalleryOn before calling preload function
18871			this.lGalleryOn = true;
18872			if (rec === true) {
18873				if (!$currentSlide.hasClass('lg-complete_')) {
18874					$currentSlide
18875						.find('.lg-object')
18876						.first()
18877						.on('load.lg error.lg', function () {
18878						_this.preload(index);
18879					});
18880				}
18881				else {
18882					this.preload(index);
18883				}
18884			}
18885		};
18886		/**
18887		 * @desc Remove dummy image content and load next slides
18888		 * Called only for the first time if zoomFromOrigin animation is enabled
18889		 * @param index
18890		 * @param $currentSlide
18891		 * @param speed
18892		 */
18893		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18894			var _this = this;
18895			setTimeout(function () {
18896				$currentSlide.find('.lg-dummy-img').remove();
18897				$currentSlide.removeClass('lg-first-slide');
18898				_this.outer.removeClass('lg-first-slide-loading');
18899				_this.isDummyImageRemoved = true;
18900				_this.preload(index);
18901			}, speed + 300);
18902		};
18903		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18904			var _this = this;
18905			if (numberOfItems === void 0) { numberOfItems = 0; }
18906			var itemsToBeInsertedToDom = [];
18907			// Minimum 2 items should be there
18908			var possibleNumberOfItems = Math.max(numberOfItems, 3);
18909			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18910			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18911			if (this.galleryItems.length <= 3) {
18912				this.galleryItems.forEach(function (_element, index) {
18913					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18914				});
18915				return itemsToBeInsertedToDom;
18916			}
18917			if (index < (this.galleryItems.length - 1) / 2) {
18918				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18919					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18920				}
18921				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18922				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18923					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18924				}
18925			}
18926			else {
18927				for (var idx = index; idx <= this.galleryItems.length - 1 &&
18928					idx < index + possibleNumberOfItems / 2; idx++) {
18929					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18930				}
18931				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18932				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18933					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18934				}
18935			}
18936			if (this.settings.loop) {
18937				if (index === this.galleryItems.length - 1) {
18938					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18939				}
18940				else if (index === 0) {
18941					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18942				}
18943			}
18944			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18945				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18946			}
18947			return itemsToBeInsertedToDom;
18948		};
18949		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18950			var _this = this;
18951			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18952			itemsToBeInsertedToDom.forEach(function (item) {
18953				if (_this.currentItemsInDom.indexOf(item) === -1) {
18954					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18955				}
18956			});
18957			this.currentItemsInDom.forEach(function (item) {
18958				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18959					$LG("#" + item).remove();
18960				}
18961			});
18962			return itemsToBeInsertedToDom;
18963		};
18964		/**
18965		 * Get previous index of the slide
18966		 */
18967		LightGallery.prototype.getPreviousSlideIndex = function () {
18968			var prevIndex = 0;
18969			try {
18970				var currentItemId = this.outer
18971					.find('.lg-current')
18972					.first()
18973					.attr('id');
18974				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18975			}
18976			catch (error) {
18977				prevIndex = 0;
18978			}
18979			return prevIndex;
18980		};
18981		LightGallery.prototype.setDownloadValue = function (index) {
18982			if (this.settings.download) {
18983				var currentGalleryItem = this.galleryItems[index];
18984				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18985					currentGalleryItem.downloadUrl === 'false';
18986				if (hideDownloadBtn) {
18987					this.outer.addClass('lg-hide-download');
18988				}
18989				else {
18990					var $download = this.getElementById('lg-download');
18991					this.outer.removeClass('lg-hide-download');
18992					$download.attr('href', currentGalleryItem.downloadUrl ||
18993						currentGalleryItem.src);
18994					if (currentGalleryItem.download) {
18995						//Uncode edit ##START##
18996						if ( typeof currentGalleryItem.video !== 'undefined' && currentGalleryItem.video ) {
18997							var currentVideo = JSON.parse( currentGalleryItem.video ),
18998								download_name = currentVideo.source[0].src;
18999							$download.attr('href', download_name).removeAttr('download');
19000						} else {
19001							var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
19002								download_name = download_url.substring(download_url.lastIndexOf('/')+1);
19003							$download.attr('download', download_name);
19004						}
19005						// $download.attr('download', currentGalleryItem.download);
19006						//Uncode edit ##END##
19007					}
19008				}
19009			}
19010		};
19011		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
19012			var _this = this;
19013			if (this.lGalleryOn) {
19014				previousSlideItem.addClass('lg-slide-progress');
19015			}
19016			setTimeout(function () {
19017				// remove all transitions
19018				_this.outer.addClass('lg-no-trans');
19019				_this.outer
19020					.find('.lg-item')
19021					.removeClass('lg-prev-slide lg-next-slide');
19022				if (direction === 'prev') {
19023					//prevslide
19024					currentSlideItem.addClass('lg-prev-slide');
19025					previousSlideItem.addClass('lg-next-slide');
19026				}
19027				else {
19028					// next slide
19029					currentSlideItem.addClass('lg-next-slide');
19030					previousSlideItem.addClass('lg-prev-slide');
19031				}
19032				// give 50 ms for browser to add/remove class
19033				setTimeout(function () {
19034					_this.outer.find('.lg-item').removeClass('lg-current');
19035					currentSlideItem.addClass('lg-current');
19036					// reset all transitions
19037					_this.outer.removeClass('lg-no-trans');
19038				}, 50);
19039			}, this.lGalleryOn ? this.settings.slideDelay : 0);
19040		};
19041		/**
19042		 * Goto a specific slide.
19043		 * @param {Number} index - index of the slide
19044		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
19045		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
19046		 * @param {String} direction - Direction of the slide(next/prev)
19047		 * @category lGPublicMethods
19048		 * @example
19049		 *  const plugin = lightGallery();
19050		 *  // to go to 3rd slide
19051		 *  plugin.slide(2);
19052		 *
19053		 */
19054		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
19055			var _this = this;
19056			var prevIndex = this.getPreviousSlideIndex();
19057			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
19058			// Prevent multiple call, Required for hsh plugin
19059			if (this.lGalleryOn && prevIndex === index) {
19060				return;
19061			}
19062			var numberOfGalleryItems = this.galleryItems.length;
19063			if (!this.lgBusy) {
19064				if (this.settings.counter) {
19065					this.updateCurrentCounter(index);
19066				}
19067				var currentSlideItem = this.getSlideItem(index);
19068				var previousSlideItem_1 = this.getSlideItem(prevIndex);
19069				var currentGalleryItem = this.galleryItems[index];
19070				var videoInfo = currentGalleryItem.__slideVideoInfo;
19071				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
19072				this.setDownloadValue(index);
19073				if (videoInfo) {
19074					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
19075					//Uncode edit ##START##
19076					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19077					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
19078					//Uncode edit ##END##
19079					this.resizeVideoSlide(index, videoSize);
19080				}
19081				this.LGel.trigger(lGEvents.beforeSlide, {
19082					prevIndex: prevIndex,
19083					index: index,
19084					fromTouch: !!fromTouch,
19085					fromThumb: !!fromThumb,
19086					//Uncode edit ##START##
19087					currentSlide: currentSlideItem,
19088					previousSlide: previousSlideItem_1,
19089					info: currentGalleryItem,
19090					item: this.items[index]
19091					//Uncode edit ##END##
19092				});
19093				this.lgBusy = true;
19094				clearTimeout(this.hideBarTimeout);
19095				this.arrowDisable(index);
19096				if (!direction) {
19097					if (index < prevIndex) {
19098						direction = 'prev';
19099					}
19100					else if (index > prevIndex) {
19101						direction = 'next';
19102					}
19103				}
19104				if (!fromTouch) {
19105					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
19106				}
19107				else {
19108					this.outer
19109						.find('.lg-item')
19110						.removeClass('lg-prev-slide lg-current lg-next-slide');
19111					var touchPrev = void 0;
19112					var touchNext = void 0;
19113					if (numberOfGalleryItems > 2) {
19114						touchPrev = index - 1;
19115						touchNext = index + 1;
19116						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
19117							// next slide
19118							touchNext = 0;
19119							touchPrev = numberOfGalleryItems - 1;
19120						}
19121						else if (index === numberOfGalleryItems - 1 &&
19122							prevIndex === 0) {
19123							// prev slide
19124							touchNext = 0;
19125							touchPrev = numberOfGalleryItems - 1;
19126						}
19127					}
19128					else {
19129						touchPrev = 0;
19130						touchNext = 1;
19131					}
19132					if (direction === 'prev') {
19133						this.getSlideItem(touchNext).addClass('lg-next-slide');
19134					}
19135					else {
19136						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
19137					}
19138					currentSlideItem.addClass('lg-current');
19139				}
19140				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
19141				if (!this.lGalleryOn) {
19142					this.loadContent(index, true);
19143				}
19144				else {
19145					setTimeout(function () {
19146						_this.loadContent(index, true);
19147						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
19148						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
19149							_this.addHtml(index);
19150						}
19151					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
19152				}
19153				setTimeout(function () {
19154					_this.lgBusy = false;
19155					previousSlideItem_1.removeClass('lg-slide-progress');
19156					_this.LGel.trigger(lGEvents.afterSlide, {
19157						prevIndex: prevIndex,
19158						index: index,
19159						fromTouch: fromTouch,
19160						fromThumb: fromThumb,
19161					});
19162				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
19163			}
19164			this.index = index;
19165		};
19166		LightGallery.prototype.updateCurrentCounter = function (index) {
19167			this.getElementById('lg-counter-current').html(index + 1 + '');
19168		};
19169		LightGallery.prototype.updateCounterTotal = function () {
19170			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
19171		};
19172		LightGallery.prototype.getSlideType = function (item) {
19173			if (item.__slideVideoInfo) {
19174				return 'video';
19175			}
19176			else if (item.iframe) {
19177				return 'iframe';
19178			}
19179			//Uncode edit ##START##
19180			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
19181				return 'audio';
19182			}
19183			//Uncode edit ##END##
19184			else {
19185				return 'image';
19186			}
19187		};
19188		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
19189			var distanceX = endCoords.pageX - startCoords.pageX;
19190			var distanceY = endCoords.pageY - startCoords.pageY;
19191			var allowSwipe = false;
19192			if (this.swipeDirection) {
19193				allowSwipe = true;
19194			}
19195			else {
19196				if (Math.abs(distanceX) > 15) {
19197					this.swipeDirection = 'horizontal';
19198					allowSwipe = true;
19199				}
19200				else if (Math.abs(distanceY) > 15) {
19201					this.swipeDirection = 'vertical';
19202					allowSwipe = true;
19203				}
19204			}
19205			if (!allowSwipe) {
19206				return;
19207			}
19208			var $currentSlide = this.getSlideItem(this.index);
19209			if (this.swipeDirection === 'horizontal') {
19210				e === null || e === void 0 ? void 0 : e.preventDefault();
19211				// reset opacity and transition duration
19212				this.outer.addClass('lg-dragging');
19213				// move current slide
19214				this.setTranslate($currentSlide, distanceX, 0);
19215				// move next and prev slide with current slide
19216				var width = $currentSlide.get().offsetWidth;
19217				var slideWidthAmount = (width * 15) / 100;
19218				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
19219				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
19220				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
19221			}
19222			else if (this.swipeDirection === 'vertical') {
19223				if (this.settings.swipeToClose) {
19224					e === null || e === void 0 ? void 0 : e.preventDefault();
19225					this.$container.addClass('lg-dragging-vertical');
19226					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
19227					this.$backdrop.css('opacity', opacity);
19228					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
19229					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
19230					if (Math.abs(distanceY) > 100) {
19231						this.outer
19232							.addClass('lg-hide-items')
19233							.removeClass('lg-components-open');
19234					}
19235				}
19236			}
19237		};
19238		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
19239			var _this = this;
19240			var distance;
19241			// keep slide animation for any mode while dragg/swipe
19242			if (this.settings.mode !== 'lg-slide') {
19243				this.outer.addClass('lg-slide');
19244			}
19245			// set transition duration
19246			setTimeout(function () {
19247				_this.$container.removeClass('lg-dragging-vertical');
19248				_this.outer
19249					.removeClass('lg-dragging lg-hide-items')
19250					.addClass('lg-components-open');
19251				var triggerClick = true;
19252				if (_this.swipeDirection === 'horizontal') {
19253					distance = endCoords.pageX - startCoords.pageX;
19254					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
19255					if (distance < 0 &&
19256						distanceAbs > _this.settings.swipeThreshold) {
19257						_this.goToNextSlide(true);
19258						triggerClick = false;
19259					}
19260					else if (distance > 0 &&
19261						distanceAbs > _this.settings.swipeThreshold) {
19262						_this.goToPrevSlide(true);
19263						triggerClick = false;
19264					}
19265				}
19266				else if (_this.swipeDirection === 'vertical') {
19267					distance = Math.abs(endCoords.pageY - startCoords.pageY);
19268					if (_this.settings.closable &&
19269						_this.settings.swipeToClose &&
19270						distance > 100) {
19271						_this.closeGallery();
19272						return;
19273					}
19274					else {
19275						_this.$backdrop.css('opacity', 1);
19276					}
19277				}
19278				_this.outer.find('.lg-item').removeAttr('style');
19279				if (triggerClick &&
19280					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
19281					// Trigger click if distance is less than 5 pix
19282					var target = $LG(event.target);
19283					if (_this.isPosterElement(target)) {
19284						_this.LGel.trigger(lGEvents.posterClick);
19285					}
19286				}
19287				_this.swipeDirection = undefined;
19288			});
19289			// remove slide class once drag/swipe is completed if mode is not slide
19290			setTimeout(function () {
19291				if (!_this.outer.hasClass('lg-dragging') &&
19292					_this.settings.mode !== 'lg-slide') {
19293					_this.outer.removeClass('lg-slide');
19294				}
19295			}, this.settings.speed + 100);
19296		};
19297		LightGallery.prototype.enableSwipe = function () {
19298			var _this = this;
19299			var startCoords = {};
19300			var endCoords = {};
19301			var isMoved = false;
19302			var isSwiping = false;
19303			if (this.settings.enableSwipe) {
19304				this.$inner.on('touchstart.lg', function (e) {
19305					_this.dragOrSwipeEnabled = true;
19306					var $item = _this.getSlideItem(_this.index);
19307					if (($LG(e.target).hasClass('lg-item') ||
19308						$item.get().contains(e.target)) &&
19309						!_this.outer.hasClass('lg-zoomed') &&
19310						!_this.lgBusy &&
19311						e.targetTouches.length === 1) {
19312						isSwiping = true;
19313						_this.touchAction = 'swipe';
19314						_this.manageSwipeClass();
19315						startCoords = {
19316							pageX: e.targetTouches[0].pageX,
19317							pageY: e.targetTouches[0].pageY,
19318						};
19319					}
19320				});
19321				this.$inner.on('touchmove.lg', function (e) {
19322					if (isSwiping &&
19323						_this.touchAction === 'swipe' &&
19324						e.targetTouches.length === 1) {
19325						endCoords = {
19326							pageX: e.targetTouches[0].pageX,
19327							pageY: e.targetTouches[0].pageY,
19328						};
19329						_this.touchMove(startCoords, endCoords, e);
19330						isMoved = true;
19331					}
19332				});
19333				this.$inner.on('touchend.lg', function (event) {
19334					if (_this.touchAction === 'swipe') {
19335						if (isMoved) {
19336							isMoved = false;
19337							_this.touchEnd(endCoords, startCoords, event);
19338						}
19339						else if (isSwiping) {
19340							var target = $LG(event.target);
19341							if (_this.isPosterElement(target)) {
19342								_this.LGel.trigger(lGEvents.posterClick);
19343							}
19344						}
19345						_this.touchAction = undefined;
19346						isSwiping = false;
19347					}
19348				});
19349			}
19350		};
19351		LightGallery.prototype.enableDrag = function () {
19352			var _this = this;
19353			var startCoords = {};
19354			var endCoords = {};
19355			var isDraging = false;
19356			var isMoved = false;
19357			if (this.settings.enableDrag) {
19358				this.outer.on('mousedown.lg', function (e) {
19359					_this.dragOrSwipeEnabled = true;
19360					var $item = _this.getSlideItem(_this.index);
19361					if ($LG(e.target).hasClass('lg-item') ||
19362						$item.get().contains(e.target)) {
19363						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
19364							e.preventDefault();
19365							if (!_this.lgBusy) {
19366								_this.manageSwipeClass();
19367								startCoords = {
19368									pageX: e.pageX,
19369									pageY: e.pageY,
19370								};
19371								isDraging = true;
19372								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
19373								_this.outer.get().scrollLeft += 1;
19374								_this.outer.get().scrollLeft -= 1;
19375								// *
19376								_this.outer
19377									.removeClass('lg-grab')
19378									.addClass('lg-grabbing');
19379								_this.LGel.trigger(lGEvents.dragStart);
19380							}
19381						}
19382					}
19383				});
19384				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
19385					if (isDraging && _this.lgOpened) {
19386						isMoved = true;
19387						endCoords = {
19388							pageX: e.pageX,
19389							pageY: e.pageY,
19390						};
19391						_this.touchMove(startCoords, endCoords);
19392						_this.LGel.trigger(lGEvents.dragMove);
19393					}
19394				});
19395				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
19396					if (!_this.lgOpened) {
19397						return;
19398					}
19399					var target = $LG(event.target);
19400					if (isMoved) {
19401						isMoved = false;
19402						_this.touchEnd(endCoords, startCoords, event);
19403						_this.LGel.trigger(lGEvents.dragEnd);
19404					}
19405					else if (_this.isPosterElement(target)) {
19406						_this.LGel.trigger(lGEvents.posterClick);
19407					}
19408					// Prevent execution on click
19409					if (isDraging) {
19410						isDraging = false;
19411						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
19412					}
19413				});
19414			}
19415		};
19416		LightGallery.prototype.triggerPosterClick = function () {
19417			var _this = this;
19418			this.$inner.on('click.lg', function (event) {
19419				if (!_this.dragOrSwipeEnabled &&
19420					_this.isPosterElement($LG(event.target))) {
19421					_this.LGel.trigger(lGEvents.posterClick);
19422				}
19423			});
19424		};
19425		LightGallery.prototype.manageSwipeClass = function () {
19426			var _touchNext = this.index + 1;
19427			var _touchPrev = this.index - 1;
19428			if (this.settings.loop && this.galleryItems.length > 2) {
19429				if (this.index === 0) {
19430					_touchPrev = this.galleryItems.length - 1;
19431				}
19432				else if (this.index === this.galleryItems.length - 1) {
19433					_touchNext = 0;
19434				}
19435			}
19436			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
19437			if (_touchPrev > -1) {
19438				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
19439			}
19440			this.getSlideItem(_touchNext).addClass('lg-next-slide');
19441		};
19442		/**
19443		 * Go to next slide
19444		 * @param {Boolean} fromTouch - true if slide function called via touch event
19445		 * @category lGPublicMethods
19446		 * @example
19447		 *  const plugin = lightGallery();
19448		 *  plugin.goToNextSlide();
19449		 * @see <a href="/demos/methods/">Demo</a>
19450		 */
19451		LightGallery.prototype.goToNextSlide = function (fromTouch) {
19452			var _this = this;
19453			var _loop = this.settings.loop;
19454			if (fromTouch && this.galleryItems.length < 3) {
19455				_loop = false;
19456			}
19457			if (!this.lgBusy) {
19458				if (this.index + 1 < this.galleryItems.length) {
19459					this.index++;
19460					this.LGel.trigger(lGEvents.beforeNextSlide, {
19461						index: this.index,
19462					});
19463					this.slide(this.index, !!fromTouch, false, 'next');
19464				}
19465				else {
19466					if (_loop) {
19467						this.index = 0;
19468						this.LGel.trigger(lGEvents.beforeNextSlide, {
19469							index: this.index,
19470						});
19471						this.slide(this.index, !!fromTouch, false, 'next');
19472					}
19473					else if (this.settings.slideEndAnimation && !fromTouch) {
19474						this.outer.addClass('lg-right-end');
19475						setTimeout(function () {
19476							_this.outer.removeClass('lg-right-end');
19477						}, 400);
19478					}
19479				}
19480			}
19481		};
19482		/**
19483		 * Go to previous slides
19484		 * @param {Boolean} fromTouch - true if slide function called via touch event
19485		 * @category lGPublicMethods
19486		 * @example
19487		 *  const plugin = lightGallery({});
19488		 *  plugin.goToPrevSlide();
19489		 * @see <a href="/demos/methods/">Demo</a>
19490		 *
19491		 */
19492		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
19493			var _this = this;
19494			var _loop = this.settings.loop;
19495			if (fromTouch && this.galleryItems.length < 3) {
19496				_loop = false;
19497			}
19498			if (!this.lgBusy) {
19499				if (this.index > 0) {
19500					this.index--;
19501					this.LGel.trigger(lGEvents.beforePrevSlide, {
19502						index: this.index,
19503						fromTouch: fromTouch,
19504					});
19505					this.slide(this.index, !!fromTouch, false, 'prev');
19506				}
19507				else {
19508					if (_loop) {
19509						this.index = this.galleryItems.length - 1;
19510						this.LGel.trigger(lGEvents.beforePrevSlide, {
19511							index: this.index,
19512							fromTouch: fromTouch,
19513						});
19514						this.slide(this.index, !!fromTouch, false, 'prev');
19515					}
19516					else if (this.settings.slideEndAnimation && !fromTouch) {
19517						this.outer.addClass('lg-left-end');
19518						setTimeout(function () {
19519							_this.outer.removeClass('lg-left-end');
19520						}, 400);
19521					}
19522				}
19523			}
19524		};
19525		LightGallery.prototype.keyPress = function () {
19526			var _this = this;
19527			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19528				if (_this.lgOpened &&
19529					_this.settings.escKey === true &&
19530					e.keyCode === 27) {
19531					e.preventDefault();
19532					if (_this.settings.allowMediaOverlap &&
19533						_this.outer.hasClass('lg-can-toggle') &&
19534						_this.outer.hasClass('lg-components-open')) {
19535						_this.outer.removeClass('lg-components-open');
19536					}
19537					else {
19538						_this.closeGallery();
19539					}
19540				}
19541				if (_this.lgOpened && _this.galleryItems.length > 1) {
19542					if (e.keyCode === 37) {
19543						e.preventDefault();
19544						_this.goToPrevSlide();
19545					}
19546					if (e.keyCode === 39) {
19547						e.preventDefault();
19548						_this.goToNextSlide();
19549					}
19550				}
19551			});
19552		};
19553		LightGallery.prototype.arrow = function () {
19554			var _this = this;
19555			this.getElementById('lg-prev').on('click.lg', function () {
19556				_this.goToPrevSlide();
19557			});
19558			this.getElementById('lg-next').on('click.lg', function () {
19559				_this.goToNextSlide();
19560			});
19561		};
19562		LightGallery.prototype.arrowDisable = function (index) {
19563			// Disable arrows if settings.hideControlOnEnd is true
19564			if (!this.settings.loop && this.settings.hideControlOnEnd) {
19565				var $prev = this.getElementById('lg-prev');
19566				var $next = this.getElementById('lg-next');
19567				if (index + 1 === this.galleryItems.length) {
19568					$next.attr('disabled', 'disabled').addClass('disabled');
19569				}
19570				else {
19571					$next.removeAttr('disabled').removeClass('disabled');
19572				}
19573				if (index === 0) {
19574					$prev.attr('disabled', 'disabled').addClass('disabled');
19575				}
19576				else {
19577					$prev.removeAttr('disabled').removeClass('disabled');
19578				}
19579			}
19580		};
19581		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
19582			if (scaleX === void 0) { scaleX = 1; }
19583			if (scaleY === void 0) { scaleY = 1; }
19584			$el.css('transform', 'translate3d(' +
19585				xValue +
19586				'px, ' +
19587				yValue +
19588				'px, 0px) scale3d(' +
19589				scaleX +
19590				', ' +
19591				scaleY +
19592				', 1)');
19593		};
19594		LightGallery.prototype.mousewheel = function () {
19595			var _this = this;
19596			var lastCall = 0;
19597			this.outer.on('wheel.lg', function (e) {
19598				if (!e.deltaY || _this.galleryItems.length < 2) {
19599					return;
19600				}
19601				e.preventDefault();
19602				var now = new Date().getTime();
19603				if (now - lastCall < 1000) {
19604					return;
19605				}
19606				lastCall = now;
19607				if (e.deltaY > 0) {
19608					_this.goToNextSlide();
19609				}
19610				else if (e.deltaY < 0) {
19611					_this.goToPrevSlide();
19612				}
19613			});
19614		};
19615		LightGallery.prototype.isSlideElement = function (target) {
19616			return (target.hasClass('lg-outer') ||
19617				target.hasClass('lg-item') ||
19618				target.hasClass('lg-img-wrap'));
19619		};
19620		LightGallery.prototype.isPosterElement = function (target) {
19621			var playButton = this.getSlideItem(this.index)
19622				.find('.lg-video-play-button')
19623				.get();
19624			return (target.hasClass('lg-video-poster') ||
19625				target.hasClass('lg-video-play-button') ||
19626				(playButton && playButton.contains(target.get())));
19627		};
19628		/**
19629		 * Maximize minimize inline gallery.
19630		 * @category lGPublicMethods
19631		 */
19632		LightGallery.prototype.toggleMaximize = function () {
19633			var _this = this;
19634			this.getElementById('lg-maximize').on('click.lg', function () {
19635				_this.$container.toggleClass('lg-inline');
19636				_this.refreshOnResize();
19637			});
19638		};
19639		LightGallery.prototype.invalidateItems = function () {
19640			for (var index = 0; index < this.items.length; index++) {
19641				var element = this.items[index];
19642				var $element = $LG(element);
19643				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
19644			}
19645		};
19646		LightGallery.prototype.trapFocus = function () {
19647			var _this = this;
19648			this.$container.get().focus({
19649				preventScroll: true,
19650			});
19651			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19652				if (!_this.lgOpened) {
19653					return;
19654				}
19655				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
19656				if (!isTabPressed) {
19657					return;
19658				}
19659				var focusableEls = utils.getFocusableElements(_this.$container.get());
19660				var firstFocusableEl = focusableEls[0];
19661				var lastFocusableEl = focusableEls[focusableEls.length - 1];
19662				if (e.shiftKey) {
19663					if (document.activeElement === firstFocusableEl) {
19664						lastFocusableEl.focus();
19665						e.preventDefault();
19666					}
19667				}
19668				else {
19669					if (document.activeElement === lastFocusableEl) {
19670						firstFocusableEl.focus();
19671						e.preventDefault();
19672					}
19673				}
19674			});
19675		};
19676		LightGallery.prototype.manageCloseGallery = function () {
19677			var _this = this;
19678			if (!this.settings.closable)
19679				return;
19680			var mousedown = false;
19681			this.getElementById('lg-close').on('click.lg', function () {
19682				_this.closeGallery();
19683			});
19684			if (this.settings.closeOnTap) {
19685				// If you drag the slide and release outside gallery gets close on chrome
19686				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
19687				this.outer.on('mousedown.lg', function (e) {
19688					var target = $LG(e.target);
19689					if (_this.isSlideElement(target)) {
19690						mousedown = true;
19691					}
19692					else {
19693						mousedown = false;
19694					}
19695				});
19696				this.outer.on('mousemove.lg', function () {
19697					mousedown = false;
19698				});
19699				this.outer.on('mouseup.lg', function (e) {
19700					var target = $LG(e.target);
19701					if (_this.isSlideElement(target) && mousedown) {
19702						if (!_this.outer.hasClass('lg-dragging')) {
19703							_this.closeGallery();
19704						}
19705					}
19706				});
19707			}
19708		};
19709		/**
19710		 * Close lightGallery if it is opened.
19711		 *
19712		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
19713		 * @return returns the estimated time to close gallery completely including the close animation duration
19714		 * @category lGPublicMethods
19715		 * @example
19716		 *  const plugin = lightGallery();
19717		 *  plugin.closeGallery();
19718		 *
19719		 */
19720		LightGallery.prototype.closeGallery = function (force) {
19721			var _this = this;
19722			if (!this.lgOpened || (!this.settings.closable && !force)) {
19723				return 0;
19724			}
19725			this.LGel.trigger(lGEvents.beforeClose);
19726			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
19727				$LG(window).scrollTop(this.prevScrollTop);
19728			}
19729			var currentItem = this.items[this.index];
19730			var transform;
19731			if (this.zoomFromOrigin && currentItem) {
19732				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
19733				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
19734				//Uncode edit ##START##
19735				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
19736				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
19737				//Uncode edit ##END##
19738				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
19739			}
19740			if (this.zoomFromOrigin && transform) {
19741				this.outer.addClass('lg-closing lg-zoom-from-image');
19742				this.getSlideItem(this.index)
19743					.addClass('lg-start-end-progress')
19744					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
19745					.css('transform', transform);
19746			}
19747			else {
19748				this.outer.addClass('lg-hide-items');
19749				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
19750				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
19751				this.outer.removeClass('lg-zoom-from-image');
19752			}
19753			// Unbind all events added by lightGallery
19754			// @todo
19755			//this.$el.off('.lg.tm');
19756			this.destroyModules();
19757			this.lGalleryOn = false;
19758			this.isDummyImageRemoved = false;
19759			this.zoomFromOrigin = this.settings.zoomFromOrigin;
19760			clearTimeout(this.hideBarTimeout);
19761			this.hideBarTimeout = false;
19762			$LG('html').removeClass('lg-on');
19763			this.outer.removeClass('lg-visible lg-components-open');
19764			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
19765			this.$backdrop.removeClass('in').css('opacity', 0);
19766			var removeTimeout = this.zoomFromOrigin && transform
19767				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
19768				: this.settings.backdropDuration;
19769			this.$container.removeClass('lg-show-in');
19770			// Once the closign animation is completed and gallery is invisible
19771			setTimeout(function () {
19772				if (_this.zoomFromOrigin && transform) {
19773					_this.outer.removeClass('lg-zoom-from-image');
19774				}
19775				_this.$container.removeClass('lg-show');
19776				// Reset scrollbar
19777				_this.resetScrollBar();
19778				// Need to remove inline opacity as it is used in the stylesheet as well
19779				_this.$backdrop
19780					.removeAttr('style')
19781					.css('transition-duration', _this.settings.backdropDuration + 'ms');
19782				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 19783-19986
19783				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
19784				_this.$inner.empty();
19785				if (_this.lgOpened) {
19786					_this.LGel.trigger(lGEvents.afterClose, {
19787						instance: _this,
19788					});
19789				}
19790				if (_this.$container.get()) {
19791					_this.$container.get().blur();
19792				}
19793				_this.lgOpened = false;
19794			}, removeTimeout + 100);
19795			return removeTimeout + 100;
19796		};
19797		LightGallery.prototype.initModules = function () {
19798			this.plugins.forEach(function (module) {
19799				try {
19800					module.init();
19801				}
19802				catch (err) {
19803					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
19804				}
19805			});
19806		};
19807		LightGallery.prototype.destroyModules = function (destroy) {
19808			this.plugins.forEach(function (module) {
19809				try {
19810					if (destroy) {
19811						module.destroy();
19812					}
19813					else {
19814						module.closeGallery && module.closeGallery();
19815					}
19816				}
19817				catch (err) {
19818					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19819				}
19820			});
19821		};
19822		/**
19823		 * Refresh lightGallery with new set of children.
19824		 *
19825		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19826		 *
19827		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19828		 * @see <a href="/demos/dynamic-mode/">Demo</a>
19829		 * @category lGPublicMethods
19830		 * @example
19831		 *  const plugin = lightGallery();
19832		 *  // Delete or add children, then call
19833		 *  plugin.refresh();
19834		 *
19835		 */
19836		LightGallery.prototype.refresh = function (galleryItems) {
19837			if (!this.settings.dynamic) {
19838				this.invalidateItems();
19839			}
19840			if (galleryItems) {
19841				this.galleryItems = galleryItems;
19842			}
19843			else {
19844				this.galleryItems = this.getItems();
19845			}
19846			this.updateControls();
19847			this.openGalleryOnItemClick();
19848			this.LGel.trigger(lGEvents.updateSlides);
19849		};
19850		LightGallery.prototype.updateControls = function () {
19851			this.addSlideVideoInfo(this.galleryItems);
19852			this.updateCounterTotal();
19853			this.manageSingleSlideClassName();
19854		};
19855		/**
19856		 * Destroy lightGallery.
19857		 * Destroy lightGallery and its plugin instances completely
19858		 *
19859		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19860		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19861		 * You can use refresh method most of the times.
19862		 * @category lGPublicMethods
19863		 * @example
19864		 *  const plugin = lightGallery();
19865		 *  plugin.destroy();
19866		 *
19867		 */
19868		LightGallery.prototype.destroy = function () {
19869			var _this = this;
19870			var closeTimeout = this.closeGallery(true);
19871			setTimeout(function () {
19872				_this.destroyModules(true);
19873				if (!_this.settings.dynamic) {
19874					_this.invalidateItems();
19875				}
19876				$LG(window).off(".lg.global" + _this.lgId);
19877				_this.LGel.off('.lg');
19878				_this.$container.remove();
19879			}, closeTimeout);
19880			return closeTimeout;
19881		};
19882		return LightGallery;
19883	}());
19884
19885	function lightGallery(el, options) {
19886		return new LightGallery(el, options);
19887	}
19888
19889	return lightGallery;
19890
19891})));
19892
19893/*!
19894 * lightgallery | 2.5.0 | June 13th 2022
19895 * http://www.lightgalleryjs.com/
19896 * Copyright (c) 2020 Sachin Neravath;
19897 * @license GPLv3
19898 */
19899
19900(function (global, factory) {
19901	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19902	typeof define === 'function' && define.amd ? define(factory) :
19903	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19904}(this, (function () { 'use strict';
19905
19906	/*! *****************************************************************************
19907	Copyright (c) Microsoft Corporation.
19908
19909	Permission to use, copy, modify, and/or distribute this software for any
19910	purpose with or without fee is hereby granted.
19911
19912	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19913	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19914	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19915	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19916	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19917	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19918	PERFORMANCE OF THIS SOFTWARE.
19919	***************************************************************************** */
19920
19921	var __assign = function() {
19922		__assign = Object.assign || function __assign(t) {
19923			for (var s, i = 1, n = arguments.length; i < n; i++) {
19924				s = arguments[i];
19925				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19926			}
19927			return t;
19928		};
19929		return __assign.apply(this, arguments);
19930	};
19931
19932	var zoomSettings = {
19933		scale: 1,
19934		zoom: true,
19935		actualSize: true,
19936		showZoomInOutIcons: false,
19937		actualSizeIcons: {
19938			zoomIn: 'lg-zoom-in',
19939			zoomOut: 'lg-zoom-out',
19940		},
19941		enableZoomAfter: 300,
19942		zoomPluginStrings: {
19943			zoomIn: 'Zoom in',
19944			zoomOut: 'Zoom out',
19945			viewActualSize: 'View actual size',
19946		},
19947	};
19948
19949	/**
19950	 * List of lightGallery events
19951	 * All events should be documented here
19952	 * Below interfaces are used to build the website documentations
19953	 * */
19954	var lGEvents = {
19955		afterAppendSlide: 'lgAfterAppendSlide',
19956		init: 'lgInit',
19957		hasVideo: 'lgHasVideo',
19958		containerResize: 'lgContainerResize',
19959		updateSlides: 'lgUpdateSlides',
19960		afterAppendSubHtml: 'lgAfterAppendSubHtml',
19961		beforeOpen: 'lgBeforeOpen',
19962		afterOpen: 'lgAfterOpen',
19963		slideItemLoad: 'lgSlideItemLoad',
19964		beforeSlide: 'lgBeforeSlide',
19965		afterSlide: 'lgAfterSlide',
19966		posterClick: 'lgPosterClick',
19967		dragStart: 'lgDragStart',
19968		dragMove: 'lgDragMove',
19969		dragEnd: 'lgDragEnd',
19970		beforeNextSlide: 'lgBeforeNextSlide',
19971		beforePrevSlide: 'lgBeforePrevSlide',
19972		beforeClose: 'lgBeforeClose',
19973		afterClose: 'lgAfterClose',
19974		rotateLeft: 'lgRotateLeft',
19975		rotateRight: 'lgRotateRight',
19976		flipHorizontal: 'lgFlipHorizontal',
19977		flipVertical: 'lgFlipVertical',
19978		autoplay: 'lgAutoplay',
19979		autoplayStart: 'lgAutoplayStart',
19980		autoplayStop: 'lgAutoplayStop',
19981	};
19982
19983	var Zoom = /** @class */ (function () {
19984		function Zoom(instance, $LG) {
19985			// get lightGallery core plugin instance
19986			this.core = instance;
19987			this.$LG = $LG;
19988			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19989			return this;
19990		}
19991		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
19992		Zoom.prototype.buildTemplates = function () {
19993			var zoomIcons = this.settings.showZoomInOutIcons
19994				? "<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>"
19995				: '';
19996			if (this.settings.actualSize) {
19997				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>";
19998			}
19999			this.core.outer.addClass('lg-use-transition-for-zoom');
20000			this.core.$toolbar.first().append(zoomIcons);
20001		};
20002		/**
20003		 * @desc Enable zoom option only once the image is completely loaded
20004		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
20005		 *
20006		 * Zoom styles are defined under lg-zoomable CSS class.
20007		 */
20008		Zoom.prototype.enableZoom = function (event) {
20009			var _this = this;
20010			// delay will be 0 except first time
20011			var _speed = this.settings.enableZoomAfter + event.detail.delay;
20012			// set _speed value 0 if gallery opened from direct url and if it is first slide
20013			if (this.$LG('body').first().hasClass('lg-from-hash') &&
20014				event.detail.delay) {
20015				// will execute only once
20016				_speed = 0;
20017			}
20018			else {
20019				// Remove lg-from-hash to enable starting animation.
20020				this.$LG('body').first().removeClass('lg-from-hash');
20021			}
20022			this.zoomableTimeout = setTimeout(function () {
20023				if (!_this.isImageSlide()) {
20024					return;
20025				}
20026				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
20027				if (event.detail.index === _this.core.index) {
20028					_this.setZoomEssentials();
20029				}
20030			}, _speed + 30);
20031		};
20032		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
20033			// Add zoomable class
20034			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
20035		};
20036		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
20037			var originalRotate = rotateValue;
20038			rotateValue = Math.abs(rotateValue);
20039			var transformValues = this.getCurrentTransform(el);
20040			if (!transformValues) {
20041				return 1;
20042			}
20043			var modifier = 1;
20044			if (axis === 'X') {
20045				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
20046				if (rotateValue === 0 || rotateValue === 180) {
20047					modifier = 1;
20048				}
20049				else if (rotateValue === 90) {
20050					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
20051						(originalRotate === 90 && flipHorizontalValue === -1)) {
20052						modifier = -1;
20053					}
20054					else {
20055						modifier = 1;
20056					}
20057				}
20058				modifier = modifier * flipHorizontalValue;
20059			}
20060			else {
20061				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
20062				if (rotateValue === 0 || rotateValue === 180) {
20063					modifier = 1;
20064				}
20065				else if (rotateValue === 90) {
20066					var sinX = parseFloat(transformValues[1]);
20067					var sinMinusX = parseFloat(transformValues[2]);
20068					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
20069				}
20070				modifier = modifier * flipVerticalValue;
20071			}
20072			return modifier;
20073		};
20074		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
20075			var imageSizes = {
20076				y: 'offsetHeight',
20077				x: 'offsetWidth',
20078			};
20079			if (Math.abs(rotateValue) === 90) {
20080				// Swap axis
20081				if (axis === 'x') {
20082					axis = 'y';
20083				}
20084				else {
20085					axis = 'x';
20086				}
20087			}
20088			return $image[imageSizes[axis]];
20089		};
20090		Zoom.prototype.getDragCords = function (e, rotateValue) {
20091			if (rotateValue === 90) {
20092				return {
20093					x: e.pageY,
20094					y: e.pageX,
20095				};
20096			}
20097			else {
20098				return {
20099					x: e.pageX,
20100					y: e.pageY,
20101				};
20102			}
20103		};
20104		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
20105			var x = e.targetTouches[0].pageX;
20106			var y = e.targetTouches[0].pageY;
20107			if (rotateValue === 90) {
20108				return {
20109					x: y,
20110					y: x,
20111				};
20112			}
20113			else {
20114				return {
20115					x: x,
20116					y: y,
20117				};
20118			}
20119		};
20120		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
20121			scale = scale || this.scale || 1;
20122			var allowY = this.imageYSize * scale > this.containerRect.height;
20123			var allowX = this.imageXSize * scale > this.containerRect.width;
20124			if (rotateValue === 90) {
20125				return {
20126					allowX: allowY,
20127					allowY: allowX,
20128				};
20129			}
20130			else {
20131				return {
20132					allowX: allowX,
20133					allowY: allowY,
20134				};
20135			}
20136		};
20137		/**
20138		 *
20139		 * @param {Element} el
20140		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
20141		 * Get the current transform value
20142		 */
20143		Zoom.prototype.getCurrentTransform = function (el) {
20144			if (!el) {
20145				return;
20146			}
20147			var st = window.getComputedStyle(el, null);
20148			var tm = st.getPropertyValue('-webkit-transform') ||
20149				st.getPropertyValue('-moz-transform') ||
20150				st.getPropertyValue('-ms-transform') ||
20151				st.getPropertyValue('-o-transform') ||
20152				st.getPropertyValue('transform') ||
20153				'none';
20154			if (tm !== 'none') {
20155				return tm.split('(')[1].split(')')[0].split(',');
20156			}
20157			return;
20158		};
20159		Zoom.prototype.getCurrentRotation = function (el) {
20160			if (!el) {
20161				return 0;
20162			}
20163			var values = this.getCurrentTransform(el);
20164			if (values) {
20165				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
20166					(180 / Math.PI));
20167				// If you want rotate in 360
20168				//return (angle < 0 ? angle + 360 : angle);
20169			}
20170			return 0;
20171		};
20172		Zoom.prototype.setZoomEssentials = function () {
20173			var $image = this.core
20174				.getSlideItem(this.core.index)
20175				.find('.lg-image')
20176				.first();
20177			var rotateEl = this.core
20178				.getSlideItem(this.core.index)
20179				.find('.lg-img-rotate')
20180				.first()
20181				.get();
20182			this.rotateValue = this.getCurrentRotation(rotateEl);
20183			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
20184			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
20185			this.containerRect = this.core.outer.get().getBoundingClientRect();
20186			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
20187			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
20188		};
20189		/**
20190		 * @desc Image zoom
20191		 * Translate the wrap and scale the image to get better user experience
20192		 *
20193		 * @param {String} scale - Zoom decrement/increment value
20194		 */
20195		Zoom.prototype.zoomImage = function (scale) {
20196			// Find offset manually to avoid issue after zoom
20197			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
20198				this.containerRect.left;
20199			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20200			var topBottomSpacing = Math.abs(top - bottom) / 2;
20201			var offsetY = (this.containerRect.height -
20202				this.imageYSize -
20203				topBottomSpacing * this.modifierX) /
20204				2 +
20205				this.scrollTop +
20206				this.containerRect.top;
20207			var originalX;
20208			var originalY;
20209			if (scale === 1) {
20210				this.positionChanged = false;
20211			}
20212			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
20213			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
20214			if (this.positionChanged) {
20215				originalX = this.left / (this.scale - 1);
20216				originalY = this.top / (this.scale - 1);
20217				this.pageX = Math.abs(originalX) + offsetX;
20218				this.pageY = Math.abs(originalY) + offsetY;
20219				this.positionChanged = false;
20220			}
20221			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
20222			var _x = offsetX - this.pageX;
20223			var _y = offsetY - this.pageY;
20224			var x = (scale - 1) * _x;
20225			var y = (scale - 1) * _y;
20226			if (allowX) {
20227				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
20228					x = possibleSwipeCords.minX;
20229				}
20230				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
20231					x = possibleSwipeCords.maxX;
20232				}
20233			}
20234			else {
20235				if (scale > 1) {
20236					if (x < possibleSwipeCords.minX) {
20237						x = possibleSwipeCords.minX;
20238					}
20239					else if (x > possibleSwipeCords.maxX) {
20240						x = possibleSwipeCords.maxX;
20241					}
20242				}
20243			}
20244			if (allowY) {
20245				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
20246					y = possibleSwipeCords.minY;
20247				}
20248				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
20249					y = possibleSwipeCords.maxY;
20250				}
20251			}
20252			else {
20253				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
20254				if (scale > 1) {
20255					//If image goes beyond viewport top, use the minim possible translate value
20256					if (y < possibleSwipeCords.minY) {
20257						y = possibleSwipeCords.minY;
20258					}
20259					else if (y > possibleSwipeCords.maxY) {
20260						y = possibleSwipeCords.maxY;
20261					}
20262				}
20263			}
20264			this.setZoomStyles({
20265				x: x,
20266				y: y,
20267				scale: scale,
20268			});
20269		};
20270		/**
20271		 * @desc apply scale3d to image and translate to image wrap
20272		 * @param {style} X,Y and scale
20273		 */
20274		Zoom.prototype.setZoomStyles = function (style) {
20275			var $image = this.core
20276				.getSlideItem(this.core.index)
20277				.find('.lg-image')
20278				.first();
20279			var $dummyImage = this.core.outer
20280				.find('.lg-current .lg-dummy-img')
20281				.first();
20282			var $imageWrap = $image.parent();
20283			this.scale = style.scale;
20284			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20285			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20286			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
20287			$imageWrap.css('transform', transform);
20288			this.left = style.x;
20289			this.top = style.y;
20290		};
20291		/**
20292		 * @param index - Index of the current slide
20293		 * @param event - event will be available only if the function is called on clicking/taping the imags
20294		 */
20295		Zoom.prototype.setActualSize = function (index, event) {
20296			var _this = this;
20297			// Allow zoom only on image
20298			if (!this.isImageSlide() ||
20299				this.core.outer.hasClass('lg-first-slide-loading')) {
20300				return;
20301			}
20302			var scale = this.getCurrentImageActualSizeScale();
20303			if (this.core.outer.hasClass('lg-zoomed')) {
20304				this.scale = 1;
20305			}
20306			else {
20307				this.scale = this.getScale(scale);
20308			}
20309			this.setPageCords(event);
20310			this.beginZoom(this.scale);
20311			this.zoomImage(this.scale);
20312			setTimeout(function () {
20313				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20314			}, 10);
20315		};
20316		Zoom.prototype.getNaturalWidth = function (index) {
20317			var $image = this.core.getSlideItem(index).find('.lg-image').first();
20318			var naturalWidth = this.core.galleryItems[index].width;
20319			return naturalWidth
20320				? parseFloat(naturalWidth)
20321				: $image.get().naturalWidth;
20322		};
20323		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
20324			var _scale;
20325			var scale;
20326			if (naturalWidth > width) {
20327				_scale = naturalWidth / width;
20328				scale = _scale || 2;
20329			}
20330			else {
20331				scale = 1;
20332			}
20333			return scale;
20334		};
20335		Zoom.prototype.getCurrentImageActualSizeScale = function () {
20336			var $image = this.core
20337				.getSlideItem(this.core.index)
20338				.find('.lg-image')
20339				.first();
20340			var width = $image.get().offsetWidth;
20341			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
20342			return this.getActualSizeScale(naturalWidth, width);
20343		};
20344		Zoom.prototype.getPageCords = function (event) {
20345			var cords = {};
20346			if (event) {
20347				cords.x = event.pageX || event.targetTouches[0].pageX;
20348				cords.y = event.pageY || event.targetTouches[0].pageY;
20349			}
20350			else {
20351				var containerRect = this.core.outer.get().getBoundingClientRect();
20352				cords.x = containerRect.width / 2 + containerRect.left;
20353				cords.y =
20354					containerRect.height / 2 + this.scrollTop + containerRect.top;
20355			}
20356			return cords;
20357		};
20358		Zoom.prototype.setPageCords = function (event) {
20359			var pageCords = this.getPageCords(event);
20360			this.pageX = pageCords.x;
20361			this.pageY = pageCords.y;
20362		};
20363		// If true, zoomed - in else zoomed out
20364		Zoom.prototype.beginZoom = function (scale) {
20365			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20366			if (scale > 1) {
20367				this.core.outer.addClass('lg-zoomed');
20368				var $actualSize = this.core.getElementById('lg-actual-size');
20369				$actualSize
20370					.removeClass(this.settings.actualSizeIcons.zoomIn)
20371					.addClass(this.settings.actualSizeIcons.zoomOut);
20372			}
20373			else {
20374				this.resetZoom();
20375			}
20376			return scale > 1;
20377		};
20378		Zoom.prototype.getScale = function (scale) {
20379			var actualSizeScale = this.getCurrentImageActualSizeScale();
20380			if (scale < 1) {
20381				scale = 1;
20382			}
20383			else if (scale > actualSizeScale) {
20384				scale = actualSizeScale;
20385			}
20386			return scale;
20387		};
20388		Zoom.prototype.init = function () {
20389			var _this = this;
20390			if (!this.settings.zoom) {
20391				return;
20392			}
20393			this.buildTemplates();
20394			this.enableZoomOnSlideItemLoad();
20395			var tapped = null;
20396			this.core.outer.on('dblclick.lg', function (event) {
20397				if (!_this.$LG(event.target).hasClass('lg-image')) {
20398					return;
20399				}
20400				_this.setActualSize(_this.core.index, event);
20401			});
20402			this.core.outer.on('touchstart.lg', function (event) {
20403				var $target = _this.$LG(event.target);
20404				if (event.targetTouches.length === 1 &&
20405					$target.hasClass('lg-image')) {
20406					if (!tapped) {
20407						tapped = setTimeout(function () {
20408							tapped = null;
20409						}, 300);
20410					}
20411					else {
20412						clearTimeout(tapped);
20413						tapped = null;
20414						event.preventDefault();
20415						_this.setActualSize(_this.core.index, event);
20416					}
20417				}
20418			});
20419			// Update zoom on resize and orientationchange
20420			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
20421				if (!_this.core.lgOpened || !_this.isImageSlide())
20422					return;
20423				_this.setPageCords();
20424				_this.setZoomEssentials();
20425				_this.zoomImage(_this.scale);
20426			});
20427			// Update zoom on resize and orientationchange
20428			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
20429				if (!_this.core.lgOpened)
20430					return;
20431				_this.scrollTop = _this.$LG(window).scrollTop();
20432			});
20433			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
20434				if (_this.core.outer.find('.lg-current .lg-image').get()) {
20435					_this.scale -= _this.settings.scale;
20436					_this.scale = _this.getScale(_this.scale);
20437					_this.beginZoom(_this.scale);
20438					_this.zoomImage(_this.scale);
20439				}
20440			});
20441			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
20442				_this.zoomIn();
20443			});
20444			this.core.getElementById('lg-actual-size').on('click.lg', function () {
20445				_this.setActualSize(_this.core.index);
20446			});
20447			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
20448				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
20449			});
20450			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
20451				_this.scrollTop = _this.$LG(window).scrollTop();
20452				// Set the initial value center
20453				_this.pageX = _this.core.outer.width() / 2;
20454				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
20455				_this.scale = 1;
20456			});
20457			// Reset zoom on slide change
20458			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
20459				var prevIndex = event.detail.prevIndex;
20460				_this.scale = 1;
20461				_this.positionChanged = false;
20462				_this.resetZoom(prevIndex);
20463				if (_this.isImageSlide()) {
20464					_this.setZoomEssentials();
20465				}
20466			});
20467			// Drag option after zoom
20468			this.zoomDrag();
20469			this.pinchZoom();
20470			this.zoomSwipe();
20471			// Store the zoomable timeout value just to clear it while closing
20472			this.zoomableTimeout = false;
20473			this.positionChanged = false;
20474		};
20475		Zoom.prototype.zoomIn = function (scale) {
20476			// Allow zoom only on image
20477			if (!this.isImageSlide()) {
20478				return;
20479			}
20480			if (scale) {
20481				this.scale = scale;
20482			}
20483			else {
20484				this.scale += this.settings.scale;
20485			}
20486			this.scale = this.getScale(this.scale);
20487			this.beginZoom(this.scale);
20488			this.zoomImage(this.scale);
20489		};
20490		// Reset zoom effect
20491		Zoom.prototype.resetZoom = function (index) {
20492			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
20493			var $actualSize = this.core.getElementById('lg-actual-size');
20494			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
20495			$actualSize
20496				.removeClass(this.settings.actualSizeIcons.zoomOut)
20497				.addClass(this.settings.actualSizeIcons.zoomIn);
20498			$item.find('.lg-img-wrap').first().removeAttr('style');
20499			$item.find('.lg-image').first().removeAttr('style');
20500			this.scale = 1;
20501			this.left = 0;
20502			this.top = 0;
20503			// Reset pagx pagy values to center
20504			this.setPageCords();
20505		};
20506		Zoom.prototype.getTouchDistance = function (e) {
20507			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
20508				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
20509				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
20510					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
20511		};
20512		Zoom.prototype.pinchZoom = function () {
20513			var _this = this;
20514			var startDist = 0;
20515			var pinchStarted = false;
20516			var initScale = 1;
20517			var $item = this.core.getSlideItem(this.core.index);
20518			this.core.$inner.on('touchstart.lg', function (e) {
20519				$item = _this.core.getSlideItem(_this.core.index);
20520				if (!_this.isImageSlide()) {
20521					return;
20522				}
20523				if (e.targetTouches.length === 2 &&
20524					!_this.core.outer.hasClass('lg-first-slide-loading') &&
20525					(_this.$LG(e.target).hasClass('lg-item') ||
20526						$item.get().contains(e.target))) {
20527					initScale = _this.scale || 1;
20528					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20529					_this.core.touchAction = 'pinch';
20530					startDist = _this.getTouchDistance(e);
20531				}
20532			});
20533			this.core.$inner.on('touchmove.lg', function (e) {
20534				if (e.targetTouches.length === 2 &&
20535					_this.core.touchAction === 'pinch' &&
20536					(_this.$LG(e.target).hasClass('lg-item') ||
20537						$item.get().contains(e.target))) {
20538					e.preventDefault();
20539					var endDist = _this.getTouchDistance(e);
20540					var distance = startDist - endDist;
20541					if (!pinchStarted && Math.abs(distance) > 5) {
20542						pinchStarted = true;
20543					}
20544					if (pinchStarted) {
20545						_this.scale = Math.max(1, initScale + -distance * 0.008);
20546						_this.zoomImage(_this.scale);
20547					}
20548				}
20549			});
20550			this.core.$inner.on('touchend.lg', function (e) {
20551				if (_this.core.touchAction === 'pinch' &&
20552					(_this.$LG(e.target).hasClass('lg-item') ||
20553						$item.get().contains(e.target))) {
20554					pinchStarted = false;
20555					startDist = 0;
20556					if (_this.scale <= 1) {
20557						_this.resetZoom();
20558					}
20559					else {
20560						_this.scale = _this.getScale(_this.scale);
20561						_this.zoomImage(_this.scale);
20562						_this.core.outer.addClass('lg-zoomed');
20563					}
20564					_this.core.touchAction = undefined;
20565				}
20566			});
20567		};
20568		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
20569			var distanceXnew = endCoords.x - startCoords.x;
20570			var distanceYnew = endCoords.y - startCoords.y;
20571			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
20572			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
20573			if (speedX > 2) {
20574				speedX += 1;
20575			}
20576			if (speedY > 2) {
20577				speedY += 1;
20578			}
20579			distanceXnew = distanceXnew * speedX;
20580			distanceYnew = distanceYnew * speedY;
20581			var _LGel = this.core
20582				.getSlideItem(this.core.index)
20583				.find('.lg-img-wrap')
20584				.first();
20585			var distance = {};
20586			distance.x = this.left + distanceXnew * this.modifierX;
20587			distance.y = this.top + distanceYnew * this.modifierY;
20588			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
20589			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
20590				if (allowY) {
20591					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20592						distance.y = possibleSwipeCords.minY;
20593					}
20594					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20595						distance.y = possibleSwipeCords.maxY;
20596					}
20597				}
20598				if (allowX) {
20599					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20600						distance.x = possibleSwipeCords.minX;
20601					}
20602					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20603						distance.x = possibleSwipeCords.maxX;
20604					}
20605				}
20606				if (allowY) {
20607					this.top = distance.y;
20608				}
20609				else {
20610					distance.y = this.top;
20611				}
20612				if (allowX) {
20613					this.left = distance.x;
20614				}
20615				else {
20616					distance.x = this.left;
20617				}
20618				this.setZoomSwipeStyles(_LGel, distance);
20619				this.positionChanged = true;
20620			}
20621		};
20622		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
20623			var distance = {};
20624			if (allowY) {
20625				distance.y =
20626					this.top + (endCoords.y - startCoords.y) * this.modifierY;
20627				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20628					var diffMinY = possibleSwipeCords.minY - distance.y;
20629					distance.y = possibleSwipeCords.minY - diffMinY / 6;
20630				}
20631				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20632					var diffMaxY = distance.y - possibleSwipeCords.maxY;
20633					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
20634				}
20635			}
20636			else {
20637				distance.y = this.top;
20638			}
20639			if (allowX) {
20640				distance.x =
20641					this.left + (endCoords.x - startCoords.x) * this.modifierX;
20642				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20643					var diffMinX = possibleSwipeCords.minX - distance.x;
20644					distance.x = possibleSwipeCords.minX - diffMinX / 6;
20645				}
20646				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20647					var difMaxX = distance.x - possibleSwipeCords.maxX;
20648					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
20649				}
20650			}
20651			else {
20652				distance.x = this.left;
20653			}
20654			return distance;
20655		};
20656		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
20657			return x >= minX;
20658		};
20659		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
20660			return x <= maxX;
20661		};
20662		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
20663			return y >= minY;
20664		};
20665		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
20666			return y <= maxY;
20667		};
20668		Zoom.prototype.isImageSlide = function () {
20669			var currentItem = this.core.galleryItems[this.core.index];
20670			return this.core.getSlideType(currentItem) === 'image';
20671		};
20672		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
20673			var dataScale = scale || this.scale || 1;
20674			var elDataScale = Math.abs(dataScale);
20675			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20676			var topBottomSpacing = Math.abs(top - bottom) / 2;
20677			var minY = (this.imageYSize - this.containerRect.height) / 2 +
20678				topBottomSpacing * this.modifierX;
20679			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
20680			var minX = (this.imageXSize - this.containerRect.width) / 2;
20681			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
20682			var possibleSwipeCords = {
20683				minY: minY,
20684				maxY: maxY,
20685				minX: minX,
20686				maxX: maxX,
20687			};
20688			if (Math.abs(rotateValue) === 90) {
20689				possibleSwipeCords = {
20690					minY: minX,
20691					maxY: maxX,
20692					minX: minY,
20693					maxX: maxY,
20694				};
20695			}
20696			return possibleSwipeCords;
20697		};
20698		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
20699			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
20700		};
20701		Zoom.prototype.zoomSwipe = function () {
20702			var _this = this;
20703			var startCoords = {};
20704			var endCoords = {};
20705			var isMoved = false;
20706			// Allow x direction drag
20707			var allowX = false;
20708			// Allow Y direction drag
20709			var allowY = false;
20710			var startTime = new Date();
20711			var endTime = new Date();
20712			var possibleSwipeCords;
20713			var _LGel;
20714			var $item = this.core.getSlideItem(this.core.index);
20715			this.core.$inner.on('touchstart.lg', function (e) {
20716				// Allow zoom only on image
20717				if (!_this.isImageSlide()) {
20718					return;
20719				}
20720				$item = _this.core.getSlideItem(_this.core.index);
20721				if ((_this.$LG(e.target).hasClass('lg-item') ||
20722					$item.get().contains(e.target)) &&
20723					e.targetTouches.length === 1 &&
20724					_this.core.outer.hasClass('lg-zoomed')) {
20725					e.preventDefault();
20726					startTime = new Date();
20727					_this.core.touchAction = 'zoomSwipe';
20728					_LGel = _this.core
20729						.getSlideItem(_this.core.index)
20730						.find('.lg-img-wrap')
20731						.first();
20732					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20733					allowY = dragAllowedAxises.allowY;
20734					allowX = dragAllowedAxises.allowX;
20735					if (allowX || allowY) {
20736						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20737					}
20738					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20739					// reset opacity and transition duration
20740					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
20741				}
20742			});
20743			this.core.$inner.on('touchmove.lg', function (e) {
20744				if (e.targetTouches.length === 1 &&
20745					_this.core.touchAction === 'zoomSwipe' &&
20746					(_this.$LG(e.target).hasClass('lg-item') ||
20747						$item.get().contains(e.target))) {
20748					e.preventDefault();
20749					_this.core.touchAction = 'zoomSwipe';
20750					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20751					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20752					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
20753						Math.abs(endCoords.y - startCoords.y) > 15) {
20754						isMoved = true;
20755						_this.setZoomSwipeStyles(_LGel, distance);
20756					}
20757				}
20758			});
20759			this.core.$inner.on('touchend.lg', function (e) {
20760				if (_this.core.touchAction === 'zoomSwipe' &&
20761					(_this.$LG(e.target).hasClass('lg-item') ||
20762						$item.get().contains(e.target))) {
20763					_this.core.touchAction = undefined;
20764					_this.core.outer.removeClass('lg-zoom-dragging');
20765					if (!isMoved) {
20766						return;
20767					}
20768					isMoved = false;
20769					endTime = new Date();
20770					var touchDuration = endTime.valueOf() - startTime.valueOf();
20771					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20772				}
20773			});
20774		};
20775		Zoom.prototype.zoomDrag = function () {
20776			var _this = this;
20777			var startCoords = {};
20778			var endCoords = {};
20779			var isDragging = false;
20780			var isMoved = false;
20781			// Allow x direction drag
20782			var allowX = false;
20783			// Allow Y direction drag
20784			var allowY = false;
20785			var startTime;
20786			var endTime;
20787			var possibleSwipeCords;
20788			var _LGel;
20789			this.core.outer.on('mousedown.lg.zoom', function (e) {
20790				// Allow zoom only on image
20791				if (!_this.isImageSlide()) {
20792					return;
20793				}
20794				var $item = _this.core.getSlideItem(_this.core.index);
20795				if (_this.$LG(e.target).hasClass('lg-item') ||
20796					$item.get().contains(e.target)) {
20797					startTime = new Date();
20798					_LGel = _this.core
20799						.getSlideItem(_this.core.index)
20800						.find('.lg-img-wrap')
20801						.first();
20802					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20803					allowY = dragAllowedAxises.allowY;
20804					allowX = dragAllowedAxises.allowX;
20805					if (_this.core.outer.hasClass('lg-zoomed')) {
20806						if (_this.$LG(e.target).hasClass('lg-object') &&
20807							(allowX || allowY)) {
20808							e.preventDefault();
20809							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20810							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20811							isDragging = true;
20812							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20813							_this.core.outer.get().scrollLeft += 1;
20814							_this.core.outer.get().scrollLeft -= 1;
20815							_this.core.outer
20816								.removeClass('lg-grab')
20817								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20818							// reset opacity and transition duration
20819						}
20820					}
20821				}
20822			});
20823			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20824				if (isDragging) {
20825					isMoved = true;
20826					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20827					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20828					_this.setZoomSwipeStyles(_LGel, distance);
20829				}
20830			});
20831			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20832				if (isDragging) {
20833					endTime = new Date();
20834					isDragging = false;
20835					_this.core.outer.removeClass('lg-zoom-dragging');
20836					// Fix for chrome mouse move on click
20837					if (isMoved &&
20838						(startCoords.x !== endCoords.x ||
20839							startCoords.y !== endCoords.y)) {
20840						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20841						var touchDuration = endTime.valueOf() - startTime.valueOf();
20842						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20843					}
20844					isMoved = false;
20845				}
20846				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20847			});
20848		};
20849		Zoom.prototype.closeGallery = function () {
20850			this.resetZoom();
20851		};
20852		Zoom.prototype.destroy = function () {
20853			// Unbind all events added by lightGallery zoom plugin
20854			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20855			this.core.LGel.off('.lg.zoom');
20856			this.core.LGel.off('.zoom');
20857			clearTimeout(this.zoomableTimeout);
20858			this.zoomableTimeout = false;
20859		};
20860		return Zoom;
20861	}());
20862
20863	return Zoom;
20864
20865})));
20866/*!
20867 * lightgallery | 2.5.0 | June 13th 2022
20868 * http://www.lightgalleryjs.com/
20869 * Copyright (c) 2020 Sachin Neravath;
20870 * @license GPLv3
20871 */
20872
20873(function (global, factory) {
20874	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20875	typeof define === 'function' && define.amd ? define(factory) :
20876	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20877}(this, (function () { 'use strict';
20878
20879	/*! *****************************************************************************
20880	Copyright (c) Microsoft Corporation.
20881
20882	Permission to use, copy, modify, and/or distribute this software for any
20883	purpose with or without fee is hereby granted.
20884
20885	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20886	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20887	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20888	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20889	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20890	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20891	PERFORMANCE OF THIS SOFTWARE.
20892	***************************************************************************** */
20893
20894	var __assign = function() {
20895		__assign = Object.assign || function __assign(t) {
20896			for (var s, i = 1, n = arguments.length; i < n; i++) {
20897				s = arguments[i];
20898				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20899			}
20900			return t;
20901		};
20902		return __assign.apply(this, arguments);
20903	};
20904
20905	var fullscreenSettings = {
20906		fullScreen: true,
20907		fullscreenPluginStrings: {
20908			toggleFullscreen: 'Toggle Fullscreen',
20909		},
20910	};
20911
20912	var FullScreen = /** @class */ (function () {
20913		function FullScreen(instance, $LG) {
20914			// get lightGallery core plugin instance
20915			this.core = instance;
20916			this.$LG = $LG;
20917			// extend module default settings with lightGallery core settings
20918			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20919			return this;
20920		}
20921		FullScreen.prototype.init = function () {
20922			var fullScreen = '';
20923			if (this.settings.fullScreen) {
20924				// check for fullscreen browser support
20925				if (!document.fullscreenEnabled &&
20926					!document.webkitFullscreenEnabled &&
20927					!document.mozFullScreenEnabled &&
20928					!document.msFullscreenEnabled) {
20929					return;
20930				}
20931				else {
20932					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20933					this.core.$toolbar.append(fullScreen);
20934					this.fullScreen();
20935				}
20936			}
20937		};
20938		FullScreen.prototype.isFullScreen = function () {
20939			return (document.fullscreenElement ||
20940				document.mozFullScreenElement ||
20941				document.webkitFullscreenElement ||
20942				document.msFullscreenElement);
20943		};
20944		FullScreen.prototype.requestFullscreen = function () {
20945			var el = document.documentElement;
20946			if (el.requestFullscreen) {
20947				el.requestFullscreen();
20948			}
20949			else if (el.msRequestFullscreen) {
20950				el.msRequestFullscreen();
20951			}
20952			else if (el.mozRequestFullScreen) {
20953				el.mozRequestFullScreen();
20954			}
20955			else if (el.webkitRequestFullscreen) {
20956				el.webkitRequestFullscreen();
20957			}
20958		};
20959		FullScreen.prototype.exitFullscreen = function () {
20960			if (document.exitFullscreen) {
20961				document.exitFullscreen();
20962			}
20963			else if (document.msExitFullscreen) {
20964				document.msExitFullscreen();
20965			}
20966			else if (document.mozCancelFullScreen) {
20967				document.mozCancelFullScreen();
20968			}
20969			else if (document.webkitExitFullscreen) {
20970				document.webkitExitFullscreen();
20971			}
20972		};
20973		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20974		FullScreen.prototype.fullScreen = function () {
20975			var _this = this;
20976			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 () {
20977				if (!_this.core.lgOpened)
20978					return;
20979				_this.core.outer.toggleClass('lg-fullscreen-on');
20980			});
20981			this.core.outer
20982				.find('.lg-fullscreen')
20983				.first()
20984				.on('click.lg', function () {
20985				if (_this.isFullScreen()) {
20986					_this.exitFullscreen();
20987				}
20988				else {
20989					_this.requestFullscreen();
20990				}
20991			});
20992		};
20993		FullScreen.prototype.closeGallery = function () {
20994			// exit from fullscreen if activated
20995			if (this.isFullScreen()) {
20996				this.exitFullscreen();
20997			}
20998		};
20999		FullScreen.prototype.destroy = function () {
21000			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);
21001		};
21002		return FullScreen;
21003	}());
21004
21005	return FullScreen;
21006
21007})));
21008
21009/*!
21010 * lightgallery | 2.5.0 | June 13th 2022
21011 * http://www.lightgalleryjs.com/
21012 * Copyright (c) 2020 Sachin Neravath;
21013 * @license GPLv3
21014 */
21015
21016(function (global, factory) {
21017	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21018	typeof define === 'function' && define.amd ? define(factory) :
21019	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
21020}(this, (function () { 'use strict';
21021
21022	/*! *****************************************************************************
21023	Copyright (c) Microsoft Corporation.
21024
21025	Permission to use, copy, modify, and/or distribute this software for any
21026	purpose with or without fee is hereby granted.
21027
21028	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21029	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21030	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21031	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21032	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21033	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21034	PERFORMANCE OF THIS SOFTWARE.
21035	***************************************************************************** */
21036
21037	var __assign = function() {
21038		__assign = Object.assign || function __assign(t) {
21039			for (var s, i = 1, n = arguments.length; i < n; i++) {
21040				s = arguments[i];
21041				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21042			}
21043			return t;
21044		};
21045		return __assign.apply(this, arguments);
21046	};
21047
21048	/**
21049	 * List of lightGallery events
21050	 * All events should be documented here
21051	 * Below interfaces are used to build the website documentations
21052	 * */
21053	var lGEvents = {
21054		afterAppendSlide: 'lgAfterAppendSlide',
21055		init: 'lgInit',
21056		hasVideo: 'lgHasVideo',
21057		containerResize: 'lgContainerResize',
21058		updateSlides: 'lgUpdateSlides',
21059		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21060		beforeOpen: 'lgBeforeOpen',
21061		afterOpen: 'lgAfterOpen',
21062		slideItemLoad: 'lgSlideItemLoad',
21063		beforeSlide: 'lgBeforeSlide',
21064		afterSlide: 'lgAfterSlide',
21065		posterClick: 'lgPosterClick',
21066		dragStart: 'lgDragStart',
21067		dragMove: 'lgDragMove',
21068		dragEnd: 'lgDragEnd',
21069		beforeNextSlide: 'lgBeforeNextSlide',
21070		beforePrevSlide: 'lgBeforePrevSlide',
21071		beforeClose: 'lgBeforeClose',
21072		afterClose: 'lgAfterClose',
21073		rotateLeft: 'lgRotateLeft',
21074		rotateRight: 'lgRotateRight',
21075		flipHorizontal: 'lgFlipHorizontal',
21076		flipVertical: 'lgFlipVertical',
21077		autoplay: 'lgAutoplay',
21078		autoplayStart: 'lgAutoplayStart',
21079		autoplayStop: 'lgAutoplayStop',
21080	};
21081
21082	var hashSettings = {
21083		hash: true,
21084		galleryId: '1',
21085		customSlideName: false,
21086	};
21087
21088	var Hash = /** @class */ (function () {
21089		function Hash(instance, $LG) {
21090			// get lightGallery core plugin instance
21091			this.core = instance;
21092			this.$LG = $LG;
21093			// extend module default settings with lightGallery core settings
21094			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
21095			return this;
21096		}
21097		Hash.prototype.init = function () {
21098			var _this = this;
21099			if (!this.settings.hash) {
21100				return;
21101			}
21102			this.oldHash = window.location.hash;
21103			setTimeout(function () {
21104				_this.buildFromHash();
21105			}, 100);
21106			// Change hash value on after each slide transition
21107			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
21108			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
21109			// Listen hash change and change the slide according to slide value
21110			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
21111		};
21112		Hash.prototype.onAfterSlide = function (event) {
21113			var slideName = this.core.galleryItems[event.detail.index].slideName;
21114			slideName = this.settings.customSlideName
21115				? slideName || event.detail.index
21116				: event.detail.index;
21117			if (history.replaceState) {
21118				history.replaceState(null, '', window.location.pathname +
21119					window.location.search +
21120					'#lg=' +
21121					this.settings.galleryId +
21122					'&slide=' +
21123					slideName);
21124			}
21125			else {
21126				window.location.hash =
21127					'lg=' + this.settings.galleryId + '&slide=' + slideName;
21128			}
21129		};
21130		/**
21131		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
21132		 * @param {String} hash
21133		 * @returns {Number} Index of the slide.
21134		 */
21135		Hash.prototype.getIndexFromUrl = function (hash) {
21136			if (hash === void 0) { hash = window.location.hash; }
21137			var slideName = hash.split('&slide=')[1];
21138			var _idx = 0;
21139			if (this.settings.customSlideName) {
21140				for (var index = 0; index < this.core.galleryItems.length; index++) {
21141					var dynamicEl = this.core.galleryItems[index];
21142					if (dynamicEl.slideName === slideName) {
21143						_idx = index;
21144						break;
21145					}
21146				}
21147			}
21148			else {
21149				_idx = parseInt(slideName, 10);
21150			}
21151			return isNaN(_idx) ? 0 : _idx;
21152		};
21153		// Build Gallery if gallery id exist in the URL
21154		Hash.prototype.buildFromHash = function () {
21155			// if dynamic option is enabled execute immediately
21156			var _hash = window.location.hash;
21157			//Uncode edit ##START##
21158			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
21159			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
21160			//Uncode edit ##END##
21161				// This class is used to remove the initial animation if galleryId present in the URL
21162				this.$LG(document.body).addClass('lg-from-hash');
21163				var index = this.getIndexFromUrl(_hash);
21164				this.core.openGallery(index);
21165				return true;
21166			}
21167		};
21168		Hash.prototype.onCloseAfter = function () {
21169			// Reset to old hash value
21170			if (this.oldHash &&
21171				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
21172				if (history.replaceState) {
21173					history.replaceState(null, '', this.oldHash);
21174				}
21175				else {
21176					window.location.hash = this.oldHash;
21177				}
21178			}
21179			else {
21180				if (history.replaceState) {
21181					history.replaceState(null, document.title, window.location.pathname + window.location.search);
21182				}
21183				else {
21184					window.location.hash = '';
21185				}
21186			}
21187		};
21188		Hash.prototype.onHashchange = function () {
21189			if (!this.core.lgOpened)
21190				return;
21191			var _hash = window.location.hash;
21192			var index = this.getIndexFromUrl(_hash);
21193			// it galleryId doesn't exist in the url close the gallery
21194			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
21195				this.core.slide(index, false, false);
21196			}
21197			else if (this.core.lGalleryOn) {
21198				this.core.closeGallery();
21199			}
21200		};
21201		Hash.prototype.closeGallery = function () {
21202			if (this.settings.hash) {
21203				this.$LG(document.body).removeClass('lg-from-hash');
21204			}
21205		};
21206		Hash.prototype.destroy = function () {
21207			this.core.LGel.off('.lg.hash');
21208			this.core.LGel.off('.hash');
21209			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
21210		};
21211		return Hash;
21212	}());
21213
21214	return Hash;
21215
21216})));
21217/*!
21218 * lightgallery | 2.5.0 | June 13th 2022
21219 * http://www.lightgalleryjs.com/
21220 * Copyright (c) 2020 Sachin Neravath;
21221 * @license GPLv3
21222 */
21223
21224(function (global, factory) {
21225	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21226	typeof define === 'function' && define.amd ? define(factory) :
21227	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
21228}(this, (function () { 'use strict';
21229
21230	/*! *****************************************************************************
21231	Copyright (c) Microsoft Corporation.
21232
21233	Permission to use, copy, modify, and/or distribute this software for any
21234	purpose with or without fee is hereby granted.
21235
21236	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21237	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21238	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21239	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21240	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21241	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21242	PERFORMANCE OF THIS SOFTWARE.
21243	***************************************************************************** */
21244
21245	var __assign = function() {
21246		__assign = Object.assign || function __assign(t) {
21247			for (var s, i = 1, n = arguments.length; i < n; i++) {
21248				s = arguments[i];
21249				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21250			}
21251			return t;
21252		};
21253		return __assign.apply(this, arguments);
21254	};
21255
21256	function __spreadArrays() {
21257		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
21258		for (var r = Array(s), k = 0, i = 0; i < il; i++)
21259			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
21260				r[k] = a[j];
21261		return r;
21262	}
21263
21264	var shareSettings = {
21265		share: true,
21266		facebook: true,
21267		facebookDropdownText: 'Facebook',
21268		twitter: true,
21269		twitterDropdownText: 'Twitter',
21270		pinterest: true,
21271		pinterestDropdownText: 'Pinterest',
21272		additionalShareOptions: [],
21273		sharePluginStrings: { share: 'Share' },
21274	};
21275
21276	function getFacebookShareLink(galleryItem) {
21277		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
21278		return (facebookBaseUrl +
21279			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
21280	}
21281
21282	function getTwitterShareLink(galleryItem) {
21283		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
21284		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
21285		var text = galleryItem.tweetText;
21286		return twitterBaseUrl + text + '&url=' + url;
21287	}
21288
21289	function getPinterestShareLink(galleryItem) {
21290		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
21291		var description = galleryItem.pinterestText;
21292		var media = encodeURIComponent(galleryItem.src);
21293		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
21294		return (pinterestBaseUrl +
21295			url +
21296			'&media=' +
21297			media +
21298			'&description=' +
21299			description);
21300	}
21301
21302	/**
21303	 * List of lightGallery events
21304	 * All events should be documented here
21305	 * Below interfaces are used to build the website documentations
21306	 * */
21307	var lGEvents = {
21308		afterAppendSlide: 'lgAfterAppendSlide',
21309		init: 'lgInit',
21310		hasVideo: 'lgHasVideo',
21311		containerResize: 'lgContainerResize',
21312		updateSlides: 'lgUpdateSlides',
21313		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21314		beforeOpen: 'lgBeforeOpen',
21315		afterOpen: 'lgAfterOpen',
21316		slideItemLoad: 'lgSlideItemLoad',
21317		beforeSlide: 'lgBeforeSlide',
21318		afterSlide: 'lgAfterSlide',
21319		posterClick: 'lgPosterClick',
21320		dragStart: 'lgDragStart',
21321		dragMove: 'lgDragMove',
21322		dragEnd: 'lgDragEnd',
21323		beforeNextSlide: 'lgBeforeNextSlide',
21324		beforePrevSlide: 'lgBeforePrevSlide',
21325		beforeClose: 'lgBeforeClose',
21326		afterClose: 'lgAfterClose',
21327		rotateLeft: 'lgRotateLeft',
21328		rotateRight: 'lgRotateRight',
21329		flipHorizontal: 'lgFlipHorizontal',
21330		flipVertical: 'lgFlipVertical',
21331		autoplay: 'lgAutoplay',
21332		autoplayStart: 'lgAutoplayStart',
21333		autoplayStop: 'lgAutoplayStop',
21334	};
21335
21336	var Share = /** @class */ (function () {
21337		function Share(instance) {
21338			this.shareOptions = [];
21339			// get lightGallery core plugin instance
21340			this.core = instance;
21341			// extend module default settings with lightGallery core settings
21342			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
21343			return this;
21344		}
21345		Share.prototype.init = function () {
21346			if (!this.settings.share) {
21347				return;
21348			}
21349			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
21350			this.setLgShareMarkup();
21351			this.core.outer
21352				.find('.lg-share .lg-dropdown')
21353				.append(this.getShareListHtml());
21354			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
21355		};
21356		Share.prototype.getShareListHtml = function () {
21357			var shareHtml = '';
21358			this.shareOptions.forEach(function (shareOption) {
21359				shareHtml += shareOption.dropdownHTML;
21360			});
21361			return shareHtml;
21362		};
21363		Share.prototype.setLgShareMarkup = function () {
21364			var _this = this;
21365			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>");
21366			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
21367			var $shareButton = this.core.outer.find('.lg-share');
21368			$shareButton.first().on('click.lg', function () {
21369				_this.core.outer.toggleClass('lg-dropdown-active');
21370				if (_this.core.outer.hasClass('lg-dropdown-active')) {
21371					_this.core.outer.attr('aria-expanded', true);
21372				}
21373				else {
21374					_this.core.outer.attr('aria-expanded', false);
21375				}
21376			});
21377			this.core.outer
21378				.find('.lg-dropdown-overlay')
21379				.first()
21380				.on('click.lg', function () {
21381				_this.core.outer.removeClass('lg-dropdown-active');
21382				_this.core.outer.attr('aria-expanded', false);
21383			});
21384		};
21385		Share.prototype.onAfterSlide = function (event) {
21386			var _this = this;
21387			var index = event.detail.index;
21388			var currentItem = this.core.galleryItems[index];
21389			setTimeout(function () {
21390				_this.shareOptions.forEach(function (shareOption) {
21391					var selector = shareOption.selector;
21392					_this.core.outer
21393						.find(selector)
21394						.attr('href', shareOption.generateLink(currentItem));
21395				});
21396			}, 100);
21397		};
21398		Share.prototype.getShareListItemHTML = function (type, text) {
21399			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>";
21400		};
21401		Share.prototype.getDefaultShareOptions = function () {
21402			return __spreadArrays((this.settings.facebook
21403				? [
21404					{
21405						type: 'facebook',
21406						generateLink: getFacebookShareLink,
21407						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
21408						selector: '.lg-share-facebook',
21409					},
21410				]
21411				: []), (this.settings.twitter
21412				? [
21413					{
21414						type: 'twitter',
21415						generateLink: getTwitterShareLink,
21416						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
21417						selector: '.lg-share-twitter',
21418					},
21419				]
21420				: []), (this.settings.pinterest
21421				? [
21422					{
21423						type: 'pinterest',
21424						generateLink: getPinterestShareLink,
21425						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
21426						selector: '.lg-share-pinterest',
21427					},
21428				]
21429				: []));
21430		};
21431		Share.prototype.destroy = function () {
21432			this.core.outer.find('.lg-dropdown-overlay').remove();
21433			this.core.outer.find('.lg-share').remove();
21434			this.core.LGel.off('.lg.share');
21435			this.core.LGel.off('.share');
21436		};
21437		return Share;
21438	}());
21439
21440	return Share;
21441
21442})));
21443/*!
21444 * lightgallery | 2.5.0 | June 13th 2022
21445 * http://www.lightgalleryjs.com/
21446 * Copyright (c) 2020 Sachin Neravath;
21447 * @license GPLv3
21448 */
21449
21450(function (global, factory) {
21451	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21452	typeof define === 'function' && define.amd ? define(factory) :
21453	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
21454}(this, (function () { 'use strict';
21455
21456	/*! *****************************************************************************
21457	Copyright (c) Microsoft Corporation.
21458
21459	Permission to use, copy, modify, and/or distribute this software for any
21460	purpose with or without fee is hereby granted.
21461
21462	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21463	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21464	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21465	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21466	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21467	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21468	PERFORMANCE OF THIS SOFTWARE.
21469	***************************************************************************** */
21470
21471	var __assign = function() {
21472		__assign = Object.assign || function __assign(t) {
21473			for (var s, i = 1, n = arguments.length; i < n; i++) {
21474				s = arguments[i];
21475				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21476			}
21477			return t;
21478		};
21479		return __assign.apply(this, arguments);
21480	};
21481
21482	var thumbnailsSettings = {
21483		thumbnail: true,
21484		animateThumb: true,
21485		currentPagerPosition: 'middle',
21486		alignThumbnails: 'middle',
21487		thumbWidth: 100,
21488		thumbHeight: '80px',
21489		thumbMargin: 5,
21490		appendThumbnailsTo: '.lg-components',
21491		toggleThumb: false,
21492		enableThumbDrag: true,
21493		enableThumbSwipe: true,
21494		thumbnailSwipeThreshold: 10,
21495		loadYouTubeThumbnail: true,
21496		youTubeThumbSize: 1,
21497		thumbnailPluginStrings: {
21498			toggleThumbnails: 'Toggle thumbnails',
21499		},
21500	};
21501
21502	/**
21503	 * List of lightGallery events
21504	 * All events should be documented here
21505	 * Below interfaces are used to build the website documentations
21506	 * */
21507	var lGEvents = {
21508		afterAppendSlide: 'lgAfterAppendSlide',
21509		init: 'lgInit',
21510		hasVideo: 'lgHasVideo',
21511		containerResize: 'lgContainerResize',
21512		updateSlides: 'lgUpdateSlides',
21513		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21514		beforeOpen: 'lgBeforeOpen',
21515		afterOpen: 'lgAfterOpen',
21516		slideItemLoad: 'lgSlideItemLoad',
21517		beforeSlide: 'lgBeforeSlide',
21518		afterSlide: 'lgAfterSlide',
21519		posterClick: 'lgPosterClick',
21520		dragStart: 'lgDragStart',
21521		dragMove: 'lgDragMove',
21522		dragEnd: 'lgDragEnd',
21523		beforeNextSlide: 'lgBeforeNextSlide',
21524		beforePrevSlide: 'lgBeforePrevSlide',
21525		beforeClose: 'lgBeforeClose',
21526		afterClose: 'lgAfterClose',
21527		rotateLeft: 'lgRotateLeft',
21528		rotateRight: 'lgRotateRight',
21529		flipHorizontal: 'lgFlipHorizontal',
21530		flipVertical: 'lgFlipVertical',
21531		autoplay: 'lgAutoplay',
21532		autoplayStart: 'lgAutoplayStart',
21533		autoplayStop: 'lgAutoplayStop',
21534	};
21535
21536	var Thumbnail = /** @class */ (function () {
21537		function Thumbnail(instance, $LG) {
21538			this.thumbOuterWidth = 0;
21539			this.thumbTotalWidth = 0;
21540			this.translateX = 0;
21541			this.thumbClickable = false;
21542			// get lightGallery core plugin instance
21543			this.core = instance;
21544			this.$LG = $LG;
21545			return this;
21546		}
21547		Thumbnail.prototype.init = function () {
21548			// extend module default settings with lightGallery core settings
21549			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
21550			this.thumbOuterWidth = 0;
21551			this.thumbTotalWidth =
21552				this.core.galleryItems.length *
21553					(this.settings.thumbWidth + this.settings.thumbMargin);
21554			// Thumbnail animation value
21555			this.translateX = 0;
21556			this.setAnimateThumbStyles();
21557			if (!this.core.settings.allowMediaOverlap) {
21558				this.settings.toggleThumb = false;
21559			}
21560			if (this.settings.thumbnail) {
21561				this.build();
21562				if (this.settings.animateThumb) {
21563					if (this.settings.enableThumbDrag) {
21564						this.enableThumbDrag();
21565					}
21566					if (this.settings.enableThumbSwipe) {
21567						this.enableThumbSwipe();
21568					}
21569					this.thumbClickable = false;
21570				}
21571				else {
21572					this.thumbClickable = true;
21573				}
21574				this.toggleThumbBar();
21575				this.thumbKeyPress();
21576			}
21577		};
21578		Thumbnail.prototype.build = function () {
21579			var _this = this;
21580			this.setThumbMarkup();
21581			this.manageActiveClassOnSlideChange();
21582			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
21583				var $target = _this.$LG(e.target);
21584				if (!$target.hasAttribute('data-lg-item-id')) {
21585					return;
21586				}
21587				setTimeout(function () {
21588					// In IE9 and bellow touch does not support
21589					// Go to slide if browser does not support css transitions
21590					if (_this.thumbClickable && !_this.core.lgBusy) {
21591						var index = parseInt($target.attr('data-lg-item-id'));
21592						_this.core.slide(index, false, true, false);
21593					}
21594				}, 50);
21595			});
21596			//Uncode edit ##START##
21597			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21598			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21599			//Uncode edit ##END##
21600				var index = event.detail.index;
21601				_this.animateThumb(index);
21602			});
21603			//Uncode edit ##START##
21604			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
21605			this.core.LGel.on(lGEvents.beforeOpen, function () {
21606			//Uncode edit ##END##
21607				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21608			});
21609			//Uncode edit ##START##
21610			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
21611			this.core.LGel.on(lGEvents.updateSlides, function () {
21612			//Uncode edit ##END##
21613				_this.rebuildThumbnails();
21614			});
21615			//Uncode edit ##START##
21616			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
21617			this.core.LGel.on(lGEvents.containerResize, function () {
21618			//Uncode edit ##END##
21619				if (!_this.core.lgOpened)
21620					return;
21621				setTimeout(function () {
21622					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21623					_this.animateThumb(_this.core.index);
21624					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21625				}, 50);
21626			});
21627		};
21628		Thumbnail.prototype.setThumbMarkup = function () {
21629			var thumbOuterClassNames = 'lg-thumb-outer ';
21630			if (this.settings.alignThumbnails) {
21631				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
21632			}
21633			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
21634			this.core.outer.addClass('lg-has-thumb');
21635			if (this.settings.appendThumbnailsTo === '.lg-components') {
21636				this.core.$lgComponents.append(html);
21637			}
21638			else {
21639				this.core.outer.append(html);
21640			}
21641			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
21642			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
21643			if (this.settings.animateThumb) {
21644				this.core.outer
21645					.find('.lg-thumb')
21646					.css('transition-duration', this.core.settings.speed + 'ms')
21647					.css('width', this.thumbTotalWidth + 'px')
21648					.css('position', 'relative');
21649			}
21650			this.setThumbItemHtml(this.core.galleryItems);
21651		};
21652		Thumbnail.prototype.enableThumbDrag = function () {
21653			var _this = this;
21654			var thumbDragUtils = {
21655				cords: {
21656					startX: 0,
21657					endX: 0,
21658				},
21659				isMoved: false,
21660				newTranslateX: 0,
21661				startTime: new Date(),
21662				endTime: new Date(),
21663				touchMoveTime: 0,
21664			};
21665			var isDragging = false;
21666			this.$thumbOuter.addClass('lg-grab');
21667			this.core.outer
21668				.find('.lg-thumb')
21669				.first()
21670				.on('mousedown.lg.thumb', function (e) {
21671				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21672					// execute only on .lg-object
21673					e.preventDefault();
21674					thumbDragUtils.cords.startX = e.pageX;
21675					thumbDragUtils.startTime = new Date();
21676					_this.thumbClickable = false;
21677					isDragging = true;
21678					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
21679					_this.core.outer.get().scrollLeft += 1;
21680					_this.core.outer.get().scrollLeft -= 1;
21681					// *
21682					_this.$thumbOuter
21683						.removeClass('lg-grab')
21684						.addClass('lg-grabbing');
21685				}
21686			});
21687			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
21688				if (!_this.core.lgOpened)
21689					return;
21690				if (isDragging) {
21691					thumbDragUtils.cords.endX = e.pageX;
21692					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21693				}
21694			});
21695			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
21696				if (!_this.core.lgOpened)
21697					return;
21698				if (thumbDragUtils.isMoved) {
21699					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21700				}
21701				else {
21702					_this.thumbClickable = true;
21703				}
21704				if (isDragging) {
21705					isDragging = false;
21706					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
21707				}
21708			});
21709		};
21710		Thumbnail.prototype.enableThumbSwipe = function () {
21711			var _this = this;
21712			var thumbDragUtils = {
21713				cords: {
21714					startX: 0,
21715					endX: 0,
21716				},
21717				isMoved: false,
21718				newTranslateX: 0,
21719				startTime: new Date(),
21720				endTime: new Date(),
21721				touchMoveTime: 0,
21722			};
21723			this.$lgThumb.on('touchstart.lg', function (e) {
21724				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21725					e.preventDefault();
21726					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
21727					_this.thumbClickable = false;
21728					thumbDragUtils.startTime = new Date();
21729				}
21730			});
21731			this.$lgThumb.on('touchmove.lg', function (e) {
21732				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21733					e.preventDefault();
21734					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
21735					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21736				}
21737			});
21738			this.$lgThumb.on('touchend.lg', function () {
21739				if (thumbDragUtils.isMoved) {
21740					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21741				}
21742				else {
21743					_this.thumbClickable = true;
21744				}
21745			});
21746		};
21747		// Rebuild thumbnails
21748		Thumbnail.prototype.rebuildThumbnails = function () {
21749			var _this = this;
21750			// Remove transitions
21751			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
21752			setTimeout(function () {
21753				_this.thumbTotalWidth =
21754					_this.core.galleryItems.length *
21755						(_this.settings.thumbWidth + _this.settings.thumbMargin);
21756				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
21757				_this.$lgThumb.empty();
21758				_this.setThumbItemHtml(_this.core.galleryItems);
21759				_this.animateThumb(_this.core.index);
21760			}, 50);
21761			setTimeout(function () {
21762				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
21763			}, 200);
21764		};
21765		// @ts-check
21766		Thumbnail.prototype.setTranslate = function (value) {
21767			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
21768		};
21769		Thumbnail.prototype.getPossibleTransformX = function (left) {
21770			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
21771				left = this.thumbTotalWidth - this.thumbOuterWidth;
21772			}
21773			if (left < 0) {
21774				left = 0;
21775			}
21776			return left;
21777		};
21778		Thumbnail.prototype.animateThumb = function (index) {
21779			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
21780			if (this.settings.animateThumb) {
21781				var position = 0;
21782				switch (this.settings.currentPagerPosition) {
21783					case 'left':
21784						position = 0;
21785						break;
21786					case 'middle':
21787						position =
21788							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
21789						break;
21790					case 'right':
21791						position = this.thumbOuterWidth - this.settings.thumbWidth;
21792				}
21793				this.translateX =
21794					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
21795						1 -
21796						position;
21797				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
21798					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
21799				}
21800				if (this.translateX < 0) {
21801					this.translateX = 0;
21802				}
21803				this.setTranslate(this.translateX);
21804			}
21805		};
21806		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21807			thumbDragUtils.newTranslateX = this.translateX;
21808			thumbDragUtils.isMoved = true;
21809			thumbDragUtils.touchMoveTime = new Date().valueOf();
21810			thumbDragUtils.newTranslateX -=
21811				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21812			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21813			// move current slide
21814			this.setTranslate(thumbDragUtils.newTranslateX);
21815			this.$thumbOuter.addClass('lg-dragging');
21816			return thumbDragUtils;
21817		};
21818		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21819			thumbDragUtils.isMoved = false;
21820			thumbDragUtils.endTime = new Date();
21821			this.$thumbOuter.removeClass('lg-dragging');
21822			var touchDuration = thumbDragUtils.endTime.valueOf() -
21823				thumbDragUtils.startTime.valueOf();
21824			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21825			var speedX = Math.abs(distanceXnew) / touchDuration;
21826			// Some magical numbers
21827			// Can be improved
21828			if (speedX > 0.15 &&
21829				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21830				speedX += 1;
21831				if (speedX > 2) {
21832					speedX += 1;
21833				}
21834				speedX =
21835					speedX +
21836						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21837				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21838				distanceXnew = distanceXnew * speedX;
21839				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21840				this.setTranslate(this.translateX);
21841			}
21842			else {
21843				this.translateX = thumbDragUtils.newTranslateX;
21844			}
21845			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21846				this.settings.thumbnailSwipeThreshold) {
21847				this.thumbClickable = true;
21848			}
21849			return thumbDragUtils;
21850		};
21851		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21852			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21853			var thumbImg;
21854			if (slideVideoInfo.youtube) {
21855				if (this.settings.loadYouTubeThumbnail) {
21856					thumbImg =
21857						'//img.youtube.com/vi/' +
21858							slideVideoInfo.youtube[1] +
21859							'/' +
21860							this.settings.youTubeThumbSize +
21861							'.jpg';
21862				}
21863				else {
21864					thumbImg = thumb;
21865				}
21866			}
21867			else {
21868				thumbImg = thumb;
21869			}
21870			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>";
21871		};
21872		Thumbnail.prototype.getThumbItemHtml = function (items) {
21873			var thumbList = '';
21874			for (var i = 0; i < items.length; i++) {
21875				thumbList += this.getThumbHtml(items[i].thumb, i);
21876			}
21877			return thumbList;
21878		};
21879		Thumbnail.prototype.setThumbItemHtml = function (items) {
21880			var thumbList = this.getThumbItemHtml(items);
21881			this.$lgThumb.html(thumbList);
21882		};
21883		Thumbnail.prototype.setAnimateThumbStyles = function () {
21884			if (this.settings.animateThumb) {
21885				this.core.outer.addClass('lg-animate-thumb');
21886			}
21887		};
21888		// Manage thumbnail active calss
21889		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21890			var _this = this;
21891			// manage active class for thumbnail
21892			//Uncode edit ##START##
21893			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21894			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21895			//Uncode edit ##END##
21896				var $thumb = _this.core.outer.find('.lg-thumb-item');
21897				var index = event.detail.index;
21898				$thumb.removeClass('active');
21899				$thumb.eq(index).addClass('active');
21900			});
21901		};
21902		// Toggle thumbnail bar
21903		Thumbnail.prototype.toggleThumbBar = function () {
21904			var _this = this;
21905			if (this.settings.toggleThumb) {
21906				this.core.outer.addClass('lg-can-toggle');
21907				this.core.$toolbar.append('<button type="button" aria-label="' +
21908					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21909					'" class="lg-toggle-thumb lg-icon"></button>');
21910				this.core.outer
21911					.find('.lg-toggle-thumb')
21912					.first()
21913					.on('click.lg', function () {
21914					_this.core.outer.toggleClass('lg-components-open');
21915				});
21916			}
21917		};
21918		Thumbnail.prototype.thumbKeyPress = function () {
21919			var _this = this;
21920			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21921				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21922					return;
21923				if (e.keyCode === 38) {
21924					e.preventDefault();
21925					_this.core.outer.addClass('lg-components-open');
21926				}
21927				else if (e.keyCode === 40) {
21928					e.preventDefault();
21929					_this.core.outer.removeClass('lg-components-open');
21930				}
21931			});
21932		};
21933		Thumbnail.prototype.destroy = function () {
21934			if (this.settings.thumbnail) {
21935				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21936				this.core.LGel.off('.lg.thumb');
21937				this.core.LGel.off('.thumb');
21938				this.$thumbOuter.remove();
21939				this.core.outer.removeClass('lg-has-thumb');
21940			}
21941		};
21942		return Thumbnail;
21943	}());
21944
21945	return Thumbnail;
21946
21947})));
21948/*!
21949 * lightgallery | 2.5.0 | June 13th 2022
21950 * http://www.lightgalleryjs.com/
21951 * Copyright (c) 2020 Sachin Neravath;
21952 * @license GPLv3
21953 */
21954
21955(function (global, factory) {
21956	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21957	typeof define === 'function' && define.amd ? define(factory) :
21958	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21959}(this, (function () { 'use strict';
21960
21961	/*! *****************************************************************************
21962	Copyright (c) Microsoft Corporation.
21963
21964	Permission to use, copy, modify, and/or distribute this software for any
21965	purpose with or without fee is hereby granted.
21966
21967	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21968	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21969	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21970	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21971	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21972	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21973	PERFORMANCE OF THIS SOFTWARE.
21974	***************************************************************************** */
21975
21976	var __assign = function() {
21977		__assign = Object.assign || function __assign(t) {
21978			for (var s, i = 1, n = arguments.length; i < n; i++) {
21979				s = arguments[i];
21980				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21981			}
21982			return t;
21983		};
21984		return __assign.apply(this, arguments);
21985	};
21986
21987	var videoSettings = {
21988		autoplayFirstVideo: true,
21989		youTubePlayerParams: false,
21990		vimeoPlayerParams: false,
21991		wistiaPlayerParams: false,
21992		gotoNextSlideOnVideoEnd: true,
21993		autoplayVideoOnSlide: false,
21994		videojs: false,
21995		videojsTheme: '',
21996		videojsOptions: {},
21997	};
21998
21999	/**
22000	 * List of lightGallery events
22001	 * All events should be documented here
22002	 * Below interfaces are used to build the website documentations
22003	 * */
22004	var lGEvents = {
22005		afterAppendSlide: 'lgAfterAppendSlide',
22006		init: 'lgInit',
22007		hasVideo: 'lgHasVideo',
22008		containerResize: 'lgContainerResize',
22009		updateSlides: 'lgUpdateSlides',
22010		afterAppendSubHtml: 'lgAfterAppendSubHtml',
22011		beforeOpen: 'lgBeforeOpen',
22012		afterOpen: 'lgAfterOpen',
22013		slideItemLoad: 'lgSlideItemLoad',
22014		beforeSlide: 'lgBeforeSlide',
22015		afterSlide: 'lgAfterSlide',
22016		posterClick: 'lgPosterClick',
22017		dragStart: 'lgDragStart',
22018		dragMove: 'lgDragMove',
22019		dragEnd: 'lgDragEnd',
22020		beforeNextSlide: 'lgBeforeNextSlide',
22021		beforePrevSlide: 'lgBeforePrevSlide',
22022		beforeClose: 'lgBeforeClose',
22023		afterClose: 'lgAfterClose',
22024		rotateLeft: 'lgRotateLeft',
22025		rotateRight: 'lgRotateRight',
22026		flipHorizontal: 'lgFlipHorizontal',
22027		flipVertical: 'lgFlipVertical',
22028		autoplay: 'lgAutoplay',
22029		autoplayStart: 'lgAutoplayStart',
22030		autoplayStop: 'lgAutoplayStop',
22031	};
22032
22033	var param = function (obj) {
22034		return Object.keys(obj)
22035			.map(function (k) {
22036			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
22037		})
22038			.join('&');
22039	};
22040	var getVimeoURLParams = function (defaultParams, videoInfo) {
22041		if (!videoInfo || !videoInfo.vimeo)
22042			return '';
22043		var urlParams = videoInfo.vimeo[2] || '';
22044		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
22045			? '&' + param(defaultParams)
22046			: '';
22047		// Support private video
22048		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
22049		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
22050		var hash = urlWithHashWithParams.split('#')[0];
22051		var isPrivate = videoInfo.vimeo[1] !== hash;
22052		if (isPrivate) {
22053			urlParams = urlParams.replace("/" + hash, '');
22054		}
22055		urlParams =
22056			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
22057		// For vimeo last params gets priority if duplicates found
22058		// Uncode edit ##START##
22059		var vimeoPlayerParams = '?autoplay=0';
22060		if ( videoInfo.autoplay !== '' ) {
22061			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22062			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
22063		} else {
22064			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
22065				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
22066			}
22067		}
22068		if ( videoInfo.muted !== '' ) {
22069			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
22070		} else {
22071			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
22072				vimeoPlayerParams += '&muted=1';
22073			}
22074		}
22075		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22076		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22077		// Uncode edit ##END##
22078		return vimeoPlayerParams;
22079	};
22080
22081	/**
22082	 * Video module for lightGallery
22083	 * Supports HTML5, YouTube, Vimeo, wistia videos
22084	 *
22085	 *
22086	 * @ref Wistia
22087	 * https://wistia.com/support/integrations/wordpress(How to get url)
22088	 * https://wistia.com/support/developers/embed-options#using-embed-options
22089	 * https://wistia.com/support/developers/player-api
22090	 * https://wistia.com/support/developers/construct-an-embed-code
22091	 * http://jsfiddle.net/xvnm7xLm/
22092	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
22093	 * https://wistia.com/support/embed-and-share/sharing-videos
22094	 * https://private-sharing.wistia.com/medias/mwhrulrucj
22095	 *
22096	 * @ref Youtube
22097	 * https://developers.google.com/youtube/player_parameters#enablejsapi
22098	 * https://developers.google.com/youtube/iframe_api_reference
22099	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
22100	 *
22101	 * @ref Vimeo
22102	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
22103	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
22104	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
22105	 */
22106	var Video = /** @class */ (function () {
22107		function Video(instance) {
22108			// get lightGallery core plugin instance
22109			this.core = instance;
22110			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
22111			return this;
22112		}
22113		Video.prototype.init = function () {
22114			var _this = this;
22115			/**
22116			 * Event triggered when video url found without poster
22117			 * Append video HTML
22118			 * Play if autoplayFirstVideo is true
22119			 */
22120			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
22121			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
22122				var $el = _this.core.getSlideItem(_this.core.index);
22123				_this.loadVideoOnPosterClick($el);
22124			});
22125			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
22126			// @desc fired immediately before each slide transition.
22127			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
22128			// @desc fired immediately after each slide transition.
22129			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
22130		};
22131		/**
22132		 * @desc Event triggered when a slide is completely loaded
22133		 *
22134		 * @param {Event} event - lightGalley custom event
22135		 */
22136		Video.prototype.onSlideItemLoad = function (event) {
22137			var _this = this;
22138			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
22139			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
22140			if (this.settings.autoplayFirstVideo &&
22141				isFirstSlide &&
22142				index === this.core.index) {
22143				// Delay is just for the transition effect on video load
22144				setTimeout(function () {
22145					_this.loadAndPlayVideo(index);
22146				}, 200);
22147			}
22148			// Should not call on first slide. should check only if the slide is active
22149			if (!isFirstSlide &&
22150				this.settings.autoplayVideoOnSlide &&
22151				index === this.core.index) {
22152					setTimeout(function () {
22153						_this.loadAndPlayVideo(index);
22154					}, 500);
22155				}
22156		};
22157		/**
22158		 * @desc Event triggered when video url or poster found
22159		 * Append video HTML is poster is not given
22160		 * Play if autoplayFirstVideo is true
22161		 *
22162		 * @param {Event} event - Javascript Event object.
22163		 */
22164		Video.prototype.onHasVideo = function (event) {
22165			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
22166			if (!hasPoster) {
22167				// All functions are called separately if poster exist in loadVideoOnPosterClick function
22168				this.appendVideos(this.core.getSlideItem(index), {
22169					src: src,
22170					addClass: 'lg-object',
22171					index: index,
22172					html5Video: html5Video,
22173					// Uncode edit ##START##
22174					autoplay: event.target.getAttribute('data-lb-autoplay'),
22175					muted: event.target.getAttribute('data-lb-muted'),
22176					// Uncode edit ##END##
22177				});
22178				// Automatically navigate to next slide once video reaches the end.
22179				this.gotoNextSlideOnVideoEnd(src, index);
22180			}
22181		};
22182		/**
22183		 * @desc fired immediately before each slide transition.
22184		 * Pause the previous video
22185		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
22186		 *
22187		 * @param {Event} event - Javascript Event object.
22188		 * @param {number} prevIndex - Previous index of the slide.
22189		 * @param {number} index - Current index of the slide
22190		 */
22191		Video.prototype.onBeforeSlide = function (event) {
22192			if (this.core.lGalleryOn) {
22193				var prevIndex = event.detail.prevIndex;
22194				this.pauseVideo(prevIndex);
22195			}
22196			// Uncode edit ##START##
22197			var _a = event.detail, index = _a.index;
22198			var $slide = this.core.getSlideItem(index);
22199			
22200			var iframe = $slide.selector.querySelector('iframe');
22201			if ( iframe != null ) {
22202
22203				var data_play = iframe.getAttribute('data-autoplay');
22204				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
22205					this.loadAndPlayVideo(index);
22206
22207					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
22208						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
22209					if (videoInfo.vimeo) {
22210						var vimeoPlayer = new Vimeo.Player($videoElement.get());
22211						vimeoPlayer.on('play', function () {
22212							vimeoPlayer.setCurrentTime(0);
22213						});
22214					} else if ( videoInfo.youtube ) {
22215						try {
22216							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
22217						}
22218						catch (e) {
22219							console.warn(e);
22220						}
22221					}
22222				}
22223			}
22224			// Uncode edit ##END##
22225		};
22226		/**
22227		 * @desc fired immediately after each slide transition.
22228		 * Play video if autoplayVideoOnSlide option is enabled.
22229		 *
22230		 * @param {Event} event - Javascript Event object.
22231		 * @param {number} prevIndex - Previous index of the slide.
22232		 * @param {number} index - Current index of the slide
22233		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
22234		 */
22235		Video.prototype.onAfterSlide = function (event) {
22236			var _this = this;
22237			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
22238			// Do not call on first slide
22239			var $slide = this.core.getSlideItem(index);
22240			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
22241				if ($slide.hasClass('lg-complete')) {
22242					setTimeout(function () {
22243						_this.loadAndPlayVideo(index);
22244					}, 100);
22245				}
22246			}
22247		};
22248		Video.prototype.loadAndPlayVideo = function (index) {
22249			var $slide = this.core.getSlideItem(index);
22250			var currentGalleryItem = this.core.galleryItems[index];
22251			if (currentGalleryItem.poster) {
22252				this.loadVideoOnPosterClick($slide, true);
22253			}
22254			else {
22255				//Uncode edit ##START##
22256				// this.playVideo(index);
22257				var iframe = $slide.selector.querySelector('iframe');
22258				if ( iframe != null ) {
22259					var data_play = iframe.getAttribute('data-autoplay');
22260					if ( typeof data_play !== 'undefined' ) {
22261						if ( data_play === '1' && this.core.index == index ) {
22262							this.playVideo(index);
22263						} else {
22264							this.pauseVideo(index);
22265						}
22266					}
22267				}
22268				//Uncode edit ##END##
22269			}
22270		};
22271		/**
22272		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22273		 * @param {number} index - Index of the slide
22274		 */
22275		Video.prototype.playVideo = function (index) {
22276			this.controlVideo(index, 'play');
22277		};
22278		/**
22279		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22280		 * @param {number} index - Index of the slide
22281		 */
22282		Video.prototype.pauseVideo = function (index) {
22283			this.controlVideo(index, 'pause');
22284		};
22285		// Uncode edit ##START##
22286		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
22287		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
22288		// Uncode edit ##END##
22289			var video = '';
22290			var videoInfo = this.core.galleryItems[index]
22291				.__slideVideoInfo || {};
22292			var currentGalleryItem = this.core.galleryItems[index];
22293			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
22294			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
22295			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
22296			if (videoInfo.youtube) {
22297				var videoId = 'lg-youtube' + index;
22298				var slideUrlParams = videoInfo.youtube[2]
22299					? videoInfo.youtube[2] + '&'
22300					: '';
22301				// For youtube first parms gets priority if duplicates found
22302				// Uncode edit ##START##
22303				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
22304				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
22305				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
22306					youTubePlayerParams += '&autoplay=0';
22307				}
22308				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
22309					youTubePlayerParams += '&mute=1';
22310				}
22311				var data_video = '';
22312				if ( autoplay !== '' ) {
22313					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
22314					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22315					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
22316					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22317				}
22318				// if ( muted !== '' ) {
22319				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
22320				// }
22321				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
22322
22323				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
22324				// Uncode edit ##END##
22325				var playerParams = youTubePlayerParams +
22326					(this.settings.youTubePlayerParams
22327						? '&' + param(this.settings.youTubePlayerParams)
22328						: '');
22329				// Uncode edit ##START##
22330				// 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>";
22331				var nocookie = typeof SiteParameters.uncode_nocookie !== 'undefined' ? SiteParameters.uncode_nocookie : '';
22332				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube" + nocookie + ".com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
22333				var tag = document.createElement('script');
22334				tag.src = "//www.youtube.com/player_api";
22335				var firstScriptTag = document.getElementsByTagName('script')[0];
22336				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
22337
22338				// Replace the 'ytplayer' element with an <iframe> and
22339				// YouTube player after the API code downloads.
22340				var ytIframeplayer,
22341					setMute = muted === 'yes' ? 0 : 100;
22342				window.onYouTubePlayerAPIReady = function() {
22343					ytIframeplayer = new YT.Player(videoId, {
22344						videoId: videoInfo.youtube[1],
22345						events: {
22346							'onReady': function (event) {
22347								event.target.setVolume(setMute);
22348							}
22349						}
22350					});
22351				}
22352				// Uncode edit ##END##
22353			}
22354			else if (videoInfo.vimeo) {
22355				var videoId = 'lg-vimeo' + index;
22356				// Uncode edit ##START##
22357				videoInfo.autoplay = autoplay;
22358				videoInfo.muted = muted;
22359				// Uncode edit ##END##
22360				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
22361				// Uncode edit ##START##
22362				// 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>";
22363				var data_video = '';
22364				if ( autoplay !== '' ) {
22365					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22366				}
22367				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>";
22368				// Uncode edit ##END##
22369			}
22370			else if (videoInfo.wistia) {
22371				var wistiaId = 'lg-wistia' + index;
22372				var playerParams = param(this.settings.wistiaPlayerParams);
22373				playerParams = playerParams ? '?' + playerParams : '';
22374				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>";
22375			}
22376			else if (videoInfo.html5) {
22377				var html5VideoMarkup = '';
22378				for (var i = 0; i < html5Video.source.length; i++) {
22379					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
22380				}
22381				if (html5Video.tracks) {
22382					var _loop_1 = function (i) {
22383						var trackAttributes = '';
22384						var track = html5Video.tracks[i];
22385						Object.keys(track || {}
22385).forEach(function (key) {
22386							trackAttributes += key + "=\"" + track[key] + "\" ";
22387						});
22388						html5VideoMarkup += "<track " + trackAttributes + ">";
22389					};
22390					for (var i = 0; i < html5Video.tracks.length; i++) {
22391						_loop_1(i);
22392					}
22393				}
22394				var html5VideoAttrs_1 = '';
22395				var videoAttributes_1 = html5Video.attributes || {};
22396				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
22397					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
22398				});
22399				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
22400					? this.settings.videojsTheme + ' '
22401					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
22402			}
22403			return video;
22404		};
22405		/**
22406		 * @desc - Append videos to the slide
22407		 *
22408		 * @param {HTMLElement} el - slide element
22409		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
22410		 */
22411		Video.prototype.appendVideos = function (el, videoParams) {
22412			var _a;
22413			// Uncode edit ##START##
22414			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
22415			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
22416			// Uncode edit ##END##
22417			el.find('.lg-video-cont').append(videoHtml);
22418			var $videoElement = el.find('.lg-video-object').first();
22419			if (videoParams.html5Video) {
22420				$videoElement.on('mousedown.lg.video', function (e) {
22421					e.stopPropagation();
22422				});
22423			}
22424			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
22425				try {
22426					return videojs($videoElement.get(), this.settings.videojsOptions);
22427				}
22428				catch (e) {
22429					console.warn('lightGallery:- Make sure you have included videojs');
22430				}
22431			}
22432		};
22433		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
22434			var _this = this;
22435			var $videoElement = this.core
22436				.getSlideItem(index)
22437				.find('.lg-video-object')
22438				.first();
22439			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22440			if (this.settings.gotoNextSlideOnVideoEnd) {
22441				if (videoInfo.html5) {
22442					$videoElement.on('ended', function () {
22443						_this.core.goToNextSlide();
22444					});
22445				}
22446				else if (videoInfo.vimeo) {
22447					try {
22448						// https://github.com/vimeo/player.js/#ended
22449						new Vimeo.Player($videoElement.get()).on('ended', function () {
22450							_this.core.goToNextSlide();
22451						});
22452					}
22453					catch (e) {
22454						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22455					}
22456				}
22457				else if (videoInfo.wistia) {
22458					try {
22459						window._wq = window._wq || [];
22460						// @todo Event is gettign triggered multiple times
22461						window._wq.push({
22462							id: $videoElement.attr('id'),
22463							onReady: function (video) {
22464								video.bind('end', function () {
22465									_this.core.goToNextSlide();
22466								});
22467							},
22468						});
22469					}
22470					catch (e) {
22471						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22472					}
22473				}
22474			}
22475		};
22476		Video.prototype.controlVideo = function (index, action) {
22477			var $videoElement = this.core
22478				.getSlideItem(index)
22479				.find('.lg-video-object')
22480				.first();
22481			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22482			if (!$videoElement.get())
22483				return;
22484			if (videoInfo.youtube) {
22485				try {
22486					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
22487				}
22488				catch (e) {
22489					console.warn("lightGallery:- " + e);
22490				}
22491			}
22492			else if (videoInfo.vimeo) {
22493				try {
22494					new Vimeo.Player($videoElement.get())[action]();
22495				}
22496				catch (e) {
22497					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22498				}
22499			}
22500			else if (videoInfo.html5) {
22501				if (this.settings.videojs) {
22502					try {
22503						videojs($videoElement.get())[action]();
22504					}
22505					catch (e) {
22506						console.warn('lightGallery:- Make sure you have included videojs');
22507					}
22508				}
22509				else {
22510					$videoElement.get()[action]();
22511				}
22512			}
22513			else if (videoInfo.wistia) {
22514				try {
22515					window._wq = window._wq || [];
22516					// @todo Find a way to destroy wistia player instance
22517					window._wq.push({
22518						id: $videoElement.attr('id'),
22519						onReady: function (video) {
22520							video[action]();
22521						},
22522					});
22523				}
22524				catch (e) {
22525					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22526				}
22527			}
22528		};
22529		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
22530			var _this = this;
22531			// check slide has poster
22532			if (!$el.hasClass('lg-video-loaded')) {
22533				// check already video element present
22534				if (!$el.hasClass('lg-has-video')) {
22535					$el.addClass('lg-has-video');
22536					var _html = void 0;
22537					var _src = this.core.galleryItems[this.core.index].src;
22538					var video = this.core.galleryItems[this.core.index].video;
22539					if (video) {
22540						_html =
22541							typeof video === 'string' ? JSON.parse(video) : video;
22542					}
22543					var videoJsPlayer_1 = this.appendVideos($el, {
22544						src: _src,
22545						addClass: '',
22546						index: this.core.index,
22547						html5Video: _html,
22548					});
22549					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
22550					var $tempImg = $el.find('.lg-object').first().get();
22551					// @todo make sure it is working
22552					$el.find('.lg-video-cont').first().append($tempImg);
22553					$el.addClass('lg-video-loading');
22554					videoJsPlayer_1 &&
22555						videoJsPlayer_1.ready(function () {
22556							videoJsPlayer_1.on('loadedmetadata', function () {
22557								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22558							});
22559						});
22560					$el.find('.lg-video-object')
22561						.first()
22562						.on('load.lg error.lg loadedmetadata.lg', function () {
22563						setTimeout(function () {
22564							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22565						}, 50);
22566					});
22567				}
22568				else {
22569					this.playVideo(this.core.index);
22570				}
22571			}
22572			else if (forcePlay) {
22573				this.playVideo(this.core.index);
22574			}
22575		};
22576		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
22577			$el.addClass('lg-video-loaded');
22578			this.playVideo(index);
22579		};
22580		Video.prototype.destroy = function () {
22581			this.core.LGel.off('.lg.video');
22582			this.core.LGel.off('.video');
22583		};
22584		return Video;
22585	}());
22586
22587	return Video;
22588
22589})));
22590
22591
22592/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
22593!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:{}}
22593),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 22593
22593var 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)}
22593},{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 22593-23800
22593))}(),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});
22594
22595/**
22596 * Owl carousel
22597 * @version 2.0.0-beta.3
22598 * @author Bartosz Wojciechowski
22599 * @license The MIT License (MIT)
22600 * @todo Lazy Load Icon
22601 * @todo prevent animationend bubling
22602 * @todo itemsScaleUp
22603 * @todo Test Zepto
22604 * @todo stagePadding calculate wrong active classes
22605 */
22606;(function($, window, document, undefined) {
22607
22608	/**
22609	 * Creates a carousel.
22610	 * @class The Owl Carousel.
22611	 * @public
22612	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
22613	 * @param {Object} [options] - The options
22614	 */
22615	function Owl(element, options) {
22616
22617		/**
22618		 * Current settings for the carousel.
22619		 * @public
22620		 */
22621		this.settings = null;
22622
22623		/**
22624		 * Current options set by the caller including defaults.
22625		 * @public
22626		 */
22627		this.options = $.extend({}, Owl.Defaults, options);
22628
22629		/**
22630		 * Plugin element.
22631		 * @public
22632		 */
22633		this.$element = $(element);
22634
22635		/**
22636		 * Proxied event handlers.
22637		 * @protected
22638		 */
22639		this._handlers = {};
22640
22641		/**
22642		 * References to the running plugins of this carousel.
22643		 * @protected
22644		 */
22645		this._plugins = {};
22646
22647		/**
22648		 * Currently suppressed events to prevent them from beeing retriggered.
22649		 * @protected
22650		 */
22651		this._supress = {};
22652
22653		/**
22654		 * Absolute current position.
22655		 * @protected
22656		 */
22657		this._current = null;
22658
22659		/**
22660		 * Animation speed in milliseconds.
22661		 * @protected
22662		 */
22663		this._speed = null;
22664
22665		/**
22666		 * Coordinates of all items in pixel.
22667		 * @todo The name of this member is missleading.
22668		 * @protected
22669		 */
22670		this._coordinates = [];
22671
22672		/**
22673		 * Current breakpoint.
22674		 * @todo Real media queries would be nice.
22675		 * @protected
22676		 */
22677		this._breakpoint = null;
22678
22679		/**
22680		 * Current width of the plugin element.
22681		 */
22682		this._width = null;
22683
22684		/**
22685		 * All real items.
22686		 * @protected
22687		 */
22688		this._items = [];
22689
22690		/**
22691		 * All cloned items.
22692		 * @protected
22693		 */
22694		this._clones = [];
22695
22696		/**
22697		 * Merge values of all items.
22698		 * @todo Maybe this could be part of a plugin.
22699		 * @protected
22700		 */
22701		this._mergers = [];
22702
22703		/**
22704		 * Widths of all items.
22705		 */
22706		this._widths = [];
22707
22708		/**
22709		 * Invalidated parts within the update process.
22710		 * @protected
22711		 */
22712		this._invalidated = {};
22713
22714		/**
22715		 * Ordered list of workers for the update process.
22716		 * @protected
22717		 */
22718		this._pipe = [];
22719
22720		/**
22721		 * Current state information for the drag operation.
22722		 * @todo #261
22723		 * @protected
22724		 */
22725		this._drag = {
22726			time: null,
22727			target: null,
22728			pointer: null,
22729			stage: {
22730				start: null,
22731				current: null
22732			},
22733			direction: null
22734		};
22735
22736		/**
22737		 * Current state information and their tags.
22738		 * @type {Object}
22739		 * @protected
22740		 */
22741		this._states = {
22742			current: {},
22743			tags: {
22744				'initializing': [ 'busy' ],
22745				'animating': [ 'busy' ],
22746				'dragging': [ 'interacting' ]
22747			}
22748		};
22749
22750		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
22751			this._handlers[handler] = $.proxy(this[handler], this);
22752		}, this));
22753
22754		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
22755			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
22756				= new plugin(this);
22757		}, this));
22758
22759		$.each(Owl.Workers, $.proxy(function(priority, worker) {
22760			this._pipe.push({
22761				'filter': worker.filter,
22762				'run': $.proxy(worker.run, this)
22763			});
22764		}, this));
22765
22766		this.setup();
22767		this.initialize();
22768	}
22769
22770	/**
22771	 * Default options for the carousel.
22772	 * @public
22773	 */
22774	Owl.Defaults = {
22775		items: 3,
22776		loop: false,
22777		center: false,
22778		rewind: false,
22779
22780		mouseDrag: true,
22781		touchDrag: true,
22782		pullDrag: true,
22783		freeDrag: false,
22784
22785		margin: 0,
22786		stagePadding: 0,
22787
22788		merge: false,
22789		mergeFit: true,
22790		autoWidth: false,
22791
22792		startPosition: 0,
22793		rtl: false,
22794
22795		smartSpeed: 250,
22796		fluidSpeed: false,
22797		dragEndSpeed: false,
22798
22799		responsive: {},
22800		responsiveRefreshRate: 200,
22801		responsiveBaseElement: window,
22802
22803		fallbackEasing: 'swing',
22804
22805		info: false,
22806
22807		nestedItemSelector: false,
22808		itemElement: 'div',
22809		stageElement: 'div',
22810
22811		refreshClass: 'owl-refresh',
22812		loadedClass: 'owl-loaded',
22813		loadingClass: 'owl-loading',
22814		rtlClass: 'owl-rtl',
22815		responsiveClass: 'owl-responsive',
22816		dragClass: 'owl-drag',
22817		itemClass: 'owl-item',
22818		stageClass: 'owl-stage',
22819		stageOuterClass: 'owl-stage-outer',
22820		grabClass: 'owl-grab'
22821	};
22822
22823	/**
22824	 * Enumeration for width.
22825	 * @public
22826	 * @readonly
22827	 * @enum {String}
22828	 */
22829	Owl.Width = {
22830		Default: 'default',
22831		Inner: 'inner',
22832		Outer: 'outer'
22833	};
22834
22835	/**
22836	 * Enumeration for types.
22837	 * @public
22838	 * @readonly
22839	 * @enum {String}
22840	 */
22841	Owl.Type = {
22842		Event: 'event',
22843		State: 'state'
22844	};
22845
22846	/**
22847	 * Contains all registered plugins.
22848	 * @public
22849	 */
22850	Owl.Plugins = {};
22851
22852	/**
22853	 * List of workers involved in the update process.
22854	 */
22855	Owl.Workers = [ {
22856		filter: [ 'width', 'settings' ],
22857		run: function() {
22858			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
22859			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
22860		}
22861	}, {
22862		filter: [ 'width', 'items', 'settings' ],
22863		run: function(cache) {
22864			cache.current = this._items && this._items[this.relative(this._current)];
22865		}
22866	}, {
22867		filter: [ 'items', 'settings' ],
22868		run: function() {
22869			this.$stage.children('.cloned').remove();
22870		}
22871	}, {
22872		filter: [ 'width', 'items', 'settings' ],
22873		run: function(cache) {
22874			var margin = this.settings.margin || '',
22875				grid = !this.settings.autoWidth,
22876				rtl = this.settings.rtl,
22877				css = {
22878					'width': 'auto',
22879					'margin-left': rtl ? margin : '',
22880					'margin-right': rtl ? '' : margin
22881				};
22882
22883			!grid && this.$stage.children().css(css);
22884
22885			cache.css = css;
22886		}
22887	}, {
22888		filter: [ 'width', 'items', 'settings' ],
22889		run: function(cache) {
22890			//UNCODE edit to fix Chrome stage padding issue
22891			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
22892				merge = null,
22893				iterator = this._items.length,
22894				grid = !this.settings.autoWidth,
22895				widths = [];
22896
22897			cache.items = {
22898				merge: false,
22899				width: width
22900			};
22901
22902			while (iterator--) {
22903				merge = this._mergers[iterator];
22904				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
22905
22906				cache.items.merge = merge > 1 || cache.items.merge;
22907
22908				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22909			}
22910
22911			this._widths = widths;
22912		}
22913	}, {
22914		filter: [ 'items', 'settings' ],
22915		run: function() {
22916			var clones = [],
22917				items = this._items,
22918				settings = this.settings,
22919				view = Math.max(settings.items * 2, 4),
22920				size = Math.ceil(items.length / 2) * 2,
22921				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22922				append = '',
22923				prepend = '';
22924
22925			repeat /= 2;
22926
22927			while (repeat--) {
22928				clones.push(this.normalize(clones.length / 2, true));
22929				append = append + items[clones[clones.length - 1]][0].outerHTML;
22930				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22931				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22932			}
22933
22934			this._clones = clones;
22935
22936			// var appendVideo = $(append).find('.uncode-video-container');
22937			// if (appendVideo.length) {
22938			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22939			// }
22940			// var prependVideo = $(prepend).find('.uncode-video-container');
22941			// if (prependVideo.length) {
22942			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22943			// }
22944			$(append).addClass('cloned').appendTo(this.$stage);
22945			$(prepend).addClass('cloned').prependTo(this.$stage);
22946		}
22947	}, {
22948		filter: [ 'width', 'items', 'settings' ],
22949		run: function() {
22950			var rtl = this.settings.rtl ? 1 : -1,
22951				size = this._clones.length + this._items.length,
22952				iterator = -1,
22953				previous = 0,
22954				current = 0,
22955				coordinates = [];
22956
22957			while (++iterator < size) {
22958				previous = coordinates[iterator - 1] || 0;
22959				current = this._widths[this.relative(iterator)] + this.settings.margin;
22960				coordinates.push(previous + current * rtl);
22961			}
22962
22963			this._coordinates = coordinates;
22964		}
22965	}, {
22966		filter: [ 'width', 'items', 'settings' ],
22967		run: function() {
22968			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22969				padding = stagePadding,
22970				coordinates = this._coordinates,
22971				css = {
22972					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22973					'padding-left': padding || '',
22974					'padding-right': padding || ''
22975				};
22976
22977			this.$stage.css(css);
22978		}
22979	}, {
22980		filter: [ 'width', 'items', 'settings' ],
22981		run: function(cache) {
22982			var iterator = this._coordinates.length,
22983				grid = !this.settings.autoWidth,
22984				items = this.$stage.children();
22985
22986			if (grid && cache.items.merge) {
22987				while (iterator--) {
22988					cache.css.width = this._widths[this.relative(iterator)];
22989					items.eq(iterator).css(cache.css);
22990				}
22991			} else if (grid) {
22992				cache.css.width = cache.items.width;
22993				items.css(cache.css);
22994			}
22995		}
22996	}, {
22997		filter: [ 'items' ],
22998		run: function() {
22999			this._coordinates.length < 1 && this.$stage.removeAttr('style');
23000		}
23001	}, {
23002		filter: [ 'width', 'items', 'settings' ],
23003		run: function(cache) {
23004			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
23005			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
23006			this.reset(cache.current);
23007		}
23008	}, {
23009		filter: [ 'position' ],
23010		run: function() {
23011			this.animate(this.coordinates(this._current));
23012		}
23013	}, {
23014		filter: [ 'width', 'position', 'items', 'settings' ],
23015		run: function() {
23016			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
23017				rtl = this.settings.rtl ? 1 : -1,
23018				padding = this.settings.stagePadding * 2,
23019				begin = this.coordinates(this.current()) + padding,
23020				end = begin + this.width() * rtl,
23021				inner, outer, matches = [], i, n;
23022
23023			for (i = 0, n = this._coordinates.length; i < n; i++) {
23024				inner = this._coordinates[i - 1] || 0;
23025				outer = Math.abs(this._coordinates[i]) + padding * rtl;
23026
23027				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
23028					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
23029					matches.push(i);
23030				}
23031			}
23032
23033			this.$stage.children('.active').removeClass('active');
23034			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
23035
23036			if (this.settings.center) {
23037				this.$stage.children('.center').removeClass('center');
23038				this.$stage.children().eq(this.current()).addClass('center');
23039			}
23040		}
23041	} ];
23042
23043	/**
23044	 * Initializes the carousel.
23045	 * @protected
23046	 */
23047	Owl.prototype.initialize = function() {
23048		this.enter('initializing');
23049		this.trigger('initialize');
23050
23051		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
23052
23053		if (this.settings.autoWidth && !this.is('pre-loading')) {
23054			var imgs, nestedSelector, width;
23055			imgs = this.$element.find('img');
23056			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
23057			width = this.$element.children(nestedSelector).width();
23058
23059			if (imgs.length && width <= 0) {
23060				this.preloadAutoWidthImages(imgs);
23061			}
23062		}
23063
23064		this.$element.addClass(this.options.loadingClass);
23065
23066		// create stage
23067		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
23068			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
23069
23070		// append stage
23071		this.$element.append(this.$stage.parent());
23072
23073		// append content
23074		this.replace(this.$element.children().not(this.$stage.parent()));
23075
23076		// check visibility
23077		if (this.$element.is(':visible')) {
23078			// update view
23079			this.refresh();
23080		} else {
23081			// invalidate width
23082			this.invalidate('width');
23083		}
23084
23085		this.$element
23086			.removeClass(this.options.loadingClass)
23087			.addClass(this.options.loadedClass);
23088
23089		// register event handlers
23090		this.registerEventHandlers();
23091
23092		this.leave('initializing');
23093		this.trigger('initialized');
23094	};
23095
23096	/**
23097	 * Setups the current settings.
23098	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
23099	 * @todo Support for media queries by using `matchMedia` would be nice.
23100	 * @public
23101	 */
23102	Owl.prototype.setup = function() {
23103		var viewport = this.viewport(),
23104			overwrites = this.options.responsive,
23105			match = -1,
23106			settings = null;
23107
23108		if (!overwrites) {
23109			settings = $.extend({}, this.options);
23110		} else {
23111			$.each(overwrites, function(breakpoint) {
23112				if (breakpoint <= viewport && breakpoint > match) {
23113					match = Number(breakpoint);
23114				}
23115			});
23116
23117			settings = $.extend({}, this.options, overwrites[match]);
23118			delete settings.responsive;
23119
23120			// responsive class
23121			if (settings.responsiveClass) {
23122				this.$element.attr('class',
23123					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
23124				);
23125			}
23126		}
23127
23128		if (this.settings === null || this._breakpoint !== match) {
23129			this.trigger('change', { property: { name: 'settings', value: settings } });
23130			this._breakpoint = match;
23131			this.settings = settings;
23132			this.invalidate('settings');
23133			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
23134		}
23135	};
23136
23137	/**
23138	 * Updates option logic if necessery.
23139	 * @protected
23140	 */
23141	Owl.prototype.optionsLogic = function() {
23142		if (this.settings.autoWidth) {
23143			this.settings.stagePadding = false;
23144			this.settings.merge = false;
23145		}
23146	};
23147
23148	/**
23149	 * Prepares an item before add.
23150	 * @todo Rename event parameter `content` to `item`.
23151	 * @protected
23152	 * @returns {jQuery|HTMLElement} - The item container.
23153	 */
23154	Owl.prototype.prepare = function(item, index) {
23155		var event = this.trigger('prepare', { content: item });
23156		if (!event.data) {
23157			event.data = $('<' + this.settings.itemElement + '/>')
23158				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
23159		}
23160
23161		this.trigger('prepared', { content: event.data });
23162
23163		return event.data;
23164	};
23165
23166	/**
23167	 * Updates the view.
23168	 * @public
23169	 */
23170	Owl.prototype.update = function() {
23171		var i = 0,
23172			n = this._pipe.length,
23173			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
23174			cache = {};
23175
23176		while (i < n) {
23177			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
23178				this._pipe[i].run(cache);
23179			}
23180			i++;
23181		}
23182
23183		this._invalidated = {};
23184
23185		!this.is('valid') && this.enter('valid');
23186	};
23187
23188	/**
23189	 * Gets the width of the view.
23190	 * @public
23191	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
23192	 * @returns {Number} - The width of the view in pixel.
23193	 */
23194	Owl.prototype.width = function(dimension) {
23195		dimension = dimension || Owl.Width.Default;
23196		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
23197		switch (dimension) {
23198			case Owl.Width.Inner:
23199			case Owl.Width.Outer:
23200				return this._width;
23201			default:
23202				return this._width - stagePadding * 2 + this.settings.margin;
23203		}
23204	};
23205
23206	/**
23207	 * Refreshes the carousel primarily for adaptive purposes.
23208	 * @public
23209	 */
23210	Owl.prototype.refresh = function() {
23211		this.enter('refreshing');
23212		this.trigger('refresh');
23213
23214		this.setup();
23215
23216		this.optionsLogic();
23217
23218		this.$element.addClass(this.options.refreshClass);
23219
23220		this.update();
23221
23222		this.$element.removeClass(this.options.refreshClass);
23223
23224		this.leave('refreshing');
23225		this.trigger('refreshed');
23226	};
23227
23228	/**
23229	 * Checks window `resize` event.
23230	 * @protected
23231	 */
23232	Owl.prototype.onThrottledResize = function() {
23233		window.clearTimeout(this.resizeTimer);
23234		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
23235	};
23236
23237	/**
23238	 * Checks window `resize` event.
23239	 * @protected
23240	 */
23241	Owl.prototype.onResize = function() {
23242		if (!this._items.length) {
23243			return false;
23244		}
23245
23246		if (this._width === this.$element.width()) {
23247			return false;
23248		}
23249
23250		if (!this.$element.is(':visible')) {
23251			return false;
23252		}
23253
23254		this.enter('resizing');
23255
23256		if (this.trigger('resize').isDefaultPrevented()) {
23257			this.leave('resizing');
23258			return false;
23259		}
23260
23261		this.invalidate('width');
23262
23263		this.refresh();
23264
23265		this.leave('resizing');
23266		this.trigger('resized');
23267	};
23268
23269	/**
23270	 * Registers event handlers.
23271	 * @todo Check `msPointerEnabled`
23272	 * @todo #261
23273	 * @protected
23274	 */
23275	Owl.prototype.registerEventHandlers = function() {
23276		if ($.support.transition) {
23277			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
23278		}
23279
23280		if (this.settings.responsive !== false) {
23281			this.on(window, 'resize', this._handlers.onThrottledResize);
23282		}
23283
23284		if (this.settings.mouseDrag) {
23285			this.$element.addClass(this.options.dragClass);
23286			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
23287			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
23288		}
23289
23290		if (this.settings.touchDrag){
23291			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
23292			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
23293		}
23294	};
23295
23296	/**
23297	 * Handles `touchstart` and `mousedown` events.
23298	 * @todo Horizontal swipe threshold as option
23299	 * @todo #261
23300	 * @protected
23301	 * @param {Event} event - The event arguments.
23302	 */
23303	Owl.prototype.onDragStart = function(event) {
23304		var stage = null;
23305
23306		if (event.which === 3) {
23307			return;
23308		}
23309
23310		if ($.support.transform) {
23311			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
23312			stage = {
23313				x: stage[stage.length === 16 ? 12 : 4],
23314				y: stage[stage.length === 16 ? 13 : 5]
23315			};
23316		} else {
23317			stage = this.$stage.position();
23318			stage = {
23319				x: this.settings.rtl ?
23320					stage.left + this.$stage.width() - this.width() + this.settings.margin :
23321					stage.left,
23322				y: stage.top
23323			};
23324		}
23325
23326		if (this.is('animating')) {
23327			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
23328			this.invalidate('position');
23329		}
23330
23331		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
23332
23333		this.speed(0);
23334
23335		this._drag.time = new Date().getTime();
23336		this._drag.target = $(event.target);
23337		this._drag.stage.start = stage;
23338		this._drag.stage.current = stage;
23339		this._drag.pointer = this.pointer(event);
23340
23341		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
23342
23343		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
23344			var delta = this.difference(this._drag.pointer, this.pointer(event));
23345
23346			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
23347
23348			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
23349				return;
23350			}
23351
23352			event.preventDefault();
23353
23354			this.enter('dragging');
23355			this.trigger('drag');
23356		}, this));
23357	};
23358
23359	/**
23360	 * Handles the `touchmove` and `mousemove` events.
23361	 * @todo #261
23362	 * @protected
23363	 * @param {Event} event - The event arguments.
23364	 */
23365	Owl.prototype.onDragMove = function(event) {
23366		var minimum = null,
23367			maximum = null,
23368			pull = null,
23369			delta = this.difference(this._drag.pointer, this.pointer(event)),
23370			stage = this.difference(this._drag.stage.start, delta);
23371
23372		if (!this.is('dragging')) {
23373			return;
23374		}
23375
23376		event.preventDefault();
23377
23378		if (this.settings.loop) {
23379			minimum = this.coordinates(this.minimum());
23380			maximum = this.coordinates(this.maximum() + 1) - minimum;
23381			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
23382		} else {
23383			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
23384			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
23385			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
23386			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
23387		}
23388
23389		this._drag.stage.current = stage;
23390
23391		this.animate(stage.x);
23392	};
23393
23394	/**
23395	 * Handles the `touchend` and `mouseup` events.
23396	 * @todo #261
23397	 * @todo Threshold for click event
23398	 * @protected
23399	 * @param {Event} event - The event arguments.
23400	 */
23401	Owl.prototype.onDragEnd = function(event) {
23402		var delta = this.difference(this._drag.pointer, this.pointer(event)),
23403			stage = this._drag.stage.current,
23404			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
23405
23406		$(document).off('.owl.core');
23407
23408		this.$element.removeClass(this.options.grabClass);
23409
23410		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
23411			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
23412			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
23413			this.invalidate('position');
23414			this.update();
23415
23416			this._drag.direction = direction;
23417
23418			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
23419				this._drag.target.one('click.owl.core', function() { return false; });
23420			}
23421		}
23422
23423		if (!this.is('dragging')) {
23424			return;
23425		}
23426
23427		this.leave('dragging');
23428		this.trigger('dragged');
23429	};
23430
23431	/**
23432	 * Gets absolute position of the closest item for a coordinate.
23433	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
23434	 * @protected
23435	 * @param {Number} coordinate - The coordinate in pixel.
23436	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
23437	 * @return {Number} - The absolute position of the closest item.
23438	 */
23439	Owl.prototype.closest = function(coordinate, direction) {
23440		var position = -1,
23441			pull = 30,
23442			width = this.width(),
23443			coordinates = this.coordinates();
23444
23445		if (!this.settings.freeDrag) {
23446			// check closest item
23447			$.each(coordinates, $.proxy(function(index, value) {
23448				if (coordinate > value - pull && coordinate < value + pull) {
23449					position = index;
23450				} else if (this.op(coordinate, '<', value)
23451					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
23452					position = direction === 'left' ? index + 1 : index;
23453				}
23454				return position === -1;
23455			}, this));
23456		}
23457
23458		if (!this.settings.loop) {
23459			// non loop boundries
23460			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
23461				position = coordinate = this.minimum();
23462			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
23463				position = coordinate = this.maximum();
23464			}
23465		}
23466
23467		return position;
23468	};
23469
23470	/**
23471	 * Animates the stage.
23472	 * @todo #270
23473	 * @public
23474	 * @param {Number} coordinate - The coordinate in pixels.
23475	 */
23476	Owl.prototype.animate = function(coordinate) {
23477		var animate = this.speed() > 0;
23478
23479		this.is('animating') && this.onTransitionEnd();
23480
23481		if (animate) {
23482			this.enter('animating');
23483			this.trigger('translate');
23484		}
23485
23486		if ($.support.transform3d && $.support.transition) {
23487			this.$stage.css({
23488				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
23489				transition: (this.speed() / 1000) + 's'
23490			});
23491		} else if (animate) {
23492			this.$stage.animate({
23493				left: coordinate + 'px'
23494			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
23495		} else {
23496			this.$stage.css({
23497				left: coordinate + 'px'
23498			});
23499		}
23500	};
23501
23502	/**
23503	 * Checks whether the carousel is in a specific state or not.
23504	 * @param {String} state - The state to check.
23505	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
23506	 */
23507	Owl.prototype.is = function(state) {
23508		return this._states.current[state] && this._states.current[state] > 0;
23509	};
23510
23511	/**
23512	 * Sets the absolute position of the current item.
23513	 * @public
23514	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
23515	 * @returns {Number} - The absolute position of the current item.
23516	 */
23517	Owl.prototype.current = function(position) {
23518		if (position === undefined) {
23519			return this._current;
23520		}
23521
23522		if (this._items.length === 0) {
23523			return undefined;
23524		}
23525
23526		position = this.normalize(position);
23527
23528		if (this._current !== position) {
23529			var event = this.trigger('change', { property: { name: 'position', value: position } });
23530
23531			if (event.data !== undefined) {
23532				position = this.normalize(event.data);
23533			}
23534
23535			this._current = position;
23536
23537			this.invalidate('position');
23538
23539			this.trigger('changed', { property: { name: 'position', value: this._current } });
23540		}
23541
23542		return this._current;
23543	};
23544
23545	/**
23546	 * Invalidates the given part of the update routine.
23547	 * @param {String} [part] - The part to invalidate.
23548	 * @returns {Array.<String>} - The invalidated parts.
23549	 */
23550	Owl.prototype.invalidate = function(part) {
23551		if ($.type(part) === 'string') {
23552			this._invalidated[part] = true;
23553			this.is('valid') && this.leave('valid');
23554		}
23555		return $.map(this._invalidated, function(v, i) { return i });
23556	};
23557
23558	/**
23559	 * Resets the absolute position of the current item.
23560	 * @public
23561	 * @param {Number} position - The absolute position of the new item.
23562	 */
23563	Owl.prototype.reset = function(position) {
23564		position = this.normalize(position);
23565
23566		if (position === undefined) {
23567			return;
23568		}
23569
23570		this._speed = 0;
23571		this._current = position;
23572
23573		this.suppress([ 'translate', 'translated' ]);
23574
23575		this.animate(this.coordinates(position));
23576
23577		this.release([ 'translate', 'translated' ]);
23578	};
23579
23580	/**
23581	 * Normalizes an absolute or a relative position of an item.
23582	 * @public
23583	 * @param {Number} position - The absolute or relative position to normalize.
23584	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
23585	 * @returns {Number} - The normalized position.
23586	 */
23587	Owl.prototype.normalize = function(position, relative) {
23588		var n = this._items.length,
23589			m = relative ? 0 : this._clones.length;
23590
23591		if (!$.isNumeric(position) || n < 1) {
23592			position = undefined;
23593		} else if (position < 0 || position >= n + m) {
23594			position = ((position - m / 2) % n + n) % n + m / 2;
23595		}
23596
23597		return position;
23598	};
23599
23600	/**
23601	 * Converts an absolute position of an item into a relative one.
23602	 * @public
23603	 * @param {Number} position - The absolute position to convert.
23604	 * @returns {Number} - The converted position.
23605	 */
23606	Owl.prototype.relative = function(position) {
23607		position -= this._clones.length / 2;
23608		return this.normalize(position, true);
23609	};
23610
23611	/**
23612	 * Gets the maximum position for the current item.
23613	 * @public
23614	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23615	 * @returns {Number}
23616	 */
23617	Owl.prototype.maximum = function(relative) {
23618		var settings = this.settings,
23619			maximum = this._coordinates.length,
23620			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
23621			i = -1, j;
23622
23623		if (settings.loop) {
23624			maximum = this._clones.length / 2 + this._items.length - 1;
23625		} else if (settings.autoWidth || settings.merge) {
23626			// binary search
23627			while (maximum - i > 1) {
23628				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
23629					? i = j : maximum = j;
23630			}
23631		} else if (settings.center) {
23632			maximum = this._items.length - 1;
23633		} else {
23634			maximum = this._items.length - settings.items;
23635		}
23636
23637		if (relative) {
23638			maximum -= this._clones.length / 2;
23639		}
23640
23641		return Math.max(maximum, 0);
23642	};
23643
23644	/**
23645	 * Gets the minimum position for the current item.
23646	 * @public
23647	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23648	 * @returns {Number}
23649	 */
23650	Owl.prototype.minimum = function(relative) {
23651		return relative ? 0 : this._clones.length / 2;
23652	};
23653
23654	/**
23655	 * Gets an item at the specified relative position.
23656	 * @public
23657	 * @param {Number} [position] - The relative position of the item.
23658	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23659	 */
23660	Owl.prototype.items = function(position) {
23661		if (position === undefined) {
23662			return this._items.slice();
23663		}
23664
23665		position = this.normalize(position, true);
23666		return this._items[position];
23667	};
23668
23669	/**
23670	 * Gets an item at the specified relative position.
23671	 * @public
23672	 * @param {Number} [position] - The relative position of the item.
23673	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23674	 */
23675	Owl.prototype.mergers = function(position) {
23676		if (position === undefined) {
23677			return this._mergers.slice();
23678		}
23679
23680		position = this.normalize(position, true);
23681		return this._mergers[position];
23682	};
23683
23684	/**
23685	 * Gets the absolute positions of clones for an item.
23686	 * @public
23687	 * @param {Number} [position] - The relative position of the item.
23688	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
23689	 */
23690	Owl.prototype.clones = function(position) {
23691		var odd = this._clones.length / 2,
23692			even = odd + this._items.length,
23693			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
23694
23695		if (position === undefined) {
23696			return $.map(this._clones, function(v, i) { return map(i) });
23697		}
23698
23699		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
23700	};
23701
23702	/**
23703	 * Sets the current animation speed.
23704	 * @public
23705	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
23706	 * @returns {Number} - The current animation speed in milliseconds.
23707	 */
23708	Owl.prototype.speed = function(speed) {
23709		if (speed !== undefined) {
23710			this._speed = speed;
23711		}
23712
23713		return this._speed;
23714	};
23715
23716	/**
23717	 * Gets the coordinate of an item.
23718	 * @todo The name of this method is missleanding.
23719	 * @public
23720	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
23721	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
23722	 */
23723	Owl.prototype.coordinates = function(position) {
23724		var coordinate = null;
23725
23726		if (position === undefined) {
23727			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
23728				return this.coordinates(index);
23729			}, this));
23730		}
23731
23732		if (this.settings.center) {
23733			coordinate = this._coordinates[position];
23734			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
23735		} else {
23736			coordinate = this._coordinates[position - 1] || 0;
23737		}
23738
23739		return coordinate;
23740	};
23741
23742	/**
23743	 * Calculates the speed for a translation.
23744	 * @protected
23745	 * @param {Number} from - The absolute position of the start item.
23746	 * @param {Number} to - The absolute position of the target item.
23747	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
23748	 * @returns {Number} - The time in milliseconds for the translation.
23749	 */
23750	Owl.prototype.duration = function(from, to, factor) {
23751		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
23752	};
23753
23754	/**
23755	 * Slides to the specified item.
23756	 * @public
23757	 * @param {Number} position - The position of the item.
23758	 * @param {Number} [speed] - The time in milliseconds for the transition.
23759	 */
23760	Owl.prototype.to = function(position, speed) {
23761		var current = this.current(),
23762			revert = null,
23763			distance = position - this.relative(current),
23764			direction = (distance > 0) - (distance < 0),
23765			items = this._items.length,
23766			minimum = this.minimum(),
23767			maximum = this.maximum();
23768
23769		if (this.settings.loop) {
23770			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
23771				distance += direction * -1 * items;
23772			}
23773
23774			position = current + distance;
23775			revert = ((position - minimum) % items + items) % items + minimum;
23776
23777			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
23778				current = revert - distance;
23779				position = revert;
23780				this.reset(current);
23781			}
23782		} else if (this.settings.rewind) {
23783			maximum += 1;
23784			position = (position % maximum + maximum) % maximum;
23785		} else {
23786			position = Math.max(minimum, Math.min(maximum, position));
23787		}
23788
23789		this.speed(this.duration(current, position, speed));
23790		this.current(position);
23791
23792		if (this.$element.is(':visible')) {
23793			this.update();
23794		}
23795	};
23796
23797	/**
23798	 * Slides to the next item.
23799	 * @public
23800	 * @param {Number}
vendor: 12,284 bytes, lines 23800-24220
23800 [speed] - The time in milliseconds for the transition.
23801	 */
23802	Owl.prototype.next = function(speed) {
23803		speed = speed || false;
23804		this.to(this.relative(this.current()) + 1, speed);
23805	};
23806
23807	/**
23808	 * Slides to the previous item.
23809	 * @public
23810	 * @param {Number} [speed] - The time in milliseconds for the transition.
23811	 */
23812	Owl.prototype.prev = function(speed) {
23813		speed = speed || false;
23814		this.to(this.relative(this.current()) - 1, speed);
23815	};
23816
23817	/**
23818	 * Handles the end of an animation.
23819	 * @protected
23820	 * @param {Event} event - The event arguments.
23821	 */
23822	Owl.prototype.onTransitionEnd = function(event) {
23823
23824		// if css2 animation then event object is undefined
23825		if (event !== undefined) {
23826			event.stopPropagation();
23827
23828			// Catch only owl-stage transitionEnd event
23829			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
23830				return false;
23831			}
23832		}
23833
23834		this.leave('animating');
23835		this.trigger('translated');
23836	};
23837
23838	/**
23839	 * Gets viewport width.
23840	 * @protected
23841	 * @return {Number} - The width in pixel.
23842	 */
23843	Owl.prototype.viewport = function() {
23844		var width;
23845		if (this.options.responsiveBaseElement !== window) {
23846			width = $(this.options.responsiveBaseElement).width();
23847		} else if (window.innerWidth) {
23848			width = window.innerWidth;
23849		} else if (document.documentElement && document.documentElement.clientWidth) {
23850			width = document.documentElement.clientWidth;
23851		} else {
23852			throw 'Can not detect viewport width.';
23853		}
23854
23855		return width;
23856	};
23857
23858	/**
23859	 * Replaces the current content.
23860	 * @public
23861	 * @param {HTMLElement|jQuery|String} content - The new content.
23862	 */
23863	Owl.prototype.replace = function(content) {
23864		this.$stage.empty();
23865		this._items = [];
23866
23867		if (content) {
23868			content = (content instanceof jQuery) ? content : $(content);
23869		}
23870
23871		if (this.settings.nestedItemSelector) {
23872			content = content.find('.' + this.settings.nestedItemSelector);
23873		}
23874
23875		content.filter(function() {
23876			return this.nodeType === 1;
23877		}).each($.proxy(function(index, item) {
23878			item = this.prepare(item, index);
23879			this.$stage.append(item);
23880			this._items.push(item);
23881			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
23882		}, this));
23883
23884		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
23885
23886		this.invalidate('items');
23887	};
23888
23889	/**
23890	 * Adds an item.
23891	 * @todo Use `item` instead of `content` for the event arguments.
23892	 * @public
23893	 * @param {HTMLElement|jQuery|String} content - The item content to add.
23894	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
23895	 */
23896	Owl.prototype.add = function(content, position) {
23897		var current = this.relative(this._current);
23898
23899		position = position === undefined ? this._items.length : this.normalize(position, true);
23900		content = content instanceof jQuery ? content : $(content);
23901
23902		this.trigger('add', { content: content, position: position });
23903
23904		content = this.prepare(content, this._items[current].index());
23905
23906		if (this._items.length === 0 || position === this._items.length) {
23907			this._items.length === 0 && this.$stage.append(content);
23908			this._items.length !== 0 && this._items[position - 1].after(content);
23909			this._items.push(content);
23910			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23911		} else {
23912			this._items[position].before(content);
23913			this._items.splice(position, 0, content);
23914			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23915		}
23916
23917		this._items[current] && this.reset(this._items[current].index());
23918
23919		this.invalidate('items');
23920
23921		this.trigger('added', { content: content, position: position });
23922	};
23923
23924	/**
23925	 * Removes an item by its position.
23926	 * @todo Use `item` instead of `content` for the event arguments.
23927	 * @public
23928	 * @param {Number} position - The relative position of the item to remove.
23929	 */
23930	Owl.prototype.remove = function(position) {
23931		position = this.normalize(position, true);
23932
23933		if (position === undefined) {
23934			return;
23935		}
23936
23937		this.trigger('remove', { content: this._items[position], position: position });
23938
23939		this._items[position].remove();
23940		this._items.splice(position, 1);
23941		this._mergers.splice(position, 1);
23942
23943		this.invalidate('items');
23944
23945		this.trigger('removed', { content: null, position: position });
23946	};
23947
23948	/**
23949	 * Preloads images with auto width.
23950	 * @todo Replace by a more generic approach
23951	 * @protected
23952	 */
23953	Owl.prototype.preloadAutoWidthImages = function(images) {
23954		images.each($.proxy(function(i, element) {
23955			this.enter('pre-loading');
23956			element = $(element);
23957			$(new Image()).one('load', $.proxy(function(e) {
23958				element.attr('src', e.target.src);
23959				element.css('opacity', 1);
23960				this.leave('pre-loading');
23961				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23962			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23963		}, this));
23964	};
23965
23966	/**
23967	 * Destroys the carousel.
23968	 * @public
23969	 */
23970	Owl.prototype.destroy = function() {
23971
23972		this.$element.off('.owl.core');
23973		this.$stage.off('.owl.core');
23974		$(document).off('.owl.core');
23975
23976		if (this.settings.responsive !== false) {
23977			window.clearTimeout(this.resizeTimer);
23978			this.off(window, 'resize', this._handlers.onThrottledResize);
23979		}
23980
23981		for (var i in this._plugins) {
23982			this._plugins[i].destroy();
23983		}
23984
23985		this.$stage.children('.cloned').remove();
23986
23987		this.$stage.unwrap();
23988		this.$stage.children().contents().unwrap();
23989		this.$stage.children().unwrap();
23990
23991		this.$element
23992			.removeClass(this.options.refreshClass)
23993			.removeClass(this.options.loadingClass)
23994			.removeClass(this.options.loadedClass)
23995			.removeClass(this.options.rtlClass)
23996			.removeClass(this.options.dragClass)
23997			.removeClass(this.options.grabClass)
23998			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
23999			.removeData('owl.carousel');
24000	};
24001
24002	/**
24003	 * Operators to calculate right-to-left and left-to-right.
24004	 * @protected
24005	 * @param {Number} [a] - The left side operand.
24006	 * @param {String} [o] - The operator.
24007	 * @param {Number} [b] - The right side operand.
24008	 */
24009	Owl.prototype.op = function(a, o, b) {
24010		var rtl = this.settings.rtl;
24011		switch (o) {
24012			case '<':
24013				return rtl ? a > b : a < b;
24014			case '>':
24015				return rtl ? a < b : a > b;
24016			case '>=':
24017				return rtl ? a <= b : a >= b;
24018			case '<=':
24019				return rtl ? a >= b : a <= b;
24020			default:
24021				break;
24022		}
24023	};
24024
24025	/**
24026	 * Attaches to an internal event.
24027	 * @protected
24028	 * @param {HTMLElement} element - The event source.
24029	 * @param {String} event - The event name.
24030	 * @param {Function} listener - The event handler to attach.
24031	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
24032	 */
24033	Owl.prototype.on = function(element, event, listener, capture) {
24034		if (element.addEventListener) {
24035			element.addEventListener(event, listener, capture);
24036		} else if (element.attachEvent) {
24037			element.attachEvent('on' + event, listener);
24038		}
24039	};
24040
24041	/**
24042	 * Detaches from an internal event.
24043	 * @protected
24044	 * @param {HTMLElement} element - The event source.
24045	 * @param {String} event - The event name.
24046	 * @param {Function} listener - The attached event handler to detach.
24047	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
24048	 */
24049	Owl.prototype.off = function(element, event, listener, capture) {
24050		if (element.removeEventListener) {
24051			element.removeEventListener(event, listener, capture);
24052		} else if (element.detachEvent) {
24053			element.detachEvent('on' + event, listener);
24054		}
24055	};
24056
24057	/**
24058	 * Triggers a public event.
24059	 * @todo Remove `status`, `relatedTarget` should be used instead.
24060	 * @protected
24061	 * @param {String} name - The event name.
24062	 * @param {*} [data=null] - The event data.
24063	 * @param {String} [namespace=carousel] - The event namespace.
24064	 * @param {String} [state] - The state which is associated with the event.
24065	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
24066	 * @returns {Event} - The event arguments.
24067	 */
24068	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
24069		var status = {
24070			item: { count: this._items.length, index: this.current() }
24071		}, handler = $.camelCase(
24072			$.grep([ 'on', name, namespace ], function(v) { return v })
24073				.join('-').toLowerCase()
24074		), event = $.Event(
24075			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
24076			$.extend({ relatedTarget: this }, status, data)
24077		);
24078
24079		if (!this._supress[name]) {
24080			$.each(this._plugins, function(name, plugin) {
24081				if (plugin.onTrigger) {
24082					plugin.onTrigger(event);
24083				}
24084			});
24085
24086			this.register({ type: Owl.Type.Event, name: name });
24087			this.$element.trigger(event);
24088
24089			if (this.settings && typeof this.settings[handler] === 'function') {
24090				this.settings[handler].call(this, event);
24091			}
24092		}
24093
24094		return event;
24095	};
24096
24097	/**
24098	 * Enters a state.
24099	 * @param name - The state name.
24100	 */
24101	Owl.prototype.enter = function(name) {
24102		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24103			if (this._states.current[name] === undefined) {
24104				this._states.current[name] = 0;
24105			}
24106
24107			this._states.current[name]++;
24108		}, this));
24109	};
24110
24111	/**
24112	 * Leaves a state.
24113	 * @param name - The state name.
24114	 */
24115	Owl.prototype.leave = function(name) {
24116		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24117			this._states.current[name]--;
24118		}, this));
24119	};
24120
24121	/**
24122	 * Registers an event or state.
24123	 * @public
24124	 * @param {Object} object - The event or state to register.
24125	 */
24126	Owl.prototype.register = function(object) {
24127		if (object.type === Owl.Type.Event) {
24128			if (!$.event.special[object.name]) {
24129				$.event.special[object.name] = {};
24130			}
24131
24132			if (!$.event.special[object.name].owl) {
24133				var _default = $.event.special[object.name]._default;
24134				$.event.special[object.name]._default = function(e) {
24135					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
24136						return _default.apply(this, arguments);
24137					}
24138					return e.namespace && e.namespace.indexOf('owl') > -1;
24139				};
24140				$.event.special[object.name].owl = true;
24141			}
24142		} else if (object.type === Owl.Type.State) {
24143			if (!this._states.tags[object.name]) {
24144				this._states.tags[object.name] = object.tags;
24145			} else {
24146				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
24147			}
24148
24149			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
24150				return $.inArray(tag, this._states.tags[object.name]) === i;
24151			}, this));
24152		}
24153	};
24154
24155	/**
24156	 * Suppresses events.
24157	 * @protected
24158	 * @param {Array.<String>} events - The events to suppress.
24159	 */
24160	Owl.prototype.suppress = function(events) {
24161		$.each(events, $.proxy(function(index, event) {
24162			this._supress[event] = true;
24163		}, this));
24164	};
24165
24166	/**
24167	 * Releases suppressed events.
24168	 * @protected
24169	 * @param {Array.<String>} events - The events to release.
24170	 */
24171	Owl.prototype.release = function(events) {
24172		$.each(events, $.proxy(function(index, event) {
24173			delete this._supress[event];
24174		}, this));
24175	};
24176
24177	/**
24178	 * Gets unified pointer coordinates from event.
24179	 * @todo #261
24180	 * @protected
24181	 * @param {Event} - The `mousedown` or `touchstart` event.
24182	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
24183	 */
24184	Owl.prototype.pointer = function(event) {
24185		var result = { x: null, y: null };
24186
24187		event = event.originalEvent || event || window.event;
24188
24189		event = event.touches && event.touches.length ?
24190			event.touches[0] : event.changedTouches && event.changedTouches.length ?
24191				event.changedTouches[0] : event;
24192
24193		if (event.pageX) {
24194			result.x = event.pageX;
24195			result.y = event.pageY;
24196		} else {
24197			result.x = event.clientX;
24198			result.y = event.clientY;
24199		}
24200
24201		return result;
24202	};
24203
24204	/**
24205	 * Gets the difference of two vectors.
24206	 * @todo #261
24207	 * @protected
24208	 * @param {Object} - The first vector.
24209	 * @param {Object} - The second vector.
24210	 * @returns {Object} - The difference.
24211	 */
24212	Owl.prototype.difference = function(first, second) {
24213		return {
24214			x: first.x - second.x,
24215			y: first.y - second.y
24216		};
24217	};
24218
24219	/**
24220	 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 24221-25503
24221	 * @todo Navigation plugin `next` and `prev`
24222	 * @public
24223	 */
24224	$.fn.owlCarousel = function(option) {
24225		var args = Array.prototype.slice.call(arguments, 1);
24226
24227		return this.each(function() {
24228			var $this = $(this),
24229				data = $this.data('owl.carousel');
24230
24231			if (!data) {
24232				data = new Owl(this, typeof option == 'object' && option);
24233				$this.data('owl.carousel', data);
24234
24235				$.each([
24236					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
24237				], function(i, event) {
24238					data.register({ type: Owl.Type.Event, name: event });
24239					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
24240						if (e.namespace && e.relatedTarget !== this) {
24241							this.suppress([ event ]);
24242							data[event].apply(this, [].slice.call(arguments, 1));
24243							this.release([ event ]);
24244						}
24245					}, data));
24246				});
24247			}
24248
24249			if (typeof option == 'string' && option.charAt(0) !== '_') {
24250				data[option].apply(data, args);
24251			}
24252		});
24253	};
24254
24255	/**
24256	 * The constructor for the jQuery Plugin
24257	 * @public
24258	 */
24259	$.fn.owlCarousel.Constructor = Owl;
24260
24261})(window.Zepto || window.jQuery, window, document);
24262
24263/**
24264 * AutoRefresh Plugin
24265 * @version 2.0.0-beta.3
24266 * @author Artus Kolanowski
24267 * @license The MIT License (MIT)
24268 */
24269;(function($, window, document, undefined) {
24270
24271	/**
24272	 * Creates the auto refresh plugin.
24273	 * @class The Auto Refresh Plugin
24274	 * @param {Owl} carousel - The Owl Carousel
24275	 */
24276	var AutoRefresh = function(carousel) {
24277		/**
24278		 * Reference to the core.
24279		 * @protected
24280		 * @type {Owl}
24281		 */
24282		this._core = carousel;
24283
24284		/**
24285		 * Refresh interval.
24286		 * @protected
24287		 * @type {number}
24288		 */
24289		this._interval = null;
24290
24291		/**
24292		 * Whether the element is currently visible or not.
24293		 * @protected
24294		 * @type {Boolean}
24295		 */
24296		this._visible = null;
24297
24298		/**
24299		 * All event handlers.
24300		 * @protected
24301		 * @type {Object}
24302		 */
24303		this._handlers = {
24304			'initialized.owl.carousel': $.proxy(function(e) {
24305				if (e.namespace && this._core.settings.autoRefresh) {
24306					this.watch();
24307				}
24308			}, this)
24309		};
24310
24311		// set default options
24312		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
24313
24314		// register event handlers
24315		this._core.$element.on(this._handlers);
24316	};
24317
24318	/**
24319	 * Default options.
24320	 * @public
24321	 */
24322	AutoRefresh.Defaults = {
24323		autoRefresh: true,
24324		autoRefreshInterval: 500
24325	};
24326
24327	/**
24328	 * Watches the element.
24329	 */
24330	AutoRefresh.prototype.watch = function() {
24331		if (this._interval) {
24332			return;
24333		}
24334
24335		this._visible = this._core.$element.is(':visible');
24336		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
24337	};
24338
24339	/**
24340	 * Refreshes the element.
24341	 */
24342	AutoRefresh.prototype.refresh = function() {
24343		if (this._core.$element.is(':visible') === this._visible) {
24344			return;
24345		}
24346
24347		this._visible = !this._visible;
24348
24349		this._core.$element.toggleClass('owl-hidden', !this._visible);
24350
24351		this._visible && (this._core.invalidate('width') && this._core.refresh());
24352	};
24353
24354	/**
24355	 * Destroys the plugin.
24356	 */
24357	AutoRefresh.prototype.destroy = function() {
24358		var handler, property;
24359
24360		window.clearInterval(this._interval);
24361
24362		for (handler in this._handlers) {
24363			this._core.$element.off(handler, this._handlers[handler]);
24364		}
24365		for (property in Object.getOwnPropertyNames(this)) {
24366			typeof this[property] != 'function' && (this[property] = null);
24367		}
24368	};
24369
24370	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
24371
24372})(window.Zepto || window.jQuery, window, document);
24373
24374/**
24375 * Lazy Plugin
24376 * @version 2.0.0-beta.3
24377 * @author Bartosz Wojciechowski
24378 * @license The MIT License (MIT)
24379 */
24380;(function($, window, document, undefined) {
24381
24382	/**
24383	 * Creates the lazy plugin.
24384	 * @class The Lazy Plugin
24385	 * @param {Owl} carousel - The Owl Carousel
24386	 */
24387	var Lazy = function(carousel) {
24388
24389		/**
24390		 * Reference to the core.
24391		 * @protected
24392		 * @type {Owl}
24393		 */
24394		this._core = carousel;
24395
24396		/**
24397		 * Already loaded items.
24398		 * @protected
24399		 * @type {Array.<jQuery>}
24400		 */
24401		this._loaded = [];
24402
24403		/**
24404		 * Event handlers.
24405		 * @protected
24406		 * @type {Object}
24407		 */
24408		this._handlers = {
24409			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
24410				if (!e.namespace) {
24411					return;
24412				}
24413
24414				if (!this._core.settings || !this._core.settings.lazyLoad) {
24415					return;
24416				}
24417
24418				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
24419					var settings = this._core.settings,
24420						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
24421						i = ((settings.center && n * -1) || 0),
24422						position = ((e.property && e.property.value) || this._core.current()) + i,
24423						clones = this._core.clones().length,
24424						load = $.proxy(function(i, v) { this.load(v) }, this);
24425
24426					while (i++ < n) {
24427						this.load(clones / 2 + this._core.relative(position));
24428						clones && $.each(this._core.clones(this._core.relative(position)), load);
24429						position++;
24430					}
24431				}
24432			}, this)
24433		};
24434
24435		// set the default options
24436		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
24437
24438		// register event handler
24439		this._core.$element.on(this._handlers);
24440	}
24441
24442	/**
24443	 * Default options.
24444	 * @public
24445	 */
24446	Lazy.Defaults = {
24447		lazyLoad: false
24448	}
24449
24450	/**
24451	 * Loads all resources of an item at the specified position.
24452	 * @param {Number} position - The absolute position of the item.
24453	 * @protected
24454	 */
24455	Lazy.prototype.load = function(position) {
24456		var $item = this._core.$stage.children().eq(position),
24457			$elements = $item && $item.find('.owl-lazy');
24458
24459		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
24460			return;
24461		}
24462
24463		$elements.each($.proxy(function(index, element) {
24464			var $element = $(element), image,
24465				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
24466
24467			this._core.trigger('load', { element: $element, url: url }, 'lazy');
24468
24469			if ($element.is('img')) {
24470				$element.one('load.owl.lazy', $.proxy(function() {
24471					$element.css('opacity', 1);
24472					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24473				}, this)).attr('src', url);
24474			} else {
24475				image = new Image();
24476				image.onload = $.proxy(function() {
24477					$element.css({
24478						'background-image': 'url(' + url + ')',
24479						'opacity': '1'
24480					});
24481					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24482				}, this);
24483				image.src = url;
24484			}
24485		}, this));
24486
24487		this._loaded.push($item.get(0));
24488	}
24489
24490	/**
24491	 * Destroys the plugin.
24492	 * @public
24493	 */
24494	Lazy.prototype.destroy = function() {
24495		var handler, property;
24496
24497		for (handler in this.handlers) {
24498			this._core.$element.off(handler, this.handlers[handler]);
24499		}
24500		for (property in Object.getOwnPropertyNames(this)) {
24501			typeof this[property] != 'function' && (this[property] = null);
24502		}
24503	};
24504
24505	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
24506
24507})(window.Zepto || window.jQuery, window, document);
24508
24509/**
24510 * AutoHeight Plugin
24511 * @version 2.0.0-beta.3
24512 * @author Bartosz Wojciechowski
24513 * @license The MIT License (MIT)
24514 */
24515;(function($, window, document, undefined) {
24516
24517	/**
24518	 * Creates the auto height plugin.
24519	 * @class The Auto Height Plugin
24520	 * @param {Owl} carousel - The Owl Carousel
24521	 */
24522	var AutoHeight = function(carousel) {
24523		/**
24524		 * Reference to the core.
24525		 * @protected
24526		 * @type {Owl}
24527		 */
24528		this._core = carousel;
24529
24530		/**
24531		 * All event handlers.
24532		 * @protected
24533		 * @type {Object}
24534		 */
24535		this._handlers = {
24536			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
24537				if (e.namespace && this._core.settings.autoHeight) {
24538					this.update();
24539				}
24540			}, this),
24541			'changed.owl.carousel': $.proxy(function(e) {
24542				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
24543					this.update();
24544				}
24545			}, this),
24546			'loaded.owl.lazy': $.proxy(function(e) {
24547				if (e.namespace && this._core.settings.autoHeight
24548					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
24549					this.update();
24550				}
24551			}, this)
24552		};
24553
24554		// set default options
24555		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
24556
24557		// register event handlers
24558		this._core.$element.on(this._handlers);
24559	};
24560
24561	/**
24562	 * Default options.
24563	 * @public
24564	 */
24565	AutoHeight.Defaults = {
24566		autoHeight: false,
24567		autoHeightClass: 'owl-height'
24568	};
24569
24570	/**
24571	 * Updates the view.
24572	 */
24573	AutoHeight.prototype.update = function() {
24574		var start = this._core._current,
24575			end = start + this._core.settings.items,
24576			visible = this._core.$stage.children().toArray().slice(start, end);
24577			heights = [],
24578			maxheight = 0;
24579
24580		$.each(visible, function(index, item) {
24581			heights.push($(item).height());
24582		});
24583
24584		maxheight = Math.max.apply(null, heights);
24585
24586		this._core.$stage.parent()
24587			.height(maxheight)
24588			.addClass(this._core.settings.autoHeightClass);
24589	};
24590
24591	AutoHeight.prototype.destroy = function() {
24592		var handler, property;
24593
24594		for (handler in this._handlers) {
24595			this._core.$element.off(handler, this._handlers[handler]);
24596		}
24597		for (property in Object.getOwnPropertyNames(this)) {
24598			typeof this[property] != 'function' && (this[property] = null);
24599		}
24600	};
24601
24602	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
24603
24604})(window.Zepto || window.jQuery, window, document);
24605
24606/**
24607 * Video Plugin
24608 * @version 2.0.0-beta.3
24609 * @author Bartosz Wojciechowski
24610 * @license The MIT License (MIT)
24611 */
24612;(function($, window, document, undefined) {
24613
24614	/**
24615	 * Creates the video plugin.
24616	 * @class The Video Plugin
24617	 * @param {Owl} carousel - The Owl Carousel
24618	 */
24619	var Video = function(carousel) {
24620		/**
24621		 * Reference to the core.
24622		 * @protected
24623		 * @type {Owl}
24624		 */
24625		this._core = carousel;
24626
24627		/**
24628		 * Cache all video URLs.
24629		 * @protected
24630		 * @type {Object}
24631		 */
24632		this._videos = {};
24633
24634		/**
24635		 * Current playing item.
24636		 * @protected
24637		 * @type {jQuery}
24638		 */
24639		this._playing = null;
24640
24641		/**
24642		 * All event handlers.
24643		 * @todo The cloned content removale is too late
24644		 * @protected
24645		 * @type {Object}
24646		 */
24647		this._handlers = {
24648			'initialized.owl.carousel': $.proxy(function(e) {
24649				if (e.namespace) {
24650					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
24651				}
24652			}, this),
24653			'resize.owl.carousel': $.proxy(function(e) {
24654				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
24655					e.preventDefault();
24656				}
24657			}, this),
24658			'refreshed.owl.carousel': $.proxy(function(e) {
24659				if (e.namespace && this._core.is('resizing')) {
24660					this._core.$stage.find('.cloned .owl-video-frame').remove();
24661				}
24662			}, this),
24663			'changed.owl.carousel': $.proxy(function(e) {
24664				if (e.namespace && e.property.name === 'position' && this._playing) {
24665					this.stop();
24666				}
24667			}, this),
24668			'prepared.owl.carousel': $.proxy(function(e) {
24669				if (!e.namespace) {
24670					return;
24671				}
24672
24673				var $element = $(e.content).find('.owl-video');
24674
24675				if ($element.length) {
24676					$element.css('display', 'none');
24677					this.fetch($element, $(e.content));
24678				}
24679			}, this)
24680		};
24681
24682		// set default options
24683		this._core.options = $.extend({}, Video.Defaults, this._core.options);
24684
24685		// register event handlers
24686		this._core.$element.on(this._handlers);
24687
24688		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
24689			this.play(e);
24690		}, this));
24691	};
24692
24693	/**
24694	 * Default options.
24695	 * @public
24696	 */
24697	Video.Defaults = {
24698		video: false,
24699		videoHeight: false,
24700		videoWidth: false
24701	};
24702
24703	/**
24704	 * Gets the video ID and the type (YouTube/Vimeo only).
24705	 * @protected
24706	 * @param {jQuery} target - The target containing the video data.
24707	 * @param {jQuery} item - The item containing the video.
24708	 */
24709	Video.prototype.fetch = function(target, item) {
24710		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
24711			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
24712			width = target.attr('data-width') || this._core.settings.videoWidth,
24713			height = target.attr('data-height') || this._core.settings.videoHeight,
24714			url = target.attr('href');
24715
24716		if (url) {
24717			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+)?/);
24718
24719			if (id[3].indexOf('youtu') > -1) {
24720				type = 'youtube';
24721			} else if (id[3].indexOf('vimeo') > -1) {
24722				type = 'vimeo';
24723			} else {
24724				throw new Error('Video URL not supported.');
24725			}
24726			id = id[6];
24727		} else {
24728			throw new Error('Missing video URL.');
24729		}
24730
24731		this._videos[url] = {
24732			type: type,
24733			id: id,
24734			width: width,
24735			height: height
24736		};
24737
24738		item.attr('data-video', url);
24739
24740		this.thumbnail(target, this._videos[url]);
24741	};
24742
24743	/**
24744	 * Creates video thumbnail.
24745	 * @protected
24746	 * @param {jQuery} target - The target containing the video data.
24747	 * @param {Object} info - The video info object.
24748	 * @see `fetch`
24749	 */
24750	Video.prototype.thumbnail = function(target, video) {
24751		var tnLink,
24752			icon,
24753			path,
24754			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
24755			customTn = target.find('img'),
24756			srcType = 'src',
24757			lazyClass = '',
24758			settings = this._core.settings,
24759			create = function(path) {
24760				icon = '<div class="owl-video-play-icon"></div>';
24761
24762				if (settings.lazyLoad) {
24763					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
24764				} else {
24765					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
24766				}
24767				target.after(tnLink);
24768				target.after(icon);
24769			};
24770
24771		// wrap video content into owl-video-wrapper div
24772		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
24773
24774		if (this._core.settings.lazyLoad) {
24775			srcType = 'data-src';
24776			lazyClass = 'owl-lazy';
24777		}
24778
24779		// custom thumbnail
24780		if (customTn.length) {
24781			create(customTn.attr(srcType));
24782			customTn.remove();
24783			return false;
24784		}
24785
24786		if (video.type === 'youtube') {
24787			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
24788			create(path);
24789		} else if (video.type === 'vimeo') {
24790			$.ajax({
24791				type: 'GET',
24792				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
24793				jsonp: 'callback',
24794				dataType: 'jsonp',
24795				success: function(data) {
24796					path = data[0].thumbnail_large;
24797					create(path);
24798				}
24799			});
24800		}
24801	};
24802
24803	/**
24804	 * Stops the current video.
24805	 * @public
24806	 */
24807	Video.prototype.stop = function() {
24808		this._core.trigger('stop', null, 'video');
24809		this._playing.find('.owl-video-frame').remove();
24810		this._playing.removeClass('owl-video-playing');
24811		this._playing = null;
24812		this._core.leave('playing');
24813		this._core.trigger('stopped', null, 'video');
24814	};
24815
24816	/**
24817	 * Starts the current video.
24818	 * @public
24819	 * @param {Event} event - The event arguments.
24820	 */
24821	Video.prototype.play = function(event) {
24822		var target = $(event.target),
24823			item = target.closest('.' + this._core.settings.itemClass),
24824			video = this._videos[item.attr('data-video')],
24825			width = video.width || '100%',
24826			height = video.height || this._core.$stage.height(),
24827			html;
24828
24829		if (this._playing) {
24830			return;
24831		}
24832
24833		this._core.enter('playing');
24834		this._core.trigger('play', null, 'video');
24835
24836		item = this._core.items(this._core.relative(item.index()));
24837
24838		this._core.reset(item.index());
24839
24840		if (video.type === 'youtube') {
24841			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
24842				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
24843		} else if (video.type === 'vimeo') {
24844			html = '<iframe src="//player.vimeo.com/video/' + video.id +
24845				'?autoplay=1" width="' + width + '" height="' + height +
24846				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
24847		}
24848
24849		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
24850
24851		this._playing = item.addClass('owl-video-playing');
24852	};
24853
24854	/**
24855	 * Checks whether an video is currently in full screen mode or not.
24856	 * @todo Bad style because looks like a readonly method but changes members.
24857	 * @protected
24858	 * @returns {Boolean}
24859	 */
24860	Video.prototype.isInFullScreen = function() {
24861		var element = document.fullscreenElement || document.mozFullScreenElement ||
24862				document.webkitFullscreenElement;
24863
24864		return element && $(element).parent().hasClass('owl-video-frame');
24865	};
24866
24867	/**
24868	 * Destroys the plugin.
24869	 */
24870	Video.prototype.destroy = function() {
24871		var handler, property;
24872
24873		this._core.$element.off('click.owl.video');
24874
24875		for (handler in this._handlers) {
24876			this._core.$element.off(handler, this._handlers[handler]);
24877		}
24878		for (property in Object.getOwnPropertyNames(this)) {
24879			typeof this[property] != 'function' && (this[property] = null);
24880		}
24881	};
24882
24883	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
24884
24885})(window.Zepto || window.jQuery, window, document);
24886
24887/**
24888 * Animate Plugin
24889 * @version 2.0.0-beta.3
24890 * @author Bartosz Wojciechowski
24891 * @license The MIT License (MIT)
24892 */
24893;(function($, window, document, undefined) {
24894
24895	/**
24896	 * Creates the animate plugin.
24897	 * @class The Navigation Plugin
24898	 * @param {Owl} scope - The Owl Carousel
24899	 */
24900	var Animate = function(scope) {
24901		this.core = scope;
24902		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
24903		this.swapping = true;
24904		this.previous = undefined;
24905		this.next = undefined;
24906
24907		this.handlers = {
24908			'change.owl.carousel': $.proxy(function(e) {
24909				if (e.namespace && e.property.name == 'position') {
24910					this.previous = this.core.current();
24911					this.next = e.property.value;
24912				}
24913			}, this),
24914			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24915				if (e.namespace) {
24916					this.swapping = e.type == 'translated';
24917				}
24918			}, this),
24919			'translate.owl.carousel': $.proxy(function(e) {
24920				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24921					this.swap();
24922				}
24923			}, this)
24924		};
24925
24926		this.core.$element.on(this.handlers);
24927	};
24928
24929	/**
24930	 * Default options.
24931	 * @public
24932	 */
24933	Animate.Defaults = {
24934		animateOut: false,
24935		animateIn: false
24936	};
24937
24938	/**
24939	 * Toggles the animation classes whenever an translations starts.
24940	 * @protected
24941	 * @returns {Boolean|undefined}
24942	 */
24943	Animate.prototype.swap = function() {
24944
24945		if (this.core.settings.items !== 1) {
24946			return;
24947		}
24948
24949		if (!$.support.animation || !$.support.transition) {
24950			return;
24951		}
24952
24953		this.core.speed(0);
24954
24955		var left,
24956			clear = $.proxy(this.clear, this),
24957			previous = this.core.$stage.children().eq(this.previous),
24958			next = this.core.$stage.children().eq(this.next),
24959			incoming = this.core.settings.animateIn,
24960			outgoing = this.core.settings.animateOut;
24961
24962		if (this.core.current() === this.previous) {
24963			return;
24964		}
24965
24966		if (outgoing) {
24967			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24968			previous.css( { 'left': left + 'px' } )
24969				.addClass('animated owl-animated-out')
24970				.addClass(outgoing)
24971				.on($.support.animation.end, clear);
24972		}
24973
24974		if (incoming) {
24975			next.addClass('animated owl-animated-in')
24976				.addClass(incoming)
24977				.on($.support.animation.end, clear);
24978		}
24979	};
24980
24981	Animate.prototype.clear = function(e) {
24982		if ($(e.target).hasClass('animated')) {
24983			$(e.target).css( { 'left': '' } )
24984				.removeClass('animated owl-animated-out owl-animated-in')
24985				.removeClass(this.core.settings.animateIn)
24986				.removeClass(this.core.settings.animateOut);
24987			this.core.onTransitionEnd();
24988		}
24989	};
24990
24991	/**
24992	 * Destroys the plugin.
24993	 * @public
24994	 */
24995	Animate.prototype.destroy = function() {
24996		var handler, property;
24997
24998		for (handler in this.handlers) {
24999			this.core.$element.off(handler, this.handlers[handler]);
25000		}
25001		for (property in Object.getOwnPropertyNames(this)) {
25002			typeof this[property] != 'function' && (this[property] = null);
25003		}
25004	};
25005
25006	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
25007
25008})(window.Zepto || window.jQuery, window, document);
25009
25010/**
25011 * Autoplay Plugin
25012 * @version 2.0.0-beta.3
25013 * @author Bartosz Wojciechowski
25014 * @author Artus Kolanowski
25015 * @license The MIT License (MIT)
25016 */
25017;(function($, window, document, undefined) {
25018
25019	/**
25020	 * Creates the autoplay plugin.
25021	 * @class The Autoplay Plugin
25022	 * @param {Owl} scope - The Owl Carousel
25023	 */
25024	var Autoplay = function(carousel) {
25025		/**
25026		 * Reference to the core.
25027		 * @protected
25028		 * @type {Owl}
25029		 */
25030		this._core = carousel;
25031
25032		/**
25033		 * The autoplay interval.
25034		 * @type {Number}
25035		 */
25036		this._interval = null;
25037
25038		/**
25039		 * Indicates whenever the autoplay is paused.
25040		 * @type {Boolean}
25041		 */
25042		this._paused = false;
25043
25044		/**
25045		 * All event handlers.
25046		 * @protected
25047		 * @type {Object}
25048		 */
25049		this._handlers = {
25050			'changed.owl.carousel': $.proxy(function(e) {
25051				if (e.namespace && e.property.name === 'settings') {
25052					if (this._core.settings.autoplay) {
25053						this.play();
25054					} else {
25055						this.stop();
25056					}
25057				}
25058			}, this),
25059			'initialized.owl.carousel': $.proxy(function(e) {
25060				if (e.namespace && this._core.settings.autoplay) {
25061					this.play();
25062				}
25063			}, this),
25064			'play.owl.autoplay': $.proxy(function(e, t, s) {
25065				if (e.namespace) {
25066					this.play(t, s);
25067				}
25068			}, this),
25069			'stop.owl.autoplay': $.proxy(function(e) {
25070				if (e.namespace) {
25071					this.stop();
25072				}
25073			}, this),
25074			'mouseover.owl.autoplay': $.proxy(function() {
25075				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25076					this.pause();
25077				}
25078			}, this),
25079			'mouseleave.owl.autoplay': $.proxy(function() {
25080				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25081					this.play();
25082				}
25083			}, this)
25084		};
25085
25086		// register event handlers
25087		this._core.$element.on(this._handlers);
25088
25089		// set default options
25090		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
25091	};
25092
25093	/**
25094	 * Default options.
25095	 * @public
25096	 */
25097	Autoplay.Defaults = {
25098		autoplay: false,
25099		autoplayTimeout: 5000,
25100		autoplayHoverPause: false,
25101		autoplaySpeed: false
25102	};
25103
25104	/**
25105	 * Starts the autoplay.
25106	 * @public
25107	 * @param {Number} [timeout] - The interval before the next animation starts.
25108	 * @param {Number} [speed] - The animation speed for the animations.
25109	 */
25110	Autoplay.prototype.play = function(timeout, speed) {
25111		this._paused = false;
25112
25113		if (this._core.is('rotating')) {
25114			return;
25115		}
25116
25117		this._core.enter('rotating');
25118
25119		this._interval = window.setInterval($.proxy(function() {
25120			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
25121				return;
25122			}
25123			this._core.next(speed || this._core.settings.autoplaySpeed);
25124		}, this), timeout || this._core.settings.autoplayTimeout);
25125	};
25126
25127	/**
25128	 * Stops the autoplay.
25129	 * @public
25130	 */
25131	Autoplay.prototype.stop = function() {
25132		if (!this._core.is('rotating')) {
25133			return;
25134		}
25135
25136		window.clearInterval(this._interval);
25137		this._core.leave('rotating');
25138	};
25139
25140	/**
25141	 * Stops the autoplay.
25142	 * @public
25143	 */
25144	Autoplay.prototype.pause = function() {
25145		if (!this._core.is('rotating')) {
25146			return;
25147		}
25148
25149		this._paused = true;
25150	};
25151
25152	/**
25153	 * Destroys the plugin.
25154	 */
25155	Autoplay.prototype.destroy = function() {
25156		var handler, property;
25157
25158		this.stop();
25159
25160		for (handler in this._handlers) {
25161			this._core.$element.off(handler, this._handlers[handler]);
25162		}
25163		for (property in Object.getOwnPropertyNames(this)) {
25164			typeof this[property] != 'function' && (this[property] = null);
25165		}
25166	};
25167
25168	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
25169
25170})(window.Zepto || window.jQuery, window, document);
25171
25172/**
25173 * Navigation Plugin
25174 * @version 2.0.0-beta.3
25175 * @author Artus Kolanowski
25176 * @license The MIT License (MIT)
25177 */
25178;(function($, window, document, undefined) {
25179	'use strict';
25180
25181	/**
25182	 * Creates the navigation plugin.
25183	 * @class The Navigation Plugin
25184	 * @param {Owl} carousel - The Owl Carousel.
25185	 */
25186	var Navigation = function(carousel) {
25187		/**
25188		 * Reference to the core.
25189		 * @protected
25190		 * @type {Owl}
25191		 */
25192		this._core = carousel;
25193
25194		/**
25195		 * Indicates whether the plugin is initialized or not.
25196		 * @protected
25197		 * @type {Boolean}
25198		 */
25199		this._initialized = false;
25200
25201		/**
25202		 * The current paging indexes.
25203		 * @protected
25204		 * @type {Array}
25205		 */
25206		this._pages = [];
25207
25208		/**
25209		 * All DOM elements of the user interface.
25210		 * @protected
25211		 * @type {Object}
25212		 */
25213		this._controls = {};
25214
25215		/**
25216		 * Markup for an indicator.
25217		 * @protected
25218		 * @type {Array.<String>}
25219		 */
25220		this._templates = [];
25221
25222		/**
25223		 * The carousel element.
25224		 * @type {jQuery}
25225		 */
25226		this.$element = this._core.$element;
25227
25228		/**
25229		 * Overridden methods of the carousel.
25230		 * @protected
25231		 * @type {Object}
25232		 */
25233		this._overrides = {
25234			next: this._core.next,
25235			prev: this._core.prev,
25236			to: this._core.to
25237		};
25238
25239		/**
25240		 * All event handlers.
25241		 * @protected
25242		 * @type {Object}
25243		 */
25244		this._handlers = {
25245			'prepared.owl.carousel': $.proxy(function(e) {
25246				if (e.namespace && this._core.settings.dotsData) {
25247					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
25248						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
25249				}
25250			}, this),
25251			'added.owl.carousel': $.proxy(function(e) {
25252				if (e.namespace && this._core.settings.dotsData) {
25253					this._templates.splice(e.position, 0, this._templates.pop());
25254				}
25255			}, this),
25256			'remove.owl.carousel': $.proxy(function(e) {
25257				if (e.namespace && this._core.settings.dotsData) {
25258					this._templates.splice(e.position, 1);
25259				}
25260			}, this),
25261			'changed.owl.carousel': $.proxy(function(e) {
25262				if (e.namespace && e.property.name == 'position') {
25263					this.draw();
25264				}
25265			}, this),
25266			'initialized.owl.carousel': $.proxy(function(e) {
25267				if (e.namespace && !this._initialized) {
25268					this._core.trigger('initialize', null, 'navigation');
25269					this.initialize();
25270					this.update();
25271					this.draw();
25272					this._initialized = true;
25273					this._core.trigger('initialized', null, 'navigation');
25274				}
25275			}, this),
25276			'refreshed.owl.carousel': $.proxy(function(e) {
25277				if (e.namespace && this._initialized) {
25278					this._core.trigger('refresh', null, 'navigation');
25279					this.update();
25280					this.draw();
25281					this._core.trigger('refreshed', null, 'navigation');
25282				}
25283			}, this)
25284		};
25285
25286		// set default options
25287		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
25288
25289		// register event handlers
25290		this.$element.on(this._handlers);
25291	};
25292
25293	/**
25294	 * Default options.
25295	 * @public
25296	 * @todo Rename `slideBy` to `navBy`
25297	 */
25298	Navigation.Defaults = {
25299		nav: false,
25300		navText: [ 'prev', 'next' ],
25301		navSpeed: false,
25302		navElement: 'div',
25303		navContainer: false,
25304		navContainerClass: 'owl-nav',
25305		navClass: [ 'owl-prev', 'owl-next' ],
25306		slideBy: 1,
25307		dotClass: 'owl-dot',
25308		dotsClass: 'owl-dots',
25309		dots: true,
25310		dotsEach: false,
25311		dotsData: false,
25312		dotsSpeed: false,
25313		dotsContainer: false
25314	};
25315
25316	/**
25317	 * Initializes the layout of the plugin and extends the carousel.
25318	 * @protected
25319	 */
25320	Navigation.prototype.initialize = function() {
25321		var override,
25322			settings = this._core.settings;
25323
25324		// create DOM structure for relative navigation
25325		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
25326			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
25327
25328		this._controls.$previous = $('<' + settings.navElement + '>')
25329			.addClass(settings.navClass[0])
25330			.html(settings.navText[0])
25331			.prependTo(this._controls.$relative)
25332			.on('click', $.proxy(function(e) {
25333				this.prev(settings.navSpeed);
25334			}, this));
25335		this._controls.$next = $('<' + settings.navElement + '>')
25336			.addClass(settings.navClass[1])
25337			.html(settings.navText[1])
25338			.appendTo(this._controls.$relative)
25339			.on('click', $.proxy(function(e) {
25340				this.next(settings.navSpeed);
25341			}, this));
25342
25343		// create DOM structure for absolute navigation
25344		if (!settings.dotsData) {
25345			this._templates = [ $('<div>')
25346				.addClass(settings.dotClass)
25347				.append($('<span>'))
25348				.prop('outerHTML') ];
25349		}
25350
25351		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
25352			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
25353
25354		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
25355			var index = $(e.target).parent().is(this._controls.$absolute)
25356				? $(e.target).index() : $(e.target).parent().index();
25357
25358			e.preventDefault();
25359
25360			this.to(index, settings.dotsSpeed);
25361		}, this));
25362
25363		// override public methods of the carousel
25364		for (override in this._overrides) {
25365			this._core[override] = $.proxy(this[override], this);
25366		}
25367	};
25368
25369	/**
25370	 * Destroys the plugin.
25371	 * @protected
25372	 */
25373	Navigation.prototype.destroy = function() {
25374		var handler, control, property, override;
25375
25376		for (handler in this._handlers) {
25377			this.$element.off(handler, this._handlers[handler]);
25378		}
25379		for (control in this._controls) {
25380			this._controls[control].remove();
25381		}
25382		for (override in this.overides) {
25383			this._core[override] = this._overrides[override];
25384		}
25385		for (property in Object.getOwnPropertyNames(this)) {
25386			typeof this[property] != 'function' && (this[property] = null);
25387		}
25388	};
25389
25390	/**
25391	 * Updates the internal state.
25392	 * @protected
25393	 */
25394	Navigation.prototype.update = function() {
25395		var i, j, k,
25396			lower = this._core.clones().length / 2,
25397			upper = lower + this._core.items().length,
25398			maximum = this._core.maximum(true),
25399			settings = this._core.settings,
25400			size = settings.center || settings.autoWidth || settings.dotsData
25401				? 1 : settings.dotsEach || settings.items;
25402
25403		if (settings.slideBy !== 'page') {
25404			settings.slideBy = Math.min(settings.slideBy, settings.items);
25405		}
25406
25407		if (settings.dots || settings.slideBy == 'page') {
25408			this._pages = [];
25409
25410			for (i = lower, j = 0, k = 0; i < upper; i++) {
25411				if (j >= size || j === 0) {
25412					this._pages.push({
25413						start: Math.min(maximum, i - lower),
25414						end: i - lower + size - 1
25415					});
25416					if (Math.min(maximum, i - lower) === maximum) {
25417						break;
25418					}
25419					j = 0, ++k;
25420				}
25421				j += this._core.mergers(this._core.relative(i));
25422			}
25423		}
25424	};
25425
25426	/**
25427	 * Draws the user interface.
25428	 * @todo The option `dotsData` wont work.
25429	 * @protected
25430	 */
25431	Navigation.prototype.draw = function() {
25432		var difference,
25433			settings = this._core.settings,
25434			disabled = this._core.items().length <= settings.items,
25435			index = this._core.relative(this._core.current()),
25436			loop = settings.loop || settings.rewind;
25437
25438		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
25439
25440		if (settings.nav) {
25441			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
25442			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
25443		}
25444
25445		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
25446
25447		if (settings.dots) {
25448			difference = this._pages.length - this._controls.$absolute.children().length;
25449
25450			if (settings.dotsData && difference !== 0) {
25451				this._controls.$absolute.html(this._templates.join(''));
25452			} else if (difference > 0) {
25453				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
25454			} else if (difference < 0) {
25455				this._controls.$absolute.children().slice(difference).remove();
25456			}
25457
25458			this._controls.$absolute.find('.active').removeClass('active');
25459			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
25460		}
25461	};
25462
25463	/**
25464	 * Extends event data.
25465	 * @protected
25466	 * @param {Event} event - The event object which gets thrown.
25467	 */
25468	Navigation.prototype.onTrigger = function(event) {
25469		var settings = this._core.settings;
25470
25471		event.page = {
25472			index: $.inArray(this.current(), this._pages),
25473			count: this._pages.length,
25474			size: settings && (settings.center || settings.autoWidth || settings.dotsData
25475				? 1 : settings.dotsEach || settings.items)
25476		};
25477	};
25478
25479	/**
25480	 * Gets the current page position of the carousel.
25481	 * @protected
25482	 * @returns {Number}
25483	 */
25484	Navigation.prototype.current = function() {
25485		var current = this._core.relative(this._core.current());
25486		return $.grep(this._pages, $.proxy(function(page, index) {
25487			return page.start <= current && page.end >= current;
25488		}, this)).pop();
25489	};
25490
25491	/**
25492	 * Gets the current succesor/predecessor position.
25493	 * @protected
25494	 * @returns {Number}
25495	 */
25496	Navigation.prototype.getPosition = function(successor) {
25497		var position, length,
25498			settings = this._core.settings;
25499
25500		if (settings.slideBy == 'page') {
25501			position = $.inArray(this.current(), this._pages);
25502			length = this._pages.length;
25503			successor ? ++position : --position;
vendor: 5,678 bytes, lines 25504-25728
25504			position = this._pages[((position % length) + length) % length].start;
25505		} else {
25506			position = this._core.relative(this._core.current());
25507			length = this._core.items().length;
25508			successor ? position += settings.slideBy : position -= settings.slideBy;
25509		}
25510
25511		return position;
25512	};
25513
25514	/**
25515	 * Slides to the next item or page.
25516	 * @public
25517	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25518	 */
25519	Navigation.prototype.next = function(speed) {
25520		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
25521	};
25522
25523	/**
25524	 * Slides to the previous item or page.
25525	 * @public
25526	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25527	 */
25528	Navigation.prototype.prev = function(speed) {
25529		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
25530	};
25531
25532	/**
25533	 * Slides to the specified item or page.
25534	 * @public
25535	 * @param {Number} position - The position of the item or page.
25536	 * @param {Number} [speed] - The time in milliseconds for the transition.
25537	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
25538	 */
25539	Navigation.prototype.to = function(position, speed, standard) {
25540		var length;
25541
25542		if (!standard) {
25543			length = this._pages.length;
25544			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
25545		} else {
25546			$.proxy(this._overrides.to, this._core)(position, speed);
25547		}
25548	};
25549
25550	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
25551
25552})(window.Zepto || window.jQuery, window, document);
25553
25554/**
25555 * Hash Plugin
25556 * @version 2.0.0-beta.3
25557 * @author Artus Kolanowski
25558 * @license The MIT License (MIT)
25559 */
25560;(function($, window, document, undefined) {
25561	'use strict';
25562
25563	/**
25564	 * Creates the hash plugin.
25565	 * @class The Hash Plugin
25566	 * @param {Owl} carousel - The Owl Carousel
25567	 */
25568	var Hash = function(carousel) {
25569		/**
25570		 * Reference to the core.
25571		 * @protected
25572		 * @type {Owl}
25573		 */
25574		this._core = carousel;
25575
25576		/**
25577		 * Hash index for the items.
25578		 * @protected
25579		 * @type {Object}
25580		 */
25581		this._hashes = {};
25582
25583		/**
25584		 * The carousel element.
25585		 * @type {jQuery}
25586		 */
25587		this.$element = this._core.$element;
25588
25589		/**
25590		 * All event handlers.
25591		 * @protected
25592		 * @type {Object}
25593		 */
25594		this._handlers = {
25595			/*'initialized.owl.carousel': $.proxy(function(e) {
25596				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
25597					$(window).trigger('hashchange.owl.navigation');
25598				}
25599			}, this),*/
25600			'prepared.owl.carousel': $.proxy(function(e) {
25601				if (e.namespace) {
25602					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
25603
25604					if (!hash) {
25605						return;
25606					}
25607
25608					this._hashes[hash] = e.content;
25609				}
25610			}, this),
25611			'changed.owl.carousel': $.proxy(function(e) {
25612				if (e.namespace && e.property.name === 'position') {
25613					var current = this._core.items(this._core.relative(this._core.current())),
25614						hash = $.map(this._hashes, function(item, hash) {
25615							return item === current ? hash : null;
25616						}).join();
25617
25618					if (!hash || window.location.hash.slice(1) === hash) {
25619						return;
25620					}
25621
25622					window.location.hash = hash;
25623				}
25624			}, this)
25625		};
25626
25627		// set default options
25628		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
25629
25630		// register the event handlers
25631		this.$element.on(this._handlers);
25632
25633		// register event listener for hash navigation
25634		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
25635			var hash = window.location.hash.substring(1),
25636				items = this._core.$stage.children(),
25637				position = this._hashes[hash] && items.index(this._hashes[hash]);
25638
25639			if (position === undefined || position === this._core.current()) {
25640				return;
25641			}
25642
25643			this._core.to(this._core.relative(position), false, true);
25644		}, this));*/
25645	};
25646
25647	/**
25648	 * Default options.
25649	 * @public
25650	 */
25651	Hash.Defaults = {
25652		URLhashListener: false
25653	};
25654
25655	/**
25656	 * Destroys the plugin.
25657	 * @public
25658	 */
25659	Hash.prototype.destroy = function() {
25660		var handler, property;
25661
25662		$(window).off('hashchange.owl.navigation');
25663
25664		for (handler in this._handlers) {
25665			this._core.$element.off(handler, this._handlers[handler]);
25666		}
25667		for (property in Object.getOwnPropertyNames(this)) {
25668			typeof this[property] != 'function' && (this[property] = null);
25669		}
25670	};
25671
25672	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
25673
25674})(window.Zepto || window.jQuery, window, document);
25675
25676/**
25677 * Support Plugin
25678 *
25679 * @version 2.0.0-beta.3
25680 * @author Vivid Planet Software GmbH
25681 * @author Artus Kolanowski
25682 * @license The MIT License (MIT)
25683 */
25684;(function($, window, document, undefined) {
25685
25686	var style = $('<support>').get(0).style,
25687		prefixes = 'Webkit Moz O ms'.split(' '),
25688		events = {
25689			transition: {
25690				end: {
25691					WebkitTransition: 'webkitTransitionEnd',
25692					MozTransition: 'transitionend',
25693					OTransition: 'oTransitionEnd',
25694					transition: 'transitionend'
25695				}
25696			},
25697			animation: {
25698				end: {
25699					WebkitAnimation: 'webkitAnimationEnd',
25700					MozAnimation: 'animationend',
25701					OAnimation: 'oAnimationEnd',
25702					animation: 'animationend'
25703				}
25704			}
25705		},
25706		tests = {
25707			csstransforms: function() {
25708				return !!test('transform');
25709			},
25710			csstransforms3d: function() {
25711				return !!test('perspective');
25712			},
25713			csstransitions: function() {
25714				return !!test('transition');
25715			},
25716			cssanimations: function() {
25717				return !!test('animation');
25718			}
25719		};
25720
25721	function test(property, prefixed) {
25722		var result = false,
25723			upper = property.charAt(0).toUpperCase() + property.slice(1);
25724
25725		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
25726			if (style[property] !== undefined) {
25727				result = prefixed ? property : true;
25728				return false;
25729			}
25730		});
25731
25732		return result;
25733	}
25734
25735	function prefixed(property) {
25736		return test(property, true);
25737	}
25738
25739	if (tests.csstransitions()) {
25740		/* jshint -W053 */
25741		$.support.transition = new String(prefixed('transition'))
25742		$.support.transition.end = events.transition.end[ $.support.transition ];
25743	}
25744
25745	if (tests.cssanimations()) {
25746		/* jshint -W053 */
25747		$.support.animation = new String(prefixed('animation'))
25748		$.support.animation.end = events.animation.end[ $.support.animation ];
25749	}
25750
25751	if (tests.csstransforms()) {
25752		/* jshint -W053 */
25753		$.support.transform = new String(prefixed('transform'));
25754		$.support.transform3d = tests.csstransforms3d();
25755	}
25756
25757})(window.Zepto || window.jQuery, window, document);
25758
25759(function(window, document, undefined) {
25760
25761	/**
25762	 * Find the absolute position of an element
25763	 */
25764	var absPos = function(element) {
25765		var offsetLeft, offsetTop;
25766		offsetLeft = offsetTop = 0;
25767		if (element.offsetParent) {
25768			do {
25769				offsetLeft += element.offsetLeft;
25770				offsetTop += element.offsetTop;
25771			} while (element = element.offsetParent);
25772		}
25773		return [offsetLeft, offsetTop];
25774	};
25775
25776	/**
25777	 * @constructor Progress Circle class
25778	 * @param params.canvas Canvas on which the circles will be drawn.
25779	 * @param params.minRadius Inner radius of the innermost circle, in px.
25780	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
25781	 * @param params.gapWidth Space between each circle.
25782	 * @param params.centerX X coordinate of the center of circles.
25783	 * @param params.centerY Y coordinate of the center of circles.
25784	 * @param params.infoLineBaseAngle Base angle of the info line.
25785	 * @param params.infoLineAngleInterval Angles between the info lines.
25786	 */
25787	var ProgressCircle = function(params) {
25788		this.canvas = params.canvas;
25789		this.minRadius = params.minRadius || 15;
25790		this.arcWidth = params.arcWidth || 5;
25791		this.gapWidth = params.gapWidth || 3;
25792		this.centerX = params.centerX || this.canvas.width / 2;
25793		this.centerY = params.centerY || this.canvas.height / 2;
25794		this.infoLineLength = params.infoLineLength || 60;
25795		this.horizLineLength = params.horizLineLength || 10;
25796		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
25797		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
25798
25799		this.context = this.canvas.getContext('2d');
25800
25801		this.width = this.canvas.width;
25802		this.height = this.canvas.height;
25803
25804		this.circles = [];
25805		this.runningCount = 0;
25806	};
25807
25808	ProgressCircle.prototype = {
25809		constructor: ProgressCircle,
25810
25811		/**
25812		 * @method Adds an progress monitor entry.
25813		 * @param params.fillColor Color to fill in the circle.
25814		 * @param params.outlineColor Color to outline the circle.
25815		 * @param params.progressListener Callback function to fetch the progress.
25816		 * @param params.infoListener Callback function to fetch the info.
25817		 * @returns this
25818		 */
25819		addEntry: function(params) {
25820			this.circles.push(new Circle({
25821				canvas: this.canvas,
25822				context: this.context,
25823				centerX: this.centerX,
25824				centerY: this.centerY,
25825				innerRadius: this.minRadius + this.circles.length *
25826					(this.gapWidth + this.arcWidth),
25827				arcWidth: this.arcWidth,
25828				infoLineLength: this.infoLineLength,
25829				horizLineLength: this.horizLineLength,
25830
25831				id: this.circles.length,
25832				fillColor: params.fillColor,
25833				outlineColor: params.outlineColor,
25834				progressListener: params.progressListener,
25835				infoListener: params.infoListener,
25836				infoLineAngle: this.infoLineBaseAngle +
25837					this.circles.length * this.infoLineAngleInterval,
25838			}));
25839
25840			return this;
25841		},
25842
25843		/**
25844		 * @method Starts the monitor and updates with the given interval.
25845		 * @param interval Interval between updates, in millisecond.
25846		 * @returns this
25847		 */
25848		start: function(interval) {
25849			var self = this;
25850			this.timer = setInterval(function() {
25851				self._update();
25852			}, interval || 33);
25853
25854			return this;
25855		},
25856
25857		/**
25858		 * @method Stop the animation.
25859		 */
25860		stop: function() {
25861			clearTimeout(this.timer);
25862		},
25863
25864		/**
25865		 * @private
25866		 * @method Call update on each circle and redraw them.
25867		 * @returns this
25868		 */
25869		_update: function() {
25870			this._clear();
25871			this.circles.forEach(function(circle, idx, array) {
25872				circle.update();
25873			});
25874
25875			return this;
25876		},
25877
25878		/**
25879		 * @private
25880		 * @method Clear the canvas.
25881		 * @returns this
25882		 */
25883		_clear: function() {
25884			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
25885
25886			return this;
25887		},
25888
25889	};
25890
25891	/**
25892	 * @private
25893	 * @class Individual progress circle.
25894	 * @param params.canvas Canvas on which the circle will be drawn.
25895	 * @param params.context Context of the canvas.
25896	 * @param params.innerRadius Inner radius of the circle, in px.
25897	 * @param params.arcWidth Width of each arc(circle).
25898	 * @param params.gapWidth Distance between each arc.
25899	 * @param params.centerX X coordinate of the center of circles.
25900	 * @param params.centerY Y coordinate of the center of circles.
25901	 * @param params.fillColor Color to fill in the circle.
25902	 * @param params.outlineColor Color to outline the circle.
25903	 * @param params.progressListener Callback function to fetch the progress.
25904	 * @param params.infoListener Callback function to fetch the info.
25905	 * @param params.infoLineAngle Angle of info line.
25906	 */
25907	var Circle = function(params) {
25908		this.id = params.id;
25909		this.canvas = params.canvas;
25910		this.context = params.context;
25911		this.centerX = params.centerX;
25912		this.centerY = params.centerY;
25913		this.arcWidth = params.arcWidth;
25914		this.innerRadius = params.innerRadius || 0;
25915		this.fillColor = params.fillColor || '#fff';
25916		this.outlineColor = params.outlineColor || this.fillColor;
25917		this.progressListener = params.progressListener;
25918		this.infoLineLength = params.infoLineLength || 250;
25919		this.horizLineLength = params.horizLineLength || 50;
25920		this.infoListener = params.infoListener;
25921		this.infoLineAngle = params.infoLineAngle;
25922
25923		this.outerRadius = this.innerRadius + this.arcWidth;
25924
25925		// If the info listener is not registered, then don't calculate
25926		// the related coordinates
25927		if (!this.infoListener) return;
25928
25929		// calculate the info-line turning points
25930		var angle = this.infoLineAngle,
25931			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25932
25933			sinA = Math.sin(angle),
25934			cosA = Math.cos(angle);
25935
25936		this.infoLineStartX = this.centerX + sinA * arcDistance;
25937		this.infoLineStartY = this.centerY - cosA * arcDistance;
25938
25939		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25940		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25941
25942		this.infoLineEndX = this.infoLineMidX +
25943			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25944		this.infoLineEndY = this.infoLineMidY;
25945
25946		var infoText = document.createElement('div'),
25947			style = infoText.style;
25948
25949		style.color = this.fillColor;
25950		style.position = 'absolute';
25951		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25952		// style.top will be calculated in the `drawInfo` method. Since
25953		// user may want to change the size of the font, so the top offset
25954		// must be updated in each loop.
25955		infoText.className = 'ProgressCircleInfo'; // For css styling
25956		infoText.id = 'progress_circle_info_' + this.id;
25957		document.body.appendChild(infoText);
25958		this.infoText = infoText;
25959	};
25960
25961	Circle.prototype = {
25962		constructor: Circle,
25963
25964		update: function() {
25965			this.progress = this.progressListener();
25966			this._draw();
25967
25968			if (this.infoListener) {
25969				this.info = this.infoListener();
25970				this._drawInfo();
25971			}
25972		},
25973
25974		/**
25975		 * @private
25976		 * @method Draw the circle on the canvas.
25977		 * @returns this
25978		 */
25979		_draw: function() {
25980			var ctx = this.context,
25981
25982				ANGLE_OFFSET = -Math.PI / 2,
25983
25984				startAngle = 0 + ANGLE_OFFSET,
25985				endAngle= startAngle + this.progress * Math.PI * 2,
25986
25987				x = this.centerX,
25988				y = this.centerY,
25989
25990				innerRadius = this.innerRadius - this.arcWidth - 1,
25991				outerRadius = this.outerRadius - this.arcWidth - 1;
25992
25993			if ( innerRadius < 0 )
25994				return;
25995
25996			ctx.fillStyle = this.fillColor;
25997			ctx.strokeStyle = this.outlineColor;
25998
25999			ctx.beginPath();
26000			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
26001			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
26002			ctx.closePath();
26003			ctx.stroke();
26004			ctx.fill();
26005
26006			return this;
26007		},
26008
26009		/**
26010		 * @private
26011		 * @method Draw the info lines and info text.
26012		 * @returns this
26013		 */
26014		_drawInfo: function() {
26015
26016			var pointList, lineHeight;
26017
26018			pointList = [
26019				[this.infoLineStartX, this.infoLineStartY],
26020				[this.infoLineMidX, this.infoLineMidY],
26021				[this.infoLineEndX, this.infoLineEndY],
26022			];
26023			this._drawSegments(pointList, false);
26024
26025			this.infoText.innerHTML = this.info;
26026
26027			lineHeight = this.infoText.offsetHeight;
26028			this.infoText.style.top = this.infoLineEndY +
26029				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
26030
26031			return this;
26032		},
26033
26034		/**
26035		 * @private
26036		 * @method Helper function to draw the segments
26037		 * @param pointList An array of points in the form of [x, y].
26038		 * @param close Whether to connect the first and last point.
26039		 */
26040		_drawSegments: function(pointList, close) {
26041			var ctx = this.context;
26042
26043			ctx.beginPath();
26044			ctx.moveTo(pointList[0][0], pointList[0][1]);
26045			for (var i = 1; i < pointList.length; ++i) {
26046				ctx.lineTo(pointList[i][0], pointList[i][1]);
26047			}
26048
26049			if (close) {
26050				ctx.closePath();
26051			}
26052			ctx.stroke();
26053		},
26054	};
26055
26056	window.ProgressCircle = ProgressCircle;
26057
26058})(window, document);
26059
26060
26061
26062
26063/* =========================================================
26064 * jquery.vc_chart.js v1.0
26065 * =========================================================
26066 * Copyright 2013 Wpbakery
26067 *
26068 * Jquery chart plugin for the Visual Composer.
26069 * ========================================================= */
26070(function($){
26071	/**
26072	 * Pie chart animated.
26073	 * @param element - DOM element
26074	 * @param options - settings object.
26075	 * @constructor
26076	 */
26077	var VcChart = function(element, options) {
26078		this.el = element;
26079		this.$el = $(this.el);
26080		var $this = this;
26081		$this.options = $.extend({
26082			color: 'wpb_button',
26083			units: '',
26084			width: '',
26085			label_selector: '.vc_pie_chart_value',
26086			back_selector: '.vc_pie_chart_back',
26087			responsive: true
26088		}, options);
26089		$this.init();
26090	};
26091	VcChart.prototype = {
26092		constructor: VcChart,
26093		_progress_v: 0,
26094		animated: false,
26095		colors: {
26096			'wpb_button': 'rgba(247, 247, 247, 1)',
26097			'btn-primary': 'rgba(0, 136, 204, 1)',
26098			'btn-info': 'rgba(88, 185, 218, 1)',
26099			'btn-success': 'rgba(106, 177, 101, 1)',
26100			'btn-warning': 'rgba(255, 153, 0, 1)',
26101			'btn-danger': 'rgba(255, 103, 91, 1)',
26102			'btn-inverse': 'rgba(85, 85, 85, 1)'
26103		},
26104		init: function() {
26105			this.setupColor();
26106			this.value = this.$el.data('pie-value')/100;
26107			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
26108			this.$wrapper = $('.vc_pie_wrapper', this.$el);
26109			this.$label = $(this.options.label_selector, this.$el);
26110			this.$back = $(this.options.back_selector, this.$el);
26111			this.$canvas = this.$el.find('canvas');
26112			this.arcWidth = this.$el.data('pie-width') * 2;
26113			this.draw();
26114			this.setWayPoint();
26115			if(this.options.responsive === true) this.setResponsive();
26116			if (UNCODE.isMobile) this._progress_v = this.value;
26117		},
26118		setupColor: function() {
26119			// if(typeof this.colors[this.options.color] !== 'undefined') {
26120			//     this.color = this.colors[this.options.color];
26121			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
26122			//     this.color = this.options.color;
26123			// } else {
26124			//     this.color = 'rgba(247, 247, 247, 0.2)';
26125			// }
26126			if(typeof this.options.color !== 'undefined') {
26127				this.color = this.options.color;
26128			} else this.color = 'rgba(247, 247, 247, 0.2)';
26129
26130		},
26131		setResponsive: function() {
26132			var that = this;
26133			if (!UNCODE.isMobile) {
26134				$(window).resize(function(){
26135					if(that.animated === true) that.circle.stop();
26136					that.draw(true);
26137				});
26138			}
26139		},
26140		draw: function(redraw) {
26141			var w = this.$el.addClass('vc_ready').width() * 2,
26142				border_w = this.arcWidth,
26143				radius;
26144			if(!w) w = this.$el.parents(':visible').first().width()-2;
26145			//w = Math.round(w/100*80);
26146			//if (w < 250) w = 250;
26147			radius = w/2;
26148			this.$wrapper.css({"width" : (w / 2) + "px"});
26149			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
26150			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
26151			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
26152			this.$el.addClass('vc_ready');
26153			this.circle = new ProgressCircle({
26154				canvas: this.$canvas.get(0),
26155				minRadius: radius,
26156				arcWidth: border_w
26157			});
26158			if(redraw === true && this.animated === true) {
26159				this._progress_v = this.value;
26160				this.circle.addEntry({
26161					fillColor: this.color,
26162					progressListener: $.proxy(this.setProgress, this)
26163				}).start();
26164			}
26165		},
26166		setProgress: function() {
26167			if (this._progress_v >= this.value) {
26168				this.circle.stop();
26169				this.animated = true;
26170				this.$label.html(this.label_value + this.options.units);
26171				return this._progress_v;
26172			}
26173			this._progress_v += 0.01;
26174			if (!isNaN(this.label_value)) {
26175				var label_value = this._progress_v/this.value*this.label_value;
26176				var val = Math.round(label_value) + this.options.units;
26177				this.$label.html(val);
26178			} else this.$label.html(this.label_value + this.options.units);
26179			return this._progress_v;
26180		},
26181		animate: function() {
26182			if(this.animated !== true) {
26183				this.circle.addEntry({
26184					fillColor: this.color,
26185					progressListener: $.proxy(this.setProgress, this)
26186				}).start(10);
26187			}
26188		},
26189		setWayPoint: function() {
26190			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
26191				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
26192			} else {
26193				this.animate();
26194			}
26195		}
26196	};
26197	/**
26198	 * jQuery plugin
26199	 * @param option - object with settings
26200	 * @return {*}
26201	 */
26202	$.fn.vcChat = function(option, value) {
26203		return this.each(function () {
26204			var $this = $(this),
26205				data = $this.data('vc_chart'),
26206				options = typeof option === 'object' ? option : {
26207					color: $this.data('pie-color'),
26208					units: $this.data('pie-units')
26209				};
26210			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
26211			if (typeof option == 'string') data[option](value);
26212		});
26213	};
26214	/**
26215	 * Allows users to rewrite function inside theme.
26216	 */
26217	if ( typeof window['vc_pieChart'] !== 'function' ) {
26218		window.vc_pieChart = function() {
26219			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
26220		}
26221	}
26222	$(document).ready(function(){
26223		!window.vc_iframe && vc_pieChart();
26224
26225		/**
26226		* Tab and collapse integration.
26227		*/
26228		$('.nav-tabs a').on('shown.bs.tab', function(e){
26229			var $cont = $(e.target).closest('.tab-container'),
26230				$active = $('.tab-pane.active', $cont);
26231			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
26232		});
26233
26234		$('.panel-collapse').on('shown.bs.collapse', function (e) {
26235			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
26236		})
26237	});
26238
26239})(window.jQuery);
26240
26241/* Progress bar
26242 ---------------------------------------------------------- */
26243function uncode_progress_bar() {
26244	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
26245		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
26246			return;
26247		}
26248		if (!UNCODE.isMobile) {
26249			new Waypoint({
26250				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26251				element: val,
26252				handler: function() {
26253					var element = jQuery(this.element);
26254					element.find('.vc_single_bar').each(function(index) {
26255						var $this = jQuery(this),
26256							bar = $this.find('.vc_bar'),
26257							val = bar.data('percentage-value');
26258						setTimeout(function() {
26259							bar.css({
26260								"width": val + '%'
26261							});
26262						}, index * 200);
26263					});
26264				},
26265				offset: '80%'
26266			});
26267		} else {
26268			var element = jQuery(val);
26269			element.find('.vc_single_bar').each(function(index) {
26270				var $this = jQuery(this),
26271					bar = $this.find('.vc_bar'),
26272					val = bar.data('percentage-value');
26273				setTimeout(function() {
26274					bar.css({
26275						"width": val + '%'
26276					});
26277				}, index * 200);
26278			});
26279		}
26280	});
26281};
26282uncode_progress_bar();
26283
26284/*!
26285 * jquery.counterup.js 1.0
26286 *
26287 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
26288 * Released under the GPL v2 License
26289 *
26290 * Date: Nov 26, 2013
26291 */
26292(function($) {
26293	"use strict";
26294	$.fn.counterUp = function(options) {
26295		// Defaults
26296		var settings = $.extend({
26297			'time': 400,
26298			'delay': 10
26299		}, options);
26300		return this.each(function() {
26301			// Store the object
26302			var $this = $(this);
26303			var $settings = settings;
26304			var counterUpper = function() {
26305				var nums = [];
26306				var divisions = $settings.time / $settings.delay;
26307				var numReal = $this.attr('data-val'),
26308				num = numReal;
26309				var isComma = /[0-9]+,[0-9]+/.test(num);
26310				num = num.replace(/,/g, '');
26311				var isInt = /^[0-9]+$/.test(num);
26312				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
26313				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
26314				// Generate list of incremental numbers to display
26315				for (var i = divisions; i >= 1; i--) {
26316					// Preserve as int if input was int
26317					var newNum = parseInt(num / divisions * i);
26318					// Preserve float if input was float
26319					if (isFloat) {
26320						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
26321					}
26322					// Preserve commas if input had commas
26323					if (isComma) {
26324						while (/(\d+)(\d{3})/.test(newNum.toString())) {
26325							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
26326						}
26327					}
26328					nums.unshift(newNum);
26329				}
26330				nums.push(numReal);
26331				$this.data('counterup-nums', nums);
26332				$this.text('0');
26333				// Updates the number until we're done
26334				var f = function() {
26335					if ($this.data('counterup-nums') != null) {
26336						$this.text($this.data('counterup-nums').shift());
26337						if ($this.data('counterup-nums').length) {
26338							setTimeout($this.data('counterup-func'), $settings.delay);
26339						} else {
26340							delete $this.data('counterup-nums');
26341							$this.data('counterup-nums', null);
26342							$this.data('counterup-func', null);
26343						}
26344					}
26345				};
26346				$this.data('counterup-func', f);
26347				// Start the count up
26348				setTimeout($this.data('counterup-func'), $settings.delay);
26349			};
26350			// Perform counts when the element gets into view
26351			new Waypoint({
26352				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26353				element: this,
26354				handler: function() {
26355					counterUpper();
26356					if (!UNCODE.isUnmodalOpen) {
26357						this.destroy();
26358					}
26359				},
26360				offset: '100%'
26361			});
26362		});
26363	};
26364})(jQuery);
26365
26366/*!
26367 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
26368 * Copyright (c) 2016 Edson Hilios
26369 *
26370 * Permission is hereby granted, free of charge, to any person obtaining a copy of
26371 * this software and associated documentation files (the "Software"), to deal in
26372 * the Software without restriction, including without limitation the rights to
26373 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
26374 * the Software, and to permit persons to whom the Software is furnished to do so,
26375 * subject to the following conditions:
26376 *
26377 * The above copyright notice and this permission notice shall be included in all
26378 * copies or substantial portions of the Software.
26379 *
26380 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26381 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26382 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26383 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26384 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26385 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26386 */
26387(function(factory) {
26388	"use strict";
26389	if (typeof define === "function" && define.amd) {
26390		define([ "jquery" ], factory);
26391	} else {
26392		factory(jQuery);
26393	}
26394})(function($) {
26395	"use strict";
26396	var instances = [], matchers = [], defaultOptions = {
26397		precision: 100,
26398		elapse: false,
26399		defer: false
26400	};
26401	matchers.push(/^[0-9]*$/.source);
26402	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26403	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26404	matchers = new RegExp(matchers.join("|"));
26405	function parseDateString(dateString) {
26406		if (dateString instanceof Date) {
26407			return dateString;
26408		}
26409		if (String(dateString).match(matchers)) {
26410			if (String(dateString).match(/^[0-9]*$/)) {
26411				dateString = Number(dateString);
26412			}
26413			if (String(dateString).match(/\-/)) {
26414				dateString = String(dateString).replace(/\-/g, "/");
26415			}
26416			return new Date(dateString);
26417		} else {
26418			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
26419		}
26420	}
26421	var DIRECTIVE_KEY_MAP = {
26422		Y: "years",
26423		m: "months",
26424		n: "daysToMonth",
26425		d: "daysToWeek",
26426		w: "weeks",
26427		W: "weeksToMonth",
26428		H: "hours",
26429		M: "minutes",
26430		S: "seconds",
26431		D: "totalDays",
26432		I: "totalHours",
26433		N: "totalMinutes",
26434		T: "totalSeconds"
26435	};
26436	function escapedRegExp(str) {
26437		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
26438		return new RegExp(sanitize);
26439	}
26440	function strftime(offsetObject) {
26441		return function(format) {
26442			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
26443			if (directives) {
26444				for (var i = 0, len = directives.length; i < len; ++i) {
26445					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
26446					directive = directive[2];
26447					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
26448						value = DIRECTIVE_KEY_MAP[directive];
26449						value = Number(offsetObject[value]);
26450					}
26451					if (value !== null) {
26452						if (modifier === "!") {
26453							value = pluralize(plural, value);
26454						}
26455						if (modifier === "") {
26456							if (value < 10) {
26457								value = "0" + value.toString();
26458							}
26459						}
26460						format = format.replace(regexp, value.toString());
26461					}
26462				}
26463			}
26464			format = format.replace(/%%/, "%");
26465			return format;
26466		};
26467	}
26468	function pluralize(format, count) {
26469		var plural = "s", singular = "";
26470		if (format) {
26471			format = format.rep
vendor: 8,618 bytes, lines 26471-26615
26471lace(/(:|;|\s)/gi, "").split(/\,/);
26472			if (format.length === 1) {
26473				plural = format[0];
26474			} else {
26475				singular = format[0];
26476				plural = format[1];
26477			}
26478		}
26479		if (Math.abs(count) > 1) {
26480			return plural;
26481		} else {
26482			return singular;
26483		}
26484	}
26485	var Countdown = function(el, finalDate, options) {
26486		this.el = el;
26487		this.$el = $(el);
26488		this.interval = null;
26489		this.offset = {};
26490		this.options = $.extend({}, defaultOptions);
26491		this.instanceNumber = instances.length;
26492		instances.push(this);
26493		this.$el.data("countdown-instance", this.instanceNumber);
26494		if (options) {
26495			if (typeof options === "function") {
26496				this.$el.on("update.countdown", options);
26497				this.$el.on("stoped.countdown", options);
26498				this.$el.on("finish.countdown", options);
26499			} else {
26500				this.options = $.extend({}, defaultOptions, options);
26501			}
26502		}
26503		this.setFinalDate(finalDate);
26504		if (this.options.defer === false) {
26505			this.start();
26506		}
26507	};
26508	$.extend(Countdown.prototype, {
26509		start: function() {
26510			if (this.interval !== null) {
26511				clearInterval(this.interval);
26512			}
26513			var self = this;
26514			this.update();
26515			this.interval = setInterval(function() {
26516				self.update.call(self);
26517			}, this.options.precision);
26518		},
26519		stop: function() {
26520			clearInterval(this.interval);
26521			this.interval = null;
26522			this.dispatchEvent("stoped");
26523		},
26524		toggle: function() {
26525			if (this.interval) {
26526				this.stop();
26527			} else {
26528				this.start();
26529			}
26530		},
26531		pause: function() {
26532			this.stop();
26533		},
26534		resume: function() {
26535			this.start();
26536		},
26537		remove: function() {
26538			this.stop.call(this);
26539			instances[this.instanceNumber] = null;
26540			delete this.$el.data().countdownInstance;
26541		},
26542		setFinalDate: function(value) {
26543			this.finalDate = parseDateString(value);
26544		},
26545		update: function() {
26546			if (this.$el.closest("html").length === 0) {
26547				this.remove();
26548				return;
26549			}
26550			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
26551			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
26552			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
26553			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
26554			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
26555				return;
26556			} else {
26557				this.totalSecsLeft = newTotalSecsLeft;
26558			}
26559			this.elapsed = now >= this.finalDate;
26560			this.offset = {
26561				seconds: this.totalSecsLeft % 60,
26562				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
26563				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
26564				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26565				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26566				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
26567				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
26568				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
26569				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
26570				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
26571				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
26572				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
26573				totalMinutes: Math.floor(this.totalSecsLeft / 60),
26574				totalSeconds: this.totalSecsLeft
26575			};
26576			if (!this.options.elapse && this.totalSecsLeft === 0) {
26577				this.stop();
26578				this.dispatchEvent("finish");
26579			} else {
26580				this.dispatchEvent("update");
26581			}
26582		},
26583		dispatchEvent: function(eventName) {
26584			var event = $.Event(eventName + ".countdown");
26585			event.finalDate = this.finalDate;
26586			event.elapsed = this.elapsed;
26587			event.offset = $.extend({}, this.offset);
26588			event.strftime = strftime(this.offset);
26589			this.$el.trigger(event);
26590		}
26591	});
26592	$.fn.countdown = function() {
26593		var argumentsArray = Array.prototype.slice.call(arguments, 0);
26594		return this.each(function() {
26595			var instanceNumber = $(this).data("countdown-instance");
26596			if (instanceNumber !== undefined) {
26597				var instance = instances[instanceNumber], method = argumentsArray[0];
26598				if (Countdown.prototype.hasOwnProperty(method)) {
26599					instance[method].apply(instance, argumentsArray.slice(1));
26600				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
26601					instance.setFinalDate.call(instance, method);
26602					instance.start();
26603				} else {
26604					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
26605				}
26606			} else {
26607				new Countdown(this, argumentsArray[0], argumentsArray[1]);
26608			}
26609		});
26610	};
26611});
26612
26613!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;
26614function getStyles(config){
26615  // 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;
26615left: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+"}"
26616};
26617  var ShareUtils;
26618
26619if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
26620  Object.defineProperty(HTMLElement.prototype, "classList", {
26621    get: function() {
26622      var ret, self, update;
26623      update = function(fn) {
26624        return function(value) {
26625          var classes, index;
26626          classes = self.className.split(/\s+/);
26627          index = classes.indexOf(value);
26628          fn(classes, index, value);
26629          self.className = classes.join(" ");
26630        };
26631      };
26632      self = this;
26633      ret = {
26634        add: update(function(classes, index, value) {
26635          ~index || classes.push(value);
26636        }),
26637        remove: update(function(classes, index) {
26638          ~index && classes.splice(index, 1);
26639        }),
26640        toggle: update(function(classes, index, value) {
26641          if (~index) {
26642            classes.splice(index, 1);
26643          } else {
26644            classes.push(value);
26645          }
26646        }),
26647        contains: function(value) {
26648          return !!~self.className.split(/\s+/).indexOf(value);
26649        },
26650        item: function(i) {
26651          return self.className.split(/\s+/)[i] || null;
26652        }
26653      };
26654      Object.defineProperty(ret, "length", {
26655        get: function() {
26656          return self.className.split(/\s+/).length;
26657        }
26658      });
26659      return ret;
26660    }
26661  });
26662}
26663
26664String.prototype.to_rfc3986 = function() {
26665  var tmp;
26666  tmp = encodeURIComponent(this);
26667  return tmp.replace(/[!'()*]/g, function(c) {
26668    return "%" + c.charCodeAt(0).toString(16);
26669  });
26670};
26671
26672ShareUtils = (function() {
26673  function ShareUtils() {}
26674
26675  ShareUtils.prototype.extend = function(to, from, overwrite) {
26676    var hasProp, prop;
26677    for (prop in from) {
26678      hasProp = to[prop] !== undefined;
26679      if (hasProp && typeof from[prop] === "object") {
26680        this.extend(to[prop], from[prop], overwrite);
26681      } else {
26682        if (overwrite || !hasProp) {
26683          to[prop] = from[prop];
26684        }
26685      }
26686    }
26687  };
26688
26689  ShareUtils.prototype.hide = function(el) {
26690    return el.style.display = "none";
26691  };
26692
26693  ShareUtils.prototype.show = function(el) {
26694    return el.style.display = "block";
26695  };
26696
26697  ShareUtils.prototype.has_class = function(el, class_name) {
26698    return el.classList.contains(class_name);
26699  };
26700
26701  ShareUtils.prototype.add_class = function(el, class_name) {
26702    return el.classList.add(class_name);
26703  };
26704
26705  ShareUtils.prototype.remove_class = function(el, class_name) {
26706    return el.classList.remove(class_name);
26707  };
26708
26709  ShareUtils.prototype.is_encoded = function(str) {
26710    str = str.to_rfc3986();
26711    return decodeURIComponent(str) !== str;
26712  };
26713
26714  ShareUtils.prototype.encode = function(str) {
26715    if (typeof str === "undefined" || this.is_encoded(str)) {
26716      return str;
26717    } else {
26718      return str.to_rfc3986();
26719    }
26720  };
26721
26722  ShareUtils.prototype.popup = function(url, params) {
26723    var k, popup, qs, v;
26724    if (params == null) {
26725      params = {};
26726    }
26727    popup = {
26728      width: 500,
26729      height: 350
26730    };
26731    popup.top = (screen.height / 2) - (popup.height / 2);
26732    popup.left = (screen.width / 2) - (popup.width / 2);
26733    qs = ((function() {
26734      var _results;
26735      _results = [];
26736      for (k in params) {
26737        v = params[k];
26738        _results.push("" + k + "=" + (this.encode(v)));
26739      }
26740      return _results;
26741    }).call(this)).join('&');
26742    if (qs) {
26743      qs = "?" + qs;
26744    }
26745    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=" 
26745+ popup.width + ",height=" + popup.height);
26746  };
26747
26748  return ShareUtils;
26749
26750})();
26751var Share,
26752  __hasProp = {}.hasOwnProperty,
26753  __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; };
26754
26755Share = (function(_super) {
26756  __extends(Share, _super);
26757
26758  function Share(element, options) {
26759    this.element = element;
26760    this.el = {
26761      head: document.getElementsByTagName('head')[0],
26762      body: document.getElementsByTagName('body')[0]
26763    };
26764    this.config = {
26765      enabled_networks: 0,
26766      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
26767      url: window.location.href.replace("&", "%26"),
26768      caption: null,
26769      title: this.default_title(),
26770      image: this.default_image(),
26771      description: this.default_description(),
26772      ui: {
26773        flyout: 'top center',
26774        button_text: 'Share',
26775        button_font: true,
26776        icon_font: true
26777      },
26778      networks: {
26779        twitter: {
26780          enabled: true,
26781          url: null,
26782          title: null,
26783          description: null
26784        },
26785        facebook: {
26786          enabled: true,
26787          load_sdk: true,
26788          url: null,
26789          app_id: null,
26790          title: null,
26791          caption: null,
26792          description: null,
26793          image: null
26794        },
26795        pinterest: {
26796          enabled: true,
26797          url: null,
26798          image: null,
26799          description: null
26800        },
26801        reddit: {
26802          enabled: true,
26803          url: null,
26804          title: null
26805        },
26806        linkedin: {
26807          enabled: true,
26808          url: null,
26809          title: null,
26810          description: null
26811        },
26812        xing: {
26813          enabled: true,
26814          url: null,
26815          title: null,
26816          image: null,
26817          description: null
26818        },
26819        whatsapp: {
26820          enabled: true,
26821          title: null,
26822          url: null
26823        },
26824        email: {
26825          enabled: true,
26826          title: null,
26827          description: null,
26828          url: null
26829        }
26830      }
26831    };
26832    this.setup(element, options);
26833    return this;
26834  }
26835
26836  Share.prototype.setup = function(element, opts) {
26837    var index, instance, instances, _i, _len;
26838    instances = document.querySelectorAll(element);
26839    this.extend(this.config, opts, true);
26840    this.set_global_configuration();
26841    this.normalize_network_configuration();
26842    if (this.config.ui.icon_font) {
26843      this.inject_icons();
26844    }
26845    if (this.config.ui.button_font) {
26846      this.inject_fonts();
26847    }
26848    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
26849      this.inject_facebook_sdk();
26850    }
26851    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
26852      instance = instances[index];
26853      this.setup_instance(element, index);
26854    }
26855  };
26856
26857  Share.prototype.setup_instance = function(element, index) {
26858    var button, instance, label, network, networks, _i, _len, _results,
26859      _this = this;
26860    instance = document.querySelectorAll(element)[index];
26861    this.hide(instance);
26862    this.add_class(instance, "sharer-" + index);
26863    instance = document.querySelectorAll(element)[index];
26864    this.inject_css(instance);
26865    this.inject_html(instance);
26866    this.show(instance);
26867    label = instance.getElementsByTagName("label")[0];
26868    button = instance.getElementsByClassName("social")[0];
26869    networks = instance.getElementsByTagName('li');
26870    this.add_class(button, "networks-" + this.config.enabled_networks);
26871    label.addEventListener("click", function() {
26872      return _this.event_toggle(button);
26873    });
26874    _this = this;
26875    _results = [];
26876    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
26877      network = networks[index];
26878      _results.push(network.addEventListener("click", function() {
26879        _this.event_network(instance, this);
26880        return _this.event_close(button);
26881      }));
26882    }
26883    return _results;
26884  };
26885
26886  Share.prototype.event_toggle = function(button) {
26887    if (this.has_class(button, "active")) {
26888      return this.event_close(button);
26889    } else {
26890      return this.event_open(button);
26891    }
26892  };
26893
26894  Share.prototype.event_open = function(button) {
26895    if (this.has_class(button, "load")) {
26896      this.remove_class(button, "load");
26897    }
26898    return this.add_class(button, "active");
26899  };
26900
26901  Share.prototype.event_close = function(button) {
26902    return this.remove_class(button, "active");
26903  };
26904
26905  Share.prototype.event_network = function(instance, network) {
26906    var name;
26907    name = network.getAttribute("data-network");
26908    this.hook("before", name, instance);
26909    this["network_" + name]();
26910    return this.hook("after", name, instance);
26911  };
26912
26913  Share.prototype.open = function() {
26914    return this["public"]("open");
26915  };
26916
26917  Share.prototype.close = function() {
26918    return this["public"]("close");
26919  };
26920
26921  Share.prototype.toggle = function() {
26922    return this["public"]("toggle");
26923  };
26924
26925  Share.prototype["public"] = function(action) {
26926    var button, index, instance, _i, _len, _ref, _results;
26927    _ref = document.querySelectorAll(this.element);
26928    _results = [];
26929    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26930      instance = _ref[index];
26931      button = instance.getElementsByClassName("social")[0];
26932      _results.push(this["event_" + action](button));
26933    }
26934    return _results;
26935  };
26936
26937  Share.prototype.network_facebook = function() {
26938    if (this.config.networks.facebook.load_sdk) {
26939      if (!window.FB) {
26940        return console.error("The Facebook JS SDK hasn't loaded yet.");
26941      }
26942      return FB.ui({
26943        method: 'feed',
26944        name: this.config.networks.facebook.title,
26945        link: this.config.networks.facebook.url,
26946        picture: this.config.networks.facebook.image,
26947        caption: this.config.networks.facebook.caption,
26948        description: this.config.networks.facebook.description
26949      });
26950    } else {
26951      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26952        u: this.config.networks.facebook.url
26953      });
26954    }
26955  };
26956
26957  Share.prototype.network_twitter = function() {
26958    return this.popup('https://twitter.com/intent/tweet', {
26959      text: this.config.networks.twitter.title,
26960      url: this.config.networks.twitter.url
26961    });
26962  };
26963
26964  Share.prototype.network_pinterest = function() {
26965    return this.popup('https://www.pinterest.com/pin/create/button', {
26966      url: this.config.networks.pinterest.url,
26967      media: this.config.networks.pinterest.image,
26968      description: this.config.networks.pinterest.description
26969    });
26970  };
26971
26972  Share.prototype.network_linkedin = function() {
26973    return this.popup('https://www.linkedin.com/shareArticle', {
26974      url: this.config.networks.linkedin.url,
26975      title: this.config.networks.linkedin.title,
26976      summary: this.config.networks.linkedin.description
26977    });
26978  }
26979
26980  Share.prototype.network_xing = function() {
26981    return this.popup('https://www.xing.com/spi/shares/new', {
26982      url: this.config.networks.xing.url,
26983      image: this.config.networks.xing.image,
26984      title: this.config.networks.xing.title,
26985      summary: this.config.networks.xing.description
26986    });
26987  }
26988
26989  Share.prototype.network_whatsapp = function() {
26990    return this.popup('https://api.whatsapp.com/send', {
26991      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
26992    });
26993  }
26994
26995  Share.prototype.network_email = function() {
26996    return this.popup('mailto:', {
26997      subject: this.config.networks.email.title,
26998      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26999    });
27000  };
27001
27002  Share.prototype.inject_icons = function() {
27003  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
27004  };
27005
27006  Share.prototype.inject_fonts = function() {
27007   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
27008  };
27009
27010  Share.prototype.inject_stylesheet = function(url) {
27011    var link;
27012    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
27013      link = document.createElement("link");
27014      link.setAttribute("rel", "stylesheet");
27015      link.setAttribute("href", url);
27016      return this.el.head.appendChild(link);
27017    }
27018  };
27019
27020  Share.prototype.inject_css = function(instance) {
27021    var css, meta, selector, style;
27022    selector = "." + (instance.getAttribute('class').split(" ").join("."));
27023    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
27024      this.config.selector = selector;
27025      css = getStyles(this.config);
27026      style = document.createElement("style");
27027      style.type = "text/css";
27028      if (style.styleSheet) {
27029        style.styleSheet.cssText = css;
27030      } else {
27031        style.appendChild(document.createTextNode(css));
27032      }
27033      this.el.head.appendChild(style);
27034      delete this.config.selector;
27035      meta = document.createElement("meta");
27036      meta.setAttribute("name", "sharer" + selector);
27037      return this.el.head.appendChild(meta);
27038    }
27039  };
27040
27041  Share.prototype.inject_html = function(instance) {
27042    //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>";
27043    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>";
27044  };
27045
27046  Share.prototype.inject_facebook_sdk = function() {
27047    var fb_root, script;
27048    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
27049      script = document.createElement("script");
27050      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')";
27051      fb_root = document.createElement("div");
27052      fb_root.id = "fb-root";
27053      this.el.body.appendChild(fb_root);
27054      return this.el.body.appendChild(script);
27055    }
27056  };
27057
27058  Share.prototype.hook = function(type, network, instance) {
27059    var fn, opts;
27060    fn = this.config.networks[network][type];
27061    if (typeof fn === "function") {
27062      opts = fn.call(this.config.networks[network], instance);
27063      if (opts !== void 0) {
27064        opts = this.normalize_filter_config_updates(opts);
27065        this.extend(this.config.networks[network], opts, true);
27066        this.normalize_network_configuration();
27067      }
27068    }
27069  };
27070
27071  Share.prototype.default_title = function() {
27072    var content;
27073    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27074      return encodeURIComponent(content.getAttribute('content'));
27075    } else if (content = document.querySelector('title')) {
27076      return encodeURIComponent(content.innerText);
27077    }
27078  };
27079
27080  Share.prototype.default_image = function() {
27081    var content;
27082    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27083      return content.getAttribute('content');
27084    }
27085  };
27086
27087  Share.prototype.default_description = function() {
27088    var content;
27089    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27090      return encodeURIComponent(content.getAttribute('content'));
27091    } else {
27092      return '';
27093    }
27094  };
27095
27096  Share.prototype.set_global_configuration = function() {
27097    var display, network, option, options, _ref, _results;
27098    _ref = this.config.networks;
27099    _results = [];
27100    for (network in _ref) {
27101      options = _ref[network];
27102      for (option in options) {
27103        if (this.config.networks[network][option] == null) {
27104          this.config.networks[network][option] = this.config[option];
27105        }
27106      }
27107      if (this.config.networks[network].enabled) {
27108        display = 'block';
27109        this.config.enabled_networks += 1;
27110      } else {
27111        display = 'none';
27112      }
27113      _results.push(this.config.networks[network].display = display);
27114    }
27115    return _results;
27116  };
27117
27118  Share.prototype.normalize_network_configuration = function() {
27119    if (!this.config.networks.facebook.app_id) {
27120      this.config.networks.facebook.load_sdk = false;
27121    }
27122    if (!this.is_encoded(this.config.networks.twitter.description)) {
27123      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
27124    }
27125    if (typeof this.config.networks.facebook.app_id === 'number') {
27126      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
27127    }
27128  };
27129
27130  Share.prototype.normalize_filter_config_updates = function(opts) {
27131    if (this.config.networks.facebook.app_id !== opts.app_id) {
27132      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.");
27133      delete opts.app_id;
27134    }
27135    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
27136      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.");
27137      delete opts.app_id;
27138    }
27139    return opts;
27140  };
27141
27142  return Share;
27143
27144})(ShareUtils);
27145 return Share;
27146});
27147
27148// Generated by CoffeeScript 1.9.2
27149
27150// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
27151
27152(function() {
27153  var $, win;
27154
27155  $ = this.jQuery || window.jQuery;
27156
27157  win = $(window);
27158
27159  $.fn.stick_in_parent = function(opts) {
27160    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
27161    if (opts == null) {
27162      opts = {};
27163    }
27164    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;
27165    if (offset_top == null) {
27166      offset_top = 0;
27167    }
27168    if (parent_selector == null) {
27169      parent_selector = void 0;
27170    }
27171    if (inner_scrolling == null) {
27172      inner_scrolling = true;
27173    }
27174    if (sticky_class == null) {
27175      sticky_class = "is_stuck";
27176    }
27177    doc = $(document);
27178    if (enable_bottoming == null) {
27179      enable_bottoming = true;
27180    }
27181    outer_width = function(el) {
27182      var _el, computed, w;
27183      if (window.getComputedStyle) {
27184        _el = el[0];
27185        computed = window.getComputedStyle(el[0]);
27186        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
27187        if (computed.getPropertyValue("box-sizing") !== "border-box") {
27188          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
27189        }
27190        return w;
27191      } else {
27192        return el.outerWidth(true);
27193      }
27194    };
27195    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
27196      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
27197      if (elm.data("sticky_kit")) {
27198        return;
27199      }
27200      elm.data("sticky_kit", true);
27201      last_scroll_height = doc.height();
27202      parent = elm.parent();
27203      if (parent_selector != null) {
27204        parent = parent.closest(parent_selector);
27205      }
27206      if (!parent.length) {
27207        throw "failed to find stick parent";
27208      }
27209      fixed = false;
27210      bottomed = false;
27211      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
27212      if (spacer) {
27213        spacer.css('position', elm.css('position'));
27214      }
27215      recalc = function() {
27216        var border_top, padding_top, restore;
27217        if (detached) {
27218          return;
27219        }
27220        last_scroll_height = doc.height();
27221        border_top = parseInt(parent.css("border-top-width"), 10);
27222        padding_top = parseInt(parent.css("padding-top"), 10);
27223        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
27224        parent_top = parent.offset().top + border_top + padding_top;
27225        parent_height = parent.height();
27226        if (fixed) {
27227          fixed = false;
vendor: 6,068 bytes, lines 27228-27422
27228          bottomed = false;
27229          if (manual_spacer == null) {
27230            elm.insertAfter(spacer);
27231            spacer.detach();
27232          }
27233          elm.css({
27234            position: "",
27235            top: "",
27236            width: "",
27237            bottom: ""
27238          }).removeClass(sticky_class);
27239          restore = true;
27240        }
27241        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
27242        height = elm.outerHeight(true);
27243        el_float = elm.css("float");
27244        if (spacer) {
27245          spacer.css({
27246            width: outer_width(elm),
27247            height: height,
27248            display: elm.css("display"),
27249            "vertical-align": elm.css("vertical-align"),
27250            "float": el_float
27251          });
27252        }
27253        if (restore) {
27254          return tick();
27255        }
27256      };
27257      recalc();
27258      if (height === parent_height) {
27259        return;
27260      }
27261      last_pos = void 0;
27262      offset = offset_top;
27263      recalc_counter = recalc_every;
27264      tick = function() {
27265        var css, delta, recalced, scroll, will_bottom, win_height;
27266        if (detached) {
27267          return;
27268        }
27269        recalced = false;
27270        if (recalc_counter != null) {
27271          recalc_counter -= 1;
27272          if (recalc_counter <= 0) {
27273            recalc_counter = recalc_every;
27274            recalc();
27275            recalced = true;
27276          }
27277        }
27278        if (!recalced && doc.height() !== last_scroll_height) {
27279          recalc();
27280          recalced = true;
27281        }
27282        scroll = win.scrollTop();
27283        if (last_pos != null) {
27284          delta = scroll - last_pos;
27285        }
27286        last_pos = scroll;
27287        if (fixed) {
27288          if (enable_bottoming) {
27289            will_bottom = scroll + height + offset > parent_height + parent_top;
27290            if (bottomed && !will_bottom) {
27291              bottomed = false;
27292              elm.css({
27293                position: "fixed",
27294                bottom: "",
27295                top: offset
27296              }).trigger("sticky_kit:unbottom");
27297            }
27298          }
27299          if (scroll < top) {
27300            fixed = false;
27301            offset = offset_top;
27302            if (manual_spacer == null) {
27303              if (el_float === "left" || el_float === "right") {
27304                elm.insertAfter(spacer);
27305              }
27306              spacer.detach();
27307            }
27308            css = {
27309              position: "",
27310              width: "",
27311              top: ""
27312            };
27313            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
27314          }
27315          if (inner_scrolling) {
27316            win_height = win.height();
27317            if (height + offset_top > win_height) {
27318              if (!bottomed) {
27319                offset -= delta;
27320                offset = Math.max(win_height - height, offset);
27321                offset = Math.min(offset_top, offset);
27322                if (fixed) {
27323                  elm.css({
27324                    top: offset + "px"
27325                  });
27326                }
27327              }
27328            }
27329          }
27330        } else {
27331          if (scroll > top) {
27332            fixed = true;
27333            css = {
27334              position: "fixed",
27335              top: offset
27336            };
27337            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
27338            elm.css(css).addClass(sticky_class);
27339            if (manual_spacer == null) {
27340              elm.after(spacer);
27341              if (el_float === "left" || el_float === "right") {
27342                spacer.append(elm);
27343              }
27344            }
27345            elm.trigger("sticky_kit:stick");
27346          }
27347        }
27348        if (fixed && enable_bottoming) {
27349          if (will_bottom == null) {
27350            will_bottom = scroll + height + offset > parent_height + parent_top;
27351          }
27352          if (!bottomed && will_bottom) {
27353            bottomed = true;
27354            if (parent.css("position") === "static") {
27355              parent.css({
27356                position: "relative"
27357              });
27358            }
27359            return elm.css({
27360              position: "absolute",
27361              bottom: padding_bottom,
27362              top: "auto"
27363            }).trigger("sticky_kit:bottom");
27364          }
27365        }
27366      };
27367      recalc_and_tick = function() {
27368        recalc();
27369        return tick();
27370      };
27371      detach = function() {
27372        detached = true;
27373        win.off("touchmove", tick);
27374        win.off("scroll", tick);
27375        win.off("resize", recalc_and_tick);
27376        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
27377        elm.off("sticky_kit:detach", detach);
27378        elm.removeData("sticky_kit");
27379        elm.css({
27380          position: "",
27381          bottom: "",
27382          top: "",
27383          width: ""
27384        });
27385        parent.position("position", "");
27386        if (fixed) {
27387          if (manual_spacer == null) {
27388            if (el_float === "left" || el_float === "right") {
27389              elm.insertAfter(spacer);
27390            }
27391            spacer.remove();
27392          }
27393          return elm.removeClass(sticky_class);
27394        }
27395      };
27396      win.on("touchmove", tick);
27397      win.on("scroll", tick);
27398      win.on("resize", recalc_and_tick);
27399      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
27400      elm.on("sticky_kit:detach", detach);
27401      return setTimeout(tick, 0);
27402    };
27403    for (i = 0, len = this.length; i < len; i++) {
27404      elm = this[i];
27405      fn($(elm));
27406    }
27407    return this;
27408  };
27409
27410}).call(this);
27411/* ==========================================================================
27412 * bootstrap-tab-history.js
27413 * Author: Michael Narayan <[email protected]>
27414 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
27415 * ==========================================================================
27416 * Licensed under the Apache License, Version 2.0 (the "License"); you may
27417 * not use this file except in compliance with the License. You may obtain a
27418 * copy of the License at
27419 *
27420 * http://www.apache.org/licenses/LICENSE-2.0
27421 *
27422 * Unless required by applicable law or agreed to in writing, softw
27422are
27423 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
27424 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
27425 * License for the specific language governing permissions and limitations
27426 * under the License.
27427 * ========================================================================== */
27428
27429/* ========================================================================== */
27430/* JSHint directives                                                          */
27431/*                                                                            */
27432/* global BootstrapTabHistory: true                                           */
27433/*                                                                            */
27434/* global document                                                            */
27435/* global jQuery                                                              */
27436/* global history                                                             */
27437/* global window                                                              */
27438/* ========================================================================== */
27439
27440/**
27441 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
27442 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
27443 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
27444 *
27445 * See the README for additional information.
27446 *
27447 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
27448 */
27449
27450BootstrapTabHistory = {
27451  options: {
27452    /**
27453     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
27454     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
27455     *
27456     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
27457     *
27458     * @public
27459     * @type {?number}
27460     */
27461    defaultAnchorYOffset: 0,
27462    /**
27463     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
27464     *
27465     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
27466     *
27467     * @public
27468     * @type {string}
27469     */
27470    defaultChanger: 'replace',
27471    /**
27472     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
27473     * `null` is passed as the third parameter to these calls.
27474     *
27475     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
27476     *
27477     * @public
27478     * @type {boolean}
27479     */
27480    defaultUpdateURL: false,
27481    /**
27482     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
27483     * load.
27484     *
27485     * @public
27486     * @type {boolean}
27487     */
27488    showTabsBasedOnAnchor: true
27489  }
27490};
27491
27492(function () {
27493  'use strict';
27494
27495  jQuery(function () {
27496    if(history && history.pushState && history.replaceState) {
27497      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27498
27499      if(bootstrapTabHistory) {
27500        showTabsBasedOnState(bootstrapTabHistory);
27501      } else {
27502        showTabsBasedOnAnchor();
27503      }
27504
27505      backfillHistoryState();
27506
27507      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
27508      jQuery(window).on('popstate', onPopState);
27509    } else {
27510      showTabsBasedOnAnchor();
27511    }
27512  });
27513
27514  /**
27515   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
27516   *
27517   * @type {boolean}
27518   */
27519  var showingTabsBasedOnState = false;
27520
27521  /**
27522   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
27523   * `history.back` handling when `data-tab-history-update-url` is true.
27524   */
27525  function backfillHistoryState() {
27526    var newState = null;
27527
27528    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
27529      var $activeTabElement = jQuery(this);
27530      var selector = getTabSelector($activeTabElement);
27531
27532      if(selector) {
27533        var tabGroup = getTabGroup($activeTabElement);
27534
27535        if(tabGroup) {
27536          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
27537        }
27538      }
27539    });
27540
27541    if(newState) {
27542      history.replaceState(newState, '', null);
27543    }
27544  }
27545
27546  /**
27547   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
27548   * said bootstrapTabHistory attribute.
27549   *
27550   * @param {?object} existingState
27551   * @param {!string} tabGroup
27552   * @param {!string} selector
27553   * @returns {!object}
27554   */
27555  function createNewHistoryState(existingState, tabGroup, selector) {
27556    // Clone history.state and ensure it has a bootstrapTabHistory entry.
27557    var newState = jQuery.extend(true, {}, existingState, {
27558      bootstrapTabHistory: {}
27559    });
27560
27561    newState.bootstrapTabHistory[tabGroup] = selector;
27562
27563    return newState;
27564  }
27565
27566  /**
27567   * @param {jQuery} $tab
27568   * @returns {?string}
27569   */
27570  function getTabGroup($tab) {
27571    return parseTruthyAttributeValue($tab.data('tab-history'));
27572  }
27573
27574  /**
27575   * @param {jQuery} $tab
27576   * @returns {?string}
27577   */
27578  function getTabSelector($tab) {
27579    return $tab.data('target') || $tab.attr('href');
27580  }
27581
27582  /**
27583   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
27584   *
27585   * @param {jQuery.Event} shownEvt
27586   */
27587  function onShownTab(shownEvt) {
27588    if(!showingTabsBasedOnState) {
27589      var $activatedTab = jQuery(shownEvt.target);
27590      if ( $activatedTab.hasClass('panel-collapse') )
27591        $activatedTab = $activatedTab.closest('.panel').find('a');
27592      var selector = getTabSelector($activatedTab);
27593
27594      if(selector) {
27595        var tabGroup = getTabGroup($activatedTab);
27596
27597        if(tabGroup) {
27598          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
27599          var newState = createNewHistoryState(history.state, tabGroup, selector);
27600          var updateURL = (function ($activatedTab) {
27601            if(selector[0] === '#') {
27602              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
27603
27604              if(elementUpdateURLOption === undefined) {
27605                return BootstrapTabHistory.options.defaultUpdateURL;
27606              } else {
27607                return elementUpdateURLOption;
27608              }
27609            } else {
27610              return false;
27611            }
27612          })($activatedTab);
27613
27614          switch(historyChanger) {
27615            case 'push':
27616              history.pushState(newState, '', updateURL ? selector : null);
27617              break;
27618            case 'replace':
27619              history.replaceState(newState, '', updateURL ? selector : null);
27620              break;
27621            default:
27622              throw new Error('Unknown tab-history-changer: ' + historyChanger);
27623          }
27624        }
27625      }
27626    }
27627  }
27628
27629  /**
27630   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
27631   */
27632  function onPopState() {
27633    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27634
27635    if(bootstrapTabHistory) {
27636      showTabsBasedOnState(bootstrapTabHistory);
27637    }
27638  }
27639
27640  /**
27641   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
27642   *
27643   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
27644   *
27645   * @param {*} value
27646   * @returns {*}
27647   */
27648  function parseTruthyAttributeValue(value) {
27649    if(value) {
27650      return value;
27651    } else if(value === '') {
27652      return true;
27653    } else {
27654      return value;
27655    }
27656  }
27657
27658  /**
27659   * Show tabs based upon the anchor component of `window.location`.
27660   */
27661  function showTabsBasedOnAnchor() {
27662    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
27663      var anchor = window.location && window.location.hash;
27664
27665      if(anchor) {
27666        var $tabElement = showTabForSelector(anchor);
27667
27668        if($tabElement && window.addEventListener && window.removeEventListener) {
27669          var anchorYOffset = (function ($tabElement) {
27670            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
27671
27672            if(elementSetting === undefined) {
27673              return BootstrapTabHistory.options.defaultAnchorYOffset;
27674            } else {
27675              return elementSetting;
27676            }
27677          })($tabElement);
27678
27679          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
27680          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
27681          //   `history.state` object should have been used (unless the browser did not support the modern History API).
27682          if(anchorYOffset || anchorYOffset === 0) {
27683            var scrollListener = function resetAnchorScroll () {
27684              window.removeEventListener('scroll', scrollListener);
27685              window.scrollTo(0, anchorYOffset);
27686            };
27687
27688            window.addEventListener('scroll', scrollListener);
27689          }
27690        }
27691      }
27692    }
27693  }
27694
27695  /**
27696   * Show a tab which corresponds to the provided selector.
27697   *
27698   * @param {string} selector - A CSS selector.
27699   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
27700   */
27701  function showTabForSelector(selector) {
27702    var $tabElement = (function (selector) {
27703      var $ret = null;
27704
27705      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
27706        var $potentialTab = jQuery(this);
27707
27708        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
27709          $ret = $potentialTab;
27710          return false;
vendor: 43,483 bytes, lines 27711-28927
27711        } else {
27712         return null;
27713        }
27714      });
27715
27716      return $ret;
27717    })(selector);
27718
27719    if($tabElement) {
27720      if ( !$tabElement.parent().hasClass('active') ) {
27721        $tabElement.trigger('click');
27722      }
27723      //$tabElement.tab('show');
27724    }
27725
27726    return $tabElement;
27727  }
27728
27729  /**
27730   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
27731   *
27732   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
27733   */
27734  function showTabsBasedOnState(bootstrapTabHistory) {
27735    showingTabsBasedOnState = true;
27736
27737    try {
27738      for(var k in bootstrapTabHistory) {
27739        if(bootstrapTabHistory.hasOwnProperty(k)) {
27740          showTabForSelector(bootstrapTabHistory[k]);
27741        }
27742      }
27743    } finally {
27744      showingTabsBasedOnState = false;
27745    }
27746  }
27747})();
27748
27749/*!
27750 * justifiedGallery - v3.8.1
27751 * http://miromannino.github.io/Justified-Gallery/
27752 * Copyright (c) 2020 Miro Mannino
27753 * Licensed under the MIT license.
27754 */
27755(function (factory) {
27756  if (typeof define === 'function' && define.amd) {
27757    // AMD. Register as an anonymous module.
27758    define(['jquery'], factory);
27759  } else if (typeof module === 'object' && module.exports) {
27760    // Node/CommonJS
27761    module.exports = function (root, jQuery) {
27762      if (jQuery === undefined) {
27763        // require('jQuery') returns a factory that requires window to
27764        // build a jQuery instance, we normalize how we use modules
27765        // that require this pattern but the window provided is a noop
27766        // if it's defined (how jquery works)
27767        if (typeof window !== 'undefined') {
27768          jQuery = require('jquery');
27769        }
27770        else {
27771          jQuery = require('jquery')(root);
27772        }
27773      }
27774      factory(jQuery);
27775      return jQuery;
27776    };
27777  } else {
27778    // Browser globals
27779    factory(jQuery);
27780  }
27781}(function ($) {
27782
27783  /**
27784   * Justified Gallery controller constructor
27785   *
27786   * @param $gallery the gallery to build
27787   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
27788   * @constructor
27789   */
27790  var JustifiedGallery = function ($gallery, settings) {
27791
27792    this.settings = settings;
27793    this.checkSettings();
27794
27795    this.imgAnalyzerTimeout = null;
27796    this.entries = null;
27797    this.buildingRow = {
27798      entriesBuff: [],
27799      width: 0,
27800      height: 0,
27801      aspectRatio: 0
27802    };
27803    this.lastFetchedEntry = null;
27804    this.lastAnalyzedIndex = -1;
27805    this.yield = {
27806      every: 2, // do a flush every n flushes (must be greater than 1)
27807      flushed: 0 // flushed rows without a yield
27808    };
27809    this.border = settings.border >= 0 ? settings.border : settings.margins;
27810    this.maxRowHeight = this.retrieveMaxRowHeight();
27811    this.suffixRanges = this.retrieveSuffixRanges();
27812    this.offY = this.border;
27813    this.rows = 0;
27814    this.spinner = {
27815      phase: 0,
27816      timeSlot: 150,
27817      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
27818      intervalId: null
27819    };
27820    this.scrollBarOn = false;
27821    this.checkWidthIntervalId = null;
27822    this.galleryWidth = $gallery.width();
27823    this.$gallery = $gallery;
27824
27825  };
27826
27827  /** @returns {String} the best suffix given the width and the height */
27828  JustifiedGallery.prototype.getSuffix = function (width, height) {
27829    var longestSide, i;
27830    longestSide = (width > height) ? width : height;
27831    for (i = 0; i < this.suffixRanges.length; i++) {
27832      if (longestSide <= this.suffixRanges[i]) {
27833        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27834      }
27835    }
27836    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27837  };
27838
27839  /**
27840   * Remove the suffix from the string
27841   *
27842   * @returns {string} a new string without the suffix
27843   */
27844  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27845    return str.substring(0, str.length - suffix.length);
27846  };
27847
27848  /**
27849   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27850   */
27851  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27852    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27853  };
27854
27855  /**
27856   * Get the used suffix of a particular url
27857   *
27858   * @param str
27859   * @returns {String} return the used suffix
27860   */
27861  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27862    for (var si in this.settings.sizeRangeSuffixes) {
27863      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27864        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27865        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27866      }
27867    }
27868    return '';
27869  };
27870
27871  /**
27872   * Given an image src, with the width and the height, returns the new image src with the
27873   * best suffix to show the best quality thumbnail.
27874   *
27875   * @returns {String} the suffix to use
27876   */
27877  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27878    var newImageSrc;
27879
27880    if (this.settings.thumbnailPath) {
27881      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27882    } else {
27883      var matchRes = imageSrc.match(this.settings.extension);
27884      var ext = (matchRes !== null) ? matchRes[0] : '';
27885      newImageSrc = imageSrc.replace(this.settings.extension, '');
27886      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27887      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27888    }
27889
27890    return newImageSrc;
27891  };
27892
27893  /**
27894   * Shows the images that is in the given entry
27895   *
27896   * @param $entry the entry
27897   * @param callback the callback that is called when the show animation is finished
27898   */
27899  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27900    if (this.settings.cssAnimation) {
27901      $entry.addClass('jg-entry-visible');
27902      if (callback) callback();
27903    } else {
27904      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27905      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27906    }
27907  };
27908
27909  /**
27910   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27911   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27912   *
27913   * @param $image the image to analyze
27914   * @returns {String} the extracted src
27915   */
27916  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27917    var imageSrc = $image.data('safe-src');
27918    var imageSrcLoc = 'data-safe-src';
27919    // Begin Uncode edit
27920    if (typeof imageSrc === 'undefined') {
27921    	var imageCurrentSrc = $image[0].currentSrc;
27922    	if (imageCurrentSrc) {
27923    		imageSrc = imageCurrentSrc;
27924    	} else {
27925    		imageSrc = $image.attr('src');
27926    	}
27927		imageSrcLoc = 'src';
27928    }
27929    // End Uncode edit
27930    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27931    $image.data('jg.src', imageSrc); // this will change overtime
27932    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27933    return imageSrc;
27934  };
27935
27936  /** @returns {jQuery} the image in the given entry */
27937  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27938    var $img = $entry.find(this.settings.imgSelector);
27939    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27940    return $img.length === 0 ? null : $img;
27941  };
27942
27943  /** @returns {jQuery} the caption in the given entry */
27944  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27945    var $caption = $entry.find('> .jg-caption');
27946    return $caption.length === 0 ? null : $caption;
27947  };
27948
27949  /**
27950   * Display the entry
27951   *
27952   * @param {jQuery} $entry the entry to display
27953   * @param {int} x the x position where the entry must be positioned
27954   * @param y the y position where the entry must be positioned
27955   * @param imgWidth the image width
27956   * @param imgHeight the image height
27957   * @param rowHeight the row height of the row that owns the entry
27958   */
27959  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27960    $entry.width(imgWidth);
27961    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27962    $entry.css('top', Math.floor(y));//hacked by Uncode
27963    $entry.css('left', x);
27964
27965    var $image = this.imgFromEntry($entry);
27966    if ($image !== null) {
27967      $image.css('width', imgWidth);
27968      $image.css('height', imgHeight);
27969      $image.css('margin-left', - imgWidth / 2);
27970      $image.css('margin-top', - imgHeight / 2);
27971
27972      // Image reloading for an high quality of thumbnails
27973      var imageSrc = $image.data('jg.src');
27974      if (imageSrc) {
27975        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27976
27977        $image.one('error', function () {
27978           this.resetImgSrc($image); //revert to the original thumbnail
27979        });
27980
27981        var loadNewImage = function () {
27982          // if (imageSrc !== newImageSrc) {
27983            $image.attr('src', imageSrc);
27984          // }
27985        };
27986
27987        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27988          this.onImageEvent(imageSrc, (function() {
27989            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27990            $entry.data('jg.loaded', true);
27991          }).bind(this));
27992        } else {
27993          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27994        }
27995
27996      }
27997
27998    } else {
27999      this.showImg($entry);
28000    }
28001
28002    this.displayEntryCaption($entry);
28003  };
28004
28005  /**
28006   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
28007   * or the 'title' attributes.
28008   *
28009   * @param {jQuery} $entry the entry to process
28010   */
28011  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
28012    var $image = this.imgFromEntry($entry);
28013    if ($image !== null && this.settings.captions) {
28014      var $imgCaption = this.captionFromEntry($entry);
28015
28016      // Create it if it doesn't exists
28017      if ($imgCaption === null) {
28018        var caption = $image.attr('alt');
28019        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
28020        if (this.isValidCaption(caption)) { // Create only we found something
28021          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
28022          $entry.append($imgCaption);
28023          $entry.data('jg.createdCaption', true);
28024        }
28025      }
28026
28027      // Create events (we check again the $imgCaption because it can be still inexistent)
28028      if ($imgCaption !== null) {
28029        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
28030        this.addCaptionEventsHandlers($entry);
28031      }
28032    } else {
28033      this.removeCaptionEventsHandlers($entry);
28034    }
28035  };
28036
28037  /**
28038   * Validates the caption
28039   *
28040   * @param caption The caption that should be validated
28041   * @return {boolean} Validation result
28042   */
28043  JustifiedGallery.prototype.isValidCaption = function (caption) {
28044    return (typeof caption !== 'undefined' && caption.length > 0);
28045  };
28046
28047  /**
28048   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
28049   * It shows the caption using jQuery (or using CSS if it is configured so)
28050   *
28051   * @param {Event} eventObject the event object
28052   */
28053  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
28054    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28055    if (this.settings.cssAnimation) {
28056      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28057    } else {
28058      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28059        this.settings.captionSettings.visibleOpacity);
28060    }
28061  };
28062
28063  /**
28064   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28065   * It hides the caption using jQuery (or using CSS if it is configured so)
28066   *
28067   * @param {Event} eventObject the event object
28068   */
28069  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28070    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28071    if (this.settings.cssAnimation) {
28072      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28073    } else {
28074      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28075        this.settings.captionSettings.nonVisibleOpacity);
28076    }
28077  };
28078
28079  /**
28080   * Add the handlers of the entry for the caption
28081   *
28082   * @param $entry the entry to modify
28083   */
28084  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28085    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28086    if (typeof captionMouseEvents === 'undefined') {
28087      captionMouseEvents = {
28088        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28089        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28090      };
28091      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28092      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28093      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28094    }
28095  };
28096
28097  /**
28098   * Remove the handlers of the entry for the caption
28099   *
28100   * @param $entry the entry to modify
28101   */
28102  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28103    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28104    if (typeof captionMouseEvents !== 'undefined') {
28105      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28106      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28107      $entry.removeData('jg.captionMouseEvents');
28108    }
28109  };
28110
28111  /**
28112   * Clear the building row data to be used for a new row
28113   */
28114  JustifiedGallery.prototype.clearBuildingRow = function () {
28115    this.buildingRow.entriesBuff = [];
28116    this.buildingRow.aspectRatio = 0;
28117    this.buildingRow.width = 0;
28118  };
28119
28120  /**
28121   * Justify the building row, preparing it to
28122   *
28123   * @param isLastRow
28124   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28125   * @returns a boolean to know if the row has been justified or not
28126   */
28127  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
28128    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
28129    var minHeight = 0;
28130    var availableWidth = this.galleryWidth - 2 * this.border - (
28131      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28132    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
28133    var defaultRowHeight = this.settings.rowHeight;
28134    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
28135
28136    //Skip the last row if we can't justify it and the lastRow == 'hide'
28137    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
28138      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28139        $entry = this.buildingRow.entriesBuff[i];
28140        if (this.settings.cssAnimation)
28141          $entry.removeClass('jg-entry-visible');
28142        else {
28143          $entry.stop().fadeTo(0, 0.1);
28144          $entry.find('> img, > a > img').fadeTo(0, 0);
28145        }
28146      }
28147      return -1;
28148    }
28149
28150    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
28151    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
28152      justify = false;
28153
28154      if (this.rows > 0) {
28155        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
28156        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
28157      }
28158    }
28159
28160    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28161      $entry = this.buildingRow.entriesBuff[i];
28162      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28163
28164      if (justify) {
28165        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
28166        newImgH = rowHeight;
28167      } else {
28168        newImgW = defaultRowHeight * imgAspectRatio;
28169        newImgH = defaultRowHeight;
28170      }
28171
28172      availableWidth -= Math.round(newImgW);
28173      $entry.data('jg.jwidth', Math.round(newImgW));
28174      $entry.data('jg.jheight', Math.ceil(newImgH));
28175      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
28176    }
28177
28178    this.buildingRow.height = minHeight;
28179    return justify;
28180  };
28181
28182  /**
28183   * Flush a row: justify it, modify the gallery height accordingly to the row height
28184   *
28185   * @param isLastRow
28186   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28187   */
28188  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
28189    var settings = this.settings;
28190    var $entry, buildingRowRes, offX = this.border, i;
28191
28192    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
28193    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
28194      this.clearBuildingRow();
28195      return;
28196    }
28197
28198    if (this.maxRowHeight) {
28199      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
28200    }
28201
28202    //Align last (unjustified) row
28203    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
28204      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
28205
28206      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28207        $entry = this.buildingRow.entriesBuff[i];
28208        availableWidth -= $entry.data('jg.jwidth');
28209      }
28210
28211      if (settings.lastRow === 'center')
28212        offX += Math.round(availableWidth / 2);
28213      else if (settings.lastRow === 'right')
28214        offX += availableWidth;
28215    }
28216
28217    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
28218    for (i = 0; i <= lastEntryIdx; i++) {
28219      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
28220      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
28221      offX += $entry.data('jg.jwidth') + settings.margins;
28222    }
28223
28224    //Gallery Height
28225    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
28226    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
28227
28228    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
28229      //Ready for a new row
28230      this.offY += this.buildingRow.height + settings.margins;
28231      this.rows += 1;
28232      this.clearBuildingRow();
28233      this.settings.triggerEvent.call(this, 'jg.rowflush');
28234    }
28235  };
28236
28237
28238  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
28239  var galleryPrevStaticHeight = 0;
28240
28241  JustifiedGallery.prototype.rememberGalleryHeight = function () {
28242    galleryPrevStaticHeight = this.$gallery.height();
28243    this.$gallery.height(galleryPrevStaticHeight);
28244  };
28245
28246  // grow only
28247  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
28248    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
28249    this.$gallery.height(galleryPrevStaticHeight);
28250  };
28251
28252  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
28253    galleryPrevStaticHeight = height;
28254    this.$gallery.height(height);
28255  };
28256
28257  /**
28258   * Checks the width of the gallery container, to know if a new justification is needed
28259   */
28260  JustifiedGallery.prototype.checkWidth = function () {
28261    this.checkWidthIntervalId = setInterval($.proxy(function () {
28262
28263      // if the gallery is not currently visible, abort.
28264      if (!this.$gallery.is(":visible")) return;
28265
28266      var galleryWidth = parseFloat(this.$gallery.width());
28267      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
28268        this.galleryWidth = galleryWidth;
28269        this.rewind();
28270
28271        this.rememberGalleryHeight();
28272
28273        // Restart to analyze
28274        this.startImgAnalyzer(true);
28275      }
28276    }, this), this.settings.refreshTime);
28277  };
28278
28279  /**
28280   * @returns {boolean} a boolean saying if the spinner is active or not
28281   */
28282  JustifiedGallery.prototype.isSpinnerActive = function () {
28283    return this.spinner.intervalId !== null;
28284  };
28285
28286  /**
28287   * @returns {int} the spinner height
28288   */
28289  JustifiedGallery.prototype.getSpinnerHeight = function () {
28290    return this.spinner.$el.innerHeight();
28291  };
28292
28293  /**
28294   * Stops the spinner animation and modify the gallery height to exclude the spinner
28295   */
28296  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
28297    clearInterval(this.spinner.intervalId);
28298    this.spinner.intervalId = null;
28299    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
28300    this.spinner.$el.detach();
28301  };
28302
28303  /**
28304   * Starts the spinner animation
28305   */
28306  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
28307    var spinnerContext = this.spinner;
28308    var $spinnerPoints = spinnerContext.$el.find('span');
28309    clearInterval(spinnerContext.intervalId);
28310    this.$gallery.append(spinnerContext.$el);
28311    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
28312    spinnerContext.intervalId = setInterval(function () {
28313      if (spinnerContext.phase < $spinnerPoints.length) {
28314        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
28315      } else {
28316        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
28317      }
28318      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
28319    }, spinnerContext.timeSlot);
28320  };
28321
28322  /**
28323   * Rewind the image analysis to start from the first entry.
28324   */
28325  JustifiedGallery.prototype.rewind = function () {
28326    this.lastFetchedEntry = null;
28327    this.lastAnalyzedIndex = -1;
28328    this.offY = this.border;
28329    this.rows = 0;
28330    this.clearBuildingRow();
28331  };
28332
28333  /**
28334   * @returns {String} `settings.selector` rejecting spinner element
28335   */
28336  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
28337    return this.settings.selector + ', div:not(.jg-spinner)';
28338  };
28339
28340  /**
28341   * @returns {Array} all entries matched by `settings.selector`
28342   */
28343  JustifiedGallery.prototype.getAllEntries = function () {
28344    var selector = this.getSelectorWithoutSpinner();
28345    return this.$gallery.children(selector).toArray();
28346  };
28347
28348  /**
28349   * Update the entries searching it from the justified gallery HTML element
28350   *
28351   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
28352   * @returns {boolean} true if some entries has been founded
28353   */
28354  JustifiedGallery.prototype.updateEntries = function (norewind) {
28355    var newEntries;
28356
28357    if (norewind && this.lastFetchedEntry != null) {
28358      var selector = this.getSelectorWithoutSpinner();
28359      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
28360    } else {
28361      this.entries = [];
28362      newEntries = this.getAllEntries();
28363    }
28364
28365    if (newEntries.length > 0) {
28366
28367      // Sort or randomize
28368      if ($.isFunction(this.settings.sort)) {
28369        newEntries = this.sortArray(newEntries);
28370      } else if (this.settings.randomize) {
28371        newEntries = this.shuffleArray(newEntries);
28372      }
28373      this.lastFetchedEntry = newEntries[newEntries.length - 1];
28374
28375      // Filter
28376      if (this.settings.filter) {
28377        newEntries = this.filterArray(newEntries);
28378      } else {
28379        this.resetFilters(newEntries);
28380      }
28381
28382    }
28383
28384    this.entries = this.entries.concat(newEntries);
28385    return true;
28386  };
28387
28388  /**
28389   * Apply the entries order to the DOM, iterating the entries and appending the images
28390   *
28391   * @param entries the entries that has been modified and that must be re-ordered in the DOM
28392   */
28393  JustifiedGallery.prototype.insertToGallery = function (entries) {
28394    var that = this;
28395    $.each(entries, function () {
28396      $(this).appendTo(that.$gallery);
28397    });
28398  };
28399
28400  /**
28401   * Shuffle the array using the Fisher-Yates shuffle algorithm
28402   *
28403   * @param a the array to shuffle
28404   * @return the shuffled array
28405   */
28406  JustifiedGallery.prototype.shuffleArray = function (a) {
28407    var i, j, temp;
28408    for (i = a.length - 1; i > 0; i--) {
28409      j = Math.floor(Math.random() * (i + 1));
28410      temp = a[i];
28411      a[i] = a[j];
28412      a[j] = temp;
28413    }
28414    this.insertToGallery(a);
28415    return a;
28416  };
28417
28418  /**
28419   * Sort the array using settings.comparator as comparator
28420   *
28421   * @param a the array to sort (it is sorted)
28422   * @return the sorted array
28423   */
28424  JustifiedGallery.prototype.sortArray = function (a) {
28425    a.sort(this.settings.sort);
28426    this.insertToGallery(a);
28427    return a;
28428  };
28429
28430  /**
28431   * Reset the filters removing the 'jg-filtered' class from all the entries
28432   *
28433   * @param a the array to reset
28434   */
28435  JustifiedGallery.prototype.resetFilters = function (a) {
28436    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
28437  };
28438
28439  /**
28440   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
28441   *
28442   * @param a the array to filter
28443   * @return the filtered array
28444   */
28445  JustifiedGallery.prototype.filterArray = function (a) {
28446    var settings = this.settings;
28447    if ($.type(settings.filter) === 'string') {
28448      // Filter only keeping the entries passed in the string
28449      return a.filter(function (el) {
28450        var $el = $(el);
28451        if ($el.is(settings.filter)) {
28452          $el.removeClass('jg-filtered');
28453          return true;
28454        } else {
28455          $el.addClass('jg-filtered').removeClass('jg-visible');
28456          return false;
28457        }
28458      });
28459    } else if ($.isFunction(settings.filter)) {
28460      // Filter using the passed function
28461      var filteredArr = a.filter(settings.filter);
28462      for (var i = 0; i < a.length; i++) {
28463        if (filteredArr.indexOf(a[i]) === -1) {
28464          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
28465        } else {
28466          $(a[i]).removeClass('jg-filtered');
28467        }
28468      }
28469      return filteredArr;
28470    }
28471  };
28472
28473  /**
28474   * Revert the image src to the default value.
28475   */
28476  JustifiedGallery.prototype.resetImgSrc = function ($img) {
28477    if ($img.data('jg.originalSrcLoc') === 'src') {
28478      $img.attr('src', $img.data('jg.originalSrc'));
28479    } else {
28480      $img.attr('src', '');
28481    }
28482  };
28483
28484  /**
28485   * Destroy the Justified Gallery instance.
28486   *
28487   * It clears all the css properties added in the style attributes. We doesn't backup the original
28488   * values for those css attributes, because it costs (performance) and because in general one
28489   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
28490   * classes). Creating a backup is also difficult because JG could be called multiple times and
28491   * with different style attributes.
28492   */
28493  JustifiedGallery.prototype.destroy = function () {
28494    clearInterval(this.checkWidthIntervalId);
28495    this.stopImgAnalyzerStarter();
28496
28497    // Get fresh entries list since filtered entries are absent in `this.entries`
28498    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
28499      var $entry = $(entry);
28500
28501      // Reset entry style
28502      $entry.css('width', '');
28503      $entry.css('height', '');
28504      $entry.css('top', '');
28505      $entry.css('left', '');
28506      $entry.data('jg.loaded', undefined);
28507      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
28508
28509      // Reset image style
28510      var $img = this.imgFromEntry($entry);
28511      if ($img) {
28512        $img.css('width', '');
28513        $img.css('height', '');
28514        $img.css('margin-left', '');
28515        $img.css('margin-top', '');
28516        this.resetImgSrc($img);
28517        $img.data('jg.originalSrc', undefined);
28518        $img.data('jg.originalSrcLoc', undefined);
28519        $img.data('jg.src', undefined);
28520      }
28521
28522      // Remove caption
28523      this.removeCaptionEventsHandlers($entry);
28524      var $caption = this.captionFromEntry($entry);
28525      if ($entry.data('jg.createdCaption')) {
28526        // remove also the caption element (if created by jg)
28527        $entry.data('jg.createdCaption', undefined);
28528        if ($caption !== null) $caption.remove();
28529      } else {
28530        if ($caption !== null) $caption.fadeTo(0, 1);
28531      }
28532
28533    }, this));
28534
28535    this.$gallery.css('height', '');
28536    this.$gallery.removeClass('justified-gallery');
28537    this.$gallery.data('jg.controller', undefined);
28538    this.settings.triggerEvent.call(this, 'jg.destroy');
28539  };
28540
28541  /**
28542   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
28543   *
28544   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
28545   */
28546  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
28547    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
28548      var $entry = $(this.entries[i]);
28549      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
28550        var availableWidth = this.galleryWidth - 2 * this.border - (
28551          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28552        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28553
28554        this.buildingRow.entriesBuff.push($entry);
28555        this.buildingRow.aspectRatio += imgAspectRatio;
28556        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
28557        this.lastAnalyzedIndex = i;
28558
28559        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
28560          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28561
28562          if (++this.yield.flushed >= this.yield.every) {
28563            this.startImgAnalyzer(isForResize);
28564            return;
28565          }
28566        }
28567      } else if ($entry.data('jg.loaded') !== 'error') {
28568        return;
28569      }
28570    }
28571
28572    // Last row flush (the row is not full)
28573    if (this.buildingRow.entriesBuff.length > 0) {
28574      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28575    }
28576
28577    if (this.isSpinnerActive()) {
28578      this.stopLoadingSpinnerAnimation();
28579    }
28580
28581    /* Stop, if there is, the timeout to start the analyzeImages.
28582     This is because an image can be set loaded, and the timeout can be set,
28583     but this image can be analyzed yet.
28584     */
28585    this.stopImgAnalyzerStarter();
28586
28587    this.setGalleryFinalHeight(this.galleryHeightToSet);
28588
28589    //On complete callback
28590    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
28591  };
28592
28593  /**
28594   * Stops any ImgAnalyzer starter (that has an assigned timeout)
28595   */
28596  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
28597    this.yield.flushed = 0;
28598    if (this.imgAnalyzerTimeout !== null) {
28599      clearTimeout(this.imgAnalyzerTimeout);
28600      this.imgAnalyzerTimeout = null;
28601    }
28602  };
28603
28604  /**
28605   * Starts the image analyzer. It is not immediately called to let the browser to update the view
28606   *
28607   * @param isForResize specifies if the image analyzer must be called for resizing or not
28608   */
28609  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
28610    var that = this;
28611    this.stopImgAnalyzerStarter();
28612    this.imgAnalyzerTimeout = setTimeout(function () {
28613      that.analyzeImages(isForResize);
28614    }, 0.001); // we can't start it immediately due to a IE different behaviour
28615  };
28616
28617  /**
28618   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
28619   * because some browsers, with a 404 set complete = true.
28620   *
28621   * @param imageSrc the image src to load
28622   * @param onLoad callback that is called when the image has been loaded
28623   * @param onError callback that is called in case of an error
28624   */
28625  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
28626    if (!onLoad && !onError) return;
28627
28628    var memImage = new Image();
28629    var $memImage = $(memImage);
28630    if (onLoad) {
28631      $memImage.one('load', function () {
28632        $memImage.off('load error');
28633        onLoad(memImage);
28634      });
28635    }
28636    if (onError) {
28637      $memImage.one('error', function () {
28638        $memImage.off('load error');
28639        onError(memImage);
28640      });
28641    }
28642    memImage.src = imageSrc;
28643  };
28644
28645  /**
28646   * Init of Justified Gallery controlled
28647   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
28648   */
28649  JustifiedGallery.prototype.init = function () {
28650    var imagesToLoad = false, skippedImages = false, that = this;
28651    $.each(this.entries, function (index, entry) {
28652      var $entry = $(entry);
28653      var $image = that.imgFromEntry($entry);
28654
28655      $entry.addClass('jg-entry');
28656
28657      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
28658
28659        // Link Rel global overwrite
28660        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
28661
28662        // Link Target global overwrite
28663        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
28664
28665        if ($image !== null) {
28666
28667          // Image src
28668          var imageSrc = that.extractImgSrcFromImage($image);
28669
28670          /* If we have the height and the width, we don't wait that the image is loaded,
28671             but we start directly with the justification */
28672          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
28673            var width = parseFloat($image.attr('width'));
28674            var height = parseFloat($image.attr('height'));
28675            if ($image.prop('tagName') === 'svg') {
28676              width = parseFloat($image[0].getBBox().width);
28677              height = parseFloat($image[0].getBBox().height);
28678            }
28679            if (!isNaN(width) && !isNaN(height)) {
28680              $entry.data('jg.width', width);
28681              $entry.data('jg.height', height);
28682              $entry.data('jg.loaded', 'skipped');
28683              skippedImages = true;
28684              that.startImgAnalyzer(false);
28685              return true; // continue
28686            }
28687          }
28688
28689          $entry.data('jg.loaded', false);
28690          imagesToLoad = true;
28691
28692          // Spinner start
28693          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
28694
28695          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
28696            $entry.data('jg.width', loadImg.width);
28697            $entry.data('jg.height', loadImg.height);
28698            $entry.data('jg.loaded', true);
28699            that.startImgAnalyzer(false);
28700          }, function () { // image load error
28701            $entry.data('jg.loaded', 'error');
28702            that.startImgAnalyzer(false);
28703          });
28704
28705        } else {
28706          $entry.data('jg.loaded', true);
28707          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
28708          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
28709        }
28710
28711      }
28712
28713    });
28714
28715    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
28716    this.checkWidth();
28717  };
28718
28719  /**
28720   * Checks that it is a valid number. If a string is passed it is converted to a number
28721   *
28722   * @param settingContainer the object that contains the setting (to allow the conversion)
28723   * @param settingName the setting name
28724   */
28725  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
28726    if ($.type(settingContainer[settingName]) === 'string') {
28727      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
28728    }
28729
28730    if ($.type(settingContainer[settingName]) === 'number') {
28731      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
28732    } else {
28733      throw settingName + ' must be a number';
28734    }
28735  };
28736
28737  /**
28738   * Checks the sizeRangeSuffixes and, if necessary, converts
28739   * its keys from string (e.g. old settings with 'lt100') to int.
28740   */
28741  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
28742    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
28743      throw 'sizeRangeSuffixes must be defined and must be an object';
28744    }
28745
28746    var suffixRanges = [];
28747    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28748      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
28749    }
28750
28751    var newSizeRngSuffixes = { 0: '' };
28752    for (var i = 0; i < suffixRanges.length; i++) {
28753      if ($.type(suffixRanges[i]) === 'string') {
28754        try {
28755          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
28756          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28757        } catch (e) {
28758          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
28759        }
28760      } else {
28761        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28762      }
28763    }
28764
28765    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
28766  };
28767
28768  /**
28769   * check and convert the maxRowHeight setting
28770   * requires rowHeight to be already set
28771   * TODO: should be always called when only rowHeight is changed
28772   * @return number or null
28773   */
28774  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
28775    var newMaxRowHeight = null;
28776    var rowHeight = this.settings.rowHeight;
28777
28778    if ($.type(this.settings.maxRowHeight) === 'string') {
28779      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
28780        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
28781      } else {
28782        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
28783      }
28784    } else if ($.type(this.settings.maxRowHeight) === 'number') {
28785      newMaxRowHeight = this.settings.maxRowHeight;
28786    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
28787      return null;
28788    } else {
28789      throw 'maxRowHeight must be a number or a percentage';
28790    }
28791
28792    // check if the converted value is not a number
28793    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
28794
28795    // check values, maxRowHeight must be >= rowHeight
28796    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
28797
28798    return newMaxRowHeight;
28799  };
28800
28801  /**
28802   * Checks the settings
28803   */
28804  JustifiedGallery.prototype.checkSettings = function () {
28805    this.checkSizeRangesSuffixes();
28806
28807    this.checkOrConvertNumber(this.settings, 'rowHeight');
28808    this.checkOrConvertNumber(this.settings, 'margins');
28809    this.checkOrConvertNumber(this.settings, 'border');
28810    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
28811
28812    var lastRowModes = [
28813      'justify',
28814      'nojustify',
28815      'left',
28816      'center',
28817      'right',
28818      'hide'
28819    ];
28820    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
28821      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
28822    }
28823
28824    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28825    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28826      throw 'justifyThreshold must be in the interval [0,1]';
28827    }
28828    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28829      throw 'cssAnimation must be a boolean';
28830    }
28831
28832    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28833    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28834
28835    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28836    if (this.settings.captionSettings.visibleOpacity < 0 ||
28837      this.settings.captionSettings.visibleOpacity > 1) {
28838      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28839    }
28840
28841    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28842    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28843      this.settings.captionSettings.nonVisibleOpacity > 1) {
28844      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28845    }
28846
28847    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28848    this.checkOrConvertNumber(this.settings, 'refreshTime');
28849    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28850    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28851    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28852
28853    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28854      throw 'sort must be false or a comparison function';
28855    }
28856
28857    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28858      $.type(this.settings.filter) !== 'string') {
28859      throw 'filter must be false, a string or a filter function';
28860    }
28861  };
28862
28863  /**
28864   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28865   * @returns {Array} sorted suffix ranges
28866   */
28867  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28868    var suffixRanges = [];
28869    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28870      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28871    }
28872    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28873    return suffixRanges;
28874  };
28875
28876  /**
28877   * Update the existing settings only changing some of them
28878   *
28879   * @param newSettings the new settings (or a subgroup of them)
28880   */
28881  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28882    // In this case Justified Gallery has been called again changing only some options
28883    this.settings = $.extend({}, this.settings, newSettings);
28884    this.checkSettings();
28885
28886    // As reported in the settings: negative value = same as margins, 0 = disabled
28887    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28888
28889    this.maxRowHeight = this.retrieveMaxRowHeight();
28890    this.suffixRanges = this.retrieveSuffixRanges();
28891  };
28892
28893  JustifiedGallery.prototype.defaults = {
28894    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28895        {
28896          100: '_t',  // used when longest is less than 100px
28897          240: '_m',  // used when longest is between 101px and 240px
28898          320: '_n',  // ...
28899          500: '',
28900          640: '_z',
28901          1024: '_b'  // used as else case because it is the last
28902        }
28903    */
28904    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28905    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28906    current path, width and height */
28907    rowHeight: 120, // required? required to be > 0?
28908    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28909    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28910    // can't exceed 3 * rowHeight)
28911    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28912    margins: 1,
28913    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28914
28915    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28916
28917    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28918                             * (i.e. lastRow setting is not considered) */
28919    waitThumbnailsLoad: true,
28920    captions: true,
28921    cssAnimation: true,
28922    imagesAnimationDuration: 500, // ignored with css animations
28923    captionSettings: { // ignored with css animations
28924      animationDuration: 500,
28925      visibleOpacity: 0.7,
28926      nonVisibleOpacity: 0.0
28927    },
28928    rel: null, // rewrite the rel of each analyzed links
28929    target: null, // rewrite the target of all links
28930    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28931    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28932    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28933    randomize: false,
28934    rtl: false, // right-to-left mode
28935    sort: false, /*
28936      - false: to do not sort
28937      - function: to sort them using the function as comparator (see Array.prototype.sort())
28938    */
28939    filter: false, /*
28940      - false, null or undefined: for a disabled filter
28941      - a string: an entry is kept if entry.is(filter string) returns true
28942                  see jQuery's .is() function for further information
28943      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28944                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28945    */
28946    selector: 'a', // The selector that is used to know what are the entries of the gallery
28947    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28948    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28949      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28950    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28951  };
28952
28953
28954  /**
28955   * Justified Gallery plugin for jQuery
28956   *
28957   * Events
28958   *  - jg.complete : called when all the gallery has been created
28959   *  - jg.resize : called when the gallery has been resized
28960   *  - jg.rowflush : when a new row appears
28961   *
28962   * @param arg the action (or the settings) passed when the plugin is called
28963   * @returns {*} the object itself
28964   */
28965  $.fn.justifiedGallery = function (arg) {
28966    return this.each(function (index, gallery) {
28967
28968      var $gallery = $(gallery);
28969      $gallery.addClass('justified-gallery');
28970
28971      var controller = $gallery.data('jg.controller');
28972      if (typeof controller === 'undefined') {
28973        // Create controller and assign it to the object data
28974        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28975          if (arg === 'destroy') return; // Just a call to an unexisting object
28976          throw 'The argument must be an object';
28977        }
28978        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28979        $gallery.data('jg.controller', controller);
28980      } else if (arg === 'norewind') {
28981        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28982        // ... left to be more readable
28983      } else if (arg === 'destroy') {
28984        controller.destroy();
28985        return;
28986      } else {
28987        // In this case Justified Gallery has been called again changing only some options
28988        controller.updateSettings(arg);
28989        controller.rewind();
28990      }
28991
28992      // Update the entries list
28993      if (!controller.updateEntries(arg === 'norewind')) return;
28994
28995      // Init justified gallery
28996      controller.init();
28997
28998    });
28999  };
29000
29001}));
29002
29003/*!
29004* Customized version of iScroll.js 0.0.1
29005* It fixes bugs affecting its integration with fullpage.js
29006*/
29007/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
29008(function (window, document, Math) {
29009var rAF = window.requestAnimationFrame  ||
29010    window.webkitRequestAnimationFrame  ||
29011    window.mozRequestAnimationFrame     ||
29012    window.oRequestAnimationFrame       ||
29013    window.msRequestAnimationFrame      ||
29014    function (callback) { window.setTimeout(callback, 1000 / 60); };
29015
29016var utils = (function () {
29017    var me = {};
29018
29019    var _elementStyle = document.createElement('div').style;
29020    var _vendor = (function () {
29021        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
29022            transform,
29023            i = 0,
29024            l = vendors.length;
29025
29026        for ( ; i < l; i++ ) {
29027            transform = vendors[i] + 'ransform';
29028            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
29029        }
29030
29031        return false;
vendor: 5,154 bytes, lines 29032-29184
29032    })();
29033
29034    function _prefixStyle (style) {
29035        if ( _vendor === false ) return false;
29036        if ( _vendor === '' ) return style;
29037        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
29038    }
29039
29040    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
29041
29042    me.extend = function (target, obj) {
29043        for ( var i in obj ) {
29044            target[i] = obj[i];
29045        }
29046    };
29047
29048    me.addEvent = function (el, type, fn, capture) {
29049        el.addEventListener(type, fn, !!capture);
29050    };
29051
29052    me.removeEvent = function (el, type, fn, capture) {
29053        el.removeEventListener(type, fn, !!capture);
29054    };
29055
29056    me.prefixPointerEvent = function (pointerEvent) {
29057        return window.MSPointerEvent ?
29058            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29059            pointerEvent;
29060    };
29061
29062    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29063        var distance = current - start,
29064            speed = Math.abs(distance) / time,
29065            destination,
29066            duration;
29067
29068        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29069
29070        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29071        duration = speed / deceleration;
29072
29073        if ( destination < lowerMargin ) {
29074            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29075            distance = Math.abs(destination - current);
29076            duration = distance / speed;
29077        } else if ( destination > 0 ) {
29078            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29079            distance = Math.abs(current) + destination;
29080            duration = distance / speed;
29081        }
29082
29083        return {
29084            destination: Math.round(destination),
29085            duration: duration
29086        };
29087    };
29088
29089    var _transform = _prefixStyle('transform');
29090
29091    me.extend(me, {
29092        hasTransform: _transform !== false,
29093        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29094        hasTouch: 'ontouchstart' in window,
29095        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29096        hasTransition: _prefixStyle('transition') in _elementStyle
29097    });
29098
29099    /*
29100    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29101    - galaxy S2 is ok
29102    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29103    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29104   - galaxy S3 is badAndroid (stock brower, webview)
29105     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29106   - galaxy S4 is badAndroid (stock brower, webview)
29107     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29108   - galaxy S5 is OK
29109     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29110   - galaxy S6 is OK
29111     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29112  */
29113    me.isBadAndroid = (function() {
29114        var appVersion = window.navigator.appVersion;
29115        // Android browser is not a chrome browser.
29116        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29117            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
29118            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
29119                return parseFloat(safariVersion[1]) < 535.19;
29120            } else {
29121                return true;
29122            }
29123        } else {
29124            return false;
29125        }
29126    })();
29127
29128    me.extend(me.style = {}, {
29129        transform: _transform,
29130        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
29131        transitionDuration: _prefixStyle('transitionDuration'),
29132        transitionDelay: _prefixStyle('transitionDelay'),
29133        transformOrigin: _prefixStyle('transformOrigin')
29134    });
29135
29136    me.hasClass = function (e, c) {
29137        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
29138        return re.test(e.className);
29139    };
29140
29141    me.addClass = function (e, c) {
29142        if ( me.hasClass(e, c) ) {
29143            return;
29144        }
29145
29146        var newclass = e.className.split(' ');
29147        newclass.push(c);
29148        e.className = newclass.join(' ');
29149    };
29150
29151    me.removeClass = function (e, c) {
29152        if ( !me.hasClass(e, c) ) {
29153            return;
29154        }
29155
29156        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
29157        e.className = e.className.replace(re, ' ');
29158    };
29159
29160    me.offset = function (el) {
29161        var left = -el.offsetLeft,
29162            top = -el.offsetTop;
29163
29164        // jshint -W084
29165        while (el = el.offsetParent) {
29166            left -= el.offsetLeft;
29167            top -= el.offsetTop;
29168        }
29169        // jshint +W084
29170
29171        return {
29172            left: left,
29173            top: top
29174        };
29175    };
29176
29177    me.preventDefaultException = function (el, exceptions) {
29178        for ( var i in exceptions ) {
29179            if ( exceptions[i].test(el[i]) ) {
29180                return true;
29181            }
29182        }
29183
29184        return false;
vendor: 5,660 bytes, lines 29185-29350
29185    };
29186
29187    me.extend(me.eventType = {}, {
29188        touchstart: 1,
29189        touchmove: 1,
29190        touchend: 1,
29191
29192        mousedown: 2,
29193        mousemove: 2,
29194        mouseup: 2,
29195
29196        pointerdown: 3,
29197        pointermove: 3,
29198        pointerup: 3,
29199
29200        MSPointerDown: 3,
29201        MSPointerMove: 3,
29202        MSPointerUp: 3
29203    });
29204
29205    me.extend(me.ease = {}, {
29206        quadratic: {
29207            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
29208            fn: function (k) {
29209                return k * ( 2 - k );
29210            }
29211        },
29212        circular: {
29213            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)
29214            fn: function (k) {
29215                return Math.sqrt( 1 - ( --k * k ) );
29216            }
29217        },
29218        back: {
29219            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
29220            fn: function (k) {
29221                var b = 4;
29222                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
29223            }
29224        },
29225        bounce: {
29226            style: '',
29227            fn: function (k) {
29228                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
29229                    return 7.5625 * k * k;
29230                } else if ( k < ( 2 / 2.75 ) ) {
29231                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
29232                } else if ( k < ( 2.5 / 2.75 ) ) {
29233                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
29234                } else {
29235                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
29236                }
29237            }
29238        },
29239        elastic: {
29240            style: '',
29241            fn: function (k) {
29242                var f = 0.22,
29243                    e = 0.4;
29244
29245                if ( k === 0 ) { return 0; }
29246                if ( k == 1 ) { return 1; }
29247
29248                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
29249            }
29250        }
29251    });
29252
29253    me.tap = function (e, eventName) {
29254        var ev = document.createEvent('Event');
29255        ev.initEvent(eventName, true, true);
29256        ev.pageX = e.pageX;
29257        ev.pageY = e.pageY;
29258        e.target.dispatchEvent(ev);
29259    };
29260
29261    me.click = function (e) {
29262        var target = e.target,
29263            ev;
29264
29265        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
29266            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
29267            // initMouseEvent is deprecated.
29268            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
29269            ev.initEvent('click', true, true);
29270            ev.view = e.view || window;
29271            ev.detail = 1;
29272            ev.screenX = target.screenX || 0;
29273            ev.screenY = target.screenY || 0;
29274            ev.clientX = target.clientX || 0;
29275            ev.clientY = target.clientY || 0;
29276            ev.ctrlKey = !!e.ctrlKey;
29277            ev.altKey = !!e.altKey;
29278            ev.shiftKey = !!e.shiftKey;
29279            ev.metaKey = !!e.metaKey;
29280            ev.button = 0;
29281            ev.relatedTarget = null;
29282            ev._constructed = true;
29283            target.dispatchEvent(ev);
29284        }
29285    };
29286
29287    return me;
29288})();
29289function IScroll (el, options) {
29290    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
29291    this.scroller = this.wrapper.children[0];
29292    this.scrollerStyle = this.scroller.style;       // cache style for better performance
29293
29294    this.options = {
29295
29296        resizeScrollbars: true,
29297
29298        mouseWheelSpeed: 20,
29299
29300        snapThreshold: 0.334,
29301
29302// INSERT POINT: OPTIONS
29303        disablePointer : !utils.hasPointer,
29304        disableTouch : utils.hasPointer || !utils.hasTouch,
29305        disableMouse : utils.hasPointer || utils.hasTouch,
29306        startX: 0,
29307        startY: 0,
29308        scrollY: true,
29309        directionLockThreshold: 5,
29310        momentum: true,
29311
29312        bounce: true,
29313        bounceTime: 600,
29314        bounceEasing: '',
29315
29316        preventDefault: true,
29317        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
29318
29319        HWCompositing: true,
29320        useTransition: true,
29321        useTransform: true,
29322        bindToWrapper: typeof window.onmousedown === "undefined"
29323    };
29324
29325    for ( var i in options ) {
29326        this.options[i] = options[i];
29327    }
29328
29329    // Normalize options
29330    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
29331
29332    this.options.useTransition = utils.hasTransition && this.options.useTransition;
29333    this.options.useTransform = utils.hasTransform && this.options.useTransform;
29334
29335    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
29336    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
29337
29338    // If you want eventPassthrough I have to lock one of the axes
29339    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
29340    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
29341
29342    // With eventPassthrough we also need lockDirection mechanism
29343    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
29344    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
29345
29346    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
29347
29348    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
29349
29350    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 29351-29522
29351        this.options.tap = 'tap';
29352    }
29353
29354    // https://github.com/cubiq/iscroll/issues/1029
29355    if (!this.options.useTransition && !this.options.useTransform) {
29356        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
29357            this.scrollerStyle.position = "relative";
29358        }
29359    }
29360
29361    if ( this.options.shrinkScrollbars == 'scale' ) {
29362        this.options.useTransition = false;
29363    }
29364
29365    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
29366
29367// INSERT POINT: NORMALIZATION
29368
29369    // Some defaults
29370    this.x = 0;
29371    this.y = 0;
29372    this.directionX = 0;
29373    this.directionY = 0;
29374    this._events = {};
29375
29376// INSERT POINT: DEFAULTS
29377
29378    this._init();
29379    this.refresh();
29380
29381    this.scrollTo(this.options.startX, this.options.startY);
29382    this.enable();
29383}
29384
29385IScroll.prototype = {
29386    version: '5.2.0',
29387
29388    _init: function () {
29389        this._initEvents();
29390
29391        if ( this.options.scrollbars || this.options.indicators ) {
29392            this._initIndicators();
29393        }
29394
29395        if ( this.options.mouseWheel ) {
29396            this._initWheel();
29397        }
29398
29399        if ( this.options.snap ) {
29400            this._initSnap();
29401        }
29402
29403        if ( this.options.keyBindings ) {
29404            this._initKeys();
29405        }
29406
29407// INSERT POINT: _init
29408
29409    },
29410
29411    destroy: function () {
29412        this._initEvents(true);
29413        clearTimeout(this.resizeTimeout);
29414        this.resizeTimeout = null;
29415        this._execEvent('destroy');
29416    },
29417
29418    _transitionEnd: function (e) {
29419        if ( e.target != this.scroller || !this.isInTransition ) {
29420            return;
29421        }
29422
29423        this._transitionTime();
29424        if ( !this.resetPosition(this.options.bounceTime) ) {
29425            this.isInTransition = false;
29426            this._execEvent('scrollEnd');
29427        }
29428    },
29429
29430    _start: function (e) {
29431        // React to left mouse button only
29432        if ( utils.eventType[e.type] != 1 ) {
29433          // for button property
29434          // http://unixpapa.com/js/mouse.html
29435          var button;
29436        if (!e.which) {
29437          /* IE case */
29438          button = (e.button < 2) ? 0 :
29439                   ((e.button == 4) ? 1 : 2);
29440        } else {
29441          /* All others */
29442          button = e.button;
29443        }
29444            if ( button !== 0 ) {
29445                return;
29446            }
29447        }
29448
29449        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
29450            return;
29451        }
29452
29453        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29454            e.preventDefault();
29455        }
29456
29457        var point = e.touches ? e.touches[0] : e,
29458            pos;
29459
29460        this.initiated  = utils.eventType[e.type];
29461        this.moved      = false;
29462        this.distX      = 0;
29463        this.distY      = 0;
29464        this.directionX = 0;
29465        this.directionY = 0;
29466        this.directionLocked = 0;
29467
29468        this.startTime = utils.getTime();
29469
29470        if ( this.options.useTransition && this.isInTransition ) {
29471            this._transitionTime();
29472            this.isInTransition = false;
29473            pos = this.getComputedPosition();
29474            this._translate(Math.round(pos.x), Math.round(pos.y));
29475            this._execEvent('scrollEnd');
29476        } else if ( !this.options.useTransition && this.isAnimating ) {
29477            this.isAnimating = false;
29478            this._execEvent('scrollEnd');
29479        }
29480
29481        this.startX    = this.x;
29482        this.startY    = this.y;
29483        this.absStartX = this.x;
29484        this.absStartY = this.y;
29485        this.pointX    = point.pageX;
29486        this.pointY    = point.pageY;
29487
29488        this._execEvent('beforeScrollStart');
29489    },
29490
29491    _move: function (e) {
29492        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29493            return;
29494        }
29495
29496        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
29497            e.preventDefault();
29498        }
29499
29500        var point       = e.touches ? e.touches[0] : e,
29501            deltaX      = point.pageX - this.pointX,
29502            deltaY      = point.pageY - this.pointY,
29503            timestamp   = utils.getTime(),
29504            newX, newY,
29505            absDistX, absDistY;
29506
29507        this.pointX     = point.pageX;
29508        this.pointY     = point.pageY;
29509
29510        this.distX      += deltaX;
29511        this.distY      += deltaY;
29512        absDistX        = Math.abs(this.distX);
29513        absDistY        = Math.abs(this.distY);
29514
29515        // We need to move at least 10 pixels for the scrolling to initiate
29516        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
29517            return;
29518        }
29519
29520        // If you are scrolling in one direction lock the other
29521        if ( !this.directionLocked && !this.options.freeScroll ) {
29522            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 29523-29709
29523                this.directionLocked = 'h';     // lock horizontally
29524            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
29525                this.directionLocked = 'v';     // lock vertically
29526            } else {
29527                this.directionLocked = 'n';     // no lock
29528            }
29529        }
29530
29531        if ( this.directionLocked == 'h' ) {
29532            if ( this.options.eventPassthrough == 'vertical' ) {
29533                e.preventDefault();
29534            } else if ( this.options.eventPassthrough == 'horizontal' ) {
29535                this.initiated = false;
29536                return;
29537            }
29538
29539            deltaY = 0;
29540        } else if ( this.directionLocked == 'v' ) {
29541            if ( this.options.eventPassthrough == 'horizontal' ) {
29542                e.preventDefault();
29543            } else if ( this.options.eventPassthrough == 'vertical' ) {
29544                this.initiated = false;
29545                return;
29546            }
29547
29548            deltaX = 0;
29549        }
29550
29551        deltaX = this.hasHorizontalScroll ? deltaX : 0;
29552        deltaY = this.hasVerticalScroll ? deltaY : 0;
29553
29554        newX = this.x + deltaX;
29555        newY = this.y + deltaY;
29556
29557        // Slow down if outside of the boundaries
29558        if ( newX > 0 || newX < this.maxScrollX ) {
29559            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
29560        }
29561        if ( newY > 0 || newY < this.maxScrollY ) {
29562            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
29563        }
29564
29565        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
29566        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
29567
29568        if ( !this.moved ) {
29569            this._execEvent('scrollStart');
29570        }
29571
29572        this.moved = true;
29573
29574        this._translate(newX, newY);
29575
29576/* REPLACE START: _move */
29577
29578        if ( timestamp - this.startTime > 300 ) {
29579            this.startTime = timestamp;
29580            this.startX = this.x;
29581            this.startY = this.y;
29582        }
29583
29584/* REPLACE END: _move */
29585
29586    },
29587
29588    _end: function (e) {
29589        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29590            return;
29591        }
29592
29593        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29594            e.preventDefault();
29595        }
29596
29597        var point = e.changedTouches ? e.changedTouches[0] : e,
29598            momentumX,
29599            momentumY,
29600            duration = utils.getTime() - this.startTime,
29601            newX = Math.round(this.x),
29602            newY = Math.round(this.y),
29603            distanceX = Math.abs(newX - this.startX),
29604            distanceY = Math.abs(newY - this.startY),
29605            time = 0,
29606            easing = '';
29607
29608        this.isInTransition = 0;
29609        this.initiated = 0;
29610        this.endTime = utils.getTime();
29611
29612        // reset if we are outside of the boundaries
29613        if ( this.resetPosition(this.options.bounceTime) ) {
29614            return;
29615        }
29616
29617        this.scrollTo(newX, newY);  // ensures that the last position is rounded
29618
29619        // we scrolled less than 10 pixels
29620        if ( !this.moved ) {
29621            if ( this.options.tap ) {
29622                utils.tap(e, this.options.tap);
29623            }
29624
29625            if ( this.options.click ) {
29626                utils.click(e);
29627            }
29628
29629            this._execEvent('scrollCancel');
29630            return;
29631        }
29632
29633        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
29634            this._execEvent('flick');
29635            return;
29636        }
29637
29638        // start momentum animation if needed
29639        if ( this.options.momentum && duration < 300 ) {
29640            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 };
29641            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 };
29642            newX = momentumX.destination;
29643            newY = momentumY.destination;
29644            time = Math.max(momentumX.duration, momentumY.duration);
29645            this.isInTransition = 1;
29646        }
29647
29648
29649        if ( this.options.snap ) {
29650            var snap = this._nearestSnap(newX, newY);
29651            this.currentPage = snap;
29652            time = this.options.snapSpeed || Math.max(
29653                    Math.max(
29654                        Math.min(Math.abs(newX - snap.x), 1000),
29655                        Math.min(Math.abs(newY - snap.y), 1000)
29656                    ), 300);
29657            newX = snap.x;
29658            newY = snap.y;
29659
29660            this.directionX = 0;
29661            this.directionY = 0;
29662            easing = this.options.bounceEasing;
29663        }
29664
29665// INSERT POINT: _end
29666
29667        if ( newX != this.x || newY != this.y ) {
29668            // change easing function when scroller goes out of the boundaries
29669            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
29670                easing = utils.ease.quadratic;
29671            }
29672
29673            this.scrollTo(newX, newY, time, easing);
29674            return;
29675        }
29676
29677        this._execEvent('scrollEnd');
29678    },
29679
29680    _resize: function () {
29681        var that = this;
29682
29683        clearTimeout(this.resizeTimeout);
29684
29685        this.resizeTimeout = setTimeout(function () {
29686            that.refresh();
29687        }, this.options.resizePolling);
29688    },
29689
29690    resetPosition: function (time) {
29691        var x = this.x,
29692            y = this.y;
29693
29694        time = time || 0;
29695
29696        if ( !this.hasHorizontalScroll || this.x > 0 ) {
29697            x = 0;
29698        } else if ( this.x < this.maxScrollX ) {
29699            x = this.maxScrollX;
29700        }
29701
29702        if ( !this.hasVerticalScroll || this.y > 0 ) {
29703            y = 0;
29704        } else if ( this.y < this.maxScrollY ) {
29705            y = this.maxScrollY;
29706        }
29707
29708        if ( x == this.x && y == this.y ) {
29709            return false;
vendor: 5,509 bytes, lines 29710-29914
29710        }
29711
29712        this.scrollTo(x, y, time, this.options.bounceEasing);
29713
29714        return true;
29715    },
29716
29717    disable: function () {
29718        this.enabled = false;
29719    },
29720
29721    enable: function () {
29722        this.enabled = true;
29723    },
29724
29725    refresh: function () {
29726        var rf = this.wrapper.offsetHeight;     // Force reflow
29727
29728        this.wrapperWidth   = this.wrapper.clientWidth;
29729        this.wrapperHeight  = this.wrapper.clientHeight;
29730
29731/* REPLACE START: refresh */
29732
29733        this.scrollerWidth  = this.scroller.offsetWidth;
29734        this.scrollerHeight = this.scroller.offsetHeight;
29735
29736        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
29737        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
29738
29739/* REPLACE END: refresh */
29740
29741        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
29742        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
29743
29744        if ( !this.hasHorizontalScroll ) {
29745            this.maxScrollX = 0;
29746            this.scrollerWidth = this.wrapperWidth;
29747        }
29748
29749        if ( !this.hasVerticalScroll ) {
29750            this.maxScrollY = 0;
29751            this.scrollerHeight = this.wrapperHeight;
29752        }
29753
29754        this.endTime = 0;
29755        this.directionX = 0;
29756        this.directionY = 0;
29757
29758        this.wrapperOffset = utils.offset(this.wrapper);
29759
29760        this._execEvent('refresh');
29761
29762        this.resetPosition();
29763
29764// INSERT POINT: _refresh
29765
29766    },
29767
29768
29769    on: function (type, fn) {
29770        if ( !this._events[type] ) {
29771            this._events[type] = [];
29772        }
29773
29774        this._events[type].push(fn);
29775    },
29776
29777    off: function (type, fn) {
29778        if ( !this._events[type] ) {
29779            return;
29780        }
29781
29782        var index = this._events[type].indexOf(fn);
29783
29784        if ( index > -1 ) {
29785            this._events[type].splice(index, 1);
29786        }
29787    },
29788
29789    _execEvent: function (type) {
29790        if ( !this._events[type] ) {
29791            return;
29792        }
29793
29794        var i = 0,
29795            l = this._events[type].length;
29796
29797        if ( !l ) {
29798            return;
29799        }
29800
29801        for ( ; i < l; i++ ) {
29802            this._events[type][i].apply(this, [].slice.call(arguments, 1));
29803        }
29804    },
29805
29806    scrollBy: function (x, y, time, easing) {
29807        x = this.x + x;
29808        y = this.y + y;
29809        time = time || 0;
29810
29811        this.scrollTo(x, y, time, easing);
29812    },
29813
29814    scrollTo: function (x, y, time, easing) {
29815        easing = easing || utils.ease.circular;
29816
29817        this.isInTransition = this.options.useTransition && time > 0;
29818        var transitionType = this.options.useTransition && easing.style;
29819        if ( !time || transitionType ) {
29820                if(transitionType) {
29821                    this._transitionTimingFunction(easing.style);
29822                    this._transitionTime(time);
29823                }
29824            this._translate(x, y);
29825        } else {
29826            this._animate(x, y, time, easing.fn);
29827        }
29828    },
29829
29830    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29831        el = el.nodeType ? el : this.scroller.querySelector(el);
29832
29833        if ( !el ) {
29834            return;
29835        }
29836
29837        var pos = utils.offset(el);
29838
29839        pos.left -= this.wrapperOffset.left;
29840        pos.top  -= this.wrapperOffset.top;
29841
29842        // if offsetX/Y are true we center the element to the screen
29843        if ( offsetX === true ) {
29844            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29845        }
29846        if ( offsetY === true ) {
29847            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29848        }
29849
29850        pos.left -= offsetX || 0;
29851        pos.top  -= offsetY || 0;
29852
29853        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29854        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29855
29856        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29857
29858        this.scrollTo(pos.left, pos.top, time, easing);
29859    },
29860
29861    _transitionTime: function (time) {
29862        if (!this.options.useTransition) {
29863            return;
29864        }
29865        time = time || 0;
29866        var durationProp = utils.style.transitionDuration;
29867        if(!durationProp) {
29868            return;
29869        }
29870
29871        this.scrollerStyle[durationProp] = time + 'ms';
29872
29873        if ( !time && utils.isBadAndroid ) {
29874            this.scrollerStyle[durationProp] = '0.0001ms';
29875            // remove 0.0001ms
29876            var self = this;
29877            rAF(function() {
29878                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29879                    self.scrollerStyle[durationProp] = '0s';
29880                }
29881            });
29882        }
29883
29884
29885        if ( this.indicators ) {
29886            for ( var i = this.indicators.length; i--; ) {
29887                this.indicators[i].transitionTime(time);
29888            }
29889        }
29890
29891
29892// INSERT POINT: _transitionTime
29893
29894    },
29895
29896    _transitionTimingFunction: function (easing) {
29897        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29898
29899
29900        if ( this.indicators ) {
29901            for ( var i = this.indicators.length; i--; ) {
29902                this.indicators[i].transitionTimingFunction(easing);
29903            }
29904        }
29905
29906
29907// INSERT POINT: _transitionTimingFunction
29908
29909    },
29910
29911    _translate: function (x, y) {
29912        //Uncode addition
29913        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29914            return false;
vendor: 9,939 bytes, lines 29915-30226
29915
29916        if ( this.options.useTransform ) {
29917
29918/* REPLACE START: _translate */
29919
29920            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29921
29922/* REPLACE END: _translate */
29923
29924        } else {
29925            x = Math.round(x);
29926            y = Math.round(y);
29927            this.scrollerStyle.left = x + 'px';
29928            this.scrollerStyle.top = y + 'px';
29929        }
29930
29931        this.x = x;
29932        this.y = y;
29933
29934
29935        if ( this.indicators ) {
29936            for ( var i = this.indicators.length; i--; ) {
29937                this.indicators[i].updatePosition();
29938            }
29939        }
29940
29941        //Uncode addition
29942        var uncodevent = new CustomEvent('fp-slide-scroll');
29943        window.dispatchEvent(uncodevent);
29944
29945// INSERT POINT: _translate
29946
29947    },
29948
29949    _initEvents: function (remove) {
29950        var eventType = remove ? utils.removeEvent : utils.addEvent,
29951            target = this.options.bindToWrapper ? this.wrapper : window;
29952
29953        eventType(window, 'orientationchange', this);
29954        eventType(window, 'resize', this);
29955
29956        if ( this.options.click ) {
29957            eventType(this.wrapper, 'click', this, true);
29958        }
29959
29960        if ( !this.options.disableMouse ) {
29961            eventType(this.wrapper, 'mousedown', this);
29962            eventType(target, 'mousemove', this);
29963            eventType(target, 'mousecancel', this);
29964            eventType(target, 'mouseup', this);
29965        }
29966
29967        if ( utils.hasPointer && !this.options.disablePointer ) {
29968            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29969            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29970            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29971            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29972        }
29973
29974        if ( utils.hasTouch && !this.options.disableTouch ) {
29975            eventType(this.wrapper, 'touchstart', this);
29976            eventType(target, 'touchmove', this);
29977            eventType(target, 'touchcancel', this);
29978            eventType(target, 'touchend', this);
29979        }
29980
29981        eventType(this.scroller, 'transitionend', this);
29982        eventType(this.scroller, 'webkitTransitionEnd', this);
29983        eventType(this.scroller, 'oTransitionEnd', this);
29984        eventType(this.scroller, 'MSTransitionEnd', this);
29985    },
29986
29987    getComputedPosition: function () {
29988        var matrix = window.getComputedStyle(this.scroller, null),
29989            x, y;
29990
29991        if ( this.options.useTransform ) {
29992            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29993            x = +(matrix[12] || matrix[4]);
29994            y = +(matrix[13] || matrix[5]);
29995        } else {
29996            x = +matrix.left.replace(/[^-\d.]/g, '');
29997            y = +matrix.top.replace(/[^-\d.]/g, '');
29998        }
29999
30000        return { x: x, y: y };
30001    },
30002    _initIndicators: function () {
30003        var interactive = this.options.interactiveScrollbars,
30004            customStyle = typeof this.options.scrollbars != 'string',
30005            indicators = [],
30006            indicator;
30007
30008        var that = this;
30009
30010        this.indicators = [];
30011
30012        if ( this.options.scrollbars ) {
30013            // Vertical scrollbar
30014            if ( this.options.scrollY ) {
30015                indicator = {
30016                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
30017                    interactive: interactive,
30018                    defaultScrollbars: true,
30019                    customStyle: customStyle,
30020                    resize: this.options.resizeScrollbars,
30021                    shrink: this.options.shrinkScrollbars,
30022                    fade: this.options.fadeScrollbars,
30023                    listenX: false
30024                };
30025
30026                this.wrapper.appendChild(indicator.el);
30027                indicators.push(indicator);
30028            }
30029
30030            // Horizontal scrollbar
30031            if ( this.options.scrollX ) {
30032                indicator = {
30033                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
30034                    interactive: interactive,
30035                    defaultScrollbars: true,
30036                    customStyle: customStyle,
30037                    resize: this.options.resizeScrollbars,
30038                    shrink: this.options.shrinkScrollbars,
30039                    fade: this.options.fadeScrollbars,
30040                    listenY: false
30041                };
30042
30043                this.wrapper.appendChild(indicator.el);
30044                indicators.push(indicator);
30045            }
30046        }
30047
30048        if ( this.options.indicators ) {
30049            // TODO: check concat compatibility
30050            indicators = indicators.concat(this.options.indicators);
30051        }
30052
30053        for ( var i = indicators.length; i--; ) {
30054            this.indicators.push( new Indicator(this, indicators[i]) );
30055        }
30056
30057        // TODO: check if we can use array.map (wide compatibility and performance issues)
30058        function _indicatorsMap (fn) {
30059            if (that.indicators) {
30060                for ( var i = that.indicators.length; i--; ) {
30061                    fn.call(that.indicators[i]);
30062                }
30063            }
30064        }
30065
30066        if ( this.options.fadeScrollbars ) {
30067            this.on('scrollEnd', function () {
30068                _indicatorsMap(function () {
30069                    this.fade();
30070                });
30071            });
30072
30073            this.on('scrollCancel', function () {
30074                _indicatorsMap(function () {
30075                    this.fade();
30076                });
30077            });
30078
30079            this.on('scrollStart', function () {
30080                _indicatorsMap(function () {
30081                    this.fade(1);
30082                });
30083            });
30084
30085            this.on('beforeScrollStart', function () {
30086                _indicatorsMap(function () {
30087                    this.fade(1, true);
30088                });
30089            });
30090        }
30091
30092
30093        this.on('refresh', function () {
30094            _indicatorsMap(function () {
30095                this.refresh();
30096            });
30097        });
30098
30099        this.on('destroy', function () {
30100            _indicatorsMap(function () {
30101                this.destroy();
30102            });
30103
30104            delete this.indicators;
30105        });
30106    },
30107
30108    _initWheel: function () {
30109        utils.addEvent(this.wrapper, 'wheel', this);
30110        utils.addEvent(this.wrapper, 'mousewheel', this);
30111        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30112
30113        this.on('destroy', function () {
30114            clearTimeout(this.wheelTimeout);
30115            this.wheelTimeout = null;
30116            utils.removeEvent(this.wrapper, 'wheel', this);
30117            utils.removeEvent(this.wrapper, 'mousewheel', this);
30118            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
30119        });
30120    },
30121
30122    _wheel: function (e) {
30123        if ( !this.enabled ) {
30124            return;
30125        }
30126
30127        var wheelDeltaX, wheelDeltaY,
30128            newX, newY,
30129            that = this;
30130
30131        if ( this.wheelTimeout === undefined ) {
30132            that._execEvent('scrollStart');
30133        }
30134
30135        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
30136        clearTimeout(this.wheelTimeout);
30137        this.wheelTimeout = setTimeout(function () {
30138            if(!that.options.snap) {
30139                that._execEvent('scrollEnd');
30140            }
30141            that.wheelTimeout = undefined;
30142        }, 400);
30143
30144        if ( 'deltaX' in e ) {
30145            if (e.deltaMode === 1) {
30146                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
30147                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
30148            } else {
30149                wheelDeltaX = -e.deltaX;
30150                wheelDeltaY = -e.deltaY;
30151            }
30152        } else if ( 'wheelDeltaX' in e ) {
30153            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
30154            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
30155        } else if ( 'wheelDelta' in e ) {
30156            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
30157        } else if ( 'detail' in e ) {
30158            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
30159        } else {
30160            return;
30161        }
30162
30163        wheelDeltaX *= this.options.invertWheelDirection;
30164        wheelDeltaY *= this.options.invertWheelDirection;
30165
30166        if ( !this.hasVerticalScroll ) {
30167            wheelDeltaX = wheelDeltaY;
30168            wheelDeltaY = 0;
30169        }
30170
30171        if ( this.options.snap ) {
30172            newX = this.currentPage.pageX;
30173            newY = this.currentPage.pageY;
30174
30175            if ( wheelDeltaX > 0 ) {
30176                newX--;
30177            } else if ( wheelDeltaX < 0 ) {
30178                newX++;
30179            }
30180
30181            if ( wheelDeltaY > 0 ) {
30182                newY--;
30183            } else if ( wheelDeltaY < 0 ) {
30184                newY++;
30185            }
30186
30187            this.goToPage(newX, newY);
30188
30189            return;
30190        }
30191
30192        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
30193        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
30194
30195        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
30196        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
30197
30198        if ( newX > 0 ) {
30199            newX = 0;
30200        } else if ( newX < this.maxScrollX ) {
30201            newX = this.maxScrollX;
30202        }
30203
30204        if ( newY > 0 ) {
30205            newY = 0;
30206        } else if ( newY < this.maxScrollY ) {
30207            newY = this.maxScrollY;
30208        }
30209
30210        this.scrollTo(newX, newY, 0);
30211
30212// INSERT POINT: _wheel
30213    },
30214
30215    _initSnap: function () {
30216        this.currentPage = {};
30217
30218        if ( typeof this.options.snap == 'string' ) {
30219            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
30220        }
30221
30222        this.on('refresh', function () {
30223            var i = 0, l,
30224                m = 0, n,
30225                cx, cy,
30226                x = 0, y,
vendor: 7,339 bytes, lines 30227-30480
30227                stepX = this.options.snapStepX || this.wrapperWidth,
30228                stepY = this.options.snapStepY || this.wrapperHeight,
30229                el;
30230
30231            this.pages = [];
30232
30233            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
30234                return;
30235            }
30236
30237            if ( this.options.snap === true ) {
30238                cx = Math.round( stepX / 2 );
30239                cy = Math.round( stepY / 2 );
30240
30241                while ( x > -this.scrollerWidth ) {
30242                    this.pages[i] = [];
30243                    l = 0;
30244                    y = 0;
30245
30246                    while ( y > -this.scrollerHeight ) {
30247                        this.pages[i][l] = {
30248                            x: Math.max(x, this.maxScrollX),
30249                            y: Math.max(y, this.maxScrollY),
30250                            width: stepX,
30251                            height: stepY,
30252                            cx: x - cx,
30253                            cy: y - cy
30254                        };
30255
30256                        y -= stepY;
30257                        l++;
30258                    }
30259
30260                    x -= stepX;
30261                    i++;
30262                }
30263            } else {
30264                el = this.options.snap;
30265                l = el.length;
30266                n = -1;
30267
30268                for ( ; i < l; i++ ) {
30269                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
30270                        m = 0;
30271                        n++;
30272                    }
30273
30274                    if ( !this.pages[m] ) {
30275                        this.pages[m] = [];
30276                    }
30277
30278                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
30279                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
30280                    cx = x - Math.round(el[i].offsetWidth / 2);
30281                    cy = y - Math.round(el[i].offsetHeight / 2);
30282
30283                    this.pages[m][n] = {
30284                        x: x,
30285                        y: y,
30286                        width: el[i].offsetWidth,
30287                        height: el[i].offsetHeight,
30288                        cx: cx,
30289                        cy: cy
30290                    };
30291
30292                    if ( x > this.maxScrollX ) {
30293                        m++;
30294                    }
30295                }
30296            }
30297
30298            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
30299
30300            // Update snap threshold if needed
30301            if ( this.options.snapThreshold % 1 === 0 ) {
30302                this.snapThresholdX = this.options.snapThreshold;
30303                this.snapThresholdY = this.options.snapThreshold;
30304            } else {
30305                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
30306                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
30307            }
30308        });
30309
30310        this.on('flick', function () {
30311            var time = this.options.snapSpeed || Math.max(
30312                    Math.max(
30313                        Math.min(Math.abs(this.x - this.startX), 1000),
30314                        Math.min(Math.abs(this.y - this.startY), 1000)
30315                    ), 300);
30316
30317            this.goToPage(
30318                this.currentPage.pageX + this.directionX,
30319                this.currentPage.pageY + this.directionY,
30320                time
30321            );
30322        });
30323    },
30324
30325    _nearestSnap: function (x, y) {
30326        if ( !this.pages.length ) {
30327            return { x: 0, y: 0, pageX: 0, pageY: 0 };
30328        }
30329
30330        var i = 0,
30331            l = this.pages.length,
30332            m = 0;
30333
30334        // Check if we exceeded the snap threshold
30335        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
30336            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
30337            return this.currentPage;
30338        }
30339
30340        if ( x > 0 ) {
30341            x = 0;
30342        } else if ( x < this.maxScrollX ) {
30343            x = this.maxScrollX;
30344        }
30345
30346        if ( y > 0 ) {
30347            y = 0;
30348        } else if ( y < this.maxScrollY ) {
30349            y = this.maxScrollY;
30350        }
30351
30352        for ( ; i < l; i++ ) {
30353            if ( x >= this.pages[i][0].cx ) {
30354                x = this.pages[i][0].x;
30355                break;
30356            }
30357        }
30358
30359        l = this.pages[i].length;
30360
30361        for ( ; m < l; m++ ) {
30362            if ( y >= this.pages[0][m].cy ) {
30363                y = this.pages[0][m].y;
30364                break;
30365            }
30366        }
30367
30368        if ( i == this.currentPage.pageX ) {
30369            i += this.directionX;
30370
30371            if ( i < 0 ) {
30372                i = 0;
30373            } else if ( i >= this.pages.length ) {
30374                i = this.pages.length - 1;
30375            }
30376
30377            x = this.pages[i][0].x;
30378        }
30379
30380        if ( m == this.currentPage.pageY ) {
30381            m += this.directionY;
30382
30383            if ( m < 0 ) {
30384                m = 0;
30385            } else if ( m >= this.pages[0].length ) {
30386                m = this.pages[0].length - 1;
30387            }
30388
30389            y = this.pages[0][m].y;
30390        }
30391
30392        return {
30393            x: x,
30394            y: y,
30395            pageX: i,
30396            pageY: m
30397        };
30398    },
30399
30400    goToPage: function (x, y, time, easing) {
30401        easing = easing || this.options.bounceEasing;
30402
30403        if ( x >= this.pages.length ) {
30404            x = this.pages.length - 1;
30405        } else if ( x < 0 ) {
30406            x = 0;
30407        }
30408
30409        if ( y >= this.pages[x].length ) {
30410            y = this.pages[x].length - 1;
30411        } else if ( y < 0 ) {
30412            y = 0;
30413        }
30414
30415        var posX = this.pages[x][y].x,
30416            posY = this.pages[x][y].y;
30417
30418        time = time === undefined ? this.options.snapSpeed || Math.max(
30419            Math.max(
30420                Math.min(Math.abs(posX - this.x), 1000),
30421                Math.min(Math.abs(posY - this.y), 1000)
30422            ), 300) : time;
30423
30424        this.currentPage = {
30425            x: posX,
30426            y: posY,
30427            pageX: x,
30428            pageY: y
30429        };
30430
30431        this.scrollTo(posX, posY, time, easing);
30432    },
30433
30434    next: function (time, easing) {
30435        var x = this.currentPage.pageX,
30436            y = this.currentPage.pageY;
30437
30438        x++;
30439
30440        if ( x >= this.pages.length && this.hasVerticalScroll ) {
30441            x = 0;
30442            y++;
30443        }
30444
30445        this.goToPage(x, y, time, easing);
30446    },
30447
30448    prev: function (time, easing) {
30449        var x = this.currentPage.pageX,
30450            y = this.currentPage.pageY;
30451
30452        x--;
30453
30454        if ( x < 0 && this.hasVerticalScroll ) {
30455            x = 0;
30456            y--;
30457        }
30458
30459        this.goToPage(x, y, time, easing);
30460    },
30461
30462    _initKeys: function (e) {
30463        // default key bindings
30464        var keys = {
30465            pageUp: 33,
30466            pageDown: 34,
30467            end: 35,
30468            home: 36,
30469            left: 37,
30470            up: 38,
30471            right: 39,
30472            down: 40
30473        };
30474        var i;
30475
30476        // if you give me characters I give you keycode
30477        if ( typeof this.options.keyBindings == 'object' ) {
30478            for ( i in this.options.keyBindings ) {
30479                if ( typeof this.options.keyBindings[i] == 'string' ) {
30480                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 30480-30833
30480deAt(0);
30481                }
30482            }
30483        } else {
30484            this.options.keyBindings = {};
30485        }
30486
30487        for ( i in keys ) {
30488            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
30489        }
30490
30491        utils.addEvent(window, 'keydown', this);
30492
30493        this.on('destroy', function () {
30494            utils.removeEvent(window, 'keydown', this);
30495        });
30496    },
30497
30498    _key: function (e) {
30499        if ( !this.enabled ) {
30500            return;
30501        }
30502
30503        var snap = this.options.snap,   // we are using this alot, better to cache it
30504            newX = snap ? this.currentPage.pageX : this.x,
30505            newY = snap ? this.currentPage.pageY : this.y,
30506            now = utils.getTime(),
30507            prevTime = this.keyTime || 0,
30508            acceleration = 0.250,
30509            pos;
30510
30511        if ( this.options.useTransition && this.isInTransition ) {
30512            pos = this.getComputedPosition();
30513
30514            this._translate(Math.round(pos.x), Math.round(pos.y));
30515            this.isInTransition = false;
30516        }
30517
30518        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
30519
30520        switch ( e.keyCode ) {
30521            case this.options.keyBindings.pageUp:
30522                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30523                    newX += snap ? 1 : this.wrapperWidth;
30524                } else {
30525                    newY += snap ? 1 : this.wrapperHeight;
30526                }
30527                break;
30528            case this.options.keyBindings.pageDown:
30529                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30530                    newX -= snap ? 1 : this.wrapperWidth;
30531                } else {
30532                    newY -= snap ? 1 : this.wrapperHeight;
30533                }
30534                break;
30535            case this.options.keyBindings.end:
30536                newX = snap ? this.pages.length-1 : this.maxScrollX;
30537                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
30538                break;
30539            case this.options.keyBindings.home:
30540                newX = 0;
30541                newY = 0;
30542                break;
30543            case this.options.keyBindings.left:
30544                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
30545                break;
30546            case this.options.keyBindings.up:
30547                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
30548                break;
30549            case this.options.keyBindings.right:
30550                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
30551                break;
30552            case this.options.keyBindings.down:
30553                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
30554                break;
30555            default:
30556                return;
30557        }
30558
30559        if ( snap ) {
30560            this.goToPage(newX, newY);
30561            return;
30562        }
30563
30564        if ( newX > 0 ) {
30565            newX = 0;
30566            this.keyAcceleration = 0;
30567        } else if ( newX < this.maxScrollX ) {
30568            newX = this.maxScrollX;
30569            this.keyAcceleration = 0;
30570        }
30571
30572        if ( newY > 0 ) {
30573            newY = 0;
30574            this.keyAcceleration = 0;
30575        } else if ( newY < this.maxScrollY ) {
30576            newY = this.maxScrollY;
30577            this.keyAcceleration = 0;
30578        }
30579
30580        this.scrollTo(newX, newY, 0);
30581
30582        this.keyTime = now;
30583    },
30584
30585    _animate: function (destX, destY, duration, easingFn) {
30586        var that = this,
30587            startX = this.x,
30588            startY = this.y,
30589            startTime = utils.getTime(),
30590            destTime = startTime + duration;
30591
30592        function step () {
30593            var now = utils.getTime(),
30594                newX, newY,
30595                easing;
30596
30597            if ( now >= destTime ) {
30598                that.isAnimating = false;
30599                that._translate(destX, destY);
30600
30601                if ( !that.resetPosition(that.options.bounceTime) ) {
30602                    that._execEvent('scrollEnd');
30603                }
30604
30605                return;
30606            }
30607
30608            now = ( now - startTime ) / duration;
30609            easing = easingFn(now);
30610            newX = ( destX - startX ) * easing + startX;
30611            newY = ( destY - startY ) * easing + startY;
30612            that._translate(newX, newY);
30613
30614            if ( that.isAnimating ) {
30615                rAF(step);
30616            }
30617        }
30618
30619        this.isAnimating = true;
30620        step();
30621    },
30622    handleEvent: function (e) {
30623        switch ( e.type ) {
30624            case 'touchstart':
30625            case 'pointerdown':
30626            case 'MSPointerDown':
30627            case 'mousedown':
30628                this._start(e);
30629                break;
30630            case 'touchmove':
30631            case 'pointermove':
30632            case 'MSPointerMove':
30633            case 'mousemove':
30634                this._move(e);
30635                break;
30636            case 'touchend':
30637            case 'pointerup':
30638            case 'MSPointerUp':
30639            case 'mouseup':
30640            case 'touchcancel':
30641            case 'pointercancel':
30642            case 'MSPointerCancel':
30643            case 'mousecancel':
30644                this._end(e);
30645                break;
30646            case 'orientationchange':
30647            case 'resize':
30648                this._resize();
30649                break;
30650            case 'transitionend':
30651            case 'webkitTransitionEnd':
30652            case 'oTransitionEnd':
30653            case 'MSTransitionEnd':
30654                this._transitionEnd(e);
30655                break;
30656            case 'wheel':
30657            case 'DOMMouseScroll':
30658            case 'mousewheel':
30659                this._wheel(e);
30660                break;
30661            case 'keydown':
30662                this._key(e);
30663                break;
30664            case 'click':
30665                if ( this.enabled && !e._constructed ) {
30666                    e.preventDefault();
30667                    e.stopPropagation();
30668                }
30669                break;
30670        }
30671    }
30672};
30673function createDefaultScrollbar (direction, interactive, type) {
30674    var scrollbar = document.createElement('div'),
30675        indicator = document.createElement('div');
30676
30677    if ( type === true ) {
30678        scrollbar.style.cssText = 'position:absolute;z-index:9999';
30679        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';
30680    }
30681
30682    indicator.className = 'iScrollIndicator';
30683
30684    if ( direction == 'h' ) {
30685        if ( type === true ) {
30686            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
30687            indicator.style.height = '100%';
30688        }
30689        scrollbar.className = 'iScrollHorizontalScrollbar';
30690    } else {
30691        if ( type === true ) {
30692            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
30693            indicator.style.width = '100%';
30694        }
30695        scrollbar.className = 'iScrollVerticalScrollbar';
30696    }
30697
30698    scrollbar.style.cssText += ';overflow:hidden';
30699
30700    if ( !interactive ) {
30701        scrollbar.style.pointerEvents = 'none';
30702    }
30703
30704    scrollbar.appendChild(indicator);
30705
30706    return scrollbar;
30707}
30708
30709function Indicator (scroller, options) {
30710    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
30711    this.wrapperStyle = this.wrapper.style;
30712    this.indicator = this.wrapper.children[0];
30713    this.indicatorStyle = this.indicator.style;
30714    this.scroller = scroller;
30715
30716    this.options = {
30717        listenX: true,
30718        listenY: true,
30719        interactive: false,
30720        resize: true,
30721        defaultScrollbars: false,
30722        shrink: false,
30723        fade: false,
30724        speedRatioX: 0,
30725        speedRatioY: 0
30726    };
30727
30728    for ( var i in options ) {
30729        this.options[i] = options[i];
30730    }
30731
30732    this.sizeRatioX = 1;
30733    this.sizeRatioY = 1;
30734    this.maxPosX = 0;
30735    this.maxPosY = 0;
30736
30737    if ( this.options.interactive ) {
30738        if ( !this.options.disableTouch ) {
30739            utils.addEvent(this.indicator, 'touchstart', this);
30740            utils.addEvent(window, 'touchend', this);
30741        }
30742        if ( !this.options.disablePointer ) {
30743            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30744            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
30745        }
30746        if ( !this.options.disableMouse ) {
30747            utils.addEvent(this.indicator, 'mousedown', this);
30748            utils.addEvent(window, 'mouseup', this);
30749        }
30750    }
30751
30752    if ( this.options.fade ) {
30753        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
30754        var durationProp = utils.style.transitionDuration;
30755        if(!durationProp) {
30756            return;
30757        }
30758        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
30759        // remove 0.0001ms
30760        var self = this;
30761        if(utils.isBadAndroid) {
30762            rAF(function() {
30763                if(self.wrapperStyle[durationProp] === '0.0001ms') {
30764                    self.wrapperStyle[durationProp] = '0s';
30765                }
30766            });
30767        }
30768        this.wrapperStyle.opacity = '0';
30769    }
30770}
30771
30772Indicator.prototype = {
30773    handleEvent: function (e) {
30774        switch ( e.type ) {
30775            case 'touchstart':
30776            case 'pointerdown':
30777            case 'MSPointerDown':
30778            case 'mousedown':
30779                this._start(e);
30780                break;
30781            case 'touchmove':
30782            case 'pointermove':
30783            case 'MSPointerMove':
30784            case 'mousemove':
30785                this._move(e);
30786                break;
30787            case 'touchend':
30788            case 'pointerup':
30789            case 'MSPointerUp':
30790            case 'mouseup':
30791            case 'touchcancel':
30792            case 'pointercancel':
30793            case 'MSPointerCancel':
30794            case 'mousecancel':
30795                this._end(e);
30796                break;
30797        }
30798    },
30799
30800    destroy: function () {
30801        if ( this.options.fadeScrollbars ) {
30802            clearTimeout(this.fadeTimeout);
30803            this.fadeTimeout = null;
30804        }
30805        if ( this.options.interactive ) {
30806            utils.removeEvent(this.indicator, 'touchstart', this);
30807            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30808            utils.removeEvent(this.indicator, 'mousedown', this);
30809
30810            utils.removeEvent(window, 'touchmove', this);
30811            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30812            utils.removeEvent(window, 'mousemove', this);
30813
30814            utils.removeEvent(window, 'touchend', this);
30815            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
30816            utils.removeEvent(window, 'mouseup', this);
30817        }
30818
30819        if ( this.options.defaultScrollbars ) {
30820            this.wrapper.parentNode.removeChild(this.wrapper);
30821        }
30822    },
30823
30824    _start: function (e) {
30825        var point = e.touches ? e.touches[0] : e;
30826
30827        e.preventDefault();
30828        e.stopPropagation();
30829
30830        this.transitionTime();
30831
30832        this.initiated = true;
30833        this.moved = false;
vendor: 9,615 bytes, lines 30834-31092
30834        this.lastPointX = point.pageX;
30835        this.lastPointY = point.pageY;
30836
30837        this.startTime  = utils.getTime();
30838
30839        if ( !this.options.disableTouch ) {
30840            utils.addEvent(window, 'touchmove', this);
30841        }
30842        if ( !this.options.disablePointer ) {
30843            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30844        }
30845        if ( !this.options.disableMouse ) {
30846            utils.addEvent(window, 'mousemove', this);
30847        }
30848
30849        this.scroller._execEvent('beforeScrollStart');
30850    },
30851
30852    _move: function (e) {
30853        var point = e.touches ? e.touches[0] : e,
30854            deltaX, deltaY,
30855            newX, newY,
30856            timestamp = utils.getTime();
30857
30858        if ( !this.moved ) {
30859            this.scroller._execEvent('scrollStart');
30860        }
30861
30862        this.moved = true;
30863
30864        deltaX = point.pageX - this.lastPointX;
30865        this.lastPointX = point.pageX;
30866
30867        deltaY = point.pageY - this.lastPointY;
30868        this.lastPointY = point.pageY;
30869
30870        newX = this.x + deltaX;
30871        newY = this.y + deltaY;
30872
30873        this._pos(newX, newY);
30874
30875// INSERT POINT: indicator._move
30876
30877        e.preventDefault();
30878        e.stopPropagation();
30879    },
30880
30881    _end: function (e) {
30882        if ( !this.initiated ) {
30883            return;
30884        }
30885
30886        this.initiated = false;
30887
30888        e.preventDefault();
30889        e.stopPropagation();
30890
30891        utils.removeEvent(window, 'touchmove', this);
30892        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30893        utils.removeEvent(window, 'mousemove', this);
30894
30895        if ( this.scroller.options.snap ) {
30896            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30897
30898            var time = this.options.snapSpeed || Math.max(
30899                    Math.max(
30900                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30901                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30902                    ), 300);
30903
30904            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30905                this.scroller.directionX = 0;
30906                this.scroller.directionY = 0;
30907                this.scroller.currentPage = snap;
30908                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30909            }
30910        }
30911
30912        if ( this.moved ) {
30913            this.scroller._execEvent('scrollEnd');
30914        }
30915    },
30916
30917    transitionTime: function (time) {
30918        time = time || 0;
30919        var durationProp = utils.style.transitionDuration;
30920        if(!durationProp) {
30921            return;
30922        }
30923
30924        this.indicatorStyle[durationProp] = time + 'ms';
30925
30926        if ( !time && utils.isBadAndroid ) {
30927            this.indicatorStyle[durationProp] = '0.0001ms';
30928            // remove 0.0001ms
30929            var self = this;
30930            rAF(function() {
30931                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30932                    self.indicatorStyle[durationProp] = '0s';
30933                }
30934            });
30935        }
30936    },
30937
30938    transitionTimingFunction: function (easing) {
30939        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30940    },
30941
30942    refresh: function () {
30943        this.transitionTime();
30944
30945        if ( this.options.listenX && !this.options.listenY ) {
30946            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30947        } else if ( this.options.listenY && !this.options.listenX ) {
30948            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30949        } else {
30950            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30951        }
30952
30953        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30954            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30955            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30956
30957            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30958                if ( this.options.listenX ) {
30959                    this.wrapper.style.right = '8px';
30960                } else {
30961                    this.wrapper.style.bottom = '8px';
30962                }
30963            }
30964        } else {
30965            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30966            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30967
30968            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30969                if ( this.options.listenX ) {
30970                    this.wrapper.style.right = '2px';
30971                } else {
30972                    this.wrapper.style.bottom = '2px';
30973                }
30974            }
30975        }
30976
30977        var r = this.wrapper.offsetHeight;  // force refresh
30978
30979        if ( this.options.listenX ) {
30980            this.wrapperWidth = this.wrapper.clientWidth;
30981            if ( this.options.resize ) {
30982                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30983                this.indicatorStyle.width = this.indicatorWidth + 'px';
30984            } else {
30985                this.indicatorWidth = this.indicator.clientWidth;
30986            }
30987
30988            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30989
30990            if ( this.options.shrink == 'clip' ) {
30991                this.minBoundaryX = -this.indicatorWidth + 8;
30992                this.maxBoundaryX = this.wrapperWidth - 8;
30993            } else {
30994                this.minBoundaryX = 0;
30995                this.maxBoundaryX = this.maxPosX;
30996            }
30997
30998            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30999        }
31000
31001        if ( this.options.listenY ) {
31002            this.wrapperHeight = this.wrapper.clientHeight;
31003            if ( this.options.resize ) {
31004                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
31005                this.indicatorStyle.height = this.indicatorHeight + 'px';
31006            } else {
31007                this.indicatorHeight = this.indicator.clientHeight;
31008            }
31009
31010            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31011
31012            if ( this.options.shrink == 'clip' ) {
31013                this.minBoundaryY = -this.indicatorHeight + 8;
31014                this.maxBoundaryY = this.wrapperHeight - 8;
31015            } else {
31016                this.minBoundaryY = 0;
31017                this.maxBoundaryY = this.maxPosY;
31018            }
31019
31020            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31021            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
31022        }
31023
31024        this.updatePosition();
31025    },
31026
31027    updatePosition: function () {
31028        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
31029            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
31030
31031        if ( !this.options.ignoreBoundaries ) {
31032            if ( x < this.minBoundaryX ) {
31033                if ( this.options.shrink == 'scale' ) {
31034                    this.width = Math.max(this.indicatorWidth + x, 8);
31035                    this.indicatorStyle.width = this.width + 'px';
31036                }
31037                x = this.minBoundaryX;
31038            } else if ( x > this.maxBoundaryX ) {
31039                if ( this.options.shrink == 'scale' ) {
31040                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
31041                    this.indicatorStyle.width = this.width + 'px';
31042                    x = this.maxPosX + this.indicatorWidth - this.width;
31043                } else {
31044                    x = this.maxBoundaryX;
31045                }
31046            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
31047                this.width = this.indicatorWidth;
31048                this.indicatorStyle.width = this.width + 'px';
31049            }
31050
31051            if ( y < this.minBoundaryY ) {
31052                if ( this.options.shrink == 'scale' ) {
31053                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
31054                    this.indicatorStyle.height = this.height + 'px';
31055                }
31056                y = this.minBoundaryY;
31057            } else if ( y > this.maxBoundaryY ) {
31058                if ( this.options.shrink == 'scale' ) {
31059                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31060                    this.indicatorStyle.height = this.height + 'px';
31061                    y = this.maxPosY + this.indicatorHeight - this.height;
31062                } else {
31063                    y = this.maxBoundaryY;
31064                }
31065            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31066                this.height = this.indicatorHeight;
31067                this.indicatorStyle.height = this.height + 'px';
31068            }
31069        }
31070
31071        this.x = x;
31072        this.y = y;
31073
31074        if ( this.scroller.options.useTransform ) {
31075            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31076        } else {
31077            this.indicatorStyle.left = x + 'px';
31078            this.indicatorStyle.top = y + 'px';
31079        }
31080    },
31081
31082    _pos: function (x, y) {
31083        if ( x < 0 ) {
31084            x = 0;
31085        } else if ( x > this.maxPosX ) {
31086            x = this.maxPosX;
31087        }
31088
31089        if ( y < 0 ) {
31090            y = 0;
31091        } else if ( y > this.maxPosY ) {
31092            y = this.maxPosY;
31093        }
31094
31095        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31096        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31097
31098        this.scroller.scrollTo(x, y);
31099    },
31100
31101    fade: function (val, hold) {
31102        if ( hold && !this.visible ) {
31103            return;
31104        }
31105
31106        clearTimeout(this.fadeTimeout);
31107        this.fadeTimeout = null;
31108
31109        var time = val ? 250 : 500,
31110            delay = val ? 0 : 300;
31111
31112        val = val ? '1' : '0';
31113
31114        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31115
31116        this.fadeTimeout = setTimeout((function (val) {
31117            this.wrapperStyle.opacity = val;
31118            this.visible = +val;
31119        }).bind(this, val), delay);
31120    }
31121};
31122
31123IScroll.utils = utils;
31124
31125if ( typeof module != 'undefined' && module.exports ) {
31126    module.exports = IScroll;
31127} else if ( typeof define == 'function' && define.amd ) {
31128        define( function () { return IScroll; } );
31129} else {
31130    window.IScroll = IScroll;
31131}
31132
31133})(window, document, Math);
31134/*!
31135 * fullPage 2.9.4
31136 * https://github.com/alvarotrigo/fullPage.js
31137 * @license MIT licensed
31138 *
31139 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
31140 */
31141(function(global, factory) {
31142    'use strict';
31143    if (typeof define === 'function' && define.amd) {
31144        define(['jquery'], function($) {
31145          return factory($, global, global.document, global.Math);
31146        });
31147    } else if (typeof exports === "object" && exports) {
31148        module.exports = factory(require('jquery'), global, global.document, global.Math);
31149    } else {
31150        factory(jQuery, global, global.document, global.Math);
31151    }
31152})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
31153    'use strict';
31154
31155    // keeping central set of classnames and selectors
31156    var WRAPPER =               'fullpage-wrapper';
31157    var WRAPPER_SEL =           '.' + WRAPPER;
31158
31159    // slimscroll
31160    var SCROLLABLE =            'fp-scrollable';
31161    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
31162
31163    // util
31164    var RESPONSIVE =            'fp-responsive';
31165    var NO_TRANSITION =         'fp-notransition';
31166    var DESTROYED =             'fp-destroyed';
31167    var ENABLED =               'fp-enabled';
31168    var VIEWING_PREFIX =        'fp-viewing';
31169    var ACTIVE =                'active';
31170    var ACTIVE_SEL =            '.' + ACTIVE;
31171    var COMPLETELY =            'fp-completely';
31172    var COMPLETELY_SEL =        '.' + COMPLETELY;
31173
31174    // section
31175    var SECTION_DEFAULT_SEL =   '.section';
31176    var SECTION =               'fp-section';
31177    var SECTION_SEL =           '.' + SECTION;
31178    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
31179    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
31180    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
31181    var TABLE_CELL =            'fp-tableCell';
31182    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
31183    var AUTO_HEIGHT =           'fp-auto-height';
31184    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
31185    var NORMAL_SCROLL =         'fp-normal-scroll';
31186    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
31187
31188    // section nav
31189    var SECTION_NAV =           'fp-nav';
31190    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
31191    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
31192    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
31193    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
31194
31195    // slide
31196    var SLIDE_DEFAULT_SEL =     '.slide';
31197    var SLIDE =                 'fp-slide';
31198    var SLIDE_SEL =             '.' + SLIDE;
31199    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
31200    var SLIDES_WRAPPER =        'fp-slides';
31201    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
31202    var SLIDES_CONTAINER =      'fp-slidesContainer';
31203    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
31204    var TABLE =                 'fp-table';
31205
31206    // slide nav
31207    var SLIDES_NAV =            'fp-slidesNav';
31208    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
31209    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
31210    var SLIDES_ARROW =          'fp-controlArrow';
31211    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
31212    var SLIDES_PREV =           'fp-prev';
31213    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
31214    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
31215    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
31216    var SLIDES_NEXT =           'fp-next';
31217    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
31218    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
31219    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
31220
31221    var $window = $(window);
31222    var $document = $(document);
31223
31224    // Default options for iScroll.js used when using scrollOverflow
31225    var iscrollOptions = {
31226        scrollbars: true,
31227        mouseWheel: true,
31228        hideScrollbars: false,
31229        fadeScrollbars: false,
31230        disableMouse: true,
31231        interactiveScrollbars: true,
31232        bounce: false,
31233    };
31234
31235    $.fn.fullpage = function(options) {
31236        //only once my friend!
31237        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
31238
31239        // common jQuery objects
31240        var $htmlBody = $('html, body');
31241        var $body = $('body');
31242
31243        var FP = $.fn.fullpage;
31244
31245        // Creating some defaults, extending them with any options that were provided
31246        options = $.extend({
31247            //navigation
31248            menu: false,
31249            anchors:[],
31250            lockAnchors: false,
31251            navigation: false,
31252            navigationPosition: 'right',
31253            navigationTooltips: [],
31254            showActiveTooltip: false,
31255            slidesNavigation: false,
31256            slidesNavPosition: 'bottom',
31257            scrollBar: false,
31258            hybrid: false,
31259
31260            //scrolling
31261            css3: true,
31262            scrollingSpeed: 700,
31263            autoScrolling: true,
31264            fitToSection: true,
31265            fitToSectionDelay: 1000,
31266            easing: 'easeInOutCubic',
31267            easingcss3: 'ease',
31268            loopBottom: false,
31269            loopTop: false,
31270            loopHorizontal: true,
31271            continuousVertical: false,
31272            continuousHorizontal: false,
31273            scrollHorizontally: false,
31274            interlockedSlides: false,
31275            dragAndMove: false,
31276            offsetSections: false,
31277            resetSliders: false,
31278            fadingEffect: false,
31279            normalScrollElements: null,
31280            scrollOverflow: false,
31281            scrollOverflowReset: false,
31282            scrollOverflowHandler: iscrollHandler,
31283            scrollOverflowOptions: null,
31284            touchSensitivity: 5,
31285            normalScrollElementTouchThreshold: 5,
31286            bigSectionsDestination: null,
31287
31288            //Accessibility
31289            keyboardScrolling: true,
31290            animateAnchor: true,
31291            recordHistory: true,
31292
31293            //design
31294            controlArrows: true,
31295            controlArrowColor: '#fff',
31296            verticalCentered: true,
31297            sectionsColor : [],
31298            paddingTop: 0,
31299            paddingBottom: 0,
31300            fixedElements: null,
31301            responsive: 0, //backwards compabitility with responsiveWiddth
31302            responsiveWidth: 0,
31303            responsiveHeight: 0,
31304            responsiveSlides: false,
31305            parallax: false,
31306            parallaxOptions: {
31307                type: 'reveal',
31308                percentage: 62,
31309                property: 'translate'
31310            },
31311
31312            //Custom selectors
31313            sectionSelector: SECTION_DEFAULT_SEL,
31314            slideSelector: SLIDE_DEFAULT_SEL,
31315
31316            //events
31317            afterLoad: null,
31318            onLeave: null,
31319            afterRender: null,
31320            afterResize: null,
31321            afterReBuild: null,
31322            afterSlideLoad: null,
31323            onSlideLeave: null,
31324            afterResponsive: null,
31325
31326            lazyLoading: true
31327        }, options);
31328
31329        //flag to avoid very fast sliding for landscape sliders
31330        var slideMoving = false;
31331
31332        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
31333        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
31334        var container = $(this);
31335        var windowsHeight = $window.height();
31336        var isResizing = false;
31337        var isWindowFocused = true;
31338        var lastScrolledDestiny;
31339        var lastScrolledSlide;
31340        var canScroll = true;
31341        var scrollings = [];
31342        var controlPressed;
31343        var startingSection;
31344        var isScrollAllowed = {};
31345        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
31346        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
31347        var MSPointer = getMSPointer();
31348        var events = {
31349            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
31350            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
31351        };
31352
31353        //cheks for passive event support
31354        //added by Uncode from new fullPage updates
31355        var g_supportsPassive = false;
31356        try {
31357          var opts = Object.defineProperty({}, 'passive', {
31358            get: function() {
31359              g_supportsPassive = true;
31360            }
31361          });
31362          window.addEventListener("testPassive", null, opts);
31363          window.removeEventListener("testPassive", null, opts);
31364        } catch (e) {}
31365
31366        //timeouts
31367        var resizeId;
31368        var afterSectionLoadsId;
31369        var afterSlideLoadsId;
31370        var scrollId;
31371        var scrollId2;
31372        var keydownId;
31373        var originals = $.extend(true, {}, options); //deep copy
31374
31375        //Uncode addition
31376        var $masthead = $('#masthead');
31377        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
31378        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
31379        var bodyBorder = UNCODE.bodyBorder;
31380        var adminBarHeight = UNCODE.adminBarHeight;
31381
31382        displayWarnings();
31383
31384        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
31385        iscrollOptions.click = isTouch; // see #2035
31386
31387        //extending iScroll options with the user custom ones
31388        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
31389
31390        //easeInOutCubic animation included in the plugin
31391        $.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;}});
31392
31393        /**
31394        * Sets the autoScroll option.
31395        * It changes the scroll bar visibility and the history of the site as a result.
31396        */
31397        function setAutoScrolling(value, type){
31398            //removing the transformation
31399            if(!value){
31400                silentScroll(0);
31401            }
31402
31403            setVariableState('autoScrolling', value, type);
31404
31405            var element = $(SECTION_ACTIVE_SEL);
31406
31407            if(options.autoScrolling && !options.scrollBar){
31408                $htmlBody.css({
31409                    'overflow' : 'hidden !important',
31410                    'height' : '100%'
31411                });
31412
31413                //Uncode addition
31414                //setRecordHistory(originals.recordHistory, 'internal');
31415
31416                //for IE touch devices
31417                container.css({
31418                    '-ms-touch-action': 'none',
31419                    'touch-action': 'none'
31420                });
31421
31422                if(element.length){
31423                    //moving the container up
31424                    silentScroll(element.position().top);
31425                }
31426
31427            }else{
31428                $htmlBody.css({
31429                    'overflow' : 'visible !important',
31430                    'height' : 'initial'
31431                });
31432
31433                //Uncode addition
31434                //setRecordHistory(false, 'internal');
31435
31436                //for IE touch devices
31437                container.css({
31438                    '-ms-touch-action': '',
31439                    'touch-action': ''
31440                });
31441
31442                //scrolling the page to the section with no animation
31443                if (element.length) {
31444                    $htmlBody.scrollTop(element.position().top);
31445                }
31446            }
31447        }
31448
31449        /**
31450        * Defines wheter to record the history for each hash change in the URL.
31451        */
31452        function setRecordHistory(value, type){
31453            setVariableState('recordHistory', value, type);
31454        }
31455
31456        /**
31457        * Defines the scrolling speed
31458        */
31459        function setScrollingSpeed(value, type){
31460            setVariableState('scrollingSpeed', value, type);
31461        }
31462
31463        /**
31464        * Sets fitToSection
31465        */
31466        function setFitToSection(value, type){
31467            setVariableState('fitToSection', value, type);
31468        }
31469
31470        /**
31471        * Sets lockAnchors
31472        */
31473        function setLockAnchors(value){
31474            options.lockAnchors = value;
31475        }
31476
31477        /**
31478        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
31479        */
31480        function setMouseWheelScrolling(value){
31481            if(value){
31482                addMouseWheelHandler();
31483                addMiddleWheelHandler();
31484            }else{
31485                removeMouseWheelHandler();
31486                removeMiddleWheelHandler();
31487            }
31488        }
31489
31490        /**
31491        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
31492        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
31493        *
31494        * @param directions string containing the direction or directions separated by comma.
31495        */
31496        function setAllowScrolling(value, directions){
31497            if(typeof directions !== 'undefined'){
31498                directions = directions.replace(/ /g,'').split(',');
31499
31500                $.each(directions, function (index, direction){
31501                    setIsScrollAllowed(value, direction, 'm');
31502                });
31503            }
31504            else if(value){
31505                setMouseWheelScrolling(true);
31506                addTouchHandler();
31507            }else{
31508                setMouseWheelScrolling(false);
31509                removeTouchHandler();
31510            }
31511        }
31512
31513        /**
31514        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
31515        */
31516        function setKeyboardScrolling(value, directions){
31517            if(typeof directions !== 'undefined'){
31518                directions = directions.replace(/ /g,'').split(',');
31519
31520                $.each(directions, function (index, direction){
31521                    setIsScrollAllowed(value, direction, 'k');
31522                });
31523            }else{
31524                options.keyboardScrolling = value;
31525            }
31526        }
31527
31528        /**
31529        * Moves the page up one section.
31530        */
31531        function moveSectionUp(){
31532            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
31533
31534            //looping to the bottom if there's no more sections above
31535            if (!prev.length && (options.loopTop || options.continuousVertical)) {
31536                prev = $(SECTION_SEL).last();
31537            }
31538
31539            if (prev.length) {
31540                scrollPage(prev, null, true);
31541            }
31542        }
31543
31544        /**
31545        * Moves the page down one section.
31546        */
31547        function moveSectionDown(){
31548            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
31549
31550            //looping to the top if there's no more sections below
31551            if(!next.length &&
31552                (options.loopBottom || options.continuousVertical)){
31553                next = $(SECTION_SEL).first();
31554            }
31555
31556            if(next.length){
31557                scrollPage(next, null, false);
31558            }
31559        }
31560
31561        /**
31562        * Moves the page to the given section and slide with no animation.
31563        * Anchors or index positions can be used as params.
31564        */
31565        function silentMoveTo(sectionAnchor, slideAnchor){
31566            setScrollingSpeed (0, 'internal');
31567            moveTo(sectionAnchor, slideAnchor);
31568            setScrollingSpeed (originals.scrollingSpeed, 'internal');
31569        }
31570
31571        /**
31572        * Moves the page to the given section and slide.
31573        * Anchors or index positions can be used as params.
31574        */
31575        function moveTo(sectionAnchor, slideAnchor){
31576            var destiny = getSectionByAnchor(sectionAnchor);
31577
31578            if (typeof slideAnchor !== 'undefined'){
31579                scrollPageAndSlide(sectionAnchor, slideAnchor);
31580            }else if(destiny.length > 0){
31581                scrollPage(destiny);
31582            }
31583        }
31584
31585        /**
31586        * Slides right the slider of the active section.
31587        * Optional `section` param.
31588        */
31589        function moveSlideRight(section){
31590            moveSlide('right', section);
31591        }
31592
31593        /**
31594        * Slides left the slider of the active section.
31595        * Optional `section` param.
31596        */
31597        function moveSlideLeft(section){
31598            moveSlide('left', section);
31599        }
31600
31601        /**
31602         * When resizing is finished, we adjust the slides sizes and positions
31603         */
31604        function reBuild(resizing){
31605            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
31606
31607            isResizing = true;
31608
31609            windowsHeight = $window.height();  //updating global var
31610
31611            $(SECTION_SEL).each(function(){
31612                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
31613                var slides = $(this).find(SLIDE_SEL);
31614
31615                //adjusting the height of the table-cell for IE and Firefox
31616                if(options.verticalCentered){
31617                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
31618                }
31619
31620                $(this).css('height', windowsHeight + 'px');
31621
31622                //resizing the scrolling divs
31623                if(options.scrollOverflow){
31624                    if(slides.length){
31625                        slides.each(function(){
31626                            createScrollBar($(this));
31627                        });
31628                    }else{
31629                        createScrollBar($(this));
31630                    }
31631                }
31632
31633                //adjusting the position fo the FULL WIDTH slides...
31634                if (slides.length > 1) {
31635                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
31636                }
31637            });
31638
31639            var activeSection = $(SECTION_ACTIVE_SEL);
31640            var sectionIndex = activeSection.index(SECTION_SEL);
31641
31642            //isn't it the first section?
31643            if(sectionIndex){
31644                //adjusting the position for the current section
31645                silentMoveTo(sectionIndex + 1);
31646            }
31647
31648            isResizing = false;
31649            // Uncode change
31650            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
31651            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
31652            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
31653        }
31654
31655        /**
31656        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
31657        * are smaller than the set limit values.
31658        */
31659        function setResponsive(active){
31660            var isResponsive = $body.hasClass(RESPONSIVE);
31661
31662            if(active){
31663                if(!isResponsive){
31664                    setAutoScrolling(false, 'internal');
31665                    setFitToSection(false, 'internal');
31666                    $(SECTION_NAV_SEL).hide();
31667                    $body.addClass(RESPONSIVE);
31668                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31669                }
31670            }
31671            else if(isResponsive){
31672                setAutoScrolling(originals.autoScrolling, 'internal');
31673                setFitToSection(originals.autoScrolling, 'internal');
31674                $(SECTION_NAV_SEL).show();
31675                $body.removeClass(RESPONSIVE);
31676                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31677            }
31678        }
31679
31680        if($(this).length){
31681            //public functions
31682            FP.setAutoScrolling = setAutoScrolling;
31683            FP.setRecordHistory = setRecordHistory;
31684            FP.setScrollingSpeed = setScrollingSpeed;
31685            FP.setFitToSection = setFitToSection;
31686            FP.setLockAnchors = setLockAnchors;
31687            FP.setMouseWheelScrolling = setMouseWheelScrolling;
31688            FP.setAllowScrolling = setAllowScrolling;
31689            FP.setKeyboardScrolling = setKeyboardScrolling;
31690            FP.moveSectionUp = moveSectionUp;
31691            FP.moveSectionDown = moveSectionDown;
31692            FP.silentMoveTo = silentMoveTo;
31693            FP.moveTo = moveTo;
31694            FP.moveSlideRight = moveSlideRight;
31695            FP.moveSlideLeft = moveSlideLeft;
31696            FP.fitToSection = fitToSection;
31697            FP.reBuild = reBuild;
31698            FP.setResponsive = setResponsive;
31699            FP.destroy = destroy;
31700
31701            init();
31702
31703            bindEvents();
31704        }
31705
31706        function init(){
31707            //if css3 is not supported, it will use jQuery animations
31708            if(options.css3){
31709                options.css3 = support3d();
31710            }
31711
31712            options.scrollBar = options.scrollBar || options.hybrid;
31713
31714            setOptionsFromDOM();
31715            prepareDom();
31716            setAllowScrolling(true);
31717            setAutoScrolling(options.autoScrolling, 'internal');
31718            responsive();
31719
31720            //setting the class for the body element
31721            setBodyClass();
31722
31723            //Uncode addition
31724            // if(document.readyState === 'complete'){
31725            //     scrollToAnchor();
31726            // }
31727            // $window.on('load', scrollToAnchor);
31728        }
31729
31730        function bindEvents(){
31731            $window
31732                //when scrolling...
31733                //.on('scroll', scrollHandler)
31734
31735                //detecting any change on the URL to scroll to the given anchor link
31736                //(a way to detect back history button as we play with the hashes on the URL)
31737                .on('hashchange', hashChangeHandler)
31738
31739                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
31740                .blur(blurHandler)
31741
31742                //when resizing the site, we adjust the heights of the sections, slimScroll...
31743                .resize(resizeHandler);
31744
31745            $document
31746                //Sliding with arrow keys, both, vertical and horizontal
31747                .keydown(keydownHandler)
31748
31749                //to prevent scrolling while zooming
31750                .keyup(keyUpHandler)
31751
31752                //Scrolls to the section when clicking the navigation bullet
31753                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
31754
31755                //Scrolls the slider to the given slide destination for the given section
31756                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
31757
31758                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
31759
31760            //Scrolling horizontally when clicking on the slider controls.
31761            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
31762
31763            /**
31764            * Applying normalScroll elements.
31765            * Ignoring the scrolls over the specified selectors.
31766            */
31767            if(options.normalScrollElements){
31768                $document.on('mouseenter', options.normalScrollElements, function () {
31769                    setMouseWheelScrolling(false);
31770                });
31771
31772                $document.on('mouseleave', options.normalScrollElements, function(){
31773                    setMouseWheelScrolling(true);
31774                });
31775            }
31776        }
31777
31778        /**
31779        * Setting options from DOM elements if they are not provided.
31780        */
31781        function setOptionsFromDOM(){
31782            var sections = container.find(options.sectionSelector);
31783
31784            //no anchors option? Checking for them in the DOM attributes
31785            if(!options.anchors.length){
31786                options.anchors = sections.filter('[data-anchor]').map(function(){
31787                    return $(this).data('anchor').toString();
31788                }).get();
31789            }
31790
31791            //no tooltips option? Checking for them in the DOM attributes
31792            if(!options.navigationTooltips.length){
31793                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
31794                    return $(this).data('tooltip').toString();
31795                }).get();
31796            }
31797        }
31798
31799        /**
31800        * Works over the DOM structure to set it up for the current fullpage options.
31801        */
31802        function prepareDom(){
31803            container.css({
31804                'height': '100%',
31805                'position': 'relative'
31806            });
31807
31808            //adding a class to recognize the container internally in the code
31809            container.addClass(WRAPPER);
31810            $('html').addClass(ENABLED);
31811
31812            windowsHeight = $window.height();
31813
31814            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
31815
31816            addInternalSelectors();
31817
31818             //styling the sections / slides / menu
31819            $(SECTION_SEL).each(function(index){
31820                var section = $(this);
31821                var slides = section.find(SLIDE_SEL);
31822                var numSlides = slides.length;
31823
31824                styleSection(section, index);
31825                styleMenu(section, index);
31826
31827                // if there's any slide
31828                if (numSlides > 0) {
31829                    styleSlides(section, slides, numSlides);
31830                }else{
31831                    if(options.verticalCentered){
31832                        addTableClass(section);
31833                    }
31834                }
31835            });
31836
31837            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31838            if(options.fixedElements && options.css3){
31839                $(options.fixedElements).appendTo($body);
31840            }
31841
31842            //vertical centered of the navigation + active bullet
31843            if(options.navigation){
31844                addVerticalNavigation();
31845            }
31846
31847            enableYoutubeAPI();
31848
31849            if(options.scrollOverflow){
31850                if(document.readyState === 'complete'){
31851                    createScrollBarHandler();
31852                }
31853                //after DOM and images are loaded
31854                $window.on('load', createScrollBarHandler);
31855            }else{
31856                afterRenderActions();
31857            }
31858        }
31859
31860        /**
31861        * Styles the horizontal slides for a section.
31862        */
31863        function styleSlides(section, slides, numSlides){
31864            var sliderWidth = numSlides * 100;
31865            var slideWidth = 100 / numSlides;
31866
31867            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31868            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31869
31870            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31871
31872            if(numSlides > 1){
31873                if(options.controlArrows){
31874                    createSlideArrows(section);
31875                }
31876
31877                if(options.slidesNavigation){
31878                    addSlidesNavigation(section, numSlides);
31879                }
31880            }
31881
31882            slides.each(function(index) {
31883                $(this).css('width', slideWidth + '%');
31884
31885                if(options.verticalCentered){
31886                    addTableClass($(this));
31887                }
31888            });
31889
31890            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31891
31892            //if the slide won't be an starting point, the default will be the first one
31893            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31893ide by default.
31894            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31895                silentLandscapeScroll(startingSlide, 'internal');
31896            }else{
31897                slides.eq(0).addClass(ACTIVE);
31898            }
31899        }
31900
31901        /**
31902        * Styling vertical sections
31903        */
31904        function styleSection(section, index){
31905            //if no active section is defined, the 1st one will be the default one
31906            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31907                section.addClass(ACTIVE);
31908            }
31909            startingSection = $(SECTION_ACTIVE_SEL);
31910
31911            section.css('height', windowsHeight + 'px');
31912
31913            if(options.paddingTop){
31914                section.css('padding-top', options.paddingTop);
31915            }
31916
31917            if(options.paddingBottom){
31918                section.css('padding-bottom', options.paddingBottom);
31919            }
31920
31921            if (typeof options.sectionsColor[index] !==  'undefined') {
31922                section.css('background-color', options.sectionsColor[index]);
31923            }
31924
31925            if (typeof options.anchors[index] !== 'undefined') {
31926                section.attr('data-anchor', options.anchors[index]);
31927            }
31928        }
31929
31930        /**
31931        * Sets the data-anchor attributes to the menu elements and activates the current one.
31932        */
31933        function styleMenu(section, index){
31934            if (typeof options.anchors[index] !== 'undefined') {
31935                //activating the menu / nav element on load
31936                if(section.hasClass(ACTIVE)){
31937                    activateMenuAndNav(options.anchors[index], index);
31938                }
31939            }
31940
31941            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31942            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31943                $(options.menu).appendTo($body);
31944            }
31945        }
31946
31947        /**
31948        * Adds internal classes to be able to provide customizable selectors
31949        * keeping the link with the style sheet.
31950        */
31951        function addInternalSelectors(){
31952            container.find(options.sectionSelector).addClass(SECTION);
31953            container.find(options.slideSelector).addClass(SLIDE);
31954        }
31955
31956        /**
31957        * Creates the control arrows for the given section
31958        */
31959        function createSlideArrows(section){
31960            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31961
31962            if(options.controlArrowColor!='#fff'){
31963                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31964                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31965            }
31966
31967            if(!options.loopHorizontal){
31968                section.find(SLIDES_ARROW_PREV_SEL).hide();
31969            }
31970        }
31971
31972        /**
31973        * Creates a vertical navigation bar.
31974        */
31975        function addVerticalNavigation(){
31976            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31977            var nav = $(SECTION_NAV_SEL);
31978
31979            nav.addClass(function() {
31980                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31981            });
31982
31983            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31984                var link = '';
31985                if (options.anchors.length) {
31986                    link = options.anchors[i];
31987                }
31988
31989                var li = '<li><a href="#' + link + '"><span></span></a>';
31990
31991                // Only add tooltip if needed (defined by user)
31992                var tooltip = options.navigationTooltips[i];
31993
31994                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31995                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31996                }
31997
31998                li += '</li>';
31999
32000                nav.find('ul').append(li);
32001            }
32002
32003            //centering it vertically
32004            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
32005
32006            //activating the current active section
32007            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
32008        }
32009
32010        /**
32011        * Creates the slim scroll scrollbar for the sections and slides inside them.
32012        */
32013        function createScrollBarHandler(){
32014            $(SECTION_SEL).each(function(){
32015                var slides = $(this).find(SLIDE_SEL);
32016
32017                if(slides.length){
32018                    slides.each(function(){
32019                        createScrollBar($(this));
32020                    });
32021                }else{
32022                    createScrollBar($(this));
32023                }
32024
32025            });
32026            afterRenderActions();
32027        }
32028
32029        /*
32030        * Enables the Youtube videos API so we can control their flow if necessary.
32031        */
32032        function enableYoutubeAPI(){
32033            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
32034                addURLParam($(this), 'enablejsapi=1');
32035            });
32036        }
32037
32038        /**
32039        * Adds a new parameter and its value to the `src` of a given element
32040        */
32041        function addURLParam(element, newParam){
32042            var originalSrc = element.attr('src');
32043            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
32044        }
32045
32046        /*
32047        * Returns the prefix sign to use for a new parameter in an existen URL.
32048        *
32049        * @return {String}  ? | &
32050        */
32051        function getUrlParamSign(url){
32052            return ( !/\?/.test( url ) ) ? '?' : '&';
32053        }
32054
32055        /**
32056        * Actions and callbacks to fire afterRender
32057        */
32058        function afterRenderActions(){
32059            var section = $(SECTION_ACTIVE_SEL);
32060
32061            section.addClass(COMPLETELY);
32062
32063            if(options.scrollOverflowHandler.afterRender){
32064                options.scrollOverflowHandler.afterRender(section);
32065            }
32066            lazyLoad(section);
32067            playMedia(section);
32068            options.scrollOverflowHandler.afterLoad();
32069
32070            if(isDestinyTheStartingSection()){
32071                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32072            }
32073
32074            // Uncode change
32075            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32076            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32077        }
32078
32079        /**
32080        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32081        */
32082        function isDestinyTheStartingSection(){
32083            var anchors =  window.location.hash.replace('#', '').split('/');
32084            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32085
32086            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32087        }
32088
32089
32090        var isScrolling = false;
32091        var lastScroll = 0;
32092
32093        //when scrolling...
32094        function scrollHandler(){
32095            var currentSection;
32096
32097            if(!options.autoScrolling || options.scrollBar){
32098                var currentScroll = $window.scrollTop();
32099                var scrollDirection = getScrollDirection(currentScroll);
32100                var visibleSectionIndex = 0;
32101                var screen_mid = currentScroll + ($window.height() / 2.0);
32102                var isAtBottom = $body.height() - $window.height() === currentScroll;
32103                var sections =  document.querySelectorAll(SECTION_SEL);
32104
32105                //when using `auto-height` for a small last section it won't be centered in the viewport
32106                if(isAtBottom){
32107                    visibleSectionIndex = sections.length - 1;
32108                }
32109                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32110                else if(!currentScroll){
32111                    visibleSectionIndex = 0;
32112                }
32113
32114                //taking the section which is showing more content in the viewport
32115                else{
32116                    for (var i = 0; i < sections.length; ++i) {
32117                        var section = sections[i];
32118
32119                        // Pick the the last section which passes the middle line of the screen.
32120                        if (section.offsetTop <= screen_mid)
32121                        {
32122                            visibleSectionIndex = i;
32123                        }
32124                    }
32125                }
32126
32127                if(isCompletelyInViewPort(scrollDirection)){
32128                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
32129                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32130                    }
32131                }
32132
32133                //geting the last one, the current one on the screen
32134                currentSection = $(sections).eq(visibleSectionIndex);
32135
32136                //setting the visible section as active when manually scrolling
32137                //executing only once the first time we reach the section
32138                if(!currentSection.hasClass(ACTIVE)){
32139                    isScrolling = true;
32140                    var leavingSection = $(SECTION_ACTIVE_SEL);
32141                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
32142                    var yMovement = getYmovement(currentSection);
32143                    var anchorLink  = currentSection.data('anchor');
32144                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
32145                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
32146                    var slideIndex;
32147                    var slideAnchorLink;
32148
32149                    if(activeSlide.length){
32150                        slideAnchorLink = activeSlide.data('anchor');
32151                        slideIndex = activeSlide.index();
32152                    }
32153
32154                    if(canScroll){
32155                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32156
32157                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
32158                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
32159
32160                        stopMedia(leavingSection);
32161                        lazyLoad(currentSection);
32162                        playMedia(currentSection);
32163
32164                        activateMenuAndNav(anchorLink, sectionIndex - 1);
32165
32166                        if(options.anchors.length){
32167                            //needed to enter in hashChange event when using the menu with anchor links
32168                            lastScrolledDestiny = anchorLink;
32169                        }
32170                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
32171                    }
32172
32173                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
32174                    clearTimeout(scrollId);
32175                    scrollId = setTimeout(function(){
32176                        isScrolling = false;
32177                    }, 100);
32178                }
32179
32180                if(options.fitToSection){
32181                    //for the auto adjust of the viewport to fit a whole section
32182                    clearTimeout(scrollId2);
32183
32184                    scrollId2 = setTimeout(function(){
32185                        //checking it again in case it changed during the delay
32186                        if(options.fitToSection){
32187                            fitToSection();
32188                        }
32189                    }, options.fitToSectionDelay);
32190                }
32191            }
32192        }
32193
32194        /**
32195        * Fits the site to the nearest active section
32196        */
32197        function fitToSection(){
32198            //checking fitToSection again in case it was set to false before the timeout delay
32199            if(canScroll){
32200                //allows to scroll to an active section and
32201                //if the section is already active, we prevent firing callbacks
32202                isResizing = true;
32203
32204                scrollPage($(SECTION_ACTIVE_SEL));
32205                isResizing = false;
32206            }
32207        }
32208
32209        /**
32210        * Determines whether the active section has seen in its whole or not.
32211        */
32212        function isCompletelyInViewPort(movement){
32213            var top = $(SECTION_ACTIVE_SEL).position().top;
32214            var bottom = top + $window.height();
32215
32216            if(movement == 'up'){
32217                return bottom >= ($window.scrollTop() + $window.height());
32218            }
32219            return top <= $window.scrollTop();
32220        }
32221
32222        /**
32223        * Gets the directon of the the scrolling fired by the scroll event.
32224        */
32225        function getScrollDirection(currentScroll){
32226            var direction = currentScroll > lastScroll ? 'down' : 'up';
32227
32228            lastScroll = currentScroll;
32229
32230            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
32231            previousDestTop = currentScroll;
32232
32233            return direction;
32234        }
32235
32236        /**
32237        * Determines the way of scrolling up or down:
32238        * by 'automatically' scrolling a section or by using the default and normal scrolling.
32239        */
32240        function scrolling(type, scrollable){
32241            if (!isScrollAllowed.m[type]){
32242                return;
32243            }
32244            var check = (type === 'down') ? 'bottom' : 'top';
32245            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
32246
32247            if(scrollable.length > 0 ){
32248                //is the scrollbar at the start/end of the scroll?
32249                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
32250                    scrollSection();
32251                }else{
32252                    return true;
32253                }
32254            }else{
32255                // moved up/down
32256                scrollSection();
32257            }
32258        }
32259
32260        /*
32261        * Preventing bouncing in iOS #2285
32262        */
32263        function preventBouncing(event){
32264            var e = event.originalEvent;
32265            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
32266                //preventing the easing on iOS devices
32267                event.preventDefault();
32268            }
32269        }
32270
32271        var touchStartY = 0;
32272        var touchStartX = 0;
32273        var touchEndY = 0;
32274        var touchEndX = 0;
32275
32276        /* Detecting touch events
32277
32278        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
32279        * This way, the touchstart and the touch moves shows an small difference between them which is the
32280        * used one to determine the direction.
32281        */
32282        function touchMoveHandler(event){
32283            var e = event.originalEvent;
32284            var activeSection = $(e.target).closest(SECTION_SEL);
32285
32286            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
32287            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
32288
32289                if(options.autoScrolling){
32290                    //preventing the easing on iOS devices
32291                    event.preventDefault();
32292                }
32293
32294                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32295                var touchEvents = getEventsPage(e);
32296
32297                touchEndY = touchEvents.y;
32298                touchEndX = touchEvents.x;
32299
32300                //if movement in the X axys is greater than in the Y and the currect section has slides...
32301                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
32302
32303                    //is the movement greater than the minimum resistance to scroll?
32304                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
32305                        if (touchStartX > touchEndX) {
32306                            if(isScrollAllowed.m.right){
32307                                moveSlideRight(activeSection); //next
32308                            }
32309                        } else {
32310                            if(isScrollAllowed.m.left){
32311                                moveSlideLeft(activeSection); //prev
32312                            }
32313                        }
32314                    }
32315                }
32316
32317                //vertical scrolling (only when autoScrolling is enabled)
32318                else if(options.autoScrolling && canScroll){
32319
32320                    //is the movement greater than the minimum resistance to scroll?
32321                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
32322                        if (touchStartY > touchEndY) {
32323                            scrolling('down', scrollable);
32324                        } else if (touchEndY > touchStartY) {
32325                            scrolling('up', scrollable);
32326                        }
32327                    }
32328                }
32329            }
32330        }
32331
32332        /**
32333         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
32334         * Currently works well for iOS - Android might need some testing
32335         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
32336         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
32337         * @return {boolean} true if there is a match to options.normalScrollElements
32338         */
32339        function checkParentForNormalScrollElement (el, hop) {
32340            hop = hop || 0;
32341            var parent = $(el).parent();
32342
32343            if (hop < options.normalScrollElementTouchThreshold &&
32344                parent.is(options.normalScrollElements) ) {
32345                return true;
32346            } else if (hop == options.normalScrollElementTouchThreshold) {
32347                return false;
32348            } else {
32349                return checkParentForNormalScrollElement(parent, ++hop);
32350            }
32351        }
32352
32353        /**
32354        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
32355        * this way we make sure that is really a touch event what IE is detecting.
32356        */
32357        function isReallyTouch(e){
32358            //if is not IE   ||  IE is detecting `touch` or `pen`
32359            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
32360        }
32361
32362        /**
32363        * Handler for the touch start event.
32364        */
32365        function touchStartHandler(event){
32366            var e = event.originalEvent;
32367
32368            //stopping the auto scroll to adjust to a section
32369            if(options.fitToSection){
32370                $htmlBody.stop();
32371            }
32372
32373            if(isReallyTouch(e)){
32374                var touchEvents = getEventsPage(e);
32375                touchStartY = touchEvents.y;
32376                touchStartX = touchEvents.x;
32377            }
32378        }
32379
32380        /**
32381        * Gets the average of the last `number` elements of the given array.
32382        */
32383        function getAverage(elements, number){
32384            var sum = 0;
32385
32386            //taking `number` elements from the end to make the average, if there are not enought, 1
32387            var lastElements = elements.slice(Math.max(elements.length - number, 1));
32388
32389            for(var i = 0; i < lastElements.length; i++){
32390                sum = sum + lastElements[i];
32391            }
32392
32393            return Math.ceil(sum/number);
32394        }
32395
32396        /**
32397         * Detecting mousewheel scrolling
32398         *
32399         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
32400         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
32401         */
32402        var prevTime = new Date().getTime();
32403
32404        function MouseWheelHandler(e) {
32405            var curTime = new Date().getTime();
32406            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
32407
32408            //autoscrolling and not zooming?
32409            if(options.autoScrolling && !controlPressed && !isNormalScroll){
32410                // cross-browser wheel delta
32411                e = e || window.event;
32412                var value = e.wheelDelta || -e.deltaY || -e.detail;
32413                var delta = Math.max(-1, Math.min(1, value));
32414
32415                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
32416                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
32417
32418                //Limiting the array to 150 (lets not waste memory!)
32419                if(scrollings.length > 149){
32420                    scrollings.shift();
32421                }
32422
32423                //keeping record of the previous scrollings
32424                scrollings.push(Math.abs(value));
32425
32426                //preventing to scroll the site on mouse wheel when scrollbar is present
32427                if(options.scrollBar){
32428                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
32429                }
32430
32431                var activeSection = $(SECTION_ACTIVE_SEL);
32432                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32433
32434                //time difference between the last scroll and the current one
32435                var timeDiff = curTime-prevTime;
32436                prevTime = curTime;
32437
32438                //haven't they scrolled in a while?
32439                //(enough to be consider a different scrolling action to scroll another section)
32440                if(timeDiff > 200){
32441                    //emptying the array, we dont care about old scrollings for our averages
32442                    scrollings = [];
32443                }
32444
32445                if(canScroll){
32446                    var averageEnd = getAverage(scrollings, 10);
32447                    var averageMiddle = getAverage(scrollings, 70);
32448                    var isAccelerating = averageEnd >= averageMiddle;
32449
32450                    //to avoid double swipes...
32451                    if(isAccelerating && isScrollingVertically){
32452                        //scrolling down?
32453                        if (delta < 0) {
32454                            scrolling('down', scrollable);
32455
32456                        //scrolling up?
32457                        }else {
32458                            scrolling('up', scrollable);
32459                        }
32460                    }
32461                }
32462
32463                return false;
32464            }
32465
32466            if(options.fitToSection){
32467                //stopping the auto scroll to adjust to a section
32468                $htmlBody.stop();
32469            }
32470        }
32471
32472        /**
32473        * Slides a slider to the given direction.
32474        * Optional `section` param.
32475        */
32476        function moveSlide(direction, section){
32477            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
32478            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
32479            var numSlides = slides.find(SLIDE_SEL).length;
32480
32481            // more than one slide needed and nothing should be sliding
32482            if (!slides.length || slideMoving || numSlides < 2) {
32483                return;
32484            }
32485
32486            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
32487            var destiny = null;
32488
32489            if(direction === 'left'){
32490                destiny = currentSlide.prev(SLIDE_SEL);
32491            }else{
32492                destiny = currentSlide.next(SLIDE_SEL);
32493            }
32494
32495            //isn't there a next slide in the secuence?
32496            if(!destiny.length){
32497                //respect loopHorizontal settin
32498                if (!options.loopHorizontal) return;
32499
32500                if(direction === 'left'){
32501                    destiny = currentSlide.siblings(':last');
32502                }else{
32503                    destiny = currentSlide.siblings(':first');
32504                }
32505            }
32506
32507            slideMoving = true;
32508
32509            landscapeScroll(slides, destiny, direction);
32510        }
32511
32512        /**
32513        * Maintains the active slides in the viewport
32514        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
32515        */
32516        function keepSlidesPosition(){
32517            $(SLIDE_ACTIVE_SEL).each(function(){
32518                silentLandscapeScroll($(this), 'internal');
32519            });
32520        }
32521
32522        var previousDestTop = 0;
32523        /**
32524        * Returns the destination Y position based on the scrolling direction and
32525        * the height of the section.
32526        */
32527        function getDestinationPosition(element){
32528            var elemPosition = element.position();
32529
32530            //top of the desination will be at the top of the viewport
32531            var position = elemPosition.top;
32532            var isScrollingDown =  elemPosition.top > previousDestTop;
32533            var sectionBottom = position - windowsHeight + element.outerHeight();
32534            var bigSectionsDestination = options.bigSectionsDestination;
32535
32536            //Uncode addition
32537            var containerH = container.outerHeight();
32538            var containerPosition = container.offset();
32539
32540            //########### Commented by Uncode - START ###########
32541            //is the destination element bigger than the viewport?
32542            // if(element.outerHeight() > windowsHeight){
32543            //     //scrolling up?
32544            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
32545            //         position = sectionBottom;
32546            //     }
32547            // }
32548
32549            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
32550            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
32551            //     //The bottom of the destination will be at the bottom of the viewport
32552            //     position = sectionBottom;
32553            // }
32554            //########### Commented by Uncode - END ###########
32555
32556            //Uncode addition
32557            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
32558                position += 18;
32559            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
32560                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
32561            }
32562
32563            /*
32564            Keeping record of the last scrolled position to determine the scrolling direction.
32565            No conventional methods can be used as the scroll bar might not be present
32566            AND the section might not be active if it is auto-height and didnt reach the middle
32567            of the viewport.
32568            */
32569            previousDestTop = position;
32570            return position;
32571        }
32572
32573        /**
32574        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
32575        */
32576        function scrollPage(element, callback, isMovementUp){
32577            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
32578
32579            var dtop = getDestinationPosition(element);
32580            var slideAnchorLink;
32581            var slideIndex;
32582
32583            //local variables
32584            var v = {
32585                element: element,
32586                callback: callback,
32587                isMovementUp: isMovementUp,
32588                dtop: dtop,
32589                yMovement: getYmovement(element),
32590                anchorLink: element.data('anchor'),
32591                sectionIndex: element.index(SECTION_SEL),
32592                activeSlide: element.find(SLIDE_ACTIVE_SEL),
32593                activeSection: $(SECTION_ACTIVE_SEL),
32594                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
32595
32596                //caching the value of isResizing at the momment the function is called
32597                //because it will be checked later inside a setTimeout and the value might change
32598                localIsResizing: isResizing
32599            };
32600
32601            //quiting when destination scroll is the same as the current one
32602            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
32603
32604            if(v.activeSlide.length){
32605                slideAnchorLink = v.activeSlide.data('anchor');
32606                slideIndex = v.activeSlide.index();
32607            }
32608
32609            // If continuousVertical && we need to wrap around
32610            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
32611                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
32612                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
32613
32614                v = createInfiniteSections(v);
32615            }
32616
32617            //callback (onLeave) if the site is not just resizing and readjusting the slides
32618            if($.isFunction(options.onLeave) && !v.localIsResizing){
32619                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
32620                    return;
32621                }
32622            }
32623
32624            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
32625            if(!v.localIsResizing){
32626                stopMedia(v.activeSection);
32627            }
32628
32629            options.scrollOverflowHandler.beforeLeave();
32630            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32631            lazyLoad(element);
32632            options.scrollOverflowHandler.onLeave();
32633
32634
32635            //preventing from activating the MouseWheelHandler event
32636            //more than once if the page is scrolling
32637            canScroll = false;
32638
32639            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
32640
32641            performMovement(v);
32642
32643            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
32644            lastScrolledDestiny = v.anchorLink;
32645
32646            //avoid firing it twice (as it does also on scroll)
32647            activateMenuAndNav(v.anchorLink, v.sectionIndex);
32648        }
32649
32650        /**
32651        * Performs the vertical movement (by CSS3 or by jQuery)
32652        */
32653        function performMovement(v){
32654            // using CSS3 translate functionality
32655            if (options.css3 && options.autoScrolling && !options.scrollBar) {
32656
32657                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32658                // that's why we round it to 0.
32659                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
32660                transformContainer(translate3d, true);
32661
32662                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
32663                //scrollingSpeed to change in case of using silentMoveTo();
32664                if(options.scrollingSpeed){
32665                    clearTimeout(afterSectionLoadsId);
32666                    afterSectionLoadsId = setTimeout(function () {
32667                        afterSectionLoads(v);
32668                    }, options.scrollingSpeed);
32669                }else{
32670                    afterSectionLoads(v);
32671                }
32672            }
32673
32674            // using jQuery animate
32675            else{
32676                var scrollSettings = getScrollSettings(v);
32677
32678                $(scrollSettings.element).animate(
32679                    scrollSettings.options,
32680                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
32681                    if(options.scrollBar){
32682
32683                        /* Hack!
32684                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
32685                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
32686
32687                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
32688                        */
32689                        setTimeout(function(){
32690                            afterSectionLoads(v);
32691                        },30);
32692                    }else{
32693                        afterSectionLoads(v);
32694                    }
32695                });
32696            }
32697        }
32698
32699        /**
32700        * Gets the scrolling settings depending on the plugin autoScrolling option
32701        */
32702        function getScrollSettings(v){
32703            var scroll = {};
32704
32705            if(options.autoScrolling && !options.scrollBar){
32706                scroll.options = { 'top': -v.dtop};
32707                scroll.element = WRAPPER_SEL;
32708            }else{
32709                scroll.options = { 'scrollTop': v.dtop};
32710                scroll.element = 'html, body';
32711            }
32712
32713            return scroll;
32714        }
32715
32716        /**
32717        * Adds sections before or after the current one to create the infinite effect.
32718        */
32719        function createInfiniteSections(v){
32720            // Scrolling down
32721            if (!v.isMovementUp) {
32722                // Move all previous sections to after the active section
32723                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
32724            }
32725            else { // Scrolling up
32726                // Move all next sections to before the active section
32727                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
32728            }
32729
32730            // Maintain the displayed position (now that we changed the element order)
32731            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32732
32733            // Maintain the active slides visible in the viewport
32734            keepSlidesPosition();
32735
32736            // save for later the elements that still need to be reordered
32737            v.wrapAroundElements = v.activeSection;
32738
32739            // Recalculate animation variables
32740            v.dtop = v.element.position().top;
32741            v.yMovement = getYmovement(v.element);
32742
32743            return v;
32744        }
32745
32746        /**
32747        * Fix section order after continuousVertical changes have been animated
32748        */
32749        function continuousVerticalFixSectionOrder (v) {
32750            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
32751            // finish moving the elements around so the direct navigation will function more simply
32752            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
32753                return;
32754            }
32755
32756            if (v.isMovementUp) {
32757                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
32758            }
32759            else {
32760                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
32761            }
32762
32763            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32764
32765            // Maintain the active slides visible in the viewport
32766            keepSlidesPosition();
32767        }
32768
32769
32770        /**
32771        * Actions to do once the section is loaded.
32772        */
32773        function afterSectionLoads (v){
32774            continuousVerticalFixSectionOrder(v);
32775
32776            //callback (afterLoad) if the site is not just resizing and readjusting the slides
32777            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
32778            options.scrollOverflowHandler.afterLoad();
32779
32780            if(!v.localIsResizing){
32781                playMedia(v.element);
32782            }
32783
32784            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32785
32786            canScroll = true;
32787
32788            $.isFunction(v.callback) && v.callback.call(this);
32789        }
32790
32791        /**
32792        * Sets the value for the given attribute from the `data-` attribute with the same suffix
32793        * ie: data-srcset ==> srcset  |  data-src ==> src
32794        */
32795        function setSrc(element, attribute){
32796            element
32797                .attr(attribute, element.data(attribute))
32798                .removeAttr('data-' + attribute);
32799        }
32800
32801        /**
32802        * Lazy loads image, video and audio elements.
32803        */
32804        function lazyLoad(destiny){
32805            if (!options.lazyLoading){
32806                return;
32807            }
32808
32809            var panel = getSlideOrSection(destiny);
32810            var element;
32811
32812            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
32813                element = $(this);
32814
32815                $.each(['src', 'srcset'], function(index, type){
32816                    var attribute = element.attr('data-' + type);
32817                    if(typeof attribute !== 'undefined' && attribute){
32818                        setSrc(element, type);
32819                    }
32820                });
32821
32822                if(element.is('source')){
32823                    element.closest('video').get(0).load();
32824                }
32825            });
32826        }
32827
32828        /**
32829        * Plays video and audio elements.
32830        */
32831        function playMedia(destiny){
32832            var panel = getSlideOrSection(destiny);
32833
32834            //playing HTML5 media elements
32835            panel.find('video, audio').each(function(){
32836                var element = $(this).get(0);
32837
32838                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32839                    element.play();
32840                }
32841            });
32842
32843            //youtube videos
32844            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32845                var element = $(this).get(0);
32846
32847                if ( element.hasAttribute('data-autoplay') ){
32848                    playYoutube(element);
32849                }
32850
32851                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32852                element.onload = function() {
32853                    if ( element.hasAttribute('data-autoplay') ){
32854                        playYoutube(element);
32855                    }
32856                };
32857            });
32858        }
32859
32860        /**
32861        * Plays a youtube video
32862        */
32863        function playYoutube(element){
32864            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32865        }
32866
32867        /**
32868        * Stops video and audio elements.
32869        */
32870        function stopMedia(destiny){
32871            var panel = getSlideOrSection(destiny);
32872
32873            //stopping HTML5 media elements
32874            panel.find('video, audio').each(function(){
32875                var element = $(this).get(0);
32876
32877                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32878                    element.pause();
32879                }
32880            });
32881
32882            //youtube videos
32883            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32884                var element = $(this).get(0);
32885
32886                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32887                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32888                }
32889            });
32890        }
32891
32892        /**
32893        * Gets the active slide (or section) for the given section
32894        */
32895        function getSlideOrSection(destiny){
32896            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32897            if( slide.length ) {
32898                destiny = $(slide);
32899            }
32900
32901            return destiny;
32902        }
32903
32904        /**
32905        * Scrolls to the anchor in the URL when loading the site
32906        */
32907        function scrollToAnchor(){
32908            //getting the anchor link in the URL and deleting the `#`
32909            var value =  window.location.hash.replace('#', '').split('/');
32910            var sectionAnchor = decodeURIComponent(value[0]);
32911            var slideAnchor = decodeURIComponent(value[1]);
32912
32913            if(sectionAnchor){  //if theres any #
32914                if(options.animateAnchor){
32915                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32916                }else{
32917                    silentMoveTo(sectionAnchor, slideAnchor);
32918                }
32919            }
32920        }
32921
32922        /**
32923        * Detecting any change on the URL to scroll to the given anchor link
32924        * (a way to detect back history button as we play with the hashes on the URL)
32925        */
32926        function hashChangeHandler(){
32927            if(!isScrolling && !options.lockAnchors){
32928                var value =  window.location.hash.replace('#', '').split('/');
32929                var sectionAnchor = decodeURIComponent(value[0]);
32930                var slideAnchor = decodeURIComponent(value[1]);
32931
32932                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32933                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32934                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32935
32936
32937                if(sectionAnchor.length){
32938                    /*in order to call scrollpage() only once for each destination at a time
32939                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32940                    event is fired on every scroll too.*/
32941                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32942                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32943                    }
32944                }
32945            }
32946        }
32947
32948        //Sliding with arrow keys, both, vertical and horizontal
32949        function keydownHandler(e) {
32950
32951            clearTimeout(keydownId);
32952
32953            var activeElement = $(':focus');
32954
32955            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32956                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32957                options.keyboardScrolling && options.autoScrolling){
32958                var keyCode = e.which;
32959
32960                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32961                var keyControls = [40, 38, 32, 33, 34];
32962                if($.inArray(keyCode, keyControls) > -1){
32963                    e.preventDefault();
32964                }
32965
32966                controlPressed = e.ctrlKey;
32967
32968                keydownId = setTimeout(function(){
32969                    onkeydown(e);
32970                },150);
32971            }
32972        }
32973
32974        function tooltipTextHandler(){
32975            $(this).prev().trigger('click');
32976        }
32977
32978        //to prevent scrolling while zooming
32979        function keyUpHandler(e){
32980            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32981                controlPressed = e.ctrlKey;
32982            }
32983        }
32984
32985        //binding the mousemove when the mouse's middle button is released
32986        function mouseDownHandler(e){
32987            //middle button
32988            if (e.which == 2){
32989                oldPageY = e.pageY;
32990                container.on('mousemove', mouseMoveHandler);
32991            }
32992        }
32993
32994        //unbinding the mousemove when the mouse's middle button is released
32995        function mouseUpHandler(e){
32996            //middle button
32997            if (e.which == 2){
32998                container.off('mousemove');
32999            }
33000        }
33001
33002        //Scrolling horizontally when clicking on the slider controls.
33003        function slideArrowHandler(){
33004            var section = $(this).closest(SECTION_SEL);
33005
33006            if ($(this).hasClass(SLIDES_PREV)) {
33007                if(isScrollAllowed.m.left){
33008                    moveSlideLeft(section);
33009                }
33010            } else {
33011                if(isScrollAllowed.m.right){
33012                    moveSlideRight(section);
33013                }
33014            }
33015        }
33016
33017        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
33018        function blurHandler(){
33019            isWindowFocused = false;
33020            controlPressed = false;
33021        }
33022
33023        //Scrolls to the section when clicking the navigation bullet
33024        function sectionBulletHandler(e){
33025            e.preventDefault();
33026            var index = $(this).parent().index();
33027            scrollPage($(SECTION_SEL).eq(index));
33028        }
33029
33030        //Scrolls the slider to the given slide destination for the given section
33031        function slideBulletHandler(e){
33032            e.preventDefault();
33033            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
33034            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
33035
33036            landscapeScroll(slides, destiny);
33037        }
33038
33039        /**
33040        * Keydown event
33041        */
33042        function onkeydown(e){
33043            var shiftPressed = e.shiftKey;
33044
33045            //do nothing if we can not scroll or we are not using horizotnal key arrows.
33046            if(!canScroll && [37,39].indexOf(e.which) < 0){
33047                return;
33048            }
33049
33050            switch (e.which) {
33051                //up
33052                case 38:
33053                case 33:
33054                    if(isScrollAllowed.k.up){
33055                        moveSectionUp();
33056                    }
33057                    break;
33058
33059                //down
33060                case 32: //spacebar
33061                    if(shiftPressed && isScrollAllowed.k.up){
33062                        moveSectionUp();
33063                        break;
33064                    }
33065                /* falls through */
33066                case 40:
33067                case 34:
33068                    if(isScrollAllowed.k.down){
33069                        moveSectionDown();
33070                    }
33071                    break;
33072
33073                //Home
33074                case 36:
33075                    if(isScrollAllowed.k.up){
33076                        moveTo(1);
33077                    }
33078                    break;
33079
33080                //End
33081                case 35:
33082                     if(isScrollAllowed.k.down){
33083                        moveTo( $(SECTION_SEL).length );
33084                    }
33085                    break;
33086
33087                //left
33088                case 37:
33089                    if(isScrollAllowed.k.left){
33090                        moveSlideLeft();
33091                    }
33092                    break;
33093
33094                //right
33095                case 39:
33096                    if(isScrollAllowed.k.right){
33097                        moveSlideRight();
33098                    }
33099                    break;
33100
33101                default:
33102                    return; // exit this handler for other keys
33103            }
33104        }
33105
33106        /**
33107        * Detecting the direction of the mouse movement.
33108        * Used only for the middle button of the mouse.
33109        */
33110        var oldPageY = 0;
33111        function mouseMoveHandler(e){
33112            if(canScroll){
33113                // moving up
33114                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33115                    moveSectionUp();
33116                }
33117
33118                // moving down
33119                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
33120                    moveSectionDown();
33121                }
33122            }
33123            oldPageY = e.pageY;
33124        }
33125
33126        /**
33127        * Scrolls horizontal sliders.
33128        */
33129        function landscapeScroll(slides, destiny, direction){
33130            var section = slides.closest(SECTION_SEL);
33131            var v = {
33132                slides: slides,
33133                destiny: destiny,
33134                direction: direction,
33135                destinyPos: destiny.position(),
33136                slideIndex: destiny.index(),
33137                section: section,
33138                sectionIndex: section.index(SECTION_SEL),
33139                anchorLink: section.data('anchor'),
33140                slidesNav: section.find(SLIDES_NAV_SEL),
33141                slideAnchor:  getAnchor(destiny),
33142                prevSlide: section.find(SLIDE_ACTIVE_SEL),
33143                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
33144
33145                //caching the value of isResizing at the momment the function is called
33146                //because it will be checked later inside a setTimeout and the value might change
33147                localIsResizing: isResizing
33148            };
33149            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
33150            v.direction = v.direction ? v.direction : v.xMovement;
33151
33152            //important!! Only do it when not resizing
33153            if(!v.localIsResizing){
33154                //preventing from scrolling to the next/prev section when using scrollHorizontally
33155                canScroll = false;
33156            }
33157
33158            if(options.onSlideLeave){
33159
33160                //if the site is not just resizing and readjusting the slides
33161                if(!v.localIsResizing && v.xMovement!=='none'){
33162                    if($.isFunction( options.onSlideLeave )){
33163                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
33164                            slideMoving = false;
33165                            return;
33166                        }
33167                    }
33168                }
33169            }
33170
33171            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33172
33173            if(!v.localIsResizing){
33174                stopMedia(v.prevSlide);
33175                lazyLoad(destiny);
33176            }
33177
33178            if(!options.loopHorizontal && options.controlArrows){
33179                //hidding it for the fist slide, showing for the rest
33180                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
33181
33182                //hidding it for the last slide, showing for the rest
33183                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
33184            }
33185
33186            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
33187            if(section.hasClass(ACTIVE) && !v.localIsResizing){
33188                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
33189            }
33190
33191            performHorizontalMove(slides, v, true);
33192        }
33193
33194
33195        function afterSlideLoads(v){
33196            activeSlidesNavigation(v.slidesNav, v.slideIndex);
33197
33198            //if the site is not just resizing and readjusting the slides
33199            if(!v.localIsResizing){
33200                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
33201
33202                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
33203                //and to prevent double scroll right after a windows resize
33204                canScroll = true;
33205
33206                playMedia(v.destiny);
33207            }
33208
33209            //letting them slide again
33210            slideMoving = false;
33211        }
33212
33213        /**
33214        * Performs the horizontal movement. (CSS3 or jQuery)
33215        *
33216        * @param fireCallback {Bool} - determines whether or not to fire the callback
33217        */
33218        function performHorizontalMove(slides, v, fireCallback){
33219            var destinyPos = v.destinyPos;
33220
33221            if(options.css3){
33222                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
33223
33224                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
33225
33226                afterSlideLoadsId = setTimeout(function(){
33227                    fireCallback && afterSlideLoads(v);
33228                }, options.scrollingSpeed, options.easing);
33229            }else{
33230                slides.animate({
33231                    scrollLeft : Math.round(destinyPos.left)
33232                }, options.scrollingSpeed, options.easing, function() {
33233
33234                    fireCallback && afterSlideLoads(v);
33235                });
33236            }
33237        }
33238
33239        /**
33240        * Sets the state for the horizontal bullet navigations.
33241        */
33242        function activeSlidesNavigation(slidesNav, slideIndex){
33243            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
33244            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
33245        }
33246
33247        var previousHeight = windowsHeight;
33248
33249        //when resizing the site, we adjust the heights of the sections, slimScroll...
33250        function resizeHandler(){
33251            //checking if it needs to get responsive
33252            responsive();
33253
33254            // rebuild immediately on touch devices
33255            if (isTouchDevice) {
33256                var activeElement = $(document.activeElement);
33257
33258                //if the keyboard is NOT visible
33259                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
33260                    var currentHeight = $window.height();
33261
33262                    //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)
33263                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
33264                        reBuild(true);
33265                        previousHeight = currentHeight;
33266                    }
33267                }
33268            }else{
33269                //in order to call the functions only when the resize is finished
33270                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
33271                clearTimeout(resizeId);
33272
33273                resizeId = setTimeout(function(){
33274                    reBuild(true);
33275                }, 350);
33276            }
33277        }
33278
33279        /**
33280        * Checks if the site needs to get responsive and disables autoScrolling if so.
33281        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
33282        */
33283        function responsive(){
33284            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
33285            var heightLimit = options.responsiveHeight;
33286
33287            //only calculating what we need. Remember its called on the resize event.
33288            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
33289            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
33290
33291            if(widthLimit && heightLimit){
33292                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
33293            }
33294            else if(widthLimit){
33295                setResponsive(isBreakingPointWidth);
33296            }
33297            else if(heightLimit){
33298                setResponsive(isBreakingPointHeight);
33299            }
33300        }
33301
33302        /**
33303        * Adds transition animations for the given element
33304        */
33305        function addAnimation(container, element){
33306            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
33307
33308            container.removeClass(NO_TRANSITION);
33309            return container.css({
33310                '-webkit-transition': transition,
33311                'transition': transition
33312            });
33313        }
33314
33315        /**
33316        * Remove transition animations for the given element
33317        */
33318        function removeAnimation(element){
33319            return element.addClass(NO_TRANSITION);
33320        }
33321
33322        /**
33323        * Activating the vertical navigation bullets according to the given slide name.
33324        */
33325        function activateNavDots(name, sectionIndex){
33326            if(options.navigation){
33327                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
33328                if(name){
33329                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
33330                }else{
33331                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
33332                }
33333            }
33334        }
33335
33336        /**
33337        * Activating the website main menu elements according to the given slide name.
33338        */
33339        function activateMenuElement(name){
33340            if(options.menu){
33341                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
33342                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
33343            }
33344        }
33345
33346        /**
33347        * Sets to active the current menu and vertical nav items.
33348        */
33349        function activateMenuAndNav(anchor, index){
33350            activateMenuElement(anchor);
33351            activateNavDots(anchor, index);
33352        }
33353
33354        /**
33355        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
33356        * from the current section.
33357        */
33358        function getYmovement(destiny){
33359            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
33360            var toIndex = destiny.index(SECTION_SEL);
33361            if( fromIndex == toIndex){
33362                return 'none';
33363            }
33364            if(fromIndex > toIndex){
33365                return 'up';
33366            }
33367            return 'down';
33368        }
33369
33370        /**
33371        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
33372        * from the current slide.
33373        */
33374        function getXmovement(fromIndex, toIndex){
33375            if( fromIndex == toIndex){
33376                return 'none';
33377            }
33378            if(fromIndex > toIndex){
33379                return 'left';
33380            }
33381            return 'right';
33382        }
33383
33384        /**
33385        * Checks if the element needs scrollbar and if the user wants to apply it.
33386        * If so it creates it.
33387        *
33388        * @param {Object} element   jQuery object of the section or slide
33389        */
33390        function createScrollBar(element){
33391            //User doesn't want scrollbar here? Sayonara baby!
33392            if(element.hasClass('fp-noscroll')) return;
33393
33394            //needed to make `scrollHeight` work under Opera 12
33395            element.css('overflow', 'hidden');
33396
33397            var scrollOverflowHandler = options.scrollOverflowHandler;
33398            var wrap = scrollOverflowHandler.wrapContent();
33399            //in case element is a slide
33400            var section = element.closest(SECTION_SEL);
33401            var scrollable = scrollOverflowHandler.scrollable(element);
33402            var contentHeight;
33403
33404            //if there was scroll, the contentHeight will be the one in the scrollable section
33405            if(scrollable.length){
33406                contentHeight = scrollOverflowHandler.scrollHeight(element);
33407            }else{
33408                contentHeight = element.get(0).scrollHeight;
33409                if(options.verticalCentered){
33410                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
33411                }
33412            }
33413
33414            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
33415
33416            //needs scroll?
33417            if ( contentHeight > scrollHeight) {
33418                //did we already have an scrollbar ? Updating it
33419                if(scrollable.length){
33420                    scrollOverflowHandler.update(element, scrollHeight);
33421                }
33422                //creating the scrolling
33423                else{
33424                    if(options.verticalCentered){
33425                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
33426                    }else{
33427                        element.wrapInner(wrap);
33428                    }
33429                    scrollOverflowHandler.create(element, scrollHeight);
33430                }
33431            }
33432            //removing the scrolling when it is not necessary anymore
33433            else{
33434                scrollOverflowHandler.remove(element);
33435            }
33436
33437            //undo
33438            element.css('overflow', '');
33439        }
33440
33441        function addTableClass(element){
33442            //In case we are styling for the 2nd time as in with reponsiveSlides
33443            if(!element.hasClass(TABLE)){
33444                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
33445            }
33446        }
33447
33448        function getTableHeight(element){
33449            var sectionHeight = windowsHeight;
33450
33451            if(options.paddingTop || options.paddingBottom){
33452                var section = element;
33453                if(!section.hasClass(SECTION)){
33454                    section = element.closest(SECTION_SEL);
33455                }
33456
33457                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
33458                sectionHeight = (windowsHeight - paddings);
33459            }
33460
33461            return sectionHeight;
33462        }
33463
33464        /**
33465        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
33466        */
33467        function transformContainer(translate3d, animated){
33468            if(animated){
33469                addAnimation(container);
33470            }else{
33471                removeAnimation(container);
33472            }
33473
33474            container.css(getTransforms(translate3d));
33475
33476            //syncronously removing the class after the animation has been applied.
33477            setTimeout(function(){
33478                container.removeClass(NO_TRANSITION);
33479            },10);
33480        }
33481
33482        /**
33483        * Gets a section by its anchor / index
33484        */
33485        function getSectionByAnchor(sectionAnchor){
33486            if(!sectionAnchor) return [];
33487
33488            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
33489            if(!section.length){
33490                section = $(SECTION_SEL).eq( sectionAnchor -1);
33491            }
33492
33493            return section;
33494        }
33495
33496        /**
33497        * Gets a slide inside a given section by its anchor / index
33498        */
33499        function getSlideByAnchor(slideAnchor, section){
33500            var slides = section.find(SLIDES_WRAPPER_SEL);
33501            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
33502
33503            if(!slide.length){
33504                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
33505            }
33506
33507            return slide;
33508        }
33509
33510        /**
33511        * Scrolls to the given section and slide anchors
33512        */
33513        function scrollPageAndSlide(destiny, slide){
33514            var section = getSectionByAnchor(destiny);
33515
33516            //do nothing if there's no section with the given anchor name
33517            if(!section.length) return;
33518
33519            //default slide
33520            if (typeof slide === 'undefined') {
33521                slide = 0;
33522            }
33523
33524            //we need to scroll to the section and then to the slide
33525            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
33526                scrollPage(section, function(){
33527                    scrollSlider(section, slide);
33528                });
33529            }
33530            //if we were already in the section
33531            else{
33532                scrollSlider(section, slide);
33533            }
33534        }
33535
33536        /**
33537        * Scrolls the slider to the given slide destination for the given section
33538        */
33539        function scrollSlider(section, slideAnchor){
33540            if(typeof slideAnchor !== 'undefined'){
33541                var slides = section.find(SLIDES_WRAPPER_SEL);
33542                var destiny =  getSlideByAnchor(slideAnchor, section);
33543
33544                if(destiny.length){
33545                    landscapeScroll(slides, destiny);
33546                }
33547            }
33548        }
33549
33550        /**
33551        * Creates a landscape navigation bar with dots for horizontal sliders.
33552        */
33553        function addSlidesNavigation(section, numSlides){
33554            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
33555            var nav = section.find(SLIDES_NAV_SEL);
33556
33557            //top or bottom
33558            nav.addClass(options.slidesNavPosition);
33559
33560            for(var i=0; i< numSlides; i++){
33561                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
33562            }
33563
33564            //centering it
33565            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
33566
33567            nav.find('li').first().find('a').addClass(ACTIVE);
33568        }
33569
33570
33571        /**
33572        * Sets the state of the website depending on the active section/slide.
33573        * It changes the URL hash when needed and updates the body class.
33574        */
33575        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
33576            var sectionHash = '';
33577
33578            if(options.anchors.length && !options.lockAnchors){
33579
33580                //isn't it the first slide?
33581                if(slideIndex){
33582                    if(typeof anchorLink !== 'undefined'){
33583                        sectionHash = anchorLink;
33584                    }
33585
33586                    //slide without anchor link? We take the index instead.
33587                    if(typeof slideAnchor === 'undefined'){
33588                        slideAnchor = slideIndex;
33589                    }
33590
33591                    lastScrolledSlide = slideAnchor;
33592                    setUrlHash(sectionHash + '/' + slideAnchor);
33593
33594                //first slide won't have slide anchor, just the section one
33595                }else if(typeof slideIndex !== 'undefined'){
33596                    lastScrolledSlide = slideAnchor;
33597                    setUrlHash(anchorLink);
33598                }
33599
33600                //section without slides
33601                else{
33602                    setUrlHash(anchorLink);
33603                }
33604            }
33605
33606            setBodyClass();
33607        }
33608
33609        /**
33610        * Sets the URL hash.
33611        */
33612        function setUrlHash(url){
33613            //Uncode addition
33614            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
33615                return false;
33616
33617            if(options.recordHistory){
33618                location.hash = url;
33619            }else{
33620                //Uncode addition
33621                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
33622                // if(isTouchDevice || isTouch){
33623                //     window.history.replaceState(undefined, undefined, '#' + url);
33624                // }else{
33625                //     var baseUrl = window.location.href.split('#')[0];
33626                //     window.location.replace( baseUrl + '#' + url );
33627                // }
33628                return false;
33629            }
33630        }
33631
33632        /**
33633        * Gets the anchor for the given slide / section. Its index will be used if there's none.
33634        */
33635        function getAnchor(element){
33636            var anchor = element.data('anchor');
33637            var index = element.index();
33638
33639            //Slide without anchor link? We take the index instead.
33640            if(typeof anchor === 'undefined'){
33641                anchor = index;
33642            }
33643
33644            return anchor;
33645        }
33646
33647        /**
33648        * Sets a class for the body of the page depending on the active section / slide
33649        */
33650        function setBodyClass(){
33651            var section = $(SECTION_ACTIVE_SEL);
33652            var slide = section.find(SLIDE_ACTIVE_SEL);
33653
33654            var sectionAnchor = getAnchor(section);
33655            var slideAnchor = getAnchor(slide);
33656
33657            var text = String(sectionAnchor);
33658
33659            if(slide.length){
33660                text = text + '-' + slideAnchor;
33661            }
33662
33663            //changing slash for dash to make it a valid CSS style
33664            text = text.replace('/', '-').replace('#','');
33665
33666            //removing previous anchor classes
33667            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
33668            $body[0].className = $body[0].className.replace(classRe, '');
33669
33670            //adding the current anchor
33671            $body.addClass(VIEWING_PREFIX + '-' + text);
33672        }
33673
33674        /**
33675        * Checks for translate3d support
33676        * @return boolean
33677        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
33678        */
33679        function support3d() {
33680            var el = document.createElement('p'),
33681                has3d,
33682                transforms = {
33683                    'webkitTransform':'-webkit-transform',
33684                    'OTransform':'-o-transform',
33685                    'msTransform':'-ms-transform',
33686                    'MozTransform':'-moz-transform',
33687                    'transform':'transform'
33688                };
33689
33690            // Add it to the body to get the computed style.
33691            document.body.insertBefore(el, null);
33692
33693            for (var t in transforms) {
33694                if (el.style[t] !== undefined) {
33695                    el.style[t] = 'translate3d(1px,1px,1px)';
33696                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
33697                }
33698            }
33699
33700            document.body.removeChild(el);
33701
33702            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
33703        }
33704
33705        /**
33706        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
33707        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
33708        */
33709        function removeMouseWheelHandler(){
33710            if (document.addEventListener) {
33711                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
33712                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
33713                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
33714            } else {
33715                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
33716            }
33717        }
33718
33719        /**
33720        * Adds the auto scrolling action for the mouse wheel and trackpad.
33721        * After this function is called, the mousewheel and trackpad movements will scroll through sections
33722        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
33723        */
33724        function addMouseWheelHandler(){
33725            var prefix = '';
33726            var _addEventListener;
33727
33728            if (window.addEventListener){
33729                _addEventListener = "addEventListener";
33730            }else{
33731                _addEventListener = "attachEvent";
33732                prefix = 'on';
33733            }
33734
33735             // detect available wheel event
33736            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
33737                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
33738                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
33739            var passiveEvent = g_supportsPassive ? {passive: false }
33739: false;
33740
33741
33742            if(support == 'DOMMouseScroll'){
33743                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
33744            }
33745
33746            //handle MozMousePixelScroll in older Firefox
33747            else{
33748                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
33749            }
33750        }
33751
33752        /**
33753        * Binding the mousemove when the mouse's middle button is pressed
33754        */
33755        function addMiddleWheelHandler(){
33756            container
33757                .on('mousedown', mouseDownHandler)
33758                .on('mouseup', mouseUpHandler);
33759        }
33760
33761        /**
33762        * Unbinding the mousemove when the mouse's middle button is released
33763        */
33764        function removeMiddleWheelHandler(){
33765            container
33766                .off('mousedown', mouseDownHandler)
33767                .off('mouseup', mouseUpHandler);
33768        }
33769
33770        /**
33771        * Adds the possibility to auto scroll through sections on touch devices.
33772        */
33773        function addTouchHandler(){
33774            if(isTouchDevice || isTouch){
33775                if(options.autoScrolling){
33776                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
33777                }
33778
33779                $(WRAPPER_SEL)
33780                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
33781                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
33782            }
33783        }
33784
33785        /**
33786        * Removes the auto scrolling for touch devices.
33787        */
33788        function removeTouchHandler(){
33789            if(isTouchDevice || isTouch){
33790                $(WRAPPER_SEL)
33791                    .off(events.touchstart)
33792                    .off(events.touchmove);
33793            }
33794        }
33795
33796        /*
33797        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
33798        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
33799        */
33800        function getMSPointer(){
33801            var pointer;
33802
33803            //IE >= 11 & rest of browsers
33804            if(window.PointerEvent){
33805                pointer = { down: 'pointerdown', move: 'pointermove'};
33806            }
33807
33808            //IE < 11
33809            else{
33810                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
33811            }
33812
33813            return pointer;
33814        }
33815
33816        /**
33817        * Gets the pageX and pageY properties depending on the browser.
33818        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
33819        */
33820        function getEventsPage(e){
33821            var events = [];
33822
33823            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
33824            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33825
33826            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33827            if(isTouch && isReallyTouch(e) && options.scrollBar){
33828                events.y = e.touches[0].pageY;
33829                events.x = e.touches[0].pageX;
33830            }
33831
33832            return events;
33833        }
33834
33835        /**
33836        * Slides silently (with no animation) the active slider to the given slide.
33837        * @param noCallback {bool} true or defined -> no callbacks
33838        */
33839        function silentLandscapeScroll(activeSlide, noCallbacks){
33840            setScrollingSpeed (0, 'internal');
33841
33842            if(typeof noCallbacks !== 'undefined'){
33843                //preventing firing callbacks afterSlideLoad etc.
33844                isResizing = true;
33845            }
33846
33847            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33848
33849            if(typeof noCallbacks !== 'undefined'){
33850                isResizing = false;
33851            }
33852
33853            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33854        }
33855
33856        /**
33857        * Scrolls silently (with no animation) the page to the given Y position.
33858        */
33859        function silentScroll(top){
33860            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33861            // that's why we round it to 0.
33862            var roundedTop = Math.round(top);
33863
33864            if (options.css3 && options.autoScrolling && !options.scrollBar){
33865                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33866                transformContainer(translate3d, false);
33867            }
33868            else if(options.autoScrolling && !options.scrollBar){
33869                container.css('top', -roundedTop);
33870            }
33871            else{
33872                $htmlBody.scrollTop(roundedTop);
33873            }
33874        }
33875
33876        /**
33877        * Returns the cross-browser transform string.
33878        */
33879        function getTransforms(translate3d){
33880            return {
33881                '-webkit-transform': translate3d,
33882                '-moz-transform': translate3d,
33883                '-ms-transform':translate3d,
33884                'transform': translate3d
33885            };
33886        }
33887
33888        /**
33889        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33890        * @type  m (mouse) or k (keyboard)
33891        */
33892        function setIsScrollAllowed(value, direction, type){
33893            switch (direction){
33894                case 'up': isScrollAllowed[type].up = value; break;
33895                case 'down': isScrollAllowed[type].down = value; break;
33896                case 'left': isScrollAllowed[type].left = value; break;
33897                case 'right': isScrollAllowed[type].right = value; break;
33898                case 'all':
33899                    if(type == 'm'){
33900                        setAllowScrolling(value);
33901                    }else{
33902                        setKeyboardScrolling(value);
33903                    }
33904            }
33905        }
33906
33907        /*
33908        * Destroys fullpage.js plugin events and optinally its html markup and styles
33909        */
33910        function destroy(all){
33911            setAutoScrolling(false, 'internal');
33912            setAllowScrolling(false);
33913            setKeyboardScrolling(false);
33914            container.addClass(DESTROYED);
33915
33916            clearTimeout(afterSlideLoadsId);
33917            clearTimeout(afterSectionLoadsId);
33918            clearTimeout(resizeId);
33919            clearTimeout(scrollId);
33920            clearTimeout(scrollId2);
33921
33922            $window
33923                .off('scroll', scrollHandler)
33924                .off('hashchange', hashChangeHandler)
33925                .off('resize', resizeHandler);
33926
33927            $document
33928                .off('click touchstart', SECTION_NAV_SEL + ' a')
33929                .off('mouseenter', SECTION_NAV_SEL + ' li')
33930                .off('mouseleave', SECTION_NAV_SEL + ' li')
33931                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33932                .off('mouseover', options.normalScrollElements)
33933                .off('mouseout', options.normalScrollElements);
33934
33935            $(SECTION_SEL)
33936                .off('click touchstart', SLIDES_ARROW_SEL);
33937
33938            clearTimeout(afterSlideLoadsId);
33939            clearTimeout(afterSectionLoadsId);
33940
33941            //lets make a mess!
33942            if(all){
33943                destroyStructure();
33944            }
33945        }
33946
33947        /*
33948        * Removes inline styles added by fullpage.js
33949        */
33950        function destroyStructure(){
33951            //reseting the `top` or `translate` properties to 0
33952            silentScroll(0);
33953
33954            //loading all the lazy load content
33955            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33956                setSrc($(this), 'src');
33957            });
33958
33959            container.find('img[data-srcset]').each(function(){
33960                setSrc($(this), 'srcset');
33961            });
33962
33963            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33964
33965            //removing inline styles
33966            $(SECTION_SEL).css( {
33967                'height': '',
33968                'background-color' : '',
33969                'padding': ''
33970            });
33971
33972            $(SLIDE_SEL).css( {
33973                'width': ''
33974            });
33975
33976            container.css({
33977                'height': '',
33978                'position': '',
33979                '-ms-touch-action': '',
33980                'touch-action': ''
33981            });
33982
33983            $htmlBody.css({
33984                'overflow': '',
33985                'height': ''
33986            });
33987
33988            // remove .fp-enabled class
33989            $('html').removeClass(ENABLED);
33990
33991            // remove .fp-responsive class
33992            $body.removeClass(RESPONSIVE);
33993
33994            // remove all of the .fp-viewing- classes
33995            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33996                if (className.indexOf(VIEWING_PREFIX) === 0) {
33997                    $body.removeClass(className);
33998                }
33999            });
34000
34001            //removing added classes
34002            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
34003                options.scrollOverflowHandler.remove($(this));
34004                $(this).removeClass(TABLE + ' ' + ACTIVE);
34005            });
34006
34007            removeAnimation(container);
34008
34009            //Unwrapping content
34010            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
34011                //unwrap not being use in case there's no child element inside and its just text
34012                $(this).replaceWith(this.childNodes);
34013            });
34014
34015            //removing the applied transition from the fullpage wrapper
34016            container.css({
34017                '-webkit-transition': 'none',
34018                'transition': 'none'
34019            });
34020
34021            //scrolling the page to the top with no animation
34022            $htmlBody.scrollTop(0);
34023
34024            //removing selectors
34025            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
34026            $.each(usedSelectors, function(index, value){
34027                $('.' + value).removeClass(value);
34028            });
34029        }
34030
34031        /*
34032        * Sets the state for a variable with multiple states (original, and temporal)
34033        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
34034        * This function is used to keep track of both states, the original and the temporal one.
34035        * If type is not 'internal', then we assume the user is globally changing the variable.
34036        */
34037        function setVariableState(variable, value, type){
34038            options[variable] = value;
34039            if(type !== 'internal'){
34040                originals[variable] = value;
34041            }
34042        }
34043
34044        /**
34045        * Displays warnings
34046        */
34047        function displayWarnings(){
34048            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
34049            //UNCODE.addition
34050            // if($('html').hasClass(ENABLED)){
34051            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
34052            //     return;
34053            // }
34054
34055            // Disable mutually exclusive settings
34056            //UNCODE.addition
34057            // if (options.continuousVertical &&
34058            //     (options.loopTop || options.loopBottom)) {
34059            //     options.continuousVertical = false;
34060            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34061            // }
34062
34063            // if(options.scrollBar && options.scrollOverflow){
34064            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34065            // }
34066
34067            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34068            //     options.continuousVertical = false;
34069            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34070            // }
34071
34072            //using extensions? Wrong file!
34073            $.each(extensions, function(index, extension){
34074                //is the option set to true?
34075                if(options[extension]){
34076                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34077                }
34078            });
34079
34080            //anchors can not have the same value as any element ID or NAME
34081            $.each(options.anchors, function(index, name){
34082
34083                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34084                var nameAttr = $document.find('[name]').filter(function() {
34085                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34086                });
34087
34088                var idAttr = $document.find('[id]').filter(function() {
34089                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34090                });
34091
34092                if(idAttr.length || nameAttr.length ){
34093                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34094                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34095                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34096                }
34097            });
34098        }
34099
34100        /**
34101        * Shows a message in the console of the given type.
34102        */
34103        function showError(type, text){
34104            console && console[type] && console[type]('fullPage: ' + text);
34105        }
34106
34107    }; //end of $.fn.fullpage
34108
34109    if(typeof IScroll !== 'undefined'){
34110        /*
34111        * Turns iScroll `mousewheel` option off dynamically
34112        * https://github.com/cubiq/iscroll/issues/1036
34113        */
34114        IScroll.prototype.wheelOn = function () {
34115            this.wrapper.addEventListener('wheel', this);
34116            this.wrapper.addEventListener('mousewheel', this);
34117            this.wrapper.addEventListener('DOMMouseScroll', this);
34118        };
34119
34120        /*
34121        * Turns iScroll `mousewheel` option on dynamically
34122        * https://github.com/cubiq/iscroll/issues/1036
34123        */
34124        IScroll.prototype.wheelOff = function () {
34125            this.wrapper.removeEventListener('wheel', this);
34126            this.wrapper.removeEventListener('mousewheel', this);
34127            this.wrapper.removeEventListener('DOMMouseScroll', this);
34128        };
34129    }
34130
34131    /**
34132     * An object to handle overflow scrolling.
34133     * This uses jquery.slimScroll to accomplish overflow scrolling.
34134     * It is possible to pass in an alternate scrollOverflowHandler
34135     * to the fullpage.js option that implements the same functions
34136     * as this handler.
34137     *
34138     * @type {Object}
34139     */
34140    var iscrollHandler = {
34141        refreshId: null,
34142        iScrollInstances: [],
34143
34144        // Enables or disables the mouse wheel for the active section or all slides in it
34145        toggleWheel: function(value){
34146            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
34147            scrollable.each(function(){
34148                var iScrollInstance = $(this).data('iscrollInstance');
34149                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
34150                    if(value){
34151                        iScrollInstance.wheelOn();
34152                    }
34153                    else{
34154                        iScrollInstance.wheelOff();
34155                    }
34156                }
34157            });
34158        },
34159
34160        /**
34161        * Turns off iScroll for the destination section.
34162        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
34163        * scroll the destination section/slide before the sections animations ends.
34164        */
34165        onLeave: function(){
34166            iscrollHandler.toggleWheel(false);
34167        },
34168
34169        // Turns off iScroll for the leaving section
34170        beforeLeave: function(){
34171            iscrollHandler.onLeave()
34172        },
34173
34174        // Turns on iScroll on section load
34175        afterLoad: function(){
34176            iscrollHandler.toggleWheel(true);
34177        },
34178
34179        /**
34180         * Called when overflow scrolling is needed for a section.
34181         *
34182         * @param  {Object} element      jQuery object containing current section
34183         * @param  {Number} scrollHeight Current window height in pixels
34184         */
34185        create: function(element, scrollHeight) {
34186            var scrollable = element.find(SCROLLABLE_SEL);
34187
34188            scrollable.height(scrollHeight);
34189            scrollable.each(function() {
34190                var $this = $(this);
34191                var iScrollInstance = $this.data('iscrollInstance');
34192                if (iScrollInstance) {
34193                    $.each(iscrollHandler.iScrollInstances, function(){
34194                        $(this).destroy();
34195                    });
34196                }
34197
34198                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
34199                iscrollHandler.iScrollInstances.push(iScrollInstance);
34200
34201                //off by default until the section gets active
34202                iScrollInstance.wheelOff();
34203
34204                $this.data('iscrollInstance', iScrollInstance);
34205            });
34206        },
34207
34208        /**
34209         * Return a boolean depending on whether the scrollable element is a
34210         * the end or at the start of the scrolling depending on the given type.
34211         *
34212         * @param  {String}  type       Either 'top' or 'bottom'
34213         * @param  {Object}  scrollable jQuery object for the scrollable element
34214         * @return {Boolean}
34215         */
34216        isScrolled: function(type, scrollable) {
34217            var scroller = scrollable.data('iscrollInstance');
34218
34219            //no scroller?
34220            if (!scroller) {
34221                return true;
34222            }
34223
34224            //Uncode addition
34225            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
34226            //End Uncode addition
34227
34228            if (type === 'top') {
34229                return scroller.y >= 0 && !scrollable.scrollTop();
34230            } else if (type === 'bottom') {
34231                //Uncode change
34232                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34233                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34234                //End Uncode change
34235            }
34236        },
34237
34238        /**
34239         * Returns the scrollable element for the given section.
34240         * If there are landscape slides, will only return a scrollable element
34241         * if it is in the active slide.
34242         *
34243         * @param  {Object}  activeSection jQuery object containing current section
34244         * @return {Boolean}
34245         */
34246        scrollable: function(activeSection){
34247            // if there are landscape slides, we check if the scrolling bar is in the current one or not
34248            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
34249                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
34250            }
34251            return activeSection.find(SCROLLABLE_SEL);
34252        },
34253
34254        /**
34255         * Returns the scroll height of the wrapped content.
34256         * If this is larger than the window height minus section padding,
34257         * overflow scrolling is needed.
34258         *
34259         * @param  {Object} element jQuery object containing current section
34260         * @return {Number}
34261         */
34262        scrollHeight: function(element) {
34263            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
34264        },
34265
34266        /**
34267         * Called when overflow scrolling is no longer needed for a section.
34268         *
34269         * @param  {Object}
34269 element      jQuery object containing current section
34270         */
34271        remove: function(element) {
34272            var scrollable = element.find(SCROLLABLE_SEL);
34273            if (scrollable.length) {
34274                var iScrollInstance = scrollable.data('iscrollInstance');
34275                iScrollInstance.destroy();
34276
34277                scrollable.data('iscrollInstance', null);
34278            }
34279            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
34280        },
34281
34282        /**
34283         * Called when overflow scrolling has already been setup but the
34284         * window height has potentially changed.
34285         *
34286         * @param  {Object} element      jQuery object containing current section
34287         * @param  {Number} scrollHeight Current window height in pixels
34288         */
34289        update: function(element, scrollHeight) {
34290            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
34291            //short period of time.
34292            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
34293            clearTimeout(iscrollHandler.refreshId);
34294            iscrollHandler.refreshId = setTimeout(function(){
34295                $.each(iscrollHandler.iScrollInstances, function(){
34296                    $(this).get(0).refresh();
34297                });
34298            }, 150);
34299
34300            //updating the wrappers height
34301            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
34302        },
34303
34304        /**
34305         * Called to get any additional elements needed to wrap the section
34306         * content in order to facilitate overflow scrolling.
34307         *
34308         * @return {String|Object} Can be a string containing HTML,
34309         *                         a DOM element, or jQuery object.
34310         */
34311        wrapContent: function() {
34312            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
34313        }
34314    };
34315});
34316
34317(function (global, factory) {
34318	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
34319	typeof define === 'function' && define.amd ? define(['exports'], factory) :
34320	(global = global || self, factory(global.window = global.window || {}));
34321}(this, (function (exports) { 'use strict';
34322
34323	/*!
34324	 * ScrollTrigger 3.8.0
34325	 * https://greensock.com
34326	 *
34327	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
34328	 * Subject to the terms at https://greensock.com/standard-license or for
34329	 * Club GreenSock members, the agreement issued with that membership.
34330	 * @author: Jack Doyle, [email protected]
34331	*/
34332	var gsap,
34333	    _coreInitted,
34334	    _win,
34335	    _doc,
34336	    _docEl,
34337	    _body,
34338	    _root,
34339	    _resizeDelay,
34340	    _raf,
34341	    _request,
34342	    _toArray,
34343	    _clamp,
34344	    _time2,
34345	    _syncInterval,
34346	    _refreshing,
34347	    _pointerIsDown,
34348	    _transformProp,
34349	    _i,
34350	    _prevWidth,
34351	    _prevHeight,
34352	    _autoRefresh,
34353	    _sort,
34354	    _suppressOverwrites,
34355	    _ignoreResize,
34356	    _limitCallbacks,
34357	    _startup = 1,
34358	    _proxies = [],
34359	    _scrollers = [],
34360	    _getTime = Date.now,
34361	    _time1 = _getTime(),
34362	    _lastScrollTime = 0,
34363	    _enabled = 1,
34364	    _passThrough = function _passThrough(v) {
34365	  return v;
34366	},
34367	    _getTarget = function _getTarget(t) {
34368	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
34369	},
34370	    _round = function _round(value) {
34371	  return Math.round(value * 100000) / 100000 || 0;
34372	},
34373	    _windowExists = function _windowExists() {
34374	  return typeof window !== "undefined";
34375	},
34376	    _getGSAP = function _getGSAP() {
34377	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
34378	},
34379	    _isViewport = function _isViewport(e) {
34380	  return !!~_root.indexOf(e);
34381	},
34382	    _getProxyProp = function _getProxyProp(element, property) {
34383	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
34384	},
34385	    _getScrollFunc = function _getScrollFunc(element, _ref) {
34386	  var s = _ref.s,
34387	      sc = _ref.sc;
34388
34389	  var i = _scrollers.indexOf(element),
34390	      offset = sc === _vertical.sc ? 1 : 2;
34391
34392	  !~i && (i = _scrollers.push(element) - 1);
34393	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
34394	    return arguments.length ? element[s] = value : element[s];
34395	  }));
34396	},
34397	    _getBoundsFunc = function _getBoundsFunc(element) {
34398	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
34399	    _winOffsets.width = _win.innerWidth;
34400	    _winOffsets.height = _win.innerHeight;
34401	    return _winOffsets;
34402	  } : function () {
34403	    return _getBounds(element);
34404	  });
34405	},
34406	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
34407	  var d = _ref2.d,
34408	      d2 = _ref2.d2,
34409	      a = _ref2.a;
34410	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
34411	    return a()[d];
34412	  } : function () {
34413	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
34414	  };
34415	},
34416	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
34417	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
34418	    return _winOffsets;
34419	  };
34420	},
34421	    _maxScroll = function _maxScroll(element, _ref3) {
34422	  var s = _ref3.s,
34423	      d2 = _ref3.d2,
34424	      d = _ref3.d,
34425	      a = _ref3.a;
34426	  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];
34427	},
34428	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
34429	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 34430-34634
34430	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
34431	  }
34432	},
34433	    _isString = function _isString(value) {
34434	  return typeof value === "string";
34435	},
34436	    _isFunction = function _isFunction(value) {
34437	  return typeof value === "function";
34438	},
34439	    _isNumber = function _isNumber(value) {
34440	  return typeof value === "number";
34441	},
34442	    _isObject = function _isObject(value) {
34443	  return typeof value === "object";
34444	},
34445	    _callIfFunc = function _callIfFunc(value) {
34446	  return _isFunction(value) && value();
34447	},
34448	    _combineFunc = function _combineFunc(f1, f2) {
34449	  return function () {
34450	    var result1 = _callIfFunc(f1),
34451	        result2 = _callIfFunc(f2);
34452
34453	    return function () {
34454	      _callIfFunc(result1);
34455
34456	      _callIfFunc(result2);
34457	    };
34458	  };
34459	},
34460	    _endAnimation = function _endAnimation(animation, reversed, pause) {
34461	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
34462	},
34463	    _callback = function _callback(self, func) {
34464	  var result = func(self);
34465	  result && result.totalTime && (self.callbackAnimation = result);
34466	},
34467	    _abs = Math.abs,
34468	    _scrollLeft = "scrollLeft",
34469	    _scrollTop = "scrollTop",
34470	    _left = "left",
34471	    _top = "top",
34472	    _right = "right",
34473	    _bottom = "bottom",
34474	    _width = "width",
34475	    _height = "height",
34476	    _Right = "Right",
34477	    _Left = "Left",
34478	    _Top = "Top",
34479	    _Bottom = "Bottom",
34480	    _padding = "padding",
34481	    _margin = "margin",
34482	    _Width = "Width",
34483	    _Height = "Height",
34484	    _px = "px",
34485	    _horizontal = {
34486	  s: _scrollLeft,
34487	  p: _left,
34488	  p2: _Left,
34489	  os: _right,
34490	  os2: _Right,
34491	  d: _width,
34492	  d2: _Width,
34493	  a: "x",
34494	  sc: function sc(value) {
34495	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
34496	  }
34497	},
34498	    _vertical = {
34499	  s: _scrollTop,
34500	  p: _top,
34501	  p2: _Top,
34502	  os: _bottom,
34503	  os2: _Bottom,
34504	  d: _height,
34505	  d2: _Height,
34506	  a: "y",
34507	  op: _horizontal,
34508	  sc: function sc(value) {
34509	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
34510	  }
34511	},
34512	    _getComputedStyle = function _getComputedStyle(element) {
34513	  return _win.getComputedStyle(element);
34514	},
34515	    _makePositionable = function _makePositionable(element) {
34516	  var position = _getComputedStyle(element).position;
34517
34518	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
34519	},
34520	    _setDefaults = function _setDefaults(obj, defaults) {
34521	  for (var p in defaults) {
34522	    p in obj || (obj[p] = defaults[p]);
34523	  }
34524
34525	  return obj;
34526	},
34527	    _getBounds = function _getBounds(element, withoutTransforms) {
34528	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
34529	    x: 0,
34530	    y: 0,
34531	    xPercent: 0,
34532	    yPercent: 0,
34533	    rotation: 0,
34534	    rotationX: 0,
34535	    rotationY: 0,
34536	    scale: 1,
34537	    skewX: 0,
34538	    skewY: 0
34539	  }).progress(1),
34540	      bounds = element.getBoundingClientRect();
34541	  tween && tween.progress(0).kill();
34542	  return bounds;
34543	},
34544	    _getSize = function _getSize(element, _ref4) {
34545	  var d2 = _ref4.d2;
34546	  return element["offset" + d2] || element["client" + d2] || 0;
34547	},
34548	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
34549	  var a = [],
34550	      labels = timeline.labels,
34551	      duration = timeline.duration(),
34552	      p;
34553
34554	  for (p in labels) {
34555	    a.push(labels[p] / duration);
34556	  }
34557
34558	  return a;
34559	},
34560	    _getClosestLabel = function _getClosestLabel(animation) {
34561	  return function (value) {
34562	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
34563	  };
34564	},
34565	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
34566	  var snap = gsap.utils.snap(snapIncrementOrArray),
34567	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
34568	    return a - b;
34569	  });
34570	  return a ? function (value, direction) {
34571	    var i;
34572
34573	    if (!direction) {
34574	      return snap(value);
34575	    }
34576
34577	    if (direction > 0) {
34578	      value -= 1e-4;
34579
34580	      for (i = 0; i < a.length; i++) {
34581	        if (a[i] >= value) {
34582	          return a[i];
34583	        }
34584	      }
34585
34586	      return a[i - 1];
34587	    } else {
34588	      i = a.length;
34589	      value += 1e-4;
34590
34591	      while (i--) {
34592	        if (a[i] <= value) {
34593	          return a[i];
34594	        }
34595	      }
34596	    }
34597
34598	    return a[0];
34599	  } : function (value, direction) {
34600	    var snapped = snap(value);
34601	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
34602	  };
34603	},
34604	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
34605	  return function (value, st) {
34606	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
34607	  };
34608	},
34609	    _multiListener = function _multiListener(func, element, types, callback) {
34610	  return types.split(",").forEach(function (type) {
34611	    return func(element, type, callback);
34612	  });
34613	},
34614	    _addListener = function _addListener(element, type, func) {
34615	  return element.addEventListener(type, func, {
34616	    passive: true
34617	  });
34618	},
34619	    _removeListener = function _removeListener(element, type, func) {
34620	  return element.removeEventListener(type, func);
34621	},
34622	    _markerDefaults = {
34623	  startColor: "green",
34624	  endColor: "red",
34625	  indent: 0,
34626	  fontSize: "16px",
34627	  fontWeight: "normal"
34628	},
34629	    _defaults = {
34630	  toggleActions: "play",
34631	  anticipatePin: 0
34632	},
34633	    _keywords = {
34634	  top: 0,
34635	  left: 0,
34636	  center: 0.5,
34637	  bottom: 1,
34638	  right: 1
34639	},
34640	    _offsetToPx = function _offsetToPx(value, size) {
34641	  if (_isString(value)) {
34642	    var eqIndex = value.indexOf("="),
34643	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
34644
34645	    if (~eqIndex) {
34646	      value.indexOf("%") > eqIndex && (relative *= size / 100);
34647	      value = value.substr(0, eqIndex - 1);
34648	    }
34649
34650	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
34651	  }
34652
34653	  return value;
34654	},
34655	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
34656	  var startColor = _ref5.startColor,
34657	      endColor = _ref5.endColor,
34658	      fontSize = _ref5.fontSize,
34659	      indent = _ref5.indent,
34660	      fontWeight = _ref5.fontWeight;
34661
34662	  var e = _doc.createElement("div"),
34663	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
34664	      isScroller = type.indexOf("scroller") !== -1,
34665	      parent = useFixedPosition ? _body : container,
34666	      isStart = type.indexOf("start") !== -1,
34667	      color = isStart ? startColor : endColor,
34668	      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;";
34669
34670	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
34671	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
34672	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
34673	  e._isStart = isStart;
34674	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
34675	  e.style.cssText = css;
34676	  e.innerText = name || name === 0 ? type + "-" + name : type;
34677	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
34678	  e._offset = e["offset" + direction.op.d2];
34679
34680	  _positionMarker(e, 0, direction, isStart);
34681
34682	  return e;
34683	},
34684	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
34685	  var vars = {
34686	    display: "block"
34687	  },
34688	      side = direction[flipped ? "os2" : "p2"],
34689	      oppositeSide = direction[flipped ? "p2" : "os2"];
34690	  marker._isFlipped = flipped;
34691	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
34692	  vars[direction.a] = flipped ? "1px" : 0;
34693	  vars["border" + side + _Width] = 1;
34694	  vars["border" + oppositeSide + _Width] = 0;
34695	  vars[direction.p] = start + "px";
34696	  gsap.set(marker, vars);
34697	},
34698	    _triggers = [],
34699	    _ids = {},
34700	    _sync = function _sync() {
34701	  return _getTime() - _lastScrollTime > 20 && _updateAll();
34702	},
34703	    _onScroll = function _onScroll() {
34704	  var time = _getTime();
34705
34706	  if (_lastScrollTime !== time) {
34707	    _updateAll();
34708
34709	    _lastScrollTime || _dispatch("scrollStart");
34710	    _lastScrollTime = time;
34711	  } else if (!_request) {
34712	    _request = _raf(_updateAll);
34713	  }
34714	},
34715	    _onResize = function _onResize() {
34716	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
34717	},
34718	    _listeners = {},
34719	    _emptyArray = [],
34720	    _media = [],
34721	    _creatingMedia,
34722	    _lastMediaTick,
34723	    _onMediaChange = function _onMediaChange(e) {
34724	  var tick = gsap.ticker.frame,
34725	      matches = [],
34726	      i = 0,
34727	      index;
34728
34729	  if (_lastMediaTick !== tick || _startup) {
34730	    _revertAll();
34731
34732	    for (; i < _media.length; i += 4) {
34733	      index = _win.matchMedia(_media[i]).matches;
34734
34735	      if (index !== _media[i + 3]) {
34736	        _media[i + 3] = index;
34737	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
34738	      }
34739	    }
34740
34741	    _revertRecorded();
34742
34743	    for (i = 0; i < matches.length; i++) {
34744	      index = matches[i];
34745	      _creatingMedia = _media[index];
34746	      _media[index + 2] = _media[index + 1](e);
34747	    }
34748
34749	    _creatingMedia = 0;
34750	    _coreInitted && _refreshAll(0, 1);
34751	    _lastMediaTick = tick;
34752
34753	    _dispatch("matchMedia");
34754	  }
34755	},
34756	    _softRefresh = function _softRefresh() {
34757	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
34758	},
34759	    _dispatch = function _dispatch(type) {
34760	  return _listeners[type] && _listeners[type].map(function (f) {
34761	    return f();
34762	  }) || _emptyArray;
34763	},
34764	    _savedStyles = [],
34765	    _revertRecorded = function _revertRecorded(media) {
34766	  for (var i = 0; i < _savedStyles.length; i += 5) {
34767	    if (!media || _savedStyles[i + 4] === media) {
34768	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
34769	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
34770	      _savedStyles[i + 3].uncache = 1;
34771	    }
34772	  }
34773	},
34774	    _revertAll = function _revertAll(kill, media) {
34775	  var trigger;
34776
34777	  for (_i = 0; _i < _triggers.length; _i++) {
34778	    trigger = _triggers[_i];
34779
34780	    if (!media || trigger.media === media) {
34781	      if (kill) {
34782	        trigger.kill(1);
34783	      } else {
34784	        trigger.revert();
34785	      }
34786	    }
34787	  }
34788
34789	  media && _revertRecorded(media);
34790	  media || _dispatch("revert");
34791	},
34792	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 34793-35127
34793	  return _scrollers.forEach(function (obj) {
34794	    return typeof obj === "function" && (obj.rec = 0);
34795	  });
34796	},
34797	    _refreshingAll,
34798	    _refreshAll = function _refreshAll(force, skipRevert) {
34799	  if (_lastScrollTime && !force) {
34800	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34801
34802	    return;
34803	  }
34804
34805	  _refreshingAll = true;
34806
34807	  var refreshInits = _dispatch("refreshInit");
34808
34809	  _sort && ScrollTrigger.sort();
34810	  skipRevert || _revertAll();
34811
34812	  _triggers.forEach(function (t) {
34813	    return t.refresh();
34814	  });
34815
34816	  refreshInits.forEach(function (result) {
34817	    return result && result.render && result.render(-1);
34818	  });
34819
34820	  _clearScrollMemory();
34821
34822	  _resizeDelay.pause();
34823
34824	  _refreshingAll = false;
34825
34826	  _dispatch("refresh");
34827	},
34828	    _lastScroll = 0,
34829	    _direction = 1,
34830	    _updateAll = function _updateAll() {
34831	  if (!_refreshingAll) {
34832	    var l = _triggers.length,
34833	        time = _getTime(),
34834	        recordVelocity = time - _time1 >= 50,
34835	        scroll = l && _triggers[0].scroll();
34836
34837	    _direction = _lastScroll > scroll ? -1 : 1;
34838	    _lastScroll = scroll;
34839
34840	    if (recordVelocity) {
34841	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34842	        _lastScrollTime = 0;
34843
34844	        _dispatch("scrollEnd");
34845	      }
34846
34847	      _time2 = _time1;
34848	      _time1 = time;
34849	    }
34850
34851	    if (_direction < 0) {
34852	      _i = l;
34853
34854	      while (_i-- > 0) {
34855	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34856	      }
34857
34858	      _direction = 1;
34859	    } else {
34860	      for (_i = 0; _i < l; _i++) {
34861	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34862	      }
34863	    }
34864
34865	    _request = 0;
34866	  }
34867	},
34868	    _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"],
34869	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34870	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34871	  _setState(state);
34872
34873	  var cache = pin._gsap;
34874
34875	  if (cache.spacerIsNative) {
34876	    _setState(cache.spacerState);
34877	  } else if (pin.parentNode === spacer) {
34878	    var parent = spacer.parentNode;
34879
34880	    if (parent) {
34881	      parent.insertBefore(pin, spacer);
34882	      parent.removeChild(spacer);
34883	    }
34884	  }
34885	},
34886	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34887	  if (pin.parentNode !== spacer) {
34888	    var i = _propNamesToCopy.length,
34889	        spacerStyle = spacer.style,
34890	        pinStyle = pin.style,
34891	        p;
34892
34893	    while (i--) {
34894	      p = _propNamesToCopy[i];
34895	      spacerStyle[p] = cs[p];
34896	    }
34897
34898	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34899	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34900	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34901	    spacerStyle.overflow = "visible";
34902	    spacerStyle.boxSizing = "border-box";
34903	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34904	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34905	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34906
34907	    _setState(spacerState);
34908
34909	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34910	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34911	    pinStyle[_padding] = cs[_padding];
34912	    pin.parentNode.insertBefore(spacer, pin);
34913	    spacer.appendChild(pin);
34914	  }
34915	},
34916	    _capsExp = /([A-Z])/g,
34917	    _setState = function _setState(state) {
34918	  if (state) {
34919	    var style = state.t.style,
34920	        l = state.length,
34921	        i = 0,
34922	        p,
34923	        value;
34924	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34925
34926	    for (; i < l; i += 2) {
34927	      value = state[i + 1];
34928	      p = state[i];
34929
34930	      if (value) {
34931	        style[p] = value;
34932	      } else if (style[p]) {
34933	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34934	      }
34935	    }
34936	  }
34937	},
34938	    _getState = function _getState(element) {
34939	  var l = _stateProps.length,
34940	      style = element.style,
34941	      state = [],
34942	      i = 0;
34943
34944	  for (; i < l; i++) {
34945	    state.push(_stateProps[i], style[_stateProps[i]]);
34946	  }
34947
34948	  state.t = element;
34949	  return state;
34950	},
34951	    _copyState = function _copyState(state, override, omitOffsets) {
34952	  var result = [],
34953	      l = state.length,
34954	      i = omitOffsets ? 8 : 0,
34955	      p;
34956
34957	  for (; i < l; i += 2) {
34958	    p = state[i];
34959	    result.push(p, p in override ? override[p] : state[i + 1]);
34960	  }
34961
34962	  result.t = state.t;
34963	  return result;
34964	},
34965	    _winOffsets = {
34966	  left: 0,
34967	  top: 0
34968	},
34969	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34970	  _isFunction(value) && (value = value(self));
34971
34972	  if (_isString(value) && value.substr(0, 3) === "max") {
34973	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34974	  }
34975
34976	  var time = containerAnimation ? containerAnimation.time() : 0,
34977	      p1,
34978	      p2,
34979	      element;
34980	  containerAnimation && containerAnimation.seek(0);
34981
34982	  if (!_isNumber(value)) {
34983	    _isFunction(trigger) && (trigger = trigger(self));
34984	    var offsets = value.split(" "),
34985	        bounds,
34986	        localOffset,
34987	        globalOffset,
34988	        display;
34989	    element = _getTarget(trigger) || _body;
34990	    bounds = _getBounds(element) || {};
34991
34992	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34993	      display = element.style.display;
34994	      element.style.display = "block";
34995	      bounds = _getBounds(element);
34996	      display ? element.style.display = display : element.style.removeProperty("display");
34997	    }
34998
34999	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
35000	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
35001	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
35002	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
35003	    scrollerSize -= scrollerSize - globalOffset;
35004	  } else if (markerScroller) {
35005	    _positionMarker(markerScroller, scrollerSize, direction, true);
35006	  }
35007
35008	  if (marker) {
35009	    var position = value + scrollerSize,
35010	        isStart = marker._isStart;
35011	    p1 = "scroll" + direction.d2;
35012
35013	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
35014
35015	    if (useFixedPosition) {
35016	      scrollerBounds = _getBounds(markerScroller);
35017	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
35018	    }
35019	  }
35020
35021	  if (containerAnimation && element) {
35022	    p1 = _getBounds(element);
35023	    containerAnimation.seek(scrollerMax);
35024	    p2 = _getBounds(element);
35025	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
35026	    value = value / containerAnimation._caScrollDist * scrollerMax;
35027	  }
35028
35029	  containerAnimation && containerAnimation.seek(time);
35030	  return containerAnimation ? value : Math.round(value);
35031	},
35032	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
35033	    _reparent = function _reparent(element, parent, top, left) {
35034	  if (element.parentNode !== parent) {
35035	    var style = element.style,
35036	        p,
35037	        cs;
35038
35039	    if (parent === _body) {
35040	      element._stOrig = style.cssText;
35041	      cs = _getComputedStyle(element);
35042
35043	      for (p in cs) {
35044	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
35045	          style[p] = cs[p];
35046	        }
35047	      }
35048
35049	      style.top = top;
35050	      style.left = left;
35051	    } else {
35052	      style.cssText = element._stOrig;
35053	    }
35054
35055	    gsap.core.getCache(element).uncache = 1;
35056	    parent.appendChild(element);
35057	  }
35058	},
35059	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
35060	  var getScroll = _getScrollFunc(scroller, direction),
35061	      prop = "_scroll" + direction.p2,
35062	      lastScroll1,
35063	      lastScroll2,
35064	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
35065	    var tween = getTween.tween,
35066	        onComplete = vars.onComplete,
35067	        modifiers = {};
35068	    tween && tween.kill();
35069	    lastScroll1 = Math.round(initialValue);
35070	    vars[prop] = scrollTo;
35071	    vars.modifiers = modifiers;
35072
35073	    modifiers[prop] = function (value) {
35074	      value = _round(getScroll());
35075
35076	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
35077	        tween.kill();
35078	        getTween.tween = 0;
35079	      } else {
35080	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
35081	      }
35082
35083	      lastScroll2 = lastScroll1;
35084	      return lastScroll1 = _round(value);
35085	    };
35086
35087	    vars.onComplete = function () {
35088	      getTween.tween = 0;
35089	      onComplete && onComplete.call(tween);
35090	    };
35091
35092	    tween = getTween.tween = gsap.to(scroller, vars);
35093	    return tween;
35094	  };
35095
35096	  scroller[prop] = getScroll;
35097	  scroller.addEventListener("wheel", function () {
35098	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
35099	  }, {
35100	    passive: true
35101	  });
35102	  return getTween;
35103	};
35104
35105	_horizontal.op = _vertical;
35106	var ScrollTrigger = function () {
35107	  function ScrollTrigger(vars, animation) {
35108	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
35109	    this.init(vars, animation);
35110	  }
35111
35112	  var _proto = ScrollTrigger.prototype;
35113
35114	  _proto.init = function init(vars, animation) {
35115	    this.progress = this.start = 0;
35116	    this.vars && this.kill(1);
35117
35118	    if (!_enabled) {
35119	      this.update = this.refresh = this.kill = _passThrough;
35120	      return;
35121	    }
35122
35123	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
35124	      trigger: vars
35125	    } : vars, _defaults);
35126
35127	    var _vars = vars,
35128	        onUpdate = _vars.onUpdate,
35129	        toggleClass = _vars.toggleClass,
35130	        id = _vars.id,
35131	        onToggle = _vars.onToggle,
35132	        onRefresh = _vars.onRefresh,
35133	        scrub = _vars.scrub,
35134	        trigger = _vars.trigger,
35135	        pin = _vars.pin,
35136	        pinSpacing = _vars.pinSpacing,
35137	        invalidateOnRefresh = _vars.invalidateOnRefresh,
35138	        anticipatePin = _vars.anticipatePin,
35139	        onScrubComplete = _vars.onScrubComplete,
35140	        onSnapComplete = _vars.onSnapComplete,
35141	        once = _vars.once,
35142	        snap = _vars.snap,
35143	        pinReparent = _vars.pinReparent,
35144	        pinSpacer = _vars.pinSpacer,
35145	        containerAnimation = _vars.containerAnimation,
35146	        fastScrollEnd = _vars.fastScrollEnd,
35147	        preventOverlaps = _vars.preventOverlaps,
35148	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
35149	        isToggle = !scrub && scrub !== 0,
35150	        scroller = _getTarget(vars.scroller || _win),
35151	        scrollerCache = gsap.core.getCache(scroller),
35152	        isViewport = _isViewport(scroller),
35153	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
35154	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
35155	        toggleActions = isToggle && vars.toggleActions.split(" "),
35156	        markers = "markers" in vars ? vars.markers : _defaults.markers,
35157	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
35158	        self = this,
35159	        onRefreshInit = vars.onRefreshInit && function () {
35160	      return vars.onRefreshInit(self);
35161	    },
35162	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
35163	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
35164	        lastSnap = 0,
35165	        scrollFunc = _getScrollFunc(scroller, direction),
35166	        tweenTo,
35167	        pinCache,
35168	        snapFunc,
35169	        scroll1,
35170	        scroll2,
35171	        start,
35172	        end,
35173	        markerStart,
35174	        markerEnd,
35175	        markerStartTrigger,
35176	        markerEndTrigger,
35177	        markerVars,
35178	        change,
35179	        pinOriginalState,
35180	        pinActiveState,
35181	        pinState,
35182	        spacer,
35183	        offset,
35184	        pinGetter,
35185	        pinSetter,
35186	        pinStart,
35187	        pinChange,
35188	        spacingStart,
35189	        spacerState,
35190	        markerStartSetter,
35191	        markerEndSetter,
35192	        cs,
35193	        snap1,
35194	        snap2,
35195	        scrubTween,
35196	        scrubSmooth,
35197	        snapDurClamp,
35198	        snapDelayedCall,
35199	        prevProgress,
35200	        prevScroll,
35201	        prevAnimProgress,
35202	        caMarkerSetter;
35203
35204	    self.media = _creatingMedia;
35205	    anticipatePin *= 45;
35206	    self.scroller = scroller;
35207	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
35208	    scroll1 = scrollFunc();
35209	    self.vars = vars;
35210	    animation = animation || vars.animation;
35211	    "refreshPriority" in vars && (_sort = 1);
35212	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
35213	      top: _getTweenCreator(scroller, _vertical),
35214	      left: _getTweenCreator(scroller, _horizontal)
35215	    };
35216	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
35217
35218	    if (animation) {
35219	      animation.vars.lazy = false;
35220	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
35221	      self.animation = animation.pause();
35222	      animation.scrollTrigger = self;
35223	      scrubSmooth = _isNumber(scrub) && scrub;
35224	      scrubSmooth && (scrubTween = gsap.to(animation, {
35225	        ease: "power3",
35226	        duration: scrubSmooth,
35227	        onComplete: function onComplete() {
35228	          return onScrubComplete && onScrubComplete(self);
35229	        }
35230	      }));
35231	      snap1 = 0;
35232	      id || (id = animation.vars.id);
35233	    }
35234
35235	    _triggers.push(self);
35236
35237	    if (snap) {
35238	      if (!_isObject(snap) || snap.push) {
35239	        snap = {
35240	          snapTo: snap
35241	        };
35242	      }
35243
35244	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
35245	        scrollBehavior: "auto"
35246	      });
35247	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
35248	        return _snapDirectional(snap.snapTo)(value, st.direction);
35249	      } : gsap.utils.snap(snap.snapTo);
35250	      snapDurClamp = snap.duration || {
35251	        min: 0.1,
35252	        max: 2
35253	      };
35254	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
35255	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
35256	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
35257	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
35258	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
35259	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
35260	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
35261	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
35262	              scroll = scrollFunc(),
35263	              endScroll = Math.round(start + endValue * change),
35264	              _snap = snap,
35265	              onStart = _snap.onStart,
35266	              _onInterrupt = _snap.onInterrupt,
35267	              _onComplete = _snap.onComplete,
35268	              tween = tweenTo.tween;
35269
35270	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
35271	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
35272	              return;
35273	            }
35274
35275	            if (snap.inertia === false) {
35276	              change1 = endValue - self.progress;
35277	            }
35278
35279	            tweenTo(endScroll, {
35280	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
35281	              ease: snap.ease || "power3",
35282	              data: _abs(endScroll - scroll),
35283	              onInterrupt: function onInterrupt() {
35284	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
35285	              },
35286	              onComplete: function onComplete() {
35287	                lastSnap = scrollFunc();
35288	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
35289	                onSnapComplete && onSnapComplete(self);
35290	                _onComplete && _onComplete(self);
35291	              }
35292	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
35293	            onStart && onStart(self, tweenTo.tween);
35294	          }
35295	        } else if (self.isActive) {
35296	          snapDelayedCall.restart(true);
35297	        }
35298	      }).pause();
35299	    }
35300
35301	    id && (_ids[id] = self);
35302	    trigger = self.trigger = _getTarget(trigger || pin);
35303	    pin = pin === true ? trigger : _getTarget(pin);
35304	    _isString(toggleClass) && (toggleClass = {
35305	      targets: trigger,
35306	      className: toggleClass
35307	    });
35308
35309	    if (pin) {
35310	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
35311	      self.pin = pin;
35312	      vars.force3D !== false && gsap.set(pin, {
35313	        force3D: true
35314	      });
35315	      pinCache = gsap.core.getCache(pin);
35316
35317	      if (!pinCache.spacer) {
35318	        if (pinSpacer) {
35319	          pinSpacer = _getTarget(pinSpacer);
35320	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
35321	          pinCache.spacerIsNative = !!pinSpacer;
35322	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
35323	        }
35324
35325	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
35326	        spacer.classList.add("pin-spacer");
35327	        id && spacer.classList.add("pin-spacer-" + id);
35328	        pinCache.pinState = pinOriginalState = _getState(pin);
35329	      } else {
35330	        pinOriginalState = pinCache.pinState;
35331	      }
35332
35333	      self.spacer = spacer = pinCache.spacer;
35334	      cs = _getComputedStyle(pin);
35335	      spacingStart = cs[pinSpacing + direction.os2];
35336	      pinGetter = gsap.getProperty(pin);
35337	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
35338
35339	      _swapPinIn(pin, spacer, cs);
35340
35341	      pinState = _getState(pin);
35342	    }
35343
35344	    if (markers) {
35345	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
35346	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
35347	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
35348	      offset = markerStartTrigger["offset" + direction.op.d2];
35349	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35350	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35351	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
35352
35353	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
35354	        _makePositionable(isViewport ? _body : scroller);
35355
35356	        gsap.set([markerStartTrigger, markerEndTrigger], {
35357	          force3D: true
35358	        });
35359	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
35360	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
35361	      }
35362	    }
35363
35364	    if (containerAnimation) {
35365	      var oldOnUpdate = containerAnimation.vars.onUpdate,
35366	          oldParams = containerAnimation.vars.onUpdateParams;
35367	      containerAnimation.eventCallback("onUpdate", function () {
35368	        self.update(0, 0, 1);
35369	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
35370	      });
35371	    }
35372
35373	    self.previous = function () {
35374	      return _triggers[_triggers.indexOf(self) - 1];
35375	    };
35376
35377	    self.next = function () {
35378	      return _triggers[_triggers.indexOf(self) + 1];
35379	    };
35380
35381	    self.revert = function (revert) {
35382	      var r = revert !== false || !self.enabled,
35383	          prevRefreshing = _refreshing;
35384
35385	      if (r !== self.isReverted) {
35386	        if (r) {
35387	          self.scroll.rec || (self.scroll.rec = scrollFunc());
35388	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
35389	          prevProgress = self.progress;
35390	          prevAnimProgress = animation && animation.progress();
35391	        }
35392
35393	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35394	          return m.style.display = r ? "none" : "block";
35395	        });
35396	        r && (_refreshing = 1);
35397	        self.update(r);
35398	        _refreshing = prevRefreshing;
35399	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
35400	        self.isReverted = r;
35401	      }
35402	    };
35403
35404	    self.refresh = function (soft, force) {
35405	      if ((_refreshing || !self.enabled) && !force) {
35406	        return;
35407	      }
35408
35409	      if (pin && soft && _lastScrollTime) {
35410	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
35411
35412	        return;
35413	      }
35414
35415	      _refreshing = 1;
35416	      scrubTween && scrubTween.pause();
35417	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
35418	      self.isReverted || self.revert();
35419
35420	      var size = getScrollerSize(),
35421	          scrollerBounds = getScrollerOffsets(),
35422	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
35423	          offset = 0,
35424	          otherPinOffset = 0,
35425	          parsedEnd = vars.end,
35426	          parsedEndTrigger = vars.endTrigger || trigger,
35427	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
35428	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
35429	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
35430	          i = triggerIndex,
35431	          cs,
35432	          bounds,
35433	          scroll,
35434	          isVertical,
35435	          override,
35436	          curTrigger,
35437	          curPin,
35438	          oppositeScroll,
35439	          initted,
35440	          revertedPins;
35441
35442	      while (i--) {
35443	        curTrigger = _triggers[i];
35444	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
35445	        curPin = curTrigger.pin;
35446
35447	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
35448	          revertedPins || (revertedPins = []);
35449	          revertedPins.unshift(curTrigger);
35450	          curTrigger.revert();
35451	        }
35452	      }
35453
35454	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
35455	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
35456	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
35457
35458	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
35459	        if (~parsedEnd.indexOf(" ")) {
35460	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
35461	        } else {
35462	          offset = _offsetToPx(parsedEnd.substr(2), size);
35463	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
35464	          parsedEndTrigger = trigger;
35465	        }
35466	      }
35467
35468	      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;
35469	      change = end - start || (start -= 0.01) && 0.001;
35470	      offset = 0;
35471	      i = triggerIndex;
35472
35473	      while (i--) {
35474	        curTrigger = _triggers[i];
35475	        curPin = curTrigger.pin;
35476
35477	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
35478	          cs = curTrigger.end - curTrigger.start;
35479	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
35480	          curPin === pin && (otherPinOffset += cs);
35481	        }
35482	      }
35483
35484	      start += offset;
35485	      end += offset;
35486	      self._pinPush = otherPinOffset;
35487
35488	      if (markerStart && offset) {
35489	        cs = {};
35490	        cs[direction.a] = "+=" + offset;
35491	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
35492	        gsap.set([markerStart, markerEnd], cs);
35493	      }
35494
35495	      if (pin) {
35496	        cs = _getComputedStyle(pin);
35497	        isVertical = direction === _vertical;
35498	        scroll = scrollFunc();
35499	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
35500	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
35501
35502	        _swapPinIn(pin, spacer, cs);
35503
35504	        pinState = _getState(pin);
35505	        bounds = _getBounds(pin, true);
35506	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
35507
35508	        if (pinSpacing) {
35509	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
35510	          spacerState.t = spacer;
35511	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
35512	          i && spacerState.push(direction.d, i + _px);
35513
35514	          _setState(spacerState);
35515
35516	          useFixedPosition && scrollFunc(prevScroll);
35517	        }
35518
35519	        if (useFixedPosition) {
35520	          override = {
35521	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
35522	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
35523	            boxSizing: "border-box",
35524	            position: "fixed"
35525	          };
35526	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
35527	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
35528	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
35529	          override[_padding] = cs[_padding];
35530	          override[_padding + _Top] = cs[_padding + _Top];
35531	          override[_padding + _Right] = cs[_padding + _Right];
35532	          override[_padding + _Bottom] = cs[_padding + _Bottom];
35533	          override[_padding + _Left] = cs[_padding + _Left];
35534	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
35535	        }
35536
35537	        if (animation) {
35538	          initted = animation._initted;
35539
35540	          _suppressOverwrites(1);
35541
35542	          animation.render(animation.duration(), true, true);
35543	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
35544	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
35545	          animation.render(0, true, true);
35546	          initted || animation.invalidate();
35547
35548	          _suppressOverwrites(0);
35549	        } else {
35550	          pinChange = change;
35551	        }
35552	      } else if (trigger && scrollFunc() && !containerAnimation) {
35553	        bounds = trigger.parentNode;
35554
35555	        while (bounds && bounds !== _body) {
35556	          if (bounds._pinOffset) {
35557	            start -= bounds._pinOffset;
35558	            end -= bounds._pinOffset;
35559	          }
35560
35561	          bounds = bounds.parentNode;
35562	        }
35563	      }
35564
35565	      revertedPins && revertedPins.forEach(function (t) {
35566	        return t.revert(false);
35567	      });
35568	      self.start = start;
35569	      self.end = end;
35570	      scroll1 = scroll2 = scrollFunc();
35571
35572	      if (!containerAnimation) {
35573	        scroll1 < prevScroll && scrollFunc(prevScroll);
35574	        self.scroll.rec = 0;
35575	      }
35576
35577	      self.revert(false);
35578	      _refreshing = 0;
35579	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
35580
35581	      if (prevProgress !== self.progress) {
35582	        animation && !isToggle && animation.totalProgress(prevProgress, true);
35583	        self.progress = prevProgress;
35584	        self.update(0, 0, 1);
35585	      }
35586
35587	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
35588	      onRefresh && onRefresh(self);
35589	    };
35590
35591	    self.getVelocity = function () {
35592	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
35593	    };
35594
35595	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 35596-35834
35596	      _endAnimation(self.callbackAnimation);
35597
35598	      if (animation) {
35599	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
35600	      }
35601	    };
35602
35603	    self.getTrailing = function (name) {
35604	      var i = _triggers.indexOf(self),
35605	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
35606
35607	      return _isString(name) ? a.filter(function (t) {
35608	        return t.vars.preventOverlaps === name;
35609	      }) : a;
35610	    };
35611
35612	    self.update = function (reset, recordVelocity, forceFake) {
35613	      if (containerAnimation && !forceFake && !reset) {
35614	        return;
35615	      }
35616
35617	      var scroll = self.scroll(),
35618	          p = reset ? 0 : (scroll - start) / change,
35619	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
35620	          prevProgress = self.progress,
35621	          isActive,
35622	          wasActive,
35623	          toggleState,
35624	          action,
35625	          stateChanged,
35626	          toggled,
35627	          isAtMax,
35628	          isTakingAction;
35629
35630	      if (recordVelocity) {
35631	        scroll2 = scroll1;
35632	        scroll1 = containerAnimation ? scrollFunc() : scroll;
35633
35634	        if (snap) {
35635	          snap2 = snap1;
35636	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
35637	        }
35638	      }
35639
35640	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
35641
35642	      if (clipped !== prevProgress && self.enabled) {
35643	        isActive = self.isActive = !!clipped && clipped < 1;
35644	        wasActive = !!prevProgress && prevProgress < 1;
35645	        toggled = isActive !== wasActive;
35646	        stateChanged = toggled || !!clipped !== !!prevProgress;
35647	        self.direction = clipped > prevProgress ? 1 : -1;
35648	        self.progress = clipped;
35649
35650	        if (stateChanged && !_refreshing) {
35651	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
35652
35653	          if (isToggle) {
35654	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
35655	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
35656	          }
35657	        }
35658
35659	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
35660	          return t.endAnimation();
35661	        }));
35662
35663	        if (!isToggle) {
35664	          if (scrubTween && !_refreshing && !_startup) {
35665	            scrubTween.vars.totalProgress = clipped;
35666	            scrubTween.invalidate().restart();
35667	          } else if (animation) {
35668	            animation.totalProgress(clipped, !!_refreshing);
35669	          }
35670	        }
35671
35672	        if (pin) {
35673	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
35674
35675	          if (!useFixedPosition) {
35676	            pinSetter(pinStart + pinChange * clipped);
35677	          } else if (stateChanged) {
35678	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
35679
35680	            if (pinReparent) {
35681	              if (!reset && (isActive || isAtMax)) {
35682	                var bounds = _getBounds(pin, true),
35683	                    _offset = scroll - start;
35684
35685	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
35686	              } else {
35687	                _reparent(pin, spacer);
35688	              }
35689	            }
35690
35691	            _setState(isActive || isAtMax ? pinActiveState : pinState);
35692
35693	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
35694	          }
35695	        }
35696
35697	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
35698	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
35699	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
35700	        });
35701	        onUpdate && !isToggle && !reset && onUpdate(self);
35702
35703	        if (stateChanged && !_refreshing) {
35704	          if (isToggle) {
35705	            if (isTakingAction) {
35706	              if (action === "complete") {
35707	                animation.pause().totalProgress(1);
35708	              } else if (action === "reset") {
35709	                animation.restart(true).pause();
35710	              } else if (action === "restart") {
35711	                animation.restart(true);
35712	              } else {
35713	                animation[action]();
35714	              }
35715	            }
35716
35717	            onUpdate && onUpdate(self);
35718	          }
35719
35720	          if (toggled || !_limitCallbacks) {
35721	            onToggle && toggled && _callback(self, onToggle);
35722	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35723	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
35724
35725	            if (!toggled) {
35726	              toggleState = clipped === 1 ? 1 : 3;
35727	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35728	            }
35729	          }
35730
35731	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
35732	            _endAnimation(self.callbackAnimation);
35733
35734	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
35735	          }
35736	        } else if (isToggle && onUpdate && !_refreshing) {
35737	          onUpdate(self);
35738	        }
35739	      }
35740
35741	      if (markerEndSetter) {
35742	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
35743	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
35744	        markerEndSetter(n);
35745	      }
35746
35747	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
35748	    };
35749
35750	    self.enable = function (reset, refresh) {
35751	      if (!self.enabled) {
35752	        self.enabled = true;
35753
35754	        _addListener(scroller, "resize", _onResize);
35755
35756	        _addListener(scroller, "scroll", _onScroll);
35757
35758	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
35759
35760	        if (reset !== false) {
35761	          self.progress = prevProgress = 0;
35762	          scroll1 = scroll2 = lastSnap = scrollFunc();
35763	        }
35764
35765	        refresh !== false && self.refresh();
35766	      }
35767	    };
35768
35769	    self.getTween = function (snap) {
35770	      return snap && tweenTo ? tweenTo.tween : scrubTween;
35771	    };
35772
35773	    self.disable = function (reset, allowAnimation) {
35774	      if (self.enabled) {
35775	        reset !== false && self.revert();
35776	        self.enabled = self.isActive = false;
35777	        allowAnimation || scrubTween && scrubTween.pause();
35778	        prevScroll = 0;
35779	        pinCache && (pinCache.uncache = 1);
35780	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
35781
35782	        if (snapDelayedCall) {
35783	          snapDelayedCall.pause();
35784	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
35785	        }
35786
35787	        if (!isViewport) {
35788	          var i = _triggers.length;
35789
35790	          while (i--) {
35791	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
35792	              return;
35793	            }
35794	          }
35795
35796	          _removeListener(scroller, "resize", _onResize);
35797
35798	          _removeListener(scroller, "scroll", _onScroll);
35799	        }
35800	      }
35801	    };
35802
35803	    self.kill = function (revert, allowAnimation) {
35804	      self.disable(revert, allowAnimation);
35805	      scrubTween && scrubTween.kill();
35806	      id && delete _ids[id];
35807
35808	      var i = _triggers.indexOf(self);
35809
35810	      _triggers.splice(i, 1);
35811
35812	      i === _i && _direction > 0 && _i--;
35813	      i = 0;
35814
35815	      _triggers.forEach(function (t) {
35816	        return t.scroller === self.scroller && (i = 1);
35817	      });
35818
35819	      i || (self.scroll.rec = 0);
35820
35821	      if (animation) {
35822	        animation.scrollTrigger = null;
35823	        revert && animation.render(-1);
35824	        allowAnimation || animation.kill();
35825	      }
35826
35827	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35828	        return m.parentNode && m.parentNode.removeChild(m);
35829	      });
35830
35831	      if (pin) {
35832	        pinCache && (pinCache.uncache = 1);
35833	        i = 0;
35834
35835	        _triggers.forEach(function (t) {
35836	          return t.pin === pin && i++;
35837	        });
35838
35839	        i || (pinCache.spacer = 0);
35840	      }
35841	    };
35842
35843	    self.enable(false, false);
35844	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35845	      return start || end || self.refresh();
35846	    }) && (change = 0.01) && (start = end = 0);
35847	  };
35848
35849	  ScrollTrigger.register = function register(core) {
35850	    if (!_coreInitted) {
35851	      gsap = core || _getGSAP();
35852
35853	      if (_windowExists() && window.document) {
35854	        _win = window;
35855	        _doc = document;
35856	        _docEl = _doc.documentElement;
35857	        _body = _doc.body;
35858	      }
35859
35860	      if (gsap) {
35861	        _toArray = gsap.utils.toArray;
35862	        _clamp = gsap.utils.clamp;
35863	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35864	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35865
35866	        if (_body) {
35867	          _raf = _win.requestAnimationFrame || function (f) {
35868	            return setTimeout(f, 16);
35869	          };
35870
35871	          _addListener(_win, "wheel", _onScroll);
35872
35873	          _root = [_win, _doc, _docEl, _body];
35874
35875	          _addListener(_doc, "scroll", _onScroll);
35876
35877	          var bodyStyle = _body.style,
35878	              border = bodyStyle.borderTopStyle,
35879	              bounds;
35880	          bodyStyle.borderTopStyle = "solid";
35881	          bounds = _getBounds(_body);
35882	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35883	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35884	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35885	          _syncInterval = setInterval(_sync, 200);
35886	          gsap.delayedCall(0.5, function () {
35887	            return _startup = 0;
35888	          });
35889
35890	          _addListener(_doc, "touchcancel", _passThrough);
35891
35892	          _addListener(_body, "touchstart", _passThrough);
35893
35894	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35895	            return _pointerIsDown = 1;
35896	          });
35897
35898	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35899	            return _pointerIsDown = 0;
35900	          });
35901
35902	          _transformProp = gsap.utils.checkPrefix("transform");
35903
35904	          _stateProps.push(_transformProp);
35905
35906	          _coreInitted = _getTime();
35907	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35908	          _autoRefresh = [_doc, "visibilitychange", function () {
35909	            var w = _win.innerWidth,
35910	                h = _win.innerHeight;
35911
35912	            if (_doc.hidden) {
35913	              _prevWidth = w;
35914	              _prevHeight = h;
35915	            } else if (_prevWidth !== w || _prevHeight !== h) {
35916	              _onResize();
35917	            }
35918	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35919	            return _lastScrollTime || _refreshAll();
35920	          }, _win, "resize", _onResize];
35921
35922	          _iterateAutoRefresh(_addListener);
35923	        }
35924	      }
35925	    }
35926
35927	    return _coreInitted;
35928	  };
35929
35930	  ScrollTrigger.defaults = function defaults(config) {
35931	    for (var p in config) {
35932	      _defaults[p] = config[p];
35933	    }
35934	  };
35935
35936	  ScrollTrigger.kill = function kill() {
35937	    _enabled = 0;
35938
35939	    _triggers.slice(0).forEach(function (trigger) {
35940	      return trigger.kill(1);
35941	    });
35942	  };
35943
35944	  ScrollTrigger.config = function config(vars) {
35945	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35946	    var ms = vars.syncInterval;
35947	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35948
35949	    if ("autoRefreshEvents" in vars) {
35950	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35951	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35952	    }
35953	  };
35954
35955	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35956	    var t = _getTarget(target),
35957	        i = _scrollers.indexOf(t),
35958	        isViewport = _isViewport(t);
35959
35960	    if (~i) {
35961	      _scrollers.splice(i, isViewport ? 6 : 2);
35962	    }
35963
35964	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35965	  };
35966
35967	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35968	    var mq, p, i, func, result;
35969
35970	    for (p in vars) {
35971	      i = _media.indexOf(p);
35972	      func = vars[p];
35973	      _creatingMedia = p;
35974
35975	      if (p === "all") {
35976	        func();
35977	      } else {
35978	        mq = _win.matchMedia(p);
35979
35980	        if (mq) {
35981	          mq.matches && (result = func());
35982
35983	          if (~i) {
35984	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35985	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35986	          } else {
35987	            i = _media.length;
35988
35989	            _media.push(p, func, result);
35990
35991	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35992	          }
35993
35994	          _media[i + 3] = mq.matches;
35995	        }
35996	      }
35997
35998	      _creatingMedia = 0;
35999	    }
36000
36001	    return _media;
36002	  };
36003
36004	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
36005	    query || (_media.length = 0);
36006	    query = _media.indexOf(query);
36007	    query >= 0 && _media.splice(query, 4);
36008	  };
36009
36010	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
36011	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
36012	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
36013	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
36014	  };
36015
36016	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
36017	    _isString(element) && (element = _getTarget(element));
36018	    var bounds = element.getBoundingClientRect(),
36019	        size = bounds[horizontal ? _width : _height],
36020	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
36021	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
36022	  };
36023
36024	  return ScrollTrigger;
36025	}();
36026	ScrollTrigger.version = "3.8.0";
36027
36028	ScrollTrigger.saveStyles = function (targets) {
36029	  return targets ? _toArray(targets).forEach(function (target) {
36030	    if (target && target.style) {
36031	      var i = _savedStyles.indexOf(target);
36032
36033	      i >= 0 && _savedStyles.splice(i, 5);
36034
36035	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
36036	    }
36037	  }) : _savedStyles;
36038	};
36039
36040	ScrollTrigger.revert = function (soft, media) {
36041	  return _revertAll(!soft, media);
36042	};
36043
36044	ScrollTrigger.create = function (vars, animation) {
36045	  return new ScrollTrigger(vars, animation);
36046	};
36047
36048	ScrollTrigger.refresh = function (safe) {
36049	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
36050	};
36051
36052	ScrollTrigger.update = _updateAll;
36053	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
36054
36055	ScrollTrigger.maxScroll = function (element, horizontal) {
36056	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
36057	};
36058
36059	ScrollTrigger.getScrollFunc = function (element, horizontal) {
36060	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
36061	};
36062
36063	ScrollTrigger.getById = function (id) {
36064	  return _ids[id];
36065	};
36066
36067	ScrollTrigger.getAll = function () {
36068	  return _triggers.slice(0);
36069	};
36070
36071	ScrollTrigger.isScrolling = function () {
36072	  return !!_lastScrollTime;
36073	};
36074
36075	ScrollTrigger.snapDirectional = _snapDirectional;
36076
36077	ScrollTrigger.addEventListener = function (type, callback) {
36078	  var a = _listeners[type] || (_listeners[type] = []);
36079	  ~a.indexOf(callback) || a.push(callback);
36080	};
36081
36082	ScrollTrigger.removeEventListener = function (type, callback) {
36083	  var a = _listeners[type],
36084	      i = a && a.indexOf(callback);
36085	  i >= 0 && a.splice(i, 1);
36086	};
36087
36088	ScrollTrigger.batch = function (targets, vars) {
36089	  var result = [],
36090	      varsCopy = {},
36091	      interval = vars.interval || 0.016,
36092	      batchMax = vars.batchMax || 1e9,
36093	      proxyCallback = function proxyCallback(type, callback) {
36094	    var elements = [],
36095	        triggers = [],
36096	        delay = gsap.delayedCall(interval, function () {
36097	      callback(elements, triggers);
36098	      elements = [];
36099	      triggers = [];
36100	    }).pause();
36101	    return function (self) {
36102	      elements.length || delay.restart(true);
36103	      elements.push(self.trigger);
36104	      triggers.push(self);
36105	      batchMax <= elements.length && delay.progress(1);
36106	    };
36107	  },
36108	      p;
36109
36110	  for (p in vars) {
36111	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
36112	  }
36113
36114	  if (_isFunction(batchMax)) {
36115	    batchMax = batchMax();
36116
36117	    _addListener(ScrollTrigger, "refresh", function () {
36118	      return batchMax = vars.batchMax();
36119	    });
36120	  }
36121
36122	  _toArray(targets).forEach(function (target) {
36123	    var config = {};
36124
36125	    for (p in varsCopy) {
36126	      config[p] = varsCopy[p];
36127	    }
36128
36129	    config.trigger = target;
36130	    result.push(ScrollTrigger.create(config));
36131	  });
36132
36133	  return result;
36134	};
36135
36136	ScrollTrigger.sort = function (func) {
36137	  return _triggers.sort(func || function (a, b) {
36138	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
36139	  });
36140	};
36141
36142	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
36143
36144	exports.ScrollTrigger = ScrollTrigger;
36145	exports.default = ScrollTrigger;
36146
36147	Object.defineProperty(exports, '__esModule', { value: true });
36148
36149})));
36150
36151/* ========================================================================
36152 * Bootstrap: collapse.js v3.1.1
36153 * http://getbootstrap.com/javascript/#collapse
36154 * ========================================================================
36155 * Copyright 2011-2014 Twitter, Inc.
36156 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36157 * ======================================================================== */
36158
36159
36160+function ($) {
36161	'use strict';
36162
36163	// COLLAPSE PUBLIC CLASS DEFINITION
36164	// ================================
36165
36166	var Collapse = function (element, options) {
36167		this.$element      = $(element)
36168		this.options       = $.extend({}, Collapse.DEFAULTS, options)
36169		this.transitioning = null
36170
36171		if (this.options.parent) this.$parent = $(this.options.parent)
36172		if (this.options.toggle) this.toggle()
36173	}
36174
36175	Collapse.DEFAULTS = {
36176		toggle: true
36177	}
36178
36179	Collapse.prototype.dimension = function () {
36180		var hasWidth = this.$element.hasClass('width')
36181		return hasWidth ? 'width' : 'height'
36182	}
36183
36184	Collapse.prototype.show = function () {
36185		if (this.transitioning || this.$element.hasClass('in')) return
36186
36187		var startEvent = $.Event('show.bs.collapse')
36188		this.$element.trigger(startEvent)
36189		if (startEvent.isDefaultPrevented()) return
36190
36191		var actives = this.$parent && this.$parent.find('> .panel > .in')
36192
36193		if (actives && actives.length) {
36194			var hasData = actives.data('bs.collapse')
36195			if (hasData && hasData.transitioning) return
36196			//START UNCODE EDIT
36197			var parentNoToggle = this.$parent.data('no-toggle')
36198			if (!parentNoToggle) {
36199				actives.collapse('hide')
36200			}
36201			//END UNCODE EDIT
36202			hasData || actives.data('bs.collapse', null)
36203		}
36204
36205		var dimension = this.dimension()
36206
36207		this.$element
36208			.removeClass('collapse')
36209			.addClass('collapsing')[dimension](0)
36210
36211		this.transitioning = 1
36212
36213		var complete = function (e) {
36214			if (e && e.target != this.$element[0]) return
36215			this.$element
36216				.removeClass('collapsing')
36217				.addClass('collapse in')[dimension]('auto')
36218			this.transitioning = 0
36219			this.$element.trigger('shown.bs.collapse')
36220		}
36221
36222		if (!$.support.transition) return complete.call(this)
36223
36224		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
36225
36226		this.$element
36227			.one($.support.transition.end, $.proxy(complete, this))
36228			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
36229	}
36230
36231	Collapse.prototype.hide = function () {
36232		if (this.transitioning || !this.$element.hasClass('in')) return
36233
36234		var startEvent = $.Event('hide.bs.collapse')
36235		this.$element.trigger(startEvent)
36236		if (startEvent.isDefaultPrevented()) return
36237
36238		var dimension = this.dimension()
36239
36240		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
36241
36242		this.$element
36243			.addClass('collapsing')
36244			.removeClass('collapse')
36245			.removeClass('in')
36246
36247		this.transitioning = 1
36248
36249		var complete = function (e) {
36250			if (e && e.target != this.$element[0]) return
36251			this.transitioning = 0
36252			this.$element
36253				.trigger('hidden.bs.collapse')
36254				.removeClass('collapsing')
36255				.addClass('collapse')
36256		}
36257
36258		if (!$.support.transition) return complete.call(this)
36259
36260		this.$element
36261			[dimension](0)
36262			.one($.support.transition.end, $.proxy(complete, this))
36263			.emulateTransitionEnd(350)
36264	}
36265
36266	Collapse.prototype.toggle = function () {
36267		this[this.$element.hasClass('in') ? 'hide' : 'show']()
36268	}
36269
36270
36271	// COLLAPSE PLUGIN DEFINITION
36272	// ==========================
36273
36274	var old = $.fn.collapse
36275
36276	$.fn.collapse = function (option) {
36277		return this.each(function () {
36278			var $this   = $(this)
36279			var data    = $this.data('bs.collapse')
36280			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
36281
36282			if (!data && options.toggle && option == 'show') option = !option
36283			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
36284			if (typeof option == 'string') data[option]()
36285		})
36286	}
36287
36288	$.fn.collapse.Constructor = Collapse
36289
36290
36291	// COLLAPSE NO CONFLICT
36292	// ====================
36293
36294	$.fn.collapse.noConflict = function () {
36295		$.fn.collapse = old
36296		return this
36297	}
36298
36299
36300	// COLLAPSE DATA-API
36301	// =================
36302
36303	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
36304		var $this   = $(this), href
36305		var target  = $this.attr('data-target')
36306				|| e.preventDefault()
36307				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
36308		//Edited by Uncode to replace ID in panel [START]
36309		var _target = href.replace(/^#/, "");
36310		if ( $('[data-id="' + _target + '"]').length ) {
36311			var $target = $('[data-id="' + _target + '"]')
36312		} else {
36313			var $target = $(target)
36314		}
36315		//Edited by Uncode to replace ID in panel [END]
36316		var data    = $target.data('bs.collapse')
36317		var option  = data ? 'toggle' : $this.data()
36318		var parent  = $this.attr('data-parent')
36319		var $parent = parent && $(parent)
36320
36321		if (!data || !data.transitioning) {
36322			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
36323			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
36324		}
36325
36326		$target.collapse(option)
36327	})
36328
36329}(jQuery);
36330
36331/* ========================================================================
36332 * Bootstrap: tab.js v3.1.1
36333 * http://getbootstrap.com/javascript/#tabs
36334 * ========================================================================
36335 * Copyright 2011-2014 Twitter, Inc.
36336 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36337 * ======================================================================== */
36338
36339
36340+function ($) {
36341  'use strict';
36342
36343  // TAB CLASS DEFINITION
36344  // ====================
36345
36346  var Tab = function (element) {
36347    this.element = $(element)
36348  }
36349
36350  Tab.prototype.show = function () {
36351    var $this    = this.element
36352    var $ul      = $this.closest('ul:not(.dropdown-menu)')
36353    var selector = $this.data('target')
36354
36355    if (!selector) {
36356      selector = $this.attr('href')
36357      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
36358    }
36359
36360    if ($this.parent('li').hasClass('active')) return
36361
36362    var previous = $ul.find('.active:last a')[0]
36363    var e        = $.Event('show.bs.tab', {
36364      relatedTarget: previous
36365    })
36366
36367    $this.trigger(e)
36368
36369    if (e.isDefaultPrevented()) return
36370
36371    //Edited by Uncode to replace ID in panel [START]
36372    var _target = selector.replace(/^#/, "");
36373    if ( $('[data-id="' + _target + '"]').length )
36374      var $target = $('[data-id="' + _target + '"]')
36375    else
36376      var $target = $(selector)
36377    //Edited by Uncode to replace ID in panel [END]
36378
36379    this.activate($this.parent('li'), $ul)
36380    this.activate($target, $target.parent(), function () {
36381      $this.trigger({
36382        type: 'shown.bs.tab',
36383        relatedTarget: previous
36384      })
36385    })
36386  }
36387
36388  Tab.prototype.activate = function (element, container, callback) {
36389    var $active    = container.find('> .active').add(container.find('> .active > .active'))
36390    var transition = callback
36391      && $.support.transition
36392      && $active.hasClass('fade')
36393
36394    function next() {
36395      $active
36396        .removeClass('active')
36397        .find('> .dropdown-menu > .active')
36398        .removeClass('active')
36399
36400      $active
36401        .find('.tab-excerpt').slideUp();
36402
36403      element.addClass('active')
36404      $('.tab-excerpt', element).slideDown();
36405
36406      //if (transition) {
36407        element[0].offsetWidth // reflow for transition
36408        element.add($active).addClass('in')
36409      /*} else {
36410        element.removeClass('fade')
36411      }*/
36412
36413      if (element.parent('.dropdown-menu')) {
36414        element.closest('li.dropdown').addClass('active')
36415      }
36416
36417      callback && callback()
36418    }
36419
36420    transition ?
36421      $active
36422        .one($.support.transition.end, next)
36423        .emulateTransitionEnd(150) :
36424      next()
36425
36426    $active.removeClass('in')
36427  }
36428
36429
36430  // TAB PLUGIN DEFINITION
36431  // =====================
36432
36433  var old = $.fn.tab
36434
36435  $.fn.tab = function ( option ) {
36436    return this.each(function () {
36437      var $this = $(this)
36438      var data  = $this.data('bs.tab')
36439
36440      if (!data) $this.data('bs.tab', (data = new Tab(this)))
36441      if (typeof option == 'string') data[option]()
36442    })
36443  }
36444
36445  $.fn.tab.Constructor = Tab
36446
36447
36448  // TAB NO CONFLICT
36449  // ===============
36450
36451  $.fn.tab.noConflict = function () {
36452    $.fn.tab = old
36453    return this
36454  }
36455
36456
36457  // TAB DATA-API
36458  // ============
36459
36460  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
36461    e.preventDefault()
36462    $(this).tab('show')
36463  })
36464
36465}(jQuery);
36466
36467/* ========================================================================
36468 * Bootstrap: tooltip.js v3.1.1
36469 * http://getbootstrap.com/javascript/#tooltip
36470 * Inspired by the original jQuery.tipsy by Jason Frame
36471 * ========================================================================
36472 * Copyright 2011-2014 Twitter, Inc.
36473 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36474 * ======================================================================== */
36475
36476
36477+function ($) {
36478  'use strict';
36479
36480  // TOOLTIP PUBLIC CLASS DEFINITION
36481  // ===============================
36482
36483  var Tooltip = function (element, options) {
36484    this.type       =
36485    this.options    =
36486    this.enabled    =
36487    this.timeout    =
36488    this.hoverState =
36489    this.$element   = null
36490
36491    this.init('tooltip', element, options)
36492  }
36493
36494  Tooltip.DEFAULTS = {
36495    animation: true,
36496    placement: 'top',
36497    selector: false,
36498    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
36499    trigger: 'hover focus',
36500    title: '',
36501    delay: 0,
36502    html: false,
36503    container: false,
36504    viewport: {
36505      selector: 'body',
36506      padding: 0
36507    }
36508  }
36509
36510  Tooltip.prototype.init = function (type, element, options) {
36511    this.enabled   = true
36512    this.type      = type
36513    this.$element  = $(element)
36514    this.options   = this.getOptions(options)
36515    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
36516
36517    var triggers = this.options.trigger.split(' ')
36518
36519    for (var i = triggers.length; i--;) {
36520      var trigger = triggers[i]
36521
36522      if (trigger == 'click') {
36523        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
36524      } else if (trigger != 'manual') {
36525        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
36526        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
36527
36528        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
36529        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
36530      }
36531    }
36532
36533    this.options.selector ?
36534      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
36535      this.fixTitle()
36536  }
36537
36538  Tooltip.prototype.getDefaults = function () {
36539    return Tooltip.DEFAULTS
36540  }
36541
36542  Tooltip.prototype.getOptions = function (options) {
36543    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
36544
36545    if (options.delay && typeof options.delay == 'number') {
36546      options.delay = {
36547        show: options.delay,
36548        hide: options.delay
36549      }
36550    }
36551
36552    return options
36553  }
36554
36555  Tooltip.prototype.getDelegateOptions = function () {
36556    var options  = {}
36557    var defaults = this.getDefaults()
36558
36559    this._options && $.each(this._options, function (key, value) {
36560      if (defaults[key] != value) options[key] = value
36561    })
36562
36563    return options
36564  }
36565
36566  Tooltip.prototype.enter = function (obj) {
36567    var self = obj instanceof this.constructor ?
36568      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36569
36570    clearTimeout(self.timeout)
36571
36572    self.hoverState = 'in'
36573
36574    if (!self.options.delay || !self.options.delay.show) return self.show()
36575
36576    self.timeout = setTimeout(function () {
36577      if (self.hoverState == 'in') self.show()
36578    }, self.options.delay.show)
36579  }
36580
36581  Tooltip.prototype.leave = function (obj) {
36582    var self = obj instanceof this.constructor ?
36583      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36584
36585    clearTimeout(self.timeout)
36586
36587    self.hoverState = 'out'
36588
36589    if (!self.options.delay || !self.options.delay.hide) return self.hide()
36590
36591    self.timeout = setTimeout(function () {
36592      if (self.hoverState == 'out') self.hide()
36593    }, self.options.delay.hide)
36594  }
36595
36596  Tooltip.prototype.show = function () {
36597    var e = $.Event('show.bs.' + this.type)
36598
36599    if (this.hasContent() && this.enabled) {
36600      this.$element.trigger(e)
36601
36602      if (e.isDefaultPrevented()) return
36603      var that = this;
36604
36605      var $tip = this.tip()
36606
36607      this.setContent()
36608
36609      if (this.options.animation) $tip.addClass('fade')
36610
36611      var placement = typeof this.options.placement == 'function' ?
36612        this.options.placement.call(this, $tip[0], this.$element[0]) :
36613        this.options.placement
36614
36615      var autoToken = /\s?auto?\s?/i
36616      var autoPlace = autoToken.test(placement)
36617      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
36618
36619      $tip
36620        .detach()
36621        .cs
36621s({ top: 0, left: 0, display: 'block' })
36622        .addClass(placement)
36623
36624      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
36625
36626      var pos          = this.getPosition()
36627      var actualWidth  = $tip[0].offsetWidth
36628      var actualHeight = $tip[0].offsetHeight
36629
36630      if (autoPlace) {
36631        var orgPlacement = placement
36632        var $parent      = this.$element.parent()
36633        var parentDim    = this.getPosition($parent)
36634
36635        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
36636                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
36637                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
36638                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
36639                    placement
36640
36641        $tip
36642          .removeClass(orgPlacement)
36643          .addClass(placement)
36644      }
36645
36646      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
36647
36648      this.applyPlacement(calculatedOffset, placement)
36649      this.hoverState = null
36650
36651      var complete = function() {
36652        that.$element.trigger('shown.bs.' + that.type)
36653      }
36654
36655      $.support.transition && this.$tip.hasClass('fade') ?
36656        $tip
36657          .one($.support.transition.end, complete)
36658          .emulateTransitionEnd(150) :
36659        complete()
36660    }
36661  }
36662
36663  Tooltip.prototype.applyPlacement = function (offset, placement) {
36664    var $tip   = this.tip()
36665    var width  = $tip[0].offsetWidth
36666    var height = $tip[0].offsetHeight
36667
36668    // manually read margins because getBoundingClientRect includes difference
36669    var marginTop = parseInt($tip.css('margin-top'), 10)
36670    var marginLeft = parseInt($tip.css('margin-left'), 10)
36671
36672    // we must check for NaN for ie 8/9
36673    if (isNaN(marginTop))  marginTop  = 0
36674    if (isNaN(marginLeft)) marginLeft = 0
36675
36676    offset.top  = offset.top  + marginTop
36677    offset.left = offset.left + marginLeft
36678
36679    // $.fn.offset doesn't round pixel values
36680    // so we use setOffset directly with our own function B-0
36681    $.offset.setOffset($tip[0], $.extend({
36682      using: function (props) {
36683        $tip.css({
36684          top: Math.round(props.top),
36685          left: Math.round(props.left)
36686        })
36687      }
36688    }, offset), 0)
36689
36690    $tip.addClass('in')
36691
36692    // check to see if placing tip in new offset caused the tip to resize itself
36693    var actualWidth  = $tip[0].offsetWidth
36694    var actualHeight = $tip[0].offsetHeight
36695
36696    if (placement == 'top' && actualHeight != height) {
36697      offset.top = offset.top + height - actualHeight
36698    }
36699
36700    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
36701
36702    if (delta.left) offset.left += delta.left
36703    else offset.top += delta.top
36704
36705    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
36706    var arrowPosition       = delta.left ? 'left'        : 'top'
36707    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
36708
36709    $tip.offset(offset)
36710    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
36711  }
36712
36713  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
36714    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
36715  }
36716
36717  Tooltip.prototype.setContent = function () {
36718    var $tip  = this.tip()
36719    var title = this.getTitle()
36720
36721    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
36722    $tip.removeClass('fade in top bottom left right')
36723  }
36724
36725  Tooltip.prototype.hide = function () {
36726    var that = this
36727    var $tip = this.tip()
36728    var e    = $.Event('hide.bs.' + this.type)
36729
36730    function complete() {
36731      if (that.hoverState != 'in') $tip.detach()
36732      that.$element.trigger('hidden.bs.' + that.type)
36733    }
36734
36735    this.$element.trigger(e)
36736
36737    if (e.isDefaultPrevented()) return
36738
36739    $tip.removeClass('in')
36740
36741    $.support.transition && this.$tip.hasClass('fade') ?
36742      $tip
36743        .one($.support.transition.end, complete)
36744        .emulateTransitionEnd(150) :
36745      complete()
36746
36747    this.hoverState = null
36748
36749    return this
36750  }
36751
36752  Tooltip.prototype.fixTitle = function () {
36753    var $e = this.$element
36754    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
36755      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
36756    }
36757  }
36758
36759  Tooltip.prototype.hasContent = function () {
36760    return this.getTitle()
36761  }
36762
36763  Tooltip.prototype.getPosition = function ($element) {
36764    $element   = $element || this.$element
36765    var el     = $element[0]
36766    var isBody = el.tagName == 'BODY'
36767    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
36768      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
36769      width:  isBody ? $(window).width()  : $element.outerWidth(),
36770      height: isBody ? $(window).height() : $element.outerHeight()
36771    }, isBody ? {top: 0, left: 0} : $element.offset())
36772  }
36773
36774  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
36775    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
36776           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
36777           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
36778        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
36779
36780  }
36781
36782  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
36783    var delta = { top: 0, left: 0 }
36784    if (!this.$viewport) return delta
36785
36786    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
36787    var viewportDimensions = this.getPosition(this.$viewport)
36788
36789    if (/right|left/.test(placement)) {
36790      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
36791      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
36792      if (topEdgeOffset < viewportDimensions.top) { // top overflow
36793        delta.top = viewportDimensions.top - topEdgeOffset
36794      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
36795        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
36795EdgeOffset
36796      }
36797    } else {
36798      var leftEdgeOffset  = pos.left - viewportPadding
36799      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
36800      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
36801        delta.left = viewportDimensions.left - leftEdgeOffset
36802      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
36803        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
36804      }
36805    }
36806
36807    return delta
36808  }
36809
36810  Tooltip.prototype.getTitle = function () {
36811    var title
36812    var $e = this.$element
36813    var o  = this.options
36814
36815    title = $e.attr('data-original-title')
36816      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
36817
36818    return title
36819  }
36820
36821  Tooltip.prototype.tip = function () {
36822    return this.$tip = this.$tip || $(this.options.template)
36823  }
36824
36825  Tooltip.prototype.arrow = function () {
36826    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
36827  }
36828
36829  Tooltip.prototype.validate = function () {
36830    if (!this.$element[0].parentNode) {
36831      this.hide()
36832      this.$element = null
36833      this.options  = null
36834    }
36835  }
36836
36837  Tooltip.prototype.enable = function () {
36838    this.enabled = true
36839  }
36840
36841  Tooltip.prototype.disable = function () {
36842    this.enabled = false
36843  }
36844
36845  Tooltip.prototype.toggleEnabled = function () {
36846    this.enabled = !this.enabled
36847  }
36848
36849  Tooltip.prototype.toggle = function (e) {
36850    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36851    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36852  }
36853
36854  Tooltip.prototype.destroy = function () {
36855    clearTimeout(this.timeout)
36856    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36857  }
36858
36859
36860  // TOOLTIP PLUGIN DEFINITION
36861  // =========================
36862
36863  var old = $.fn.tooltip
36864
36865  $.fn.tooltip = function (option) {
36866    return this.each(function () {
36867      var $this   = $(this)
36868      var data    = $this.data('bs.tooltip')
36869      var options = typeof option == 'object' && option
36870
36871      if (!data && option == 'destroy') return
36872      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36873      if (typeof option == 'string') data[option]()
36874    })
36875  }
36876
36877  $.fn.tooltip.Constructor = Tooltip
36878
36879
36880  // TOOLTIP NO CONFLICT
36881  // ===================
36882
36883  $.fn.tooltip.noConflict = function () {
36884    $.fn.tooltip = old
36885    return this
36886  }
36887
36888}(jQuery);
36889
36890/* ========================================================================
36891 * Bootstrap: transition.js v3.1.1
36892 * http://getbootstrap.com/javascript/#transitions
36893 * ========================================================================
36894 * Copyright 2011-2014 Twitter, Inc.
36895 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36896 * ======================================================================== */
36897
36898
36899+function ($) {
36900  'use strict';
36901
36902  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36903  // ============================================================
36904
36905  function transitionEnd() {
36906    var el = document.createElement('bootstrap')
36907
36908    var transEndEventNames = {
36909      WebkitTransition : 'webkitTransitionEnd',
36910      MozTransition    : 'transitionend',
36911      OTransition      : 'oTransitionEnd otransitionend',
36912      transition       : 'transitionend'
36913    }
36914
36915    for (var name in transEndEventNames) {
36916      if (el.style[name] !== undefined) {
36917        return { end: transEndEventNames[name] }
36918      }
36919    }
36920
36921    return false // explicit for ie8 (  ._.)
36922  }
36923
36924  // http://blog.alexmaccaw.com/css-transitions
36925  $.fn.emulateTransitionEnd = function (duration) {
36926    var called = false, $el = this
36927    $(this).one($.support.transition.end, function () { called = true })
36928    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36929    setTimeout(callback, duration)
36930    return this
36931  }
36932
36933  $(function () {
36934    $.support.transition = transitionEnd()
36935  })
36936
36937}(jQuery);
36938
36939
36940// ------------------------------------------
36941// Rellax.js
36942// Buttery smooth parallax library
36943// Copyright (c) 2016 Moe Amaya (@moeamaya)
36944// MIT license
36945//
36946// Thanks to Paraxify.js and Jaime Cabllero
36947// for parallax concepts
36948// ------------------------------------------
36949
36950(function (root, factory) {
36951	if (typeof define === 'function' && define.amd) {
36952		// AMD. Register as an anonymous module.
36953		define([], factory);
36954	} else if (typeof module === 'object' && module.exports) {
36955		// Node. Does not work with strict CommonJS, but
36956		// only CommonJS-like environments that support module.exports,
36957		// like Node.
36958		module.exports = factory();
36959	} else {
36960		// Browser globals (root is window)
36961		root.Rellax = factory();
36962	}
36963}(typeof window !== "undefined" ? window : global, function () {
36964	var Rellax = function(el, options){
36965		"use strict";
36966
36967		var self = Object.create(Rellax.prototype);
36968
36969		var posY = 0;
36970		var screenY = 0;
36971		var posX = 0;
36972		var screenX = 0;
36973		var blocks = [];
36974		var pause = true;
36975
36976		// check what requestAnimationFrame to use, and if
36977		// it's not supported, use the onscroll event
36978		var loop = window.requestAnimationFrame ||
36979			window.webkitRequestAnimationFrame ||
36980			window.mozRequestAnimationFrame ||
36981			window.msRequestAnimationFrame ||
36982			window.oRequestAnimationFrame ||
36983			function(callback){ return setTimeout(callback, 1000 / 60); };
36984
36985		// store the id for later use
36986		var loopId = null;
36987
36988		// Test via a getter in the options object to see if the passive property is accessed
36989		var supportsPassive = false;
vendor: 10,724 bytes, lines 36990-37291
36990		try {
36991			var opts = Object.defineProperty({}, 'passive', {
36992				get: function() {
36993					supportsPassive = true;
36994				}
36995			});
36996			window.addEventListener("testPassive", null, opts);
36997			window.removeEventListener("testPassive", null, opts);
36998		} catch (e) {}
36999
37000		// check what cancelAnimation method to use
37001		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
37002
37003		// check which transform property to use
37004		var transformProp = window.transformProp || (function(){
37005				var testEl = document.createElement('div');
37006				if (testEl.style.transform === null) {
37007					var vendors = ['Webkit', 'Moz', 'ms'];
37008					for (var vendor in vendors) {
37009						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
37010							return vendors[vendor] + 'Transform';
37011						}
37012					}
37013				}
37014				return 'transform';
37015			})();
37016
37017		// Default Settings
37018		self.options = {
37019			speed: -2,
37020			verticalSpeed: null,
37021			horizontalSpeed: null,
37022			breakpoints: [576, 768, 1201],
37023			center: false,
37024			wrapper: null,
37025			relativeToWrapper: false,
37026			round: true,
37027			vertical: true,
37028			horizontal: false,
37029			verticalScrollAxis: "y",
37030			horizontalScrollAxis: "x",
37031			callback: function() {},
37032		};
37033
37034		// User defined options (might have more in the future)
37035		if (options){
37036			Object.keys(options).forEach(function(key){
37037				self.options[key] = options[key];
37038			});
37039		}
37040
37041		function validateCustomBreakpoints () {
37042			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
37043				var isAscending = true;
37044				var isNumerical = true;
37045				var lastVal;
37046				self.options.breakpoints.forEach(function (i) {
37047					if (typeof i !== 'number') isNumerical = false;
37048					if (lastVal !== null) {
37049						if (i < lastVal) isAscending = false;
37050					}
37051					lastVal = i;
37052				});
37053				if (isAscending && isNumerical) return;
37054			}
37055			// revert defaults if set incorrectly
37056			self.options.breakpoints = [576, 768, 1201];
37057			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
37058		}
37059
37060		if (options && options.breakpoints) {
37061			validateCustomBreakpoints();
37062		}
37063
37064		// By default, rellax class
37065		if (!el) {
37066			el = '.rellax';
37067		}
37068
37069		// check if el is a className or a node
37070		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
37071
37072		// Now query selector
37073		if (elements.length > 0) {
37074			self.elems = elements;
37075		}
37076
37077		// The elements don't exist
37078		else {
37079			console.warn("Rellax: The elements you're trying to select don't exist.");
37080			return;
37081		}
37082
37083		// Has a wrapper and it exists
37084		if (self.options.wrapper) {
37085			if (!self.options.wrapper.nodeType) {
37086				var wrapper = document.querySelector(self.options.wrapper);
37087
37088				if (wrapper) {
37089					self.options.wrapper = wrapper;
37090				} else {
37091					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
37092					return;
37093				}
37094			}
37095		}
37096
37097		// set a placeholder for the current breakpoint
37098		var currentBreakpoint;
37099
37100		// helper to determine current breakpoint
37101		var getCurrentBreakpoint = function (w) {
37102			var bp = self.options.breakpoints;
37103			if (w < bp[0]) return 'xs';
37104			if (w >= bp[0] && w < bp[1]) return 'sm';
37105			if (w >= bp[1] && w < bp[2]) return 'md';
37106			return 'lg';
37107		};
37108
37109		// Get and cache initial position of all elements
37110		var cacheBlocks = function() {
37111			for (var i = 0; i < self.elems.length; i++){
37112				var block = createBlock(self.elems[i]);
37113				blocks.push(block);
37114			}
37115		};
37116
37117
37118		// Let's kick this script off
37119		// Build array for cached element values
37120		var init = function() {
37121			for (var i = 0; i < blocks.length; i++){
37122				self.elems[i].style.cssText = blocks[i].style;
37123			}
37124
37125			blocks = [];
37126
37127			screenY = window.innerHeight;
37128			screenX = window.innerWidth;
37129			currentBreakpoint = getCurrentBreakpoint(screenX);
37130
37131			setPosition();
37132
37133			cacheBlocks();
37134
37135			animate();
37136
37137			// If paused, unpause and set listener for window resizing events
37138			if (pause) {
37139				window.addEventListener('resize', init);
37140				pause = false;
37141				// Start the loop
37142				update();
37143			}
37144		};
37145
37146		// We want to cache the parallax blocks'
37147		// values: base, top, height, speed
37148		// el: is dom object, return: el cache values
37149		var createBlock = function(el) {
37150			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
37151			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
37152			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
37153			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
37154			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
37155			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
37156			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
37157			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
37158			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
37159			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
37160			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
37161			var dataMin = el.getAttribute( 'data-rellax-min' );
37162			var dataMax = el.getAttribute( 'data-rellax-max' );
37163			var dataMinX = el.getAttribute('data-rellax-min-x');
37164			var dataMaxX = el.getAttribute('data-rellax-max-x');
37165			var dataMinY = el.getAttribute('data-rellax-min-y');
37166			var dataMaxY = el.getAttribute('data-rellax-max-y');
37167			var mapBreakpoints;
37168			var breakpoints = true;
37169
37170			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
37171				breakpoints = false;
37172			} else {
37173				mapBreakpoints = {
37174					'xs': dataXsSpeed,
37175					'sm': dataMobileSpeed,
37176					'md': dataTabletSpeed,
37177					'lg': dataDesktopSpeed
37178				};
37179			}
37180
37181			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
37182			// ensures elements are positioned based on HTML layout.
37183			//
37184			// If the element has the percentage attribute, the posY and posX needs to be
37185			// the current scroll position's value, so that the elements are still positioned based on HTML layout
37186			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37187			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
37188			if (self.options.relativeToWrapper) {
37189				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37190				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
37191			}
37192			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
37193			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;
37194
37195			var blockTop = posY + el.getBoundingClientRect().top;
37196			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
37197
37198			var blockLeft = posX + el.getBoundingClientRect().left;
37199			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
37200
37201			// apparently parallax equation everyone uses
37202			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
37203			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
37204			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
37205
37206			// Optional individual block speed as data attr, otherwise global speed
37207			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
37208			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
37209			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
37210
37211			// Optional individual block movement axis direction as data attr, otherwise global movement direction
37212			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
37213			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
37214
37215			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
37216
37217			// ~~Store non-translate3d transforms~~
37218			// Store inline styles and extract transforms
37219			var style = el.style.cssText;
37220			var transform = '';
37221
37222			// Check if there's an inline styled transform
37223			var searchResult = /transform\s*:/i.exec(style);
37224			if (searchResult) {
37225				// Get the index of the transform
37226				var index = searchResult.index;
37227
37228				// Trim the style to the transform point and get the following semi-colon index
37229				var trimmedStyle = style.slice(index);
37230				var delimiter = trimmedStyle.indexOf(';');
37231
37232				// Remove "transform" string and save the attribute
37233				if (delimiter) {
37234					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
37235				} else {
37236					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
37237				}
37238			}
37239
37240			return {
37241				baseX: bases.x,
37242				baseY: bases.y,
37243				top: blockTop,
37244				left: blockLeft,
37245				height: blockHeight,
37246				width: blockWidth,
37247				speed: speed,
37248				verticalSpeed: verticalSpeed,
37249				horizontalSpeed: horizontalSpeed,
37250				verticalScrollAxis: verticalScrollAxis,
37251				horizontalScrollAxis: horizontalScrollAxis,
37252				style: style,
37253				transform: transform,
37254				zindex: dataZindex,
37255				min: dataMin,
37256				max: dataMax,
37257				minX: dataMinX,
37258				maxX: dataMaxX,
37259				minY: dataMinY,
37260				maxY: dataMaxY
37261			};
37262		};
37263
37264		// set scroll position (posY, posX)
37265		// side effect method is not ideal, but okay for now
37266		// returns true if the scroll changed, false if nothing happened
37267		var setPosition = function() {
37268			var oldY = posY;
37269			var oldX = posX;
37270
37271			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37272			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
37273			// If option relativeToWrapper is true, use relative wrapper value instead.
37274			if (self.options.relativeToWrapper) {
37275				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37276				posY = scrollPosY - self.options.wrapper.offsetTop;
37277			}
37278
37279
37280			if (oldY != posY && self.options.vertical) {
37281				// scroll changed, return true
37282				return true;
37283			}
37284
37285			if (oldX != posX && self.options.horizontal) {
37286				// scroll changed, return true
37287				return true;
37288			}
37289
37290			// scroll did not change
37291			return false;
37292		};
37293
37294		// Ahh a pure function, gets new transform value
37295		// based on scrollPosition and speed
37296		// Allow for decimal pixel values
37297		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
37298			var result = {};
37299			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
37300			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
37301
37302			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
37303			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
37304
37305			return result;
37306		};
37307
37308		// Remove event listeners and loop again
37309		var deferredUpdate = function() {
37310			window.removeEventListener('resize', deferredUpdate);
37311			window.removeEventListener('orientationchange', deferredUpdate);
37312			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
37313			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
37314
37315			// loop again
37316			loopId = loop(update);
37317		};
37318
37319		// Loop
37320		var update = function() {
37321			if (setPosition() && pause === false) {
37322				animate();
37323
37324				// loop again
37325				loopId = loop(update);
37326			} else {
37327				loopId = null;
37328
37329				// Don't animate until we get a position updating event
37330				window.addEventListener('resize', deferredUpdate);
37331				window.addEventListener('orientationchange', deferredUpdate);
37332				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
37333				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
37334			}
37335		};
37336
37337		// Transform3d on parallax element
37338		var animate = function() {
37339			var positions;
37340			for (var i = 0; i < self.elems.length; i++){
37341				// Determine relevant movement directions
37342				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
37343				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
37344				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
37345				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
37346				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
37347				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
37348
37349				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
37350				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
37351
37352				// Subtracting initialize value, so element stays in same spot as HTML
37353				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
37354				var positionY = positions.y - blocks[i].baseY;
37355				var positionX = positions.x - blocks[i].baseX;
37356
37357				// The next two "if" blocks go like this:
37358				// Check if a limit is defined (first "min", then "max");
37359				// Check if we need to change the Y or the X
37360				// (Currently working only if just one of the axes is enabled)
37361				// Then, check if the new position is inside the allowed limit
37362				// If so, use new position. If not, set position to limit.
37363
37364				// Check if a min limit is defined
37365				if (blocks[i].min !== null) {
37366					if (self.options.vertical && !self.options.horizontal) {
37367						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
37368					}
37369					if (self.options.horizontal && !self.options.vertical) {
37370						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
37371					}
37372				}
37373
37374				// Check if directional min limits are defined
37375				if (blocks[i].minY != null) {
37376						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
37377				}
37378				if (blocks[i].minX != null) {
37379						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
37380				}
37381
37382				// Check if a max limit is defined
37383				if (blocks[i].max !== null) {
37384					if (self.options.vertical && !self.options.horizontal) {
37385						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
37386					}
37387					if (self.options.horizontal && !self.options.vertical) {
37388						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
37389					}
37390				}
37391
37392				// Check if directional max limits are defined
37393				if (blocks[i].maxY != null) {
37394						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
37395				}
37396				if (blocks[i].maxX != null) {
37397						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
37398				}
37399
37400				var zindex = blocks[i].zindex;
37401
37402				// Move that element
37403				// (Set the new translation and append initial inline transforms.)
37404				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
37405				self.elems[i].style[transformProp] = translate;
37406			}
37407			self.options.callback(positions);
37408		};
37409
37410		self.destroy = function() {
37411			for (var i = 0; i < self.elems.length; i++){
37412				self.elems[i].style.cssText = blocks[i].style;
37413			}
37414
37415			// Remove resize event listener if not pause, and pause
37416			if (!pause) {
37417				window.removeEventListener('resize', init);
37418				pause = true;
37419			}
37420
37421			// Clear the animation loop to prevent possible memory leak
37422			clearLoop(loopId);
37423			loopId = null;
37424		};
37425
37426		// Init
37427		init();
37428
37429		// Allow to recalculate the initial values whenever we want
37430		self.refresh = init;
37431
37432		return self;
37433	};
37434	return Rellax;
37435}));
37436
37437/*
37438 * OKVideo by OKFocus v2.3.2
37439 * http://okfoc.us
37440 *
37441 * Copyright 2014, OKFocus
37442 * Licensed under the MIT license.
37443 *
37444 */
37445var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
37446// youtube player ready
37447function onYouTubeIframeAPIReady() {
37448	YTplayers = new Array();
37449	jQuery('.uncode-video-container.video').each(function() {
37450		var playerY;
37451		if (jQuery(this).attr('data-provider') == 'youtube') {
37452			var id = jQuery(this).attr('data-id'),
37453				start = jQuery(this).attr('data-start'),
37454				end = jQuery(this).attr('data-end');
37455			start = typeof start && start !== null ? start : 0;
37456			end = typeof end && end !== null ? end : 0;
37457			options = jQuery(window).data('okoptions-' + id);
37458			if ( typeof options === 'undefined' ) {
37459				return true;
37460			}
37461			options.time = jQuery(this).attr('data-t');
37462			playerY = new YT.Player('okplayer-' + id, {
37463				videoId: options.video ? options.video.id : null,
37464				playerVars: {
37465					'autohide': 1,
37466					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
37467					'disablekb': 1,
37468					'cc_load_policy': options.captions,
37469					'controls': 0,
37470					'enablejsapi': 1,
37471					'fs': 0,
37472					'modestbranding': 1,
37473					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
37474					'iv_load_policy': options.annotations,
37475					'loop': options.loop,
37476					'showinfo': 0,
37477					'rel': 0,
37478					'wmode': 'opaque',
37479					'hd': options.hd,
37480					'mute': 1,
37481					'start': start,
37482					'end': end
37483				},
37484				events: {
37485					'onReady': OKEvents.yt.ready,
37486					'onStateChange': OKEvents.yt.onStateChange,
37487					'onError': OKEvents.yt.error
37488				}
37489			});
37490			YTplayers[id] = playerY;
37491			playerY.videoId = id;
37492		}
37493
37494	});
37495}
37496// vimeo player ready
37497function vimeoPlayerReady(id) {
37498	options = jQuery(window).data('okoptions-' + id);
37499	if ( typeof options === 'undefined' ) {
37500		return true;
37501	}
37502	var jIframe = options.jobject,
37503		iframe = jIframe[0];
37504
37505	jIframe.attr('src', jIframe.data('src'));
37506	var playerV = new Vimeo.Player(iframe);
37507	// hide player until Vimeo hides controls...
37508	playerV.on('loaded', function(e) {
37509		OKEvents.v.onReady(iframe);
37510		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
37511		if (carouselContainer.length) {
37512			UNCODE.owlPlayVideo(carouselContainer);
37513		}
37514		// "Do not try to add listeners or call functions before receiving this event."
37515		if (OKEvents.utils.isMobile()) {
37516			// mobile devices cannot listen for play event
37517			OKEvents.v.onPlay(playerV);
37518		} else {
37519			playerV.on('play', function(){
37520				OKEvents.v.onPlay(playerV);
37521				jQuery(window).trigger('okevents.v.play', [playerV]);
37522			});
37523			playerV.on('pause', function(){
37524				OKEvents.v.onPause;
37525				jQuery(window).trigger('okevents.v.pause', [playerV]);
37526			});
37527			playerV.on('ended', function(){
37528				OKEvents.v.onFinish
37529				jQuery(window).trigger('okevents.v.ended', [playerV]);
37530			});
37531		}
37532		if (options.time != null) {
37533			var optsTimeStr = (options.time).replace('t=', ''),
37534				timeV = '';
37535
37536			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
37537				var timeArr = optsTimeStr.split(/([^\d.-])/);
37538				for ( var i = 0; i < timeArr.length; i++ ) {
37539					if ( timeArr[i] === 'h' ) {
37540						timeV += parseFloat(timeArr[i-1]) * 3600;
37541					} else if ( timeArr[i] === 'm' ) {
37542						timeV += parseFloat(timeArr[i-1]) * 60;
37543					} else if ( timeArr[i] === 's' ) {
37544						timeV += parseFloat(timeArr[i-1]);
37545					}
37546				}
37547			} else {
37548				timeV = optsTimeStr;
37549			}
37550
37551			playerV.setCurrentTime(timeV);
37552		}
37553
37554		playerV.setVolume(0);
37555		playerV.play();
37556		jQuery(iframe).css({
37557			visibility: 'visible',
37558			opacity: 1
37559		});
37560		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37561		jQuery(iframe).closest('#page-header').addClass('video-started');
37562		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37563
37564		jQuery(window).trigger('okevents.v.loaded', [playerV]);
37565	});
37566}
37567OKEvents = {
37568	yt: {
37569		ready: function(event) {
37570			var id = event.target.videoId,
37571				$video = jQuery('#okplayer-' + id),
37572				options = jQuery(window).data('okoptions-' + id);
37573			if ( typeof options === 'undefined' ) {
37574				return true;
37575			}
37576			youtubePlayers[id] = event.target;
37577			event.target.setVolume(options.volume);
37578			if (options.autoplay === 1) {
37579				if (options.playlist.list) {
37580					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
37581				} else {
37582					var inCarousel = $video.closest('.owl-item');
37583					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
37584						if (options.time != null) {
37585							event.target.seekTo(parseInt(options.time));
37586						}
37587						event.target.playVideo();
37588					} else {
37589						event.target.pauseVideo();
37590					}
37591				}
37592			}
37593			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
37594
37595			$video.closest('[data-provider]').on('uncode-resume', function(){
37596				if (options.time != null) {
37597					event.target.seekTo(parseInt(options.time)).playVideo();
37598				} else {
37599					event.target.seekTo(0).playVideo();
37600				}
37601			});
37602
37603			$video.closest('[data-provider]').on('uncode-pause', function(){
37604				if (options.time != null) {
37605					event.target.seekTo(parseInt(options.time)).pauseVideo();
37606				} else {
37607					event.target.seekTo(0).pauseVideo();
37608				}
37609			});
37610			jQuery(window).trigger('okevents.y.loaded', [event]);
37611		},
37612		onStateChange: function(event) {
37613			var id = event.target.videoId,
37614				$video = jQuery('#okplayer-' + id),
37615				options = jQuery(window).data('okoptions-' + id);
37616			if ( typeof options === 'undefined' ) {
37617				return true;
37618			}
37619			youtubePlayers[id] = event.target;
37620			event.target.setVolume(options.volume);
37621			var $fluid = $video.closest('.fluid-object'),
37622				$tmb = $video.closest('.tmb'),
37623				setTime;
37624			switch (event.data) {
37625				case -1:
37626					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
37627					break;
37628				case 0:
37629					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
37630					options.loop && event.target.playVideo();
37631					break;
37632				case 1:
37633					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37634					setTimeout(function() {
37635						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
37636						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37637						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
37638						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37639					}, 300);
37640				break;
37641				case 2:
37642					OKEvents.utils.isFunction(options.onPause) && options.onPause();
37643					break;
37644				case 3:
37645					OKEvents.utils.isFunction(options.buffering) && options.buffering();
37646					break;
37647				case 5:
37648					OKEvents.utils.isFunction(options.cued) && options.cued();
37649					break;
37650				default:
37651					throw "OKVideo: received invalid data from YT player.";
37652			}
37653
37654			jQuery(window).trigger('okevents.y.change', [event]);
37655		},
37656		error: function(event) {
37657			throw event;
37658		}
37659	},
37660	v: {
37661		onReady: function(target) {
37662			if ( typeof options === 'undefined' ) {
37663				return true;
37664			}
37665			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
37666		},
37667		onPlay: function(player) {
37668			if ( typeof options === 'undefined' ) {
37669				return true;
37670			}
37671			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
37672			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37673			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37674			jQuery(player.element).closest('#page-header').addClass('video-started');
37675			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37676		},
37677		onPause: function() {
37678			if ( typeof options === 'undefined' ) {
37679				return true;
37680			}
37681			OKEvents.utils.isFunction(options.onPause) && options.onPause();
37682		},
37683		onFinish: function() {
37684			if ( typeof options === 'undefined' ) {
37685				return true;
37686			}
37687			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
37688		}
37689	},
37690	utils: {
37691		isFunction: function(func) {
37692			if (typeof func === 'function') {
37693				return true;
37694			} else {
37695				return false;
37696			}
37697		},
37698		isMobile: function() {
37699			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
37700				return true;
37701			} else {
37702				return false;
37703			}
37704		}
37705	}
37706};
37707
37708/**
37709 * vivus - JavaScript library to make drawing animation on SVG
37710 * @version v0.4.4
37711 * @link https://github.com/maxwellito/vivus
37712 * @license MIT
37713 */
37714
37715'use strict';
37716
37717(function () {
37718
37719  'use strict';
37720
37721/**
37722 * Pathformer
37723 * Beta version
37724 *
37725 * Take any SVG version 1.1 and transform
37726 * child elements to 'path' elements
37727 *
37728 * This code is purely forked from
37729 * https://github.com/Waest/SVGPathConverter
37730 */
37731
37732/**
37733 * Class constructor
37734 *
37735 * @param {DOM|String} element Dom element of the SVG or id of it
37736 */
37737function Pathformer(element) {
37738  // Test params
37739  if (typeof element === 'undefined') {
37740	throw new Error('Pathformer [constructor]: "element" parameter is required');
37741  }
37742
37743  // Set the element
37744  if (element.constructor === String) {
37745	element = document.getElementById(element);
37746	if (!element) {
37747	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
37748	}
37749  }
37750  if (element instanceof window.SVGElement ||
37751	  element instanceof window.SVGGElement ||
37752	  /^svg$/i.test(element.nodeName)) {
37753	this.el = element;
37754  } else {
37755	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
37756  }
37757
37758  // Start
37759  this.scan(element);
37760}
37761
37762/**
37763 * List of tags which can be transformed
37764 * to path elements
37765 *
37766 * @type {Array}
37767 */
37768Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
37769
37770/**
37771 * List of attribute names which contain
37772 * data. This array list them to check if
37773 * they contain bad values, like percentage.
37774 *
37775 * @type {Array}
37776 */
37777Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 37777-38575
37777y1', 'y2'];
37778
37779/**
37780 * Finds the elements compatible for transform
37781 * and apply the liked method
37782 *
37783 * @param  {object} options Object from the constructor
37784 */
37785Pathformer.prototype.scan = function (svg) {
37786  var fn, element, pathData, pathDom,
37787	  elements = svg.querySelectorAll(this.TYPES.join(','));
37788
37789  for (var i = 0; i < elements.length; i++) {
37790	element = elements[i];
37791	fn = this[element.tagName.toLowerCase() + 'ToPath'];
37792	pathData = fn(this.parseAttr(element.attributes));
37793	pathDom = this.pathMaker(element, pathData);
37794	element.parentNode.replaceChild(pathDom, element);
37795  }
37796};
37797
37798
37799/**
37800 * Read `line` element to extract and transform
37801 * data, to make it ready for a `path` object.
37802 *
37803 * @param  {DOMelement} element Line element to transform
37804 * @return {object}			 Data for a `path` element
37805 */
37806Pathformer.prototype.lineToPath = function (element) {
37807  var newElement = {},
37808	  x1 = element.x1 || 0,
37809	  y1 = element.y1 || 0,
37810	  x2 = element.x2 || 0,
37811	  y2 = element.y2 || 0;
37812
37813  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
37814  return newElement;
37815};
37816
37817/**
37818 * Read `rect` element to extract and transform
37819 * data, to make it ready for a `path` object.
37820 * The radius-border is not taken in charge yet.
37821 * (your help is more than welcomed)
37822 *
37823 * @param  {DOMelement} element Rect element to transform
37824 * @return {object}             Data for a `path` element
37825 */
37826Pathformer.prototype.rectToPath = function (element) {
37827  var newElement = {},
37828      x      = parseFloat(element.x)      || 0,
37829      y      = parseFloat(element.y)      || 0,
37830      width  = parseFloat(element.width)  || 0,
37831      height = parseFloat(element.height) || 0;
37832
37833  if (element.rx || element.ry) {
37834    var rx = parseInt(element.rx, 10) || -1,
37835        ry = parseInt(element.ry, 10) || -1;
37836    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
37837    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
37838
37839    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
37840                   'L ' + (x + width - rx) + ',' + y + ' ' +
37841                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
37842                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
37843                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
37844                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
37845                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
37846                   'L ' + x + ',' + (y + ry) + ' ' +
37847                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
37848  }
37849  else {
37850    newElement.d = 'M' + x + ' ' + y + ' ' +
37851                   'L' + (x + width) + ' ' + y + ' ' +
37852                   'L' + (x + width) + ' ' + (y + height) + ' ' +
37853                   'L' + x + ' ' + (y + height) + ' Z';
37854  }
37855  return newElement;
37856};
37857
37858/**
37859 * Read `polyline` element to extract and transform
37860 * data, to make it ready for a `path` object.
37861 *
37862 * @param  {DOMelement} element Polyline element to transform
37863 * @return {object}             Data for a `path` element
37864 */
37865Pathformer.prototype.polylineToPath = function (element) {
37866  var newElement = {},
37867      points = element.points.trim().split(' '),
37868      i, path;
37869
37870  // Reformatting if points are defined without commas
37871  if (element.points.indexOf(',') === -1) {
37872    var formattedPoints = [];
37873    for (i = 0; i < points.length; i+=2) {
37874      formattedPoints.push(points[i] + ',' + points[i+1]);
37875    }
37876    points = formattedPoints;
37877  }
37878
37879  // Generate the path.d value
37880  path = 'M' + points[0];
37881  for(i = 1; i < points.length; i++) {
37882    if (points[i].indexOf(',') !== -1) {
37883      path += 'L' + points[i];
37884    }
37885  }
37886  newElement.d = path;
37887  return newElement;
37888};
37889
37890/**
37891 * Read `polygon` element to extract and transform
37892 * data, to make it ready for a `path` object.
37893 * This method rely on polylineToPath, because the
37894 * logic is similar. The path created is just closed,
37895 * so it needs an 'Z' at the end.
37896 *
37897 * @param  {DOMelement} element Polygon element to transform
37898 * @return {object}             Data for a `path` element
37899 */
37900Pathformer.prototype.polygonToPath = function (element) {
37901  var newElement = Pathformer.prototype.polylineToPath(element);
37902
37903  newElement.d += 'Z';
37904  return newElement;
37905};
37906
37907/**
37908 * Read `ellipse` element to extract and transform
37909 * data, to make it ready for a `path` object.
37910 *
37911 * @param  {DOMelement} element ellipse element to transform
37912 * @return {object}             Data for a `path` element
37913 */
37914Pathformer.prototype.ellipseToPath = function (element) {
37915  var newElement = {},
37916      rx = parseFloat(element.rx) || 0,
37917      ry = parseFloat(element.ry) || 0,
37918      cx = parseFloat(element.cx) || 0,
37919      cy = parseFloat(element.cy) || 0,
37920      startX = cx - rx,
37921      startY = cy,
37922      endX = parseFloat(cx) + parseFloat(rx),
37923      endY = cy;
37924
37925  newElement.d = 'M' + startX + ',' + startY +
37926                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37927                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37928  return newElement;
37929};
37930
37931/**
37932 * Read `circle` element to extract and transform
37933 * data, to make it ready for a `path` object.
37934 *
37935 * @param  {DOMelement} element Circle element to transform
37936 * @return {object}             Data for a `path` element
37937 */
37938Pathformer.prototype.circleToPath = function (element) {
37939  var newElement = {},
37940      r  = parseFloat(element.r)  || 0,
37941      cx = parseFloat(element.cx) || 0,
37942      cy = parseFloat(element.cy) || 0,
37943      startX = cx - r,
37944      startY = cy,
37945      endX = parseFloat(cx) + parseFloat(r),
37946      endY = cy;
37947
37948  newElement.d =  'M' + startX + ',' + startY +
37949                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37950                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37951  return newElement;
37952};
37953
37954/**
37955 * Create `path` elements form original element
37956 * and prepared objects
37957 *
37958 * @param  {DOMelement} element  Original element to transform
37959 * @param  {object} pathData     Path data (from `toPath` methods)
37960 * @return {DOMelement}          Path element
37961 */
37962Pathformer.prototype.pathMaker = function (element, pathData) {
37963  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37964  for(i = 0; i < element.attributes.length; i++) {
37965    attr = element.attributes[i];
37966    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37967      pathTag.setAttribute(attr.name, attr.value);
37968    }
37969  }
37970  for(i in pathData) {
37971    pathTag.setAttribute(i, pathData[i]);
37972  }
37973  return pathTag;
37974};
37975
37976/**
37977 * Parse attributes of a DOM element to
37978 * get an object of attribute => value
37979 *
37980 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37981 * @return {object}                  Object of attributes
37982 */
37983Pathformer.prototype.parseAttr = function (element) {
37984  var attr, output = {};
37985  for (var i = 0; i < element.length; i++) {
37986    attr = element[i];
37987    // Check if no data attribute contains '%', or the transformation is impossible
37988    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37989      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37990    }
37991    output[attr.name] = attr.value;
37992  }
37993  return output;
37994};
37995
37996  'use strict';
37997
37998var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37999
38000/**
38001 * Vivus
38002 * Beta version
38003 *
38004 * Take any SVG and make the animation
38005 * to give give the impression of live drawing
38006 *
38007 * This in more than just inspired from codrops
38008 * At that point, it's a pure fork.
38009 */
38010
38011/**
38012 * Class constructor
38013 * option structure
38014 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
38015 *   duration: <int> (in frames)
38016 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
38017 *   delay: <int> (delay between the drawing of first and last path)
38018 *   dashGap <integer> whitespace extra margin between dashes
38019 *   pathTimingFunction <function> timing animation function for each path element of the SVG
38020 *   animTimingFunction <function> timing animation function for the complete SVG
38021 *   forceRender <boolean> force the browser to re-render all updated path items
38022 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
38023 *
38024 * The attribute 'type' is by default on 'delayed'.
38025 *  - 'delayed'
38026 *    all paths are draw at the same time but with a
38027 *    little delay between them before start
38028 *  - 'sync'
38029 *    all path are start and finish at the same time
38030 *  - 'oneByOne'
38031 *    only one path is draw at the time
38032 *    the end of the first one will trigger the draw
38033 *    of the next one
38034 *
38035 * All these values can be overwritten individually
38036 * for each path item in the SVG
38037 * The value of frames will always take the advantage of
38038 * the duration value.
38039 * If you fail somewhere, an error will be thrown.
38040 * Good luck.
38041 *
38042 * @constructor
38043 * @this {Vivus}
38044 * @param {DOM|String}   element  Dom element of the SVG or id of it
38045 * @param {Object}       options  Options about the animation
38046 * @param {Function}     callback Callback for the end of the animation
38047 */
38048function Vivus (element, options, callback) {
38049
38050  setupEnv();
38051
38052  // Setup
38053  this.isReady = false;
38054  this.setElement(element, options);
38055  this.setOptions(options);
38056  this.setCallback(callback);
38057
38058  if (this.isReady) {
38059    this.init();
38060  }
38061}
38062
38063/**
38064 * Timing functions
38065 **************************************
38066 *
38067 * Default functions to help developers.
38068 * It always take a number as parameter (between 0 to 1) then
38069 * return a number (between 0 and 1)
38070 */
38071Vivus.LINEAR          = function (x) {return x;};
38072Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
38073Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
38074Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
38075Vivus.EASE_OUT_BOUNCE = function (x) {
38076  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
38077    rate = Math.pow(base,1.5),
38078    rateR = Math.pow(1 - x, 2),
38079    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
38080  return (1- rateR) + (progress * rateR);
38081};
38082
38083
38084/**
38085 * Setters
38086 **************************************
38087 */
38088
38089/**
38090 * Check and set the element in the instance
38091 * The method will not return anything, but will throw an
38092 * error if the parameter is invalid
38093 *
38094 * @param {DOM|String}   element  SVG Dom element or id of it
38095 */
38096Vivus.prototype.setElement = function (element, options) {
38097  var onLoad, self;
38098
38099  // Basic check
38100  if (typeof element === 'undefined') {
38101    throw new Error('Vivus [constructor]: "element" parameter is required');
38102  }
38103
38104  // Set the element
38105  if (element.constructor === String) {
38106    element = document.getElementById(element);
38107    if (!element) {
38108      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
38109    }
38110  }
38111  this.parentEl = element;
38112
38113  // Load the SVG with XMLHttpRequest and extract the SVG
38114  if (options && options.file) {
38115    var self = this;
38116    onLoad = function (e) {
38117      var domSandbox = document.createElement('div');
38118      domSandbox.innerHTML = this.responseText;
38119
38120      var svgTag = domSandbox.querySelector('svg');
38121      if (!svgTag) {
38122        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
38123      }
38124
38125      self.el = svgTag
38126      self.el.setAttribute('width', '100%');
38127      self.el.setAttribute('height', '100%');
38128      self.parentEl.appendChild(self.el)
38129      self.isReady = true;
38130      self.init();
38131      self = null;
38132    }
38133
38134    var oReq = new window.XMLHttpRequest();
38135    oReq.addEventListener('load', onLoad);
38136    oReq.open('GET', options.file);
38137    oReq.send();
38138    return;
38139  }
38140
38141  switch (element.constructor) {
38142  case window.SVGSVGElement:
38143  case window.SVGElement:
38144  case window.SVGGElement:
38145    this.el = element;
38146    this.isReady = true;
38147    break;
38148
38149  case window.HTMLObjectElement:
38150    self = this;
38151    onLoad = function (e) {
38152      if (self.isReady) {
38153        return;
38154      }
38155      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
38156      if (!self.el && e) {
38157        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
38158      }
38159      else if (self.el) {
38160        if (element.getAttribute('built-by-vivus')) {
38161          self.parentEl.insertBefore(self.el, element);
38162          self.parentEl.removeChild(element);
38163          self.el.setAttribute('width', '100%');
38164          self.el.setAttribute('height', '100%');
38165        }
38166        self.isReady = true;
38167        self.init();
38168        self = null;
38169      }
38170    };
38171
38172    if (!onLoad()) {
38173      element.addEventListener('load', onLoad);
38174    }
38175    break;
38176
38177  default:
38178    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
38179  }
38180};
38181
38182/**
38183 * Set up user option to the instance
38184 * The method will not return anything, but will throw an
38185 * error if the parameter is invalid
38186 *
38187 * @param  {object} options Object from the constructor
38188 */
38189Vivus.prototype.setOptions = function (options) {
38190  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
38191  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
38192
38193  // Basic check
38194  if (options !== undefined && options.constructor !== Object) {
38195    throw new Error('Vivus [constructor]: "options" parameter must be an object');
38196  }
38197  else {
38198    options = options || {};
38199  }
38200
38201  // Set the animation type
38202  if (options.type && allowedTypes.indexOf(options.type) === -1) {
38203    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
38204  }
38205  else {
38206    this.type = options.type || allowedTypes[0];
38207  }
38208
38209  // Set the start type
38210  if (options.start && allowedStarts.indexOf(options.start) === -1) {
38211    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
38212  }
38213  else {
38214    this.start = options.start || allowedStarts[0];
38215  }
38216
38217  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
38218  this.duration     = parsePositiveInt(options.duration, 120);
38219  this.delay        = parsePositiveInt(options.delay, null);
38220  //Uncode addition
38221  this.delayStart   = parsePositiveInt(options.delayStart, null);
38222  //#END
38223  this.dashGap      = parsePositiveInt(options.dashGap, 1);
38224  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
38225  this.reverseStack = !!options.reverseStack;
38226  this.selfDestroy  = !!options.selfDestroy;
38227  this.onReady      = options.onReady;
38228  this.map          = [];
38229  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
38230
38231  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
38232
38233  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
38234  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
38235
38236  if (this.delay >= this.duration) {
38237    throw new Error('Vivus [constructor]: delay must be shorter than duration');
38238  }
38239};
38240
38241/**
38242 * Set up callback to the instance
38243 * The method will not return enything, but will throw an
38244 * error if the parameter is invalid
38245 *
38246 * @param  {Function} callback Callback for the animation end
38247 */
38248Vivus.prototype.setCallback = function (callback) {
38249  // Basic check
38250  if (!!callback && callback.constructor !== Function) {
38251    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
38252  }
38253  this.callback = callback || function () {};
38254};
38255
38256
38257/**
38258 * Core
38259 **************************************
38260 */
38261
38262/**
38263 * Map the svg, path by path.
38264 * The method return nothing, it just fill the
38265 * `map` array. Each item in this array represent
38266 * a path element from the SVG, with informations for
38267 * the animation.
38268 *
38269 * ```
38270 * [
38271 *   {
38272 *     el: <DOMobj> the path element
38273 *     length: <number> length of the path line
38274 *     startAt: <number> time start of the path animation (in frames)
38275 *     duration: <number> path animation duration (in frames)
38276 *   },
38277 *   ...
38278 * ]
38279 * ```
38280 *
38281 */
38282Vivus.prototype.mapping = function () {
38283  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
38284  timePoint = totalLength = lengthMeter = 0;
38285  paths = this.el.querySelectorAll('path');
38286
38287  for (i = 0; i < paths.length; i++) {
38288    path = paths[i];
38289    if (this.isInvisible(path)) {
38290      continue;
38291    }
38292    pathObj = {
38293      el: path,
38294      length: Math.ceil(path.getTotalLength())
38295    };
38296    // Test if the path length is correct
38297    if (isNaN(pathObj.length)) {
38298      if (window.console && console.warn) {
38299        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
38300      }
38301      continue;
38302    }
38303    this.map.push(pathObj);
38304    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
38305    path.style.strokeDashoffset = pathObj.length + this.dashGap;
38306    pathObj.length += this.dashGap;
38307    totalLength += pathObj.length;
38308
38309    this.renderPath(i);
38310  }
38311
38312  totalLength = totalLength === 0 ? 1 : totalLength;
38313  this.delay = this.delay === null ? this.duration / 3 : this.delay;
38314  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
38315
38316  // Reverse stack if asked
38317  if (this.reverseStack) {
38318    this.map.reverse();
38319  }
38320
38321  for (i = 0; i < this.map.length; i++) {
38322    pathObj = this.map[i];
38323
38324    switch (this.type) {
38325    case 'delayed':
38326      pathObj.startAt = this.delayUnit * i;
38327      pathObj.duration = this.duration - this.delay;
38328      break;
38329
38330    case 'oneByOne':
38331      pathObj.startAt = lengthMeter / totalLength * this.duration;
38332      pathObj.duration = pathObj.length / totalLength * this.duration;
38333      break;
38334
38335    case 'sync':
38336    case 'async':
38337    case 'nsync':
38338      pathObj.startAt = 0;
38339      pathObj.duration = this.duration;
38340      break;
38341
38342    case 'scenario-sync':
38343      path = pathObj.el;
38344      pAttrs = this.parseAttr(path);
38345      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
38346      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38347      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
38348      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38349      break;
38350
38351    case 'scenario':
38352      path = pathObj.el;
38353      pAttrs = this.parseAttr(path);
38354      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
38355      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38356      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38357      break;
38358    }
38359    lengthMeter += pathObj.length;
38360    this.frameLength = this.frameLength || this.duration;
38361  }
38362};
38363
38364/**
38365 * Interval method to draw the SVG from current
38366 * position of the animation. It update the value of
38367 * `currentFrame` and re-trace the SVG.
38368 *
38369 * It use this.handle to store the requestAnimationFrame
38370 * and clear it one the animation is stopped. So this
38371 * attribute can be used to know if the animation is
38372 * playing.
38373 *
38374 * Once the animation at the end, this method will
38375 * trigger the Vivus callback.
38376 *
38377 */
38378Vivus.prototype.drawer = function () {
38379  var self = this;
38380  this.currentFrame += this.speed;
38381
38382  if (this.currentFrame <= 0) {
38383    this.stop();
38384    this.reset();
38385  } else if (this.currentFrame >= this.frameLength) {
38386    this.stop();
38387    this.currentFrame = this.frameLength;
38388    this.trace();
38389    if (this.selfDestroy) {
38390      this.destroy();
38391    }
38392  } else {
38393    this.trace();
38394    this.handle = requestAnimFrame(function () {
38395      self.drawer();
38396    });
38397    return;
38398  }
38399
38400  this.callback(this);
38401  if (this.instanceCallback) {
38402    this.instanceCallback(this);
38403    this.instanceCallback = null;
38404  }
38405};
38406
38407/**
38408 * Draw the SVG at the current instant from the
38409 * `currentFrame` value. Here is where most of the magic is.
38410 * The trick is to use the `strokeDashoffset` style property.
38411 *
38412 * For optimisation reasons, a new property called `progress`
38413 * is added in each item of `map`. This one contain the current
38414 * progress of the path element. Only if the new value is different
38415 * the new value will be applied to the DOM element. This
38416 * method save a lot of resources to re-render the SVG. And could
38417 * be improved if the animation couldn't be played forward.
38418 *
38419 */
38420Vivus.prototype.trace = function () {
38421  var i, progress, path, currentFrame;
38422  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
38423  for (i = 0; i < this.map.length; i++) {
38424    path = this.map[i];
38425    progress = (currentFrame - path.startAt) / path.duration;
38426    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
38427    if (path.progress !== progress) {
38428      path.progress = progress;
38429      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
38430      this.renderPath(i);
38431    }
38432  }
38433};
38434
38435/**
38436 * Method forcing the browser to re-render a path element
38437 * from it's index in the map. Depending on the `forceRender`
38438 * value.
38439 * The trick is to replace the path element by it's clone.
38440 * This practice is not recommended because it's asking more
38441 * ressources, too much DOM manupulation..
38442 * but it's the only way to let the magic happen on IE.
38443 * By default, this fallback is only applied on IE.
38444 *
38445 * @param  {Number} index Path index
38446 */
38447Vivus.prototype.renderPath = function (index) {
38448  if (this.forceRender && this.map && this.map[index]) {
38449    var pathObj = this.map[index],
38450        newPath = pathObj.el.cloneNode(true);
38451    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
38452    pathObj.el = newPath;
38453  }
38454};
38455
38456/**
38457 * When the SVG object is loaded and ready,
38458 * this method will continue the initialisation.
38459 *
38460 * This this mainly due to the case of passing an
38461 * object tag in the constructor. It will wait
38462 * the end of the loading to initialise.
38463 *
38464 */
38465Vivus.prototype.init = function () {
38466  // Set object variables
38467  this.frameLength = 0;
38468  this.currentFrame = 0;
38469  this.map = [];
38470
38471  // Start
38472  new Pathformer(this.el);
38473  this.mapping();
38474  this.starter();
38475
38476  if (this.onReady) {
38477    this.onReady(this);
38478  }
38479};
38480
38481/**
38482 * Trigger to start of the animation.
38483 * Depending on the `start` value, a different script
38484 * will be applied.
38485 *
38486 * If the `start` value is not valid, an error will be thrown.
38487 * Even if technically, this is impossible.
38488 *
38489 */
38490Vivus.prototype.starter = function () {
38491  switch (this.start) {
38492  case 'manual':
38493    return;
38494
38495  case 'autostart':
38496    this.play();
38497    break;
38498
38499  case 'inViewport':
38500    var self = this,
38501    listener = function () {
38502      if (self.isInViewport(self.parentEl, 1)) {
38503        self.play();
38504        window.removeEventListener('scroll', listener);
38505        //Uncode addition
38506        window.removeEventListener('fp-slide-changed', listener);
38507        window.removeEventListener('fp-slide-scroll', listener);
38508        //#END
38509      }
38510    };
38511    window.addEventListener('scroll', listener);
38512    //Uncode addition
38513    window.addEventListener('fp-slide-changed', listener);
38514    window.addEventListener('fp-slide-scroll', listener);
38515    //#END
38516    listener();
38517    break;
38518  }
38519};
38520
38521
38522/**
38523 * Controls
38524 **************************************
38525 */
38526
38527/**
38528 * Get the current status of the animation between
38529 * three different states: 'start', 'progress', 'end'.
38530 * @return {string} Instance status
38531 */
38532Vivus.prototype.getStatus = function () {
38533  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
38534};
38535
38536/**
38537 * Reset the instance to the initial state : undraw
38538 * Be careful, it just reset the animation, if you're
38539 * playing the animation, this won't stop it. But just
38540 * make it start from start.
38541 *
38542 */
38543Vivus.prototype.reset = function () {
38544  return this.setFrameProgress(0);
38545};
38546
38547/**
38548 * Set the instance to the final state : drawn
38549 * Be careful, it just set the animation, if you're
38550 * playing the animation on rewind, this won't stop it.
38551 * But just make it start from the end.
38552 *
38553 */
38554Vivus.prototype.finish = function () {
38555  return this.setFrameProgress(1);
38556};
38557
38558/**
38559 * Set the level of progress of the drawing.
38560 *
38561 * @param {number} progress Level of progress to set
38562 */
38563Vivus.prototype.setFrameProgress = function (progress) {
38564  progress = Math.min(1, Math.max(0, progress));
38565  this.currentFrame = Math.round(this.frameLength * progress);
38566  this.trace();
38567  return this;
38568};
38569
38570/**
38571 * Play the animation at the desired speed.
38572 * Speed must be a valid number (no zero).
38573 * By default, the speed value is 1.
38574 * But a negative value is accepted to go forward.
38575 *
38576 * And works with float too.
38577 * But don't forget we are in JavaScript, se be nice
38578 * with him and give him a 1/2^x value.
38579 *
38580 * @param  {number} speed Animation speed [optional]
38581 */
38582Vivus.prototype.play = function (speed, callback) {
38583  this.instanceCallback = null;
38584
38585  if (speed && typeof speed === 'function') {
38586    this.instanceCallback = speed; // first parameter is actually the callback function
38587    speed = null;
38588  }
38589  else if (speed && typeof speed !== 'number') {
38590    throw new Error('Vivus [play]: invalid speed');
38591  }
38592  // if the first parameter wasn't the callback, check if the seconds was
38593  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
38594    this.instanceCallback = callback;
38595  }
38596
38597
38598  this.speed = speed || 1;
38599  //Uncode addition
38600  if (!this.handle) {
38601    var $this = this,
38602    delay = (this.delayStart != null) ? this.delayStart : 0;
38603    setTimeout(function() {
38604      $this.drawer();
38605    }, delay);
38606  }
38607  //#END
38608  return this;
38609};
38610
38611/**
38612 * Stop the current animation, if on progress.
38613 * Should not trigger any error.
38614 *
38615 */
38616Vivus.prototype.stop = function () {
38617  if (this.handle) {
38618    cancelAnimFrame(this.handle);
38619    this.handle = null;
38620  }
38621  return this;
38622};
38623
38624/**
38625 * Destroy the instance.
38626 * Remove all bad styling attributes on all
38627 * path tags
38628 *
38629 */
38630Vivus.prototype.destroy = function () {
38631  this.stop();
38632  var i, path;
38633  for (i = 0; i < this.map.length; i++) {
38634    path = this.map[i];
38635    path.el.style.strokeDashoffset = null;
38636    path.el.style.strokeDasharray = null;
38637    this.renderPath(i);
38638  }
38639};
38640
38641
38642/**
38643 * Utils methods
38644 * include methods from Codrops
38645 **************************************
38646 */
38647
38648/**
38649 * Method to best guess if a path should added into
38650 * the animation or not.
38651 *
38652 * 1. Use the `data-vivus-ignore` attribute if set
38653 * 2. Check if the instance must ignore invisible paths
38654 * 3. Check if the path is visible
38655 *
38656 * For now the visibility checking is unstable.
38657 * It will be used for a beta phase.
38658 *
38659 * Other improvments are planned. Like detecting
38660 * is the path got a stroke or a valid opacity.
38661 */
38662Vivus.prototype.isInvisible = function (el) {
38663  var rect,
38664    ignoreAttr = el.getAttribute('data-ignore');
38665
38666  if (ignoreAttr !== null) {
38667    return ignoreAttr !== 'false';
38668  }
38669
38670  if (this.ignoreInvisible) {
38671    rect = el.getBoundingClientRect();
38672    return !rect.width && !rect.height;
38673  }
38674  else {
38675    return false;
38676  }
38677};
38678
38679/**
38680 * Parse attributes of a DOM element to
38681 * get an object of {attributeName => attributeValue}
38682 *
38683 * @param  {object} element DOM element to parse
38684 * @return {object}         Object of attributes
38685 */
38686Vivus.prototype.parseAttr = function (element) {
38687  var attr, output = {};
38688  if (element && element.attributes) {
38689    for (var i = 0; i < element.attributes.length; i++) {
38690      attr = element.attributes[i];
38691      output[attr.name] = attr.value;
38692    }
38693  }
38694  return output;
38695};
38696
38697/**
38698 * Reply if an element is in the page viewport
38699 *
38700 * @param  {object} el Element to observe
38701 * @param  {number} h  Percentage of height
38702 * @return {boolean}
38703 */
38704Vivus.prototype.isInViewport = function (el, h) {
38705  var scrolled   = this.scrollY(),
38706    viewed       = scrolled + this.getViewportH(),
38707    elBCR        = el.getBoundingClientRect(),
38708    elHeight     = elBCR.height,
38709    elTop        = scrolled + elBCR.top,
38710    elBottom     = elTop + elHeight;
38711
38712  // if 0, the element is considered in the viewport as soon as it enters.
38713  // if 1, the element is considered in the viewport only when it's fully inside
38714  // value in percentage (1 >= h >= 0)
38715  h = h || 0;
38716
38717  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
38718};
38719
38720
38721/**
38722 * Get the viewport height in pixels
38723 *
38724 * @return {integer} Viewport height
38725 */
38726Vivus.prototype.getViewportH = function () {
38727  var client = this.docElem.clientHeight,
38728    inner = window.innerHeight;
38729
38730  if (client < inner) {
38731    return inner;
38732  }
38733  else {
38734    return client;
38735  }
38736};
38737
38738/**
38739 * Get the page Y offset
38740 *
38741 * @return {integer} Page Y offset
38742 */
38743Vivus.prototype.scrollY = function () {
38744  return window.pageYOffset || this.docElem.scrollTop;
38745};
38746
38747setupEnv = function () {
38748
38749  if (Vivus.prototype.docElem) {
38750    return;
38751  }
38752
38753  /**
38754   * Alias for document element
38755   *
38756   * @type {DOMelement}
38757   */
38758  Vivus.prototype.docElem = window.document.documentElement;
38759
38760  /**
38761   * Alias for `requestAnimationFrame` or
38762   * `setTimeout` function for deprecated browsers.
38763   *
38764   */
38765  requestAnimFrame = (function () {
38766    return (
38767      window.requestAnimationFrame       ||
38768      window.webkitRequestAnimationFrame ||
38769      window.mozRequestAnimationFrame    ||
38770      window.oRequestAnimationFrame      ||
38771      window.msRequestAnimationFrame     ||
38772      function(/* function */ callback){
38773        return window.setTimeout(callback, 1000 / 60);
38774      }
38775    );
38776  })();
38777
38778  /**
38779   * Alias for `cancelAnimationFrame` or
38780   * `cancelTimeout` function for deprecated browsers.
38781   *
38782   */
38783  cancelAnimFrame = (function () {
38784    return (
38785      window.cancelAnimationFrame       ||
38786      window.webkitCancelAnimationFrame ||
38787      window.mozCancelAnimationFrame    ||
38788      window.oCancelAnimationFrame      ||
38789      window.msCancelAnimationFrame     ||
38790      function(id){
38791        return window.clearTimeout(id);
38792      }
38793    );
38794  })();
38795};
38796
38797/**
38798 * Parse string to integer.
38799 * If the number is not positive or null
38800 * the method will return the default value
38801 * or 0 if undefined
38802 *
38803 * @param {string} value String to parse
38804 * @param {*}
38804 defaultValue Value to return if the result parsed is invalid
38805 * @return {number}
38806 *
38807 */
38808parsePositiveInt = function (value, defaultValue) {
38809  var output = parseInt(value, 10);
38810  return (output >= 0) ? output : defaultValue;
38811};
38812
38813
38814  if (typeof define === 'function' && define.amd) {
38815    // AMD. Register as an anonymous module.
38816    define([], function() {
38817      return Vivus;
38818    });
38819  } else if (typeof exports === 'object') {
38820    // Node. Does not work with strict CommonJS, but
38821    // only CommonJS-like environments that support module.exports,
38822    // like Node.
38823    module.exports = Vivus;
38824  } else {
38825    // Browser globals
38826    window.Vivus = Vivus;
38827  }
38828
38829}());

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.