PageSourceSearch

https://peluqueriasmadrigal.es/wp-content/themes/uncode/library/js/plugins.js?ver=2043750394

js peluqueriasmadrigal.es collected 2026-10-07 13:39:57 UTC 1,287,946 bytes, 38,768 lines download raw bytes

vendor: 4,985 bytes, lines 1-161
1/* ----------------------------------------------------------
2 * Plugins
3 * ---------------------------------------------------------- */
4
5(function (global, factory) {
6  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
7  typeof define === 'function' && define.amd ? define(['exports'], factory) :
8  (global = global || self, factory(global.window = global.window || {}));
9}(this, (function (exports) { 'use strict';
10
11  function _inheritsLoose(subClass, superClass) {
12    subClass.prototype = Object.create(superClass.prototype);
13    subClass.prototype.constructor = subClass;
14    subClass.__proto__ = superClass;
15  }
16
17  function _assertThisInitialized(self) {
18    if (self === void 0) {
19      throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
20    }
21
22    return self;
23  }
24
25  /*!
26   * GSAP 3.11.3
27   * https://greensock.com
28   *
29   * @license Copyright 2008-2022, GreenSock. All rights reserved.
30   * Subject to the terms at https://greensock.com/standard-license or for
31   * Club GreenSock members, the agreement issued with that membership.
32   * @author: Jack Doyle, [email protected]
33  */
34  var _config = {
35    autoSleep: 120,
36    force3D: "auto",
37    nullTargetWarn: 1,
38    units: {
39      lineHeight: ""
40    }
41  },
42      _defaults = {
43    duration: .5,
44    overwrite: false,
45    delay: 0
46  },
47      _suppressOverwrites,
48      _reverting,
49      _context,
50      _bigNum = 1e8,
51      _tinyNum = 1 / _bigNum,
52      _2PI = Math.PI * 2,
53      _HALF_PI = _2PI / 4,
54      _gsID = 0,
55      _sqrt = Math.sqrt,
56      _cos = Math.cos,
57      _sin = Math.sin,
58      _isString = function _isString(value) {
59    return typeof value === "string";
60  },
61      _isFunction = function _isFunction(value) {
62    return typeof value === "function";
63  },
64      _isNumber = function _isNumber(value) {
65    return typeof value === "number";
66  },
67      _isUndefined = function _isUndefined(value) {
68    return typeof value === "undefined";
69  },
70      _isObject = function _isObject(value) {
71    return typeof value === "object";
72  },
73      _isNotFalse = function _isNotFalse(value) {
74    return value !== false;
75  },
76      _windowExists = function _windowExists() {
77    return typeof window !== "undefined";
78  },
79      _isFuncOrString = function _isFuncOrString(value) {
80    return _isFunction(value) || _isString(value);
81  },
82      _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {},
83      _isArray = Array.isArray,
84      _strictNumExp = /(?:-?\.?\d|\.)+/gi,
85      _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g,
86      _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g,
87      _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi,
88      _relExp = /[+-]=-?[.\d]+/,
89      _delimitedValueExp = /[^,'"\[\]\s]+/gi,
90      _unitExp = /^[+\-=e\s\d]*\d+[.\d]*([a-z]*|%)\s*$/i,
91      _globalTimeline,
92      _win,
93      _coreInitted,
94      _doc,
95      _globals = {},
96      _installScope = {},
97      _coreReady,
98      _install = function _install(scope) {
99    return (_installScope = _merge(scope, _globals)) && gsap;
100  },
101      _missingPlugin = function _missingPlugin(property, value) {
102    return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()");
103  },
104      _warn = function _warn(message, suppress) {
105    return !suppress && console.warn(message);
106  },
107      _addGlobal = function _addGlobal(name, obj) {
108    return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals;
109  },
110      _emptyFunc = function _emptyFunc() {
111    return 0;
112  },
113      _startAtRevertConfig = {
114    suppressEvents: true,
115    isStart: true,
116    kill: false
117  },
118      _revertConfigNoKill = {
119    suppressEvents: true,
120    kill: false
121  },
122      _revertConfig = {
123    suppressEvents: true
124  },
125      _reservedProps = {},
126      _lazyTweens = [],
127      _lazyLookup = {},
128      _lastRenderedFrame,
129      _plugins = {},
130      _effects = {},
131      _nextGCFrame = 30,
132      _harnessPlugins = [],
133      _callbackNames = "",
134      _harness = function _harness(targets) {
135    var target = targets[0],
136        harnessPlugin,
137        i;
138    _isObject(target) || _isFunction(target) || (targets = [targets]);
139
140    if (!(harnessPlugin = (target._gsap || {}).harness)) {
141      i = _harnessPlugins.length;
142
143      while (i-- && !_harnessPlugins[i].targetTest(target)) {}
144
145      harnessPlugin = _harnessPlugins[i];
146    }
147
148    i = targets.length;
149
150    while (i--) {
151      targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1);
152    }
153
154    return targets;
155  },
156      _getCache = function _getCache(target) {
157    return target._gsap || _harness(toArray(target))[0]._gsap;
158  },
159      _getProperty = function _getProperty(target, property, v) {
160    return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v;
161  },
vendor: 7,375 bytes, lines 162-396
162      _forEachName = function _forEachName(names, func) {
163    return (names = names.split(",")).forEach(func) || names;
164  },
165      _round = function _round(value) {
166    return Math.round(value * 100000) / 100000 || 0;
167  },
168      _roundPrecise = function _roundPrecise(value) {
169    return Math.round(value * 10000000) / 10000000 || 0;
170  },
171      _parseRelative = function _parseRelative(start, value) {
172    var operator = value.charAt(0),
173        end = parseFloat(value.substr(2));
174    start = parseFloat(start);
175    return operator === "+" ? start + end : operator === "-" ? start - end : operator === "*" ? start * end : start / end;
176  },
177      _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) {
178    var l = toFind.length,
179        i = 0;
180
181    for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {}
182
183    return i < l;
184  },
185      _lazyRender = function _lazyRender() {
186    var l = _lazyTweens.length,
187        a = _lazyTweens.slice(0),
188        i,
189        tween;
190
191    _lazyLookup = {};
192    _lazyTweens.length = 0;
193
194    for (i = 0; i < l; i++) {
195      tween = a[i];
196      tween && tween._lazy && (tween.render(tween._lazy[0], tween._lazy[1], true)._lazy = 0);
197    }
198  },
199      _lazySafeRender = function _lazySafeRender(animation, time, suppressEvents, force) {
200    _lazyTweens.length && _lazyRender();
201    animation.render(time, suppressEvents, force || _reverting && time < 0 && (animation._initted || animation._startAt));
202    _lazyTweens.length && _lazyRender();
203  },
204      _numericIfPossible = function _numericIfPossible(value) {
205    var n = parseFloat(value);
206    return (n || n === 0) && (value + "").match(_delimitedValueExp).length < 2 ? n : _isString(value) ? value.trim() : value;
207  },
208      _passThrough = function _passThrough(p) {
209    return p;
210  },
211      _setDefaults = function _setDefaults(obj, defaults) {
212    for (var p in defaults) {
213      p in obj || (obj[p] = defaults[p]);
214    }
215
216    return obj;
217  },
218      _setKeyframeDefaults = function _setKeyframeDefaults(excludeDuration) {
219    return function (obj, defaults) {
220      for (var p in defaults) {
221        p in obj || p === "duration" && excludeDuration || p === "ease" || (obj[p] = defaults[p]);
222      }
223    };
224  },
225      _merge = function _merge(base, toMerge) {
226    for (var p in toMerge) {
227      base[p] = toMerge[p];
228    }
229
230    return base;
231  },
232      _mergeDeep = function _mergeDeep(base, toMerge) {
233    for (var p in toMerge) {
234      p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]);
235    }
236
237    return base;
238  },
239      _copyExcluding = function _copyExcluding(obj, excluding) {
240    var copy = {},
241        p;
242
243    for (p in obj) {
244      p in excluding || (copy[p] = obj[p]);
245    }
246
247    return copy;
248  },
249      _inheritDefaults = function _inheritDefaults(vars) {
250    var parent = vars.parent || _globalTimeline,
251        func = vars.keyframes ? _setKeyframeDefaults(_isArray(vars.keyframes)) : _setDefaults;
252
253    if (_isNotFalse(vars.inherit)) {
254      while (parent) {
255        func(vars, parent.vars.defaults);
256        parent = parent.parent || parent._dp;
257      }
258    }
259
260    return vars;
261  },
262      _arraysMatch = function _arraysMatch(a1, a2) {
263    var i = a1.length,
264        match = i === a2.length;
265
266    while (match && i-- && a1[i] === a2[i]) {}
267
268    return i < 0;
269  },
270      _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) {
271    if (firstProp === void 0) {
272      firstProp = "_first";
273    }
274
275    if (lastProp === void 0) {
276      lastProp = "_last";
277    }
278
279    var prev = parent[lastProp],
280        t;
281
282    if (sortBy) {
283      t = child[sortBy];
284
285      while (prev && prev[sortBy] > t) {
286        prev = prev._prev;
287      }
288    }
289
290    if (prev) {
291      child._next = prev._next;
292      prev._next = child;
293    } else {
294      child._next = parent[firstProp];
295      parent[firstProp] = child;
296    }
297
298    if (child._next) {
299      child._next._prev = child;
300    } else {
301      parent[lastProp] = child;
302    }
303
304    child._prev = prev;
305    child.parent = child._dp = parent;
306    return child;
307  },
308      _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) {
309    if (firstProp === void 0) {
310      firstProp = "_first";
311    }
312
313    if (lastProp === void 0) {
314      lastProp = "_last";
315    }
316
317    var prev = child._prev,
318        next = child._next;
319
320    if (prev) {
321      prev._next = next;
322    } else if (parent[firstProp] === child) {
323      parent[firstProp] = next;
324    }
325
326    if (next) {
327      next._prev = prev;
328    } else if (parent[lastProp] === child) {
329      parent[lastProp] = prev;
330    }
331
332    child._next = child._prev = child.parent = null;
333  },
334      _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) {
335    child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove(child);
336    child._act = 0;
337  },
338      _uncache = function _uncache(animation, child) {
339    if (animation && (!child || child._end > animation._dur || child._start < 0)) {
340      var a = animation;
341
342      while (a) {
343        a._dirty = 1;
344        a = a.parent;
345      }
346    }
347
348    return animation;
349  },
350      _recacheAncestors = function _recacheAncestors(animation) {
351    var parent = animation.parent;
352
353    while (parent && parent.parent) {
354      parent._dirty = 1;
355      parent.totalDuration();
356      parent = parent.parent;
357    }
358
359    return animation;
360  },
361      _rewindStartAt = function _rewindStartAt(tween, totalTime, suppressEvents, force) {
362    return tween._startAt && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween.vars.immediateRender && !tween.vars.autoRevert || tween._startAt.render(totalTime, true, force));
363  },
364      _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) {
365    return !animation || animation._ts && _hasNoPausedAncestors(animation.parent);
366  },
367      _elapsedCycleDuration = function _elapsedCycleDuration(animation) {
368    return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0;
369  },
370      _animationCycle = function _animationCycle(tTime, cycleDuration) {
371    var whole = Math.floor(tTime /= cycleDuration);
372    return tTime && whole === tTime ? whole - 1 : whole;
373  },
374      _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) {
375    return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur);
376  },
377      _setEnd = function _setEnd(animation) {
378    return animation._end = _roundPrecise(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0));
379  },
380      _alignPlayhead = function _alignPlayhead(animation, totalTime) {
381    var parent = animation._dp;
382
383    if (parent && parent.smoothChildTiming && animation._ts) {
384      animation._start = _roundPrecise(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts));
385
386      _setEnd(animation);
387
388      parent._dirty || _uncache(parent, animation);
389    }
390
391    return animation;
392  },
393      _postAddChecks = function _postAddChecks(timeline, child) {
394    var t;
395
396    if (child._time || child._initted && !child._dur
vendor: 11,458 bytes, lines 396-708
396) {
397      t = _parentToChildTotalTime(timeline.rawTime(), child);
398
399      if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) {
400        child.render(t, true);
401      }
402    }
403
404    if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) {
405      if (timeline._dur < timeline.duration()) {
406        t = timeline;
407
408        while (t._dp) {
409          t.rawTime() >= 0 && t.totalTime(t._tTime);
410          t = t._dp;
411        }
412      }
413
414      timeline._zTime = -_tinyNum;
415    }
416  },
417      _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) {
418    child.parent && _removeFromParent(child);
419    child._start = _roundPrecise((_isNumber(position) ? position : position || timeline !== _globalTimeline ? _parsePosition(timeline, position, child) : timeline._time) + child._delay);
420    child._end = _roundPrecise(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0));
421
422    _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0);
423
424    _isFromOrFromStart(child) || (timeline._recent = child);
425    skipChecks || _postAddChecks(timeline, child);
426    timeline._ts < 0 && _alignPlayhead(timeline, timeline._tTime);
427    return timeline;
428  },
429      _scrollTrigger = function _scrollTrigger(animation, trigger) {
430    return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation);
431  },
432      _attemptInitTween = function _attemptInitTween(tween, time, force, suppressEvents, tTime) {
433    _initTween(tween, time, tTime);
434
435    if (!tween._initted) {
436      return 1;
437    }
438
439    if (!force && tween._pt && !_reverting && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) {
440      _lazyTweens.push(tween);
441
442      tween._lazy = [tTime, suppressEvents];
443      return 1;
444    }
445  },
446      _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) {
447    var parent = _ref.parent;
448    return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent));
449  },
450      _isFromOrFromStart = function _isFromOrFromStart(_ref2) {
451    var data = _ref2.data;
452    return data === "isFromStart" || data === "isStart";
453  },
454      _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) {
455    var prevRatio = tween.ratio,
456        ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) && !(!tween._initted && _isFromOrFromStart(tween)) || (tween._ts < 0 || tween._dp._ts < 0) && !_isFromOrFromStart(tween)) ? 0 : 1,
457        repeatDelay = tween._rDelay,
458        tTime = 0,
459        pt,
460        iteration,
461        prevIteration;
462
463    if (repeatDelay && tween._repeat) {
464      tTime = _clamp(0, tween._tDur, totalTime);
465      iteration = _animationCycle(tTime, repeatDelay);
466      tween._yoyo && iteration & 1 && (ratio = 1 - ratio);
467
468      if (iteration !== _animationCycle(tween._tTime, repeatDelay)) {
469        prevRatio = 1 - ratio;
470        tween.vars.repeatRefresh && tween._initted && tween.invalidate();
471      }
472    }
473
474    if (ratio !== prevRatio || _reverting || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) {
475      if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents, tTime)) {
476        return;
477      }
478
479      prevIteration = tween._zTime;
480      tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0);
481      suppressEvents || (suppressEvents = totalTime && !prevIteration);
482      tween.ratio = ratio;
483      tween._from && (ratio = 1 - ratio);
484      tween._time = 0;
485      tween._tTime = tTime;
486      pt = tween._pt;
487
488      while (pt) {
489        pt.r(ratio, pt.d);
490        pt = pt._next;
491      }
492
493      totalTime < 0 && _rewindStartAt(tween, totalTime, suppressEvents, true);
494      tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate");
495      tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat");
496
497      if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) {
498        ratio && _removeFromParent(tween, 1);
499
500        if (!suppressEvents && !_reverting) {
501          _callback(tween, ratio ? "onComplete" : "onReverseComplete", true);
502
503          tween._prom && tween._prom();
504        }
505      }
506    } else if (!tween._zTime) {
507      tween._zTime = totalTime;
508    }
509  },
510      _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) {
511    var child;
512
513    if (time > prevTime) {
514      child = animation._first;
515
516      while (child && child._start <= time) {
517        if (child.data === "isPause" && child._start > prevTime) {
518          return child;
519        }
520
521        child = child._next;
522      }
523    } else {
524      child = animation._last;
525
526      while (child && child._start >= time) {
527        if (child.data === "isPause" && child._start < prevTime) {
528          return child;
529        }
530
531        child = child._prev;
532      }
533    }
534  },
535      _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) {
536    var repeat = animation._repeat,
537        dur = _roundPrecise(duration) || 0,
538        totalProgress = animation._tTime / animation._tDur;
539    totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur);
540    animation._dur = dur;
541    animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _roundPrecise(dur * (repeat + 1) + animation._rDelay * repeat);
542    totalProgress > 0 && !leavePlayhead && _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress);
543    animation.parent && _setEnd(animation);
544    skipUncache || _uncache(animation.parent, animation);
545    return animation;
546  },
547      _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) {
548    return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur);
549  },
550      _zeroPosition = {
551    _start: 0,
552    endTime: _emptyFunc,
553    totalDuration: _emptyFunc
554  },
555      _parsePosition = function _parsePosition(animation, position, percentAnimation) {
556    var labels = animation.labels,
557        recent = animation._recent || _zeroPosition,
558        clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur,
559        i,
560        offset,
561        isPercent;
562
563    if (_isString(position) && (isNaN(position) || position in labels)) {
564      offset = position.charAt(0);
565      isPercent = position.substr(-1) === "%";
566      i = position.indexOf("=");
567
568      if (offset === "<" || offset === ">") {
569        i >= 0 && (position = position.replace(/=/, ""));
570        return (offset === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0) * (isPercent ? (i < 0 ? recent : percentAnimation).totalDuration() / 100 : 1);
571      }
572
573      if (i < 0) {
574        position in labels || (labels[position] = clippedDuration);
575        return labels[position];
576      }
577
578      offset = parseFloat(position.charAt(i - 1) + position.substr(i + 1));
579
580      if (isPercent && percentAnimation) {
581        offset = offset / 100 * (_isArray(percentAnimation) ? percentAnimation[0] : percentAnimation).totalDuration();
582      }
583
584      return i > 1 ? _parsePosition(animation, position.substr(0, i - 1), percentAnimation) + offset : clippedDuration + offset;
585    }
586
587    return position == null ? clippedDuration : +position;
588  },
589      _createTweenType = function _createTweenType(type, params, timeline) {
590    var isLegacy = _isNumber(params[1]),
591        varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1),
592        vars = params[varsIndex],
593        irVars,
594        parent;
595
596    isLegacy && (vars.duration = params[1]);
597    vars.parent = timeline;
598
599    if (type) {
600      irVars = vars;
601      parent = timeline;
602
603      while (parent && !("immediateRender" in irVars)) {
604        irVars = parent.vars.defaults || {};
605        parent = _isNotFalse(parent.vars.inherit) && parent.parent;
606      }
607
608      vars.immediateRender = _isNotFalse(irVars.immediateRender);
609      type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1];
610    }
611
612    return new Tween(params[0], vars, params[varsIndex + 1]);
613  },
614      _conditionalReturn = function _conditionalReturn(value, func) {
615    return value || value === 0 ? func(value) : func;
616  },
617      _clamp = function _clamp(min, max, value) {
618    return value < min ? min : value > max ? max : value;
619  },
620      getUnit = function getUnit(value, v) {
621    return !_isString(value) || !(v = _unitExp.exec(value)) ? "" : v[1];
622  },
623      clamp = function clamp(min, max, value) {
624    return _conditionalReturn(value, function (v) {
625      return _clamp(min, max, v);
626    });
627  },
628      _slice = [].slice,
629      _isArrayLike = function _isArrayLike(value, nonEmpty) {
630    return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win;
631  },
632      _flatten = function _flatten(ar, leaveStrings, accumulator) {
633    if (accumulator === void 0) {
634      accumulator = [];
635    }
636
637    return ar.forEach(function (value) {
638      var _accumulator;
639
640      return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value);
641    }) || accumulator;
642  },
643      toArray = function toArray(value, scope, leaveStrings) {
644    return _context && !scope && _context.selector ? _context.selector(value) : _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call((scope || _doc).querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : [];
645  },
646      selector = function selector(value) {
647    value = toArray(value)[0] || _warn("Invalid scope") || {};
648    return function (v) {
649      var el = value.current || value.nativeElement || value;
650      return toArray(v, el.querySelectorAll ? el : el === value ? _warn("Invalid scope") || _doc.createElement("div") : value);
651    };
652  },
653      shuffle = function shuffle(a) {
654    return a.sort(function () {
655      return .5 - Math.random();
656    });
657  },
658      distribute = function distribute(v) {
659    if (_isFunction(v)) {
660      return v;
661    }
662
663    var vars = _isObject(v) ? v : {
664      each: v
665    },
666        ease = _parseEase(vars.ease),
667        from = vars.from || 0,
668        base = parseFloat(vars.base) || 0,
669        cache = {},
670        isDecimal = from > 0 && from < 1,
671        ratios = isNaN(from) || isDecimal,
672        axis = vars.axis,
673        ratioX = from,
674        ratioY = from;
675
676    if (_isString(from)) {
677      ratioX = ratioY = {
678        center: .5,
679        edges: .5,
680        end: 1
681      }[from] || 0;
682    } else if (!isDecimal && ratios) {
683      ratioX = from[0];
684      ratioY = from[1];
685    }
686
687    return function (i, target, a) {
688      var l = (a || vars).length,
689          distances = cache[l],
690          originX,
691          originY,
692          x,
693          y,
694          d,
695          j,
696          max,
697          min,
698          wrapAt;
699
700      if (!distances) {
701        wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1];
702
703        if (!wrapAt) {
704          max = -_bigNum;
705
706          while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {}
707
708          wrapAt
vendor: 3,154 bytes, lines 708-798
708--;
709        }
710
711        distances = cache[l] = [];
712        originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt;
713        originY = wrapAt === _bigNum ? 0 : ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0;
714        max = 0;
715        min = _bigNum;
716
717        for (j = 0; j < l; j++) {
718          x = j % wrapAt - originX;
719          y = originY - (j / wrapAt | 0);
720          distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x);
721          d > max && (max = d);
722          d < min && (min = d);
723        }
724
725        from === "random" && shuffle(distances);
726        distances.max = max - min;
727        distances.min = min;
728        distances.v = l = (parseFloat(vars.amount) || parseFloat(vars.each) * (wrapAt > l ? l - 1 : !axis ? Math.max(wrapAt, l / wrapAt) : axis === "y" ? l / wrapAt : wrapAt) || 0) * (from === "edges" ? -1 : 1);
729        distances.b = l < 0 ? base - l : base;
730        distances.u = getUnit(vars.amount || vars.each) || 0;
731        ease = ease && l < 0 ? _invertEase(ease) : ease;
732      }
733
734      l = (distances[i] - distances.min) / distances.max || 0;
735      return _roundPrecise(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u;
736    };
737  },
738      _roundModifier = function _roundModifier(v) {
739    var p = Math.pow(10, ((v + "").split(".")[1] || "").length);
740    return function (raw) {
741      var n = _roundPrecise(Math.round(parseFloat(raw) / v) * v * p);
742
743      return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw));
744    };
745  },
746      snap = function snap(snapTo, value) {
747    var isArray = _isArray(snapTo),
748        radius,
749        is2D;
750
751    if (!isArray && _isObject(snapTo)) {
752      radius = isArray = snapTo.radius || _bigNum;
753
754      if (snapTo.values) {
755        snapTo = toArray(snapTo.values);
756
757        if (is2D = !_isNumber(snapTo[0])) {
758          radius *= radius;
759        }
760      } else {
761        snapTo = _roundModifier(snapTo.increment);
762      }
763    }
764
765    return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) {
766      is2D = snapTo(raw);
767      return Math.abs(is2D - raw) <= radius ? is2D : raw;
768    } : function (raw) {
769      var x = parseFloat(is2D ? raw.x : raw),
770          y = parseFloat(is2D ? raw.y : 0),
771          min = _bigNum,
772          closest = 0,
773          i = snapTo.length,
774          dx,
775          dy;
776
777      while (i--) {
778        if (is2D) {
779          dx = snapTo[i].x - x;
780          dy = snapTo[i].y - y;
781          dx = dx * dx + dy * dy;
782        } else {
783          dx = Math.abs(snapTo[i] - x);
784        }
785
786        if (dx < min) {
787          min = dx;
788          closest = i;
789        }
790      }
791
792      closest = !radius || min <= radius ? snapTo[closest] : raw;
793      return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw);
794    });
795  },
796      random = function random(min, max, roundingIncrement, returnFunction) {
797    return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () {
798      return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e
vendor: 4,891 bytes, lines 798-960
798-5) && (returnFunction = roundingIncrement < 1 ? Math.pow(10, (roundingIncrement + "").length - 2) : 1) && Math.floor(Math.round((min - roundingIncrement / 2 + Math.random() * (max - min + roundingIncrement * .99)) / roundingIncrement) * roundingIncrement * returnFunction) / returnFunction;
799    });
800  },
801      pipe = function pipe() {
802    for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) {
803      functions[_key] = arguments[_key];
804    }
805
806    return function (value) {
807      return functions.reduce(function (v, f) {
808        return f(v);
809      }, value);
810    };
811  },
812      unitize = function unitize(func, unit) {
813    return function (value) {
814      return func(parseFloat(value)) + (unit || getUnit(value));
815    };
816  },
817      normalize = function normalize(min, max, value) {
818    return mapRange(min, max, 0, 1, value);
819  },
820      _wrapArray = function _wrapArray(a, wrapper, value) {
821    return _conditionalReturn(value, function (index) {
822      return a[~~wrapper(index)];
823    });
824  },
825      wrap = function wrap(min, max, value) {
826    var range = max - min;
827    return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) {
828      return (range + (value - min) % range) % range + min;
829    });
830  },
831      wrapYoyo = function wrapYoyo(min, max, value) {
832    var range = max - min,
833        total = range * 2;
834    return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) {
835      value = (total + (value - min) % total) % total || 0;
836      return min + (value > range ? total - value : value);
837    });
838  },
839      _replaceRandom = function _replaceRandom(value) {
840    var prev = 0,
841        s = "",
842        i,
843        nums,
844        end,
845        isArray;
846
847    while (~(i = value.indexOf("random(", prev))) {
848      end = value.indexOf(")", i);
849      isArray = value.charAt(i + 7) === "[";
850      nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp);
851      s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5);
852      prev = end + 1;
853    }
854
855    return s + value.substr(prev, value.length - prev);
856  },
857      mapRange = function mapRange(inMin, inMax, outMin, outMax, value) {
858    var inRange = inMax - inMin,
859        outRange = outMax - outMin;
860    return _conditionalReturn(value, function (value) {
861      return outMin + ((value - inMin) / inRange * outRange || 0);
862    });
863  },
864      interpolate = function interpolate(start, end, progress, mutate) {
865    var func = isNaN(start + end) ? 0 : function (p) {
866      return (1 - p) * start + p * end;
867    };
868
869    if (!func) {
870      var isString = _isString(start),
871          master = {},
872          p,
873          i,
874          interpolators,
875          l,
876          il;
877
878      progress === true && (mutate = 1) && (progress = null);
879
880      if (isString) {
881        start = {
882          p: start
883        };
884        end = {
885          p: end
886        };
887      } else if (_isArray(start) && !_isArray(end)) {
888        interpolators = [];
889        l = start.length;
890        il = l - 2;
891
892        for (i = 1; i < l; i++) {
893          interpolators.push(interpolate(start[i - 1], start[i]));
894        }
895
896        l--;
897
898        func = function func(p) {
899          p *= l;
900          var i = Math.min(il, ~~p);
901          return interpolators[i](p - i);
902        };
903
904        progress = end;
905      } else if (!mutate) {
906        start = _merge(_isArray(start) ? [] : {}, start);
907      }
908
909      if (!interpolators) {
910        for (p in end) {
911          _addPropTween.call(master, start, p, "get", end[p]);
912        }
913
914        func = function func(p) {
915          return _renderPropTweens(p, master) || (isString ? start.p : start);
916        };
917      }
918    }
919
920    return _conditionalReturn(progress, func);
921  },
922      _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) {
923    var labels = timeline.labels,
924        min = _bigNum,
925        p,
926        distance,
927        label;
928
929    for (p in labels) {
930      distance = labels[p] - fromTime;
931
932      if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) {
933        label = p;
934        min = distance;
935      }
936    }
937
938    return label;
939  },
940      _callback = function _callback(animation, type, executeLazyFirst) {
941    var v = animation.vars,
942        callback = v[type],
943        prevContext = _context,
944        context = animation._ctx,
945        params,
946        scope,
947        result;
948
949    if (!callback) {
950      return;
951    }
952
953    params = v[type + "Params"];
954    scope = v.callbackScope || animation;
955    executeLazyFirst && _lazyTweens.length && _lazyRender();
956    context && (_context = context);
957    result = params ? callback.apply(scope, params) : callback.call(scope);
958    _context = prevContext;
959    return result;
960  },
vendor: 7,656 bytes, lines 961-1246
961      _interrupt = function _interrupt(animation) {
962    _removeFromParent(animation);
963
964    animation.scrollTrigger && animation.scrollTrigger.kill(!!_reverting);
965    animation.progress() < 1 && _callback(animation, "onInterrupt");
966    return animation;
967  },
968      _quickTween,
969      _createPlugin = function _createPlugin(config) {
970    config = !config.name && config["default"] || config;
971
972    var name = config.name,
973        isFunc = _isFunction(config),
974        Plugin = name && !isFunc && config.init ? function () {
975      this._props = [];
976    } : config,
977        instanceDefaults = {
978      init: _emptyFunc,
979      render: _renderPropTweens,
980      add: _addPropTween,
981      kill: _killPropTweensOf,
982      modifier: _addPluginModifier,
983      rawVars: 0
984    },
985        statics = {
986      targetTest: 0,
987      get: 0,
988      getSetter: _getSetter,
989      aliases: {},
990      register: 0
991    };
992
993    _wake();
994
995    if (config !== Plugin) {
996      if (_plugins[name]) {
997        return;
998      }
999
1000      _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics));
1001
1002      _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics)));
1003
1004      _plugins[Plugin.prop = name] = Plugin;
1005
1006      if (config.targetTest) {
1007        _harnessPlugins.push(Plugin);
1008
1009        _reservedProps[name] = 1;
1010      }
1011
1012      name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin";
1013    }
1014
1015    _addGlobal(name, Plugin);
1016
1017    config.register && config.register(gsap, Plugin, PropTween);
1018  },
1019      _255 = 255,
1020      _colorLookup = {
1021    aqua: [0, _255, _255],
1022    lime: [0, _255, 0],
1023    silver: [192, 192, 192],
1024    black: [0, 0, 0],
1025    maroon: [128, 0, 0],
1026    teal: [0, 128, 128],
1027    blue: [0, 0, _255],
1028    navy: [0, 0, 128],
1029    white: [_255, _255, _255],
1030    olive: [128, 128, 0],
1031    yellow: [_255, _255, 0],
1032    orange: [_255, 165, 0],
1033    gray: [128, 128, 128],
1034    purple: [128, 0, 128],
1035    green: [0, 128, 0],
1036    red: [_255, 0, 0],
1037    pink: [_255, 192, 203],
1038    cyan: [0, _255, _255],
1039    transparent: [_255, _255, _255, 0]
1040  },
1041      _hue = function _hue(h, m1, m2) {
1042    h += h < 0 ? 1 : h > 1 ? -1 : 0;
1043    return (h * 6 < 1 ? m1 + (m2 - m1) * h * 6 : h < .5 ? m2 : h * 3 < 2 ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * _255 + .5 | 0;
1044  },
1045      splitColor = function splitColor(v, toHSL, forceAlpha) {
1046    var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0,
1047        r,
1048        g,
1049        b,
1050        h,
1051        s,
1052        l,
1053        max,
1054        min,
1055        d,
1056        wasHSL;
1057
1058    if (!a) {
1059      if (v.substr(-1) === ",") {
1060        v = v.substr(0, v.length - 1);
1061      }
1062
1063      if (_colorLookup[v]) {
1064        a = _colorLookup[v];
1065      } else if (v.charAt(0) === "#") {
1066        if (v.length < 6) {
1067          r = v.charAt(1);
1068          g = v.charAt(2);
1069          b = v.charAt(3);
1070          v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : "");
1071        }
1072
1073        if (v.length === 9) {
1074          a = parseInt(v.substr(1, 6), 16);
1075          return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255];
1076        }
1077
1078        v = parseInt(v.substr(1), 16);
1079        a = [v >> 16, v >> 8 & _255, v & _255];
1080      } else if (v.substr(0, 3) === "hsl") {
1081        a = wasHSL = v.match(_strictNumExp);
1082
1083        if (!toHSL) {
1084          h = +a[0] % 360 / 360;
1085          s = +a[1] / 100;
1086          l = +a[2] / 100;
1087          g = l <= .5 ? l * (s + 1) : l + s - l * s;
1088          r = l * 2 - g;
1089          a.length > 3 && (a[3] *= 1);
1090          a[0] = _hue(h + 1 / 3, r, g);
1091          a[1] = _hue(h, r, g);
1092          a[2] = _hue(h - 1 / 3, r, g);
1093        } else if (~v.indexOf("=")) {
1094          a = v.match(_numExp);
1095          forceAlpha && a.length < 4 && (a[3] = 1);
1096          return a;
1097        }
1098      } else {
1099        a = v.match(_strictNumExp) || _colorLookup.transparent;
1100      }
1101
1102      a = a.map(Number);
1103    }
1104
1105    if (toHSL && !wasHSL) {
1106      r = a[0] / _255;
1107      g = a[1] / _255;
1108      b = a[2] / _255;
1109      max = Math.max(r, g, b);
1110      min = Math.min(r, g, b);
1111      l = (max + min) / 2;
1112
1113      if (max === min) {
1114        h = s = 0;
1115      } else {
1116        d = max - min;
1117        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
1118        h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
1119        h *= 60;
1120      }
1121
1122      a[0] = ~~(h + .5);
1123      a[1] = ~~(s * 100 + .5);
1124      a[2] = ~~(l * 100 + .5);
1125    }
1126
1127    forceAlpha && a.length < 4 && (a[3] = 1);
1128    return a;
1129  },
1130      _colorOrderData = function _colorOrderData(v) {
1131    var values = [],
1132        c = [],
1133        i = -1;
1134    v.split(_colorExp).forEach(function (v) {
1135      var a = v.match(_numWithUnitExp) || [];
1136      values.push.apply(values, a);
1137      c.push(i += a.length + 1);
1138    });
1139    values.c = c;
1140    return values;
1141  },
1142      _formatColors = function _formatColors(s, toHSL, orderMatchData) {
1143    var result = "",
1144        colors = (s + result).match(_colorExp),
1145        type = toHSL ? "hsla(" : "rgba(",
1146        i = 0,
1147        c,
1148        shell,
1149        d,
1150        l;
1151
1152    if (!colors) {
1153      return s;
1154    }
1155
1156    colors = colors.map(function (color) {
1157      return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")";
1158    });
1159
1160    if (orderMatchData) {
1161      d = _colorOrderData(s);
1162      c = orderMatchData.c;
1163
1164      if (c.join(result) !== d.c.join(result)) {
1165        shell = s.replace(_colorExp, "1").split(_numWithUnitExp);
1166        l = shell.length - 1;
1167
1168        for (; i < l; i++) {
1169          result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift());
1170        }
1171      }
1172    }
1173
1174    if (!shell) {
1175      shell = s.split(_colorExp);
1176      l = shell.length - 1;
1177
1178      for (; i < l; i++) {
1179        result += shell[i] + colors[i];
1180      }
1181    }
1182
1183    return result + shell[l];
1184  },
1185      _colorExp = function () {
1186    var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b",
1187        p;
1188
1189    for (p in _colorLookup) {
1190      s += "|" + p + "\\b";
1191    }
1192
1193    return new RegExp(s + ")", "gi");
1194  }(),
1195      _hslExp = /hsl[a]?\(/,
1196      _colorStringFilter = function _colorStringFilter(a) {
1197    var combined = a.join(" "),
1198        toHSL;
1199    _colorExp.lastIndex = 0;
1200
1201    if (_colorExp.test(combined)) {
1202      toHSL = _hslExp.test(combined);
1203      a[1] = _formatColors(a[1], toHSL);
1204      a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1]));
1205      return true;
1206    }
1207  },
1208      _tickerActive,
1209      _ticker = function () {
1210    var _getTime = Date.now,
1211        _lagThreshold = 500,
1212        _adjustedLag = 33,
1213        _startTime = _getTime(),
1214        _lastUpdate = _startTime,
1215        _gap = 1000 / 240,
1216        _nextTime = _gap,
1217        _listeners = [],
1218        _id,
1219        _req,
1220        _raf,
1221        _self,
1222        _delta,
1223        _i,
1224        _tick = function _tick(v) {
1225      var elapsed = _getTime() - _lastUpdate,
1226          manual = v === true,
1227          overlap,
1228          dispatch,
1229          time,
1230          frame;
1231
1232      elapsed > _lagThreshold && (_startTime += elapsed - _adjustedLag);
1233      _lastUpdate += elapsed;
1234      time = _lastUpdate - _startTime;
1235      overlap = time - _nextTime;
1236
1237      if (overlap > 0 || manual) {
1238        frame = ++_self.frame;
1239        _delta = time - _self.time * 1000;
1240        _self.time = time = time / 1000;
1241        _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap);
1242        dispatch = 1;
1243      }
1244
1245      manual || (_id = _req(_tick));
1246
vendor: 4,239 bytes, lines 1247-1383
1247      if (dispatch) {
1248        for (_i = 0; _i < _listeners.length; _i++) {
1249          _listeners[_i](time, _delta, frame, v);
1250        }
1251      }
1252    };
1253
1254    _self = {
1255      time: 0,
1256      frame: 0,
1257      tick: function tick() {
1258        _tick(true);
1259      },
1260      deltaRatio: function deltaRatio(fps) {
1261        return _delta / (1000 / (fps || 60));
1262      },
1263      wake: function wake() {
1264        if (_coreReady) {
1265          if (!_coreInitted && _windowExists()) {
1266            _win = _coreInitted = window;
1267            _doc = _win.document || {};
1268            _globals.gsap = gsap;
1269            (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version);
1270
1271            _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {});
1272
1273            _raf = _win.requestAnimationFrame;
1274          }
1275
1276          _id && _self.sleep();
1277
1278          _req = _raf || function (f) {
1279            return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0);
1280          };
1281
1282          _tickerActive = 1;
1283
1284          _tick(2);
1285        }
1286      },
1287      sleep: function sleep() {
1288        (_raf ? _win.cancelAnimationFrame : clearTimeout)(_id);
1289        _tickerActive = 0;
1290        _req = _emptyFunc;
1291      },
1292      lagSmoothing: function lagSmoothing(threshold, adjustedLag) {
1293        _lagThreshold = threshold || 1 / _tinyNum;
1294        _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0);
1295      },
1296      fps: function fps(_fps) {
1297        _gap = 1000 / (_fps || 240);
1298        _nextTime = _self.time * 1000 + _gap;
1299      },
1300      add: function add(callback, once, prioritize) {
1301        var func = once ? function (t, d, f, v) {
1302          callback(t, d, f, v);
1303
1304          _self.remove(func);
1305        } : callback;
1306
1307        _self.remove(callback);
1308
1309        _listeners[prioritize ? "unshift" : "push"](func);
1310
1311        _wake();
1312
1313        return func;
1314      },
1315      remove: function remove(callback, i) {
1316        ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--;
1317      },
1318      _listeners: _listeners
1319    };
1320    return _self;
1321  }(),
1322      _wake = function _wake() {
1323    return !_tickerActive && _ticker.wake();
1324  },
1325      _easeMap = {},
1326      _customEaseExp = /^[\d.\-M][\d.\-,\s]/,
1327      _quotesExp = /["']/g,
1328      _parseObjectInString = function _parseObjectInString(value) {
1329    var obj = {},
1330        split = value.substr(1, value.length - 3).split(":"),
1331        key = split[0],
1332        i = 1,
1333        l = split.length,
1334        index,
1335        val,
1336        parsedVal;
1337
1338    for (; i < l; i++) {
1339      val = split[i];
1340      index = i !== l - 1 ? val.lastIndexOf(",") : val.length;
1341      parsedVal = val.substr(0, index);
1342      obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal;
1343      key = val.substr(index + 1).trim();
1344    }
1345
1346    return obj;
1347  },
1348      _valueInParentheses = function _valueInParentheses(value) {
1349    var open = value.indexOf("(") + 1,
1350        close = value.indexOf(")"),
1351        nested = value.indexOf("(", open);
1352    return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close);
1353  },
1354      _configEaseFromString = function _configEaseFromString(name) {
1355    var split = (name + "").split("("),
1356        ease = _easeMap[split[0]];
1357    return ease && split.length > 1 && ease.config ? ease.config.apply(null, ~name.indexOf("{") ? [_parseObjectInString(split[1])] : _valueInParentheses(name).split(",").map(_numericIfPossible)) : _easeMap._CE && _customEaseExp.test(name) ? _easeMap._CE("", name) : ease;
1358  },
1359      _invertEase = function _invertEase(ease) {
1360    return function (p) {
1361      return 1 - ease(1 - p);
1362    };
1363  },
1364      _propagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) {
1365    var child = timeline._first,
1366        ease;
1367
1368    while (child) {
1369      if (child instanceof Timeline) {
1370        _propagateYoyoEase(child, isYoyo);
1371      } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) {
1372        if (child.timeline) {
1373          _propagateYoyoEase(child.timeline, isYoyo);
1374        } else {
1375          ease = child._ease;
1376          child._ease = child._yEase;
1377          child._yEase = ease;
1378          child._yoyo = isYoyo;
1379        }
1380      }
1381
1382      child = child._next;
1383    }
vendor: 3,445 bytes, lines 1383-1494
1383
1384  },
1385      _parseEase = function _parseEase(ease, defaultEase) {
1386    return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase;
1387  },
1388      _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) {
1389    if (easeOut === void 0) {
1390      easeOut = function easeOut(p) {
1391        return 1 - easeIn(1 - p);
1392      };
1393    }
1394
1395    if (easeInOut === void 0) {
1396      easeInOut = function easeInOut(p) {
1397        return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2;
1398      };
1399    }
1400
1401    var ease = {
1402      easeIn: easeIn,
1403      easeOut: easeOut,
1404      easeInOut: easeInOut
1405    },
1406        lowercaseName;
1407
1408    _forEachName(names, function (name) {
1409      _easeMap[name] = _globals[name] = ease;
1410      _easeMap[lowercaseName = name.toLowerCase()] = easeOut;
1411
1412      for (var p in ease) {
1413        _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p];
1414      }
1415    });
1416
1417    return ease;
1418  },
1419      _easeInOutFromOut = function _easeInOutFromOut(easeOut) {
1420    return function (p) {
1421      return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2;
1422    };
1423  },
1424      _configElastic = function _configElastic(type, amplitude, period) {
1425    var p1 = amplitude >= 1 ? amplitude : 1,
1426        p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1),
1427        p3 = p2 / _2PI * (Math.asin(1 / p1) || 0),
1428        easeOut = function easeOut(p) {
1429      return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1;
1430    },
1431        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1432      return 1 - easeOut(1 - p);
1433    } : _easeInOutFromOut(easeOut);
1434
1435    p2 = _2PI / p2;
1436
1437    ease.config = function (amplitude, period) {
1438      return _configElastic(type, amplitude, period);
1439    };
1440
1441    return ease;
1442  },
1443      _configBack = function _configBack(type, overshoot) {
1444    if (overshoot === void 0) {
1445      overshoot = 1.70158;
1446    }
1447
1448    var easeOut = function easeOut(p) {
1449      return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0;
1450    },
1451        ease = type === "out" ? easeOut : type === "in" ? function (p) {
1452      return 1 - easeOut(1 - p);
1453    } : _easeInOutFromOut(easeOut);
1454
1455    ease.config = function (overshoot) {
1456      return _configBack(type, overshoot);
1457    };
1458
1459    return ease;
1460  };
1461
1462  _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) {
1463    var power = i < 5 ? i + 1 : i;
1464
1465    _insertEase(name + ",Power" + (power - 1), i ? function (p) {
1466      return Math.pow(p, power);
1467    } : function (p) {
1468      return p;
1469    }, function (p) {
1470      return 1 - Math.pow(1 - p, power);
1471    }, function (p) {
1472      return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2;
1473    });
1474  });
1475
1476  _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn;
1477
1478  _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic());
1479
1480  (function (n, c) {
1481    var n1 = 1 / c,
1482        n2 = 2 * n1,
1483        n3 = 2.5 * n1,
1484        easeOut = function easeOut(p) {
1485      return p < n1 ? n * p * p : p < n2 ? n * Math.pow(p - 1.5 / c, 2) + .75 : p < n3 ? n * (p -= 2.25 / c) * p + .9375 : n * Math.pow(p - 2.625 / c, 2) + .984375;
1486    };
1487
1488    _insertEase("Bounce", function (p) {
1489      return 1 - easeOut(1 - p);
1490    }, easeOut);
1491  })(7.5625, 2.75);
1492
1493  _insertEase("Expo", function (p) {
1494    return 
vendor: 6,314 bytes, lines 1494-1684
1494p ? Math.pow(2, 10 * (p - 1)) : 0;
1495  });
1496
1497  _insertEase("Circ", function (p) {
1498    return -(_sqrt(1 - p * p) - 1);
1499  });
1500
1501  _insertEase("Sine", function (p) {
1502    return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1;
1503  });
1504
1505  _insertEase("Back", _configBack("in"), _configBack("out"), _configBack());
1506
1507  _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = {
1508    config: function config(steps, immediateStart) {
1509      if (steps === void 0) {
1510        steps = 1;
1511      }
1512
1513      var p1 = 1 / steps,
1514          p2 = steps + (immediateStart ? 0 : 1),
1515          p3 = immediateStart ? 1 : 0,
1516          max = 1 - _tinyNum;
1517      return function (p) {
1518        return ((p2 * _clamp(0, max, p) | 0) + p3) * p1;
1519      };
1520    }
1521  };
1522  _defaults.ease = _easeMap["quad.out"];
1523
1524  _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) {
1525    return _callbackNames += name + "," + name + "Params,";
1526  });
1527
1528  var GSCache = function GSCache(target, harness) {
1529    this.id = _gsID++;
1530    target._gsap = this;
1531    this.target = target;
1532    this.harness = harness;
1533    this.get = harness ? harness.get : _getProperty;
1534    this.set = harness ? harness.getSetter : _getSetter;
1535  };
1536  var Animation = function () {
1537    function Animation(vars) {
1538      this.vars = vars;
1539      this._delay = +vars.delay || 0;
1540
1541      if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) {
1542        this._rDelay = vars.repeatDelay || 0;
1543        this._yoyo = !!vars.yoyo || !!vars.yoyoEase;
1544      }
1545
1546      this._ts = 1;
1547
1548      _setDuration(this, +vars.duration, 1, 1);
1549
1550      this.data = vars.data;
1551
1552      if (_context) {
1553        this._ctx = _context;
1554
1555        _context.data.push(this);
1556      }
1557
1558      _tickerActive || _ticker.wake();
1559    }
1560
1561    var _proto = Animation.prototype;
1562
1563    _proto.delay = function delay(value) {
1564      if (value || value === 0) {
1565        this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay);
1566        this._delay = value;
1567        return this;
1568      }
1569
1570      return this._delay;
1571    };
1572
1573    _proto.duration = function duration(value) {
1574      return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur;
1575    };
1576
1577    _proto.totalDuration = function totalDuration(value) {
1578      if (!arguments.length) {
1579        return this._tDur;
1580      }
1581
1582      this._dirty = 0;
1583      return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1));
1584    };
1585
1586    _proto.totalTime = function totalTime(_totalTime, suppressEvents) {
1587      _wake();
1588
1589      if (!arguments.length) {
1590        return this._tTime;
1591      }
1592
1593      var parent = this._dp;
1594
1595      if (parent && parent.smoothChildTiming && this._ts) {
1596        _alignPlayhead(this, _totalTime);
1597
1598        !parent._dp || parent.parent || _postAddChecks(parent, this);
1599
1600        while (parent && parent.parent) {
1601          if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) {
1602            parent.totalTime(parent._tTime, true);
1603          }
1604
1605          parent = parent.parent;
1606        }
1607
1608        if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) {
1609          _addToTimeline(this._dp, this, this._start - this._delay);
1610        }
1611      }
1612
1613      if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) {
1614        this._ts || (this._pTime = _totalTime);
1615
1616        _lazySafeRender(this, _totalTime, suppressEvents);
1617      }
1618
1619      return this;
1620    };
1621
1622    _proto.time = function time(value, suppressEvents) {
1623      return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % (this._dur + this._rDelay) || (value ? this._dur : 0), suppressEvents) : this._time;
1624    };
1625
1626    _proto.totalProgress = function totalProgress(value, suppressEvents) {
1627      return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.ratio;
1628    };
1629
1630    _proto.progress = function progress(value, suppressEvents) {
1631      return arguments.length ? this.totalTime(this.duration() * (this._yoyo && !(this.iteration() & 1) ? 1 - value : value) + _elapsedCycleDuration(this), suppressEvents) : this.duration() ? Math.min(1, this._time / this._dur) : this.ratio;
1632    };
1633
1634    _proto.iteration = function iteration(value, suppressEvents) {
1635      var cycleDuration = this.duration() + this._rDelay;
1636
1637      return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1;
1638    };
1639
1640    _proto.timeScale = function timeScale(value) {
1641      if (!arguments.length) {
1642        return this._rts === -_tinyNum ? 0 : this._rts;
1643      }
1644
1645      if (this._rts === value) {
1646        return this;
1647      }
1648
1649      var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime;
1650      this._rts = +value || 0;
1651      this._ts = this._ps || value === -_tinyNum ? 0 : this._rts;
1652      this.totalTime(_clamp(-this._delay, this._tDur, tTime), true);
1653
1654      _setEnd(this);
1655
1656      return _recacheAncestors(this);
1657    };
1658
1659    _proto.paused = function paused(value) {
1660      if (!arguments.length) {
1661        return this._ps;
1662      }
1663
1664      if (this._ps !== value) {
1665        this._ps = value;
1666
1667        if (value) {
1668          this._pTime = this._tTime || Math.max(-this._delay, this.rawTime());
1669          this._ts = this._act = 0;
1670        } else {
1671          _wake();
1672
1673          this._ts = this._rts;
1674          this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && Math.abs(this._zTime) !== _tinyNum && (this._tTime -= _tinyNum));
1675        }
1676      }
1677
1678      return this;
1679    };
1680
1681    _proto.startTime = function startTime(value) {
1682      if (arguments.length) {
1683        this._start = value;
1684        var parent = this.parent || this._dp;
vendor: 3,424 bytes, lines 1685-1797
1685        parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay);
1686        return this;
1687      }
1688
1689      return this._start;
1690    };
1691
1692    _proto.endTime = function endTime(includeRepeats) {
1693      return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts || 1);
1694    };
1695
1696    _proto.rawTime = function rawTime(wrapRepeats) {
1697      var parent = this.parent || this._dp;
1698      return !parent ? this._tTime : wrapRepeats && (!this._ts || this._repeat && this._time && this.totalProgress() < 1) ? this._tTime % (this._dur + this._rDelay) : !this._ts ? this._tTime : _parentToChildTotalTime(parent.rawTime(wrapRepeats), this);
1699    };
1700
1701    _proto.revert = function revert(config) {
1702      if (config === void 0) {
1703        config = _revertConfig;
1704      }
1705
1706      var prevIsReverting = _reverting;
1707      _reverting = config;
1708
1709      if (this._initted || this._startAt) {
1710        this.timeline && this.timeline.revert(config);
1711        this.totalTime(-0.01, config.suppressEvents);
1712      }
1713
1714      this.data !== "nested" && config.kill !== false && this.kill();
1715      _reverting = prevIsReverting;
1716      return this;
1717    };
1718
1719    _proto.globalTime = function globalTime(rawTime) {
1720      var animation = this,
1721          time = arguments.length ? rawTime : animation.rawTime();
1722
1723      while (animation) {
1724        time = animation._start + time / (animation._ts || 1);
1725        animation = animation._dp;
1726      }
1727
1728      return !this.parent && this.vars.immediateRender ? -1 : time;
1729    };
1730
1731    _proto.repeat = function repeat(value) {
1732      if (arguments.length) {
1733        this._repeat = value === Infinity ? -2 : value;
1734        return _onUpdateTotalDuration(this);
1735      }
1736
1737      return this._repeat === -2 ? Infinity : this._repeat;
1738    };
1739
1740    _proto.repeatDelay = function repeatDelay(value) {
1741      if (arguments.length) {
1742        var time = this._time;
1743        this._rDelay = value;
1744
1745        _onUpdateTotalDuration(this);
1746
1747        return time ? this.time(time) : this;
1748      }
1749
1750      return this._rDelay;
1751    };
1752
1753    _proto.yoyo = function yoyo(value) {
1754      if (arguments.length) {
1755        this._yoyo = value;
1756        return this;
1757      }
1758
1759      return this._yoyo;
1760    };
1761
1762    _proto.seek = function seek(position, suppressEvents) {
1763      return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents));
1764    };
1765
1766    _proto.restart = function restart(includeDelay, suppressEvents) {
1767      return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents));
1768    };
1769
1770    _proto.play = function play(from, suppressEvents) {
1771      from != null && this.seek(from, suppressEvents);
1772      return this.reversed(false).paused(false);
1773    };
1774
1775    _proto.reverse = function reverse(from, suppressEvents) {
1776      from != null && this.seek(from || this.totalDuration(), suppressEvents);
1777      return this.reversed(true).paused(false);
1778    };
1779
1780    _proto.pause = function pause(atTime, suppressEvents) {
1781      atTime != null && this.seek(atTime, suppressEvents);
1782      return this.paused(true);
1783    };
1784
1785    _proto.resume = function resume() {
1786      return this.paused(false);
1787    };
1788
1789    _proto.reversed = function reversed(value) {
1790      if (arguments.length) {
1791        !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0));
1792        return this;
1793      }
1794
1795      return this._rts < 0;
1796    };
1797
vendor: 8,586 bytes, lines 1798-2069
1798    _proto.invalidate = function invalidate() {
1799      this._initted = this._act = 0;
1800      this._zTime = -_tinyNum;
1801      return this;
1802    };
1803
1804    _proto.isActive = function isActive() {
1805      var parent = this.parent || this._dp,
1806          start = this._start,
1807          rawTime;
1808      return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum);
1809    };
1810
1811    _proto.eventCallback = function eventCallback(type, callback, params) {
1812      var vars = this.vars;
1813
1814      if (arguments.length > 1) {
1815        if (!callback) {
1816          delete vars[type];
1817        } else {
1818          vars[type] = callback;
1819          params && (vars[type + "Params"] = params);
1820          type === "onUpdate" && (this._onUpdate = callback);
1821        }
1822
1823        return this;
1824      }
1825
1826      return vars[type];
1827    };
1828
1829    _proto.then = function then(onFulfilled) {
1830      var self = this;
1831      return new Promise(function (resolve) {
1832        var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough,
1833            _resolve = function _resolve() {
1834          var _then = self.then;
1835          self.then = null;
1836          _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then);
1837          resolve(f);
1838          self.then = _then;
1839        };
1840
1841        if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) {
1842          _resolve();
1843        } else {
1844          self._prom = _resolve;
1845        }
1846      });
1847    };
1848
1849    _proto.kill = function kill() {
1850      _interrupt(this);
1851    };
1852
1853    return Animation;
1854  }();
1855
1856  _setDefaults(Animation.prototype, {
1857    _time: 0,
1858    _start: 0,
1859    _end: 0,
1860    _tTime: 0,
1861    _tDur: 0,
1862    _dirty: 0,
1863    _repeat: 0,
1864    _yoyo: false,
1865    parent: null,
1866    _initted: false,
1867    _rDelay: 0,
1868    _ts: 1,
1869    _dp: 0,
1870    ratio: 0,
1871    _zTime: -_tinyNum,
1872    _prom: 0,
1873    _ps: false,
1874    _rts: 1
1875  });
1876
1877  var Timeline = function (_Animation) {
1878    _inheritsLoose(Timeline, _Animation);
1879
1880    function Timeline(vars, position) {
1881      var _this;
1882
1883      if (vars === void 0) {
1884        vars = {};
1885      }
1886
1887      _this = _Animation.call(this, vars) || this;
1888      _this.labels = {};
1889      _this.smoothChildTiming = !!vars.smoothChildTiming;
1890      _this.autoRemoveChildren = !!vars.autoRemoveChildren;
1891      _this._sort = _isNotFalse(vars.sortChildren);
1892      _globalTimeline && _addToTimeline(vars.parent || _globalTimeline, _assertThisInitialized(_this), position);
1893      vars.reversed && _this.reverse();
1894      vars.paused && _this.paused(true);
1895      vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger);
1896      return _this;
1897    }
1898
1899    var _proto2 = Timeline.prototype;
1900
1901    _proto2.to = function to(targets, vars, position) {
1902      _createTweenType(0, arguments, this);
1903
1904      return this;
1905    };
1906
1907    _proto2.from = function from(targets, vars, position) {
1908      _createTweenType(1, arguments, this);
1909
1910      return this;
1911    };
1912
1913    _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) {
1914      _createTweenType(2, arguments, this);
1915
1916      return this;
1917    };
1918
1919    _proto2.set = function set(targets, vars, position) {
1920      vars.duration = 0;
1921      vars.parent = this;
1922      _inheritDefaults(vars).repeatDelay || (vars.repeat = 0);
1923      vars.immediateRender = !!vars.immediateRender;
1924      new Tween(targets, vars, _parsePosition(this, position), 1);
1925      return this;
1926    };
1927
1928    _proto2.call = function call(callback, params, position) {
1929      return _addToTimeline(this, Tween.delayedCall(0, callback, params), position);
1930    };
1931
1932    _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1933      vars.duration = duration;
1934      vars.stagger = vars.stagger || stagger;
1935      vars.onComplete = onCompleteAll;
1936      vars.onCompleteParams = onCompleteAllParams;
1937      vars.parent = this;
1938      new Tween(targets, vars, _parsePosition(this, position));
1939      return this;
1940    };
1941
1942    _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) {
1943      vars.runBackwards = 1;
1944      _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender);
1945      return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams);
1946    };
1947
1948    _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) {
1949      toVars.startAt = fromVars;
1950      _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender);
1951      return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams);
1952    };
1953
1954    _proto2.render = function render(totalTime, suppressEvents, force) {
1955      var prevTime = this._time,
1956          tDur = this._dirty ? this.totalDuration() : this._tDur,
1957          dur = this._dur,
1958          tTime = totalTime <= 0 ? 0 : _roundPrecise(totalTime),
1959          crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur),
1960          time,
1961          child,
1962          next,
1963          iteration,
1964          cycleDuration,
1965          prevPaused,
1966          pauseTween,
1967          timeScale,
1968          prevStart,
1969          prevIteration,
1970          yoyo,
1971          isYoyo;
1972      this !== _globalTimeline && tTime > tDur && totalTime >= 0 && (tTime = tDur);
1973
1974      if (tTime !== this._tTime || force || crossingStart) {
1975        if (prevTime !== this._time && dur) {
1976          tTime += this._time - prevTime;
1977          totalTime += this._time - prevTime;
1978        }
1979
1980        time = tTime;
1981        prevStart = this._start;
1982        timeScale = this._ts;
1983        prevPaused = !timeScale;
1984
1985        if (crossingStart) {
1986          dur || (prevTime = this._zTime);
1987          (totalTime || !suppressEvents) && (this._zTime = totalTime);
1988        }
1989
1990        if (this._repeat) {
1991          yoyo = this._yoyo;
1992          cycleDuration = dur + this._rDelay;
1993
1994          if (this._repeat < -1 && totalTime < 0) {
1995            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
1996          }
1997
1998          time = _roundPrecise(tTime % cycleDuration);
1999
2000          if (tTime === tDur) {
2001            iteration = this._repeat;
2002            time = dur;
2003          } else {
2004            iteration = ~~(tTime / cycleDuration);
2005
2006            if (iteration && iteration === tTime / cycleDuration) {
2007              time = dur;
2008              iteration--;
2009            }
2010
2011            time > dur && (time = dur);
2012          }
2013
2014          prevIteration = _animationCycle(this._tTime, cycleDuration);
2015          !prevTime && this._tTime && prevIteration !== iteration && (prevIteration = iteration);
2016
2017          if (yoyo && iteration & 1) {
2018            time = dur - time;
2019            isYoyo = 1;
2020          }
2021
2022          if (iteration !== prevIteration && !this._lock) {
2023            var rewinding = yoyo && prevIteration & 1,
2024                doesWrap = rewinding === (yoyo && iteration & 1);
2025            iteration < prevIteration && (rewinding = !rewinding);
2026            prevTime = rewinding ? 0 : dur;
2027            this._lock = 1;
2028            this.render(prevTime || (isYoyo ? 0 : _roundPrecise(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0;
2029            this._tTime = tTime;
2030            !suppressEvents && this.parent && _callback(this, "onRepeat");
2031            this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1);
2032
2033            if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) {
2034              return this;
2035            }
2036
2037            dur = this._dur;
2038            tDur = this._tDur;
2039
2040            if (doesWrap) {
2041              this._lock = 2;
2042              prevTime = rewinding ? dur : -0.0001;
2043              this.render(prevTime, true);
2044              this.vars.repeatRefresh && !isYoyo && this.invalidate();
2045            }
2046
2047            this._lock = 0;
2048
2049            if (!this._ts && !prevPaused) {
2050              return this;
2051            }
2052
2053            _propagateYoyoEase(this, isYoyo);
2054          }
2055        }
2056
2057        if (this._hasPause && !this._forcing && this._lock < 2) {
2058          pauseTween = _findNextPauseTween(this, _roundPrecise(prevTime), _roundPrecise(time));
2059
2060          if (pauseTween) {
2061            tTime -= time - (time = pauseTween._start);
2062          }
2063        }
2064
2065        this._tTime = tTime;
2066        this._time = time;
2067        this._act = !timeScale;
2068
2069        if (!this._initted) {
vendor: 15,188 bytes, lines 2070-2602
2070          this._onUpdate = this.vars.onUpdate;
2071          this._initted = 1;
2072          this._zTime = totalTime;
2073          prevTime = 0;
2074        }
2075
2076        if (!prevTime && time && !suppressEvents) {
2077          _callback(this, "onStart");
2078
2079          if (this._tTime !== tTime) {
2080            return this;
2081          }
2082        }
2083
2084        if (time >= prevTime && totalTime >= 0) {
2085          child = this._first;
2086
2087          while (child) {
2088            next = child._next;
2089
2090            if ((child._act || time >= child._start) && child._ts && pauseTween !== child) {
2091              if (child.parent !== this) {
2092                return this.render(totalTime, suppressEvents, force);
2093              }
2094
2095              child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force);
2096
2097              if (time !== this._time || !this._ts && !prevPaused) {
2098                pauseTween = 0;
2099                next && (tTime += this._zTime = -_tinyNum);
2100                break;
2101              }
2102            }
2103
2104            child = next;
2105          }
2106        } else {
2107          child = this._last;
2108          var adjustedTime = totalTime < 0 ? totalTime : time;
2109
2110          while (child) {
2111            next = child._prev;
2112
2113            if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) {
2114              if (child.parent !== this) {
2115                return this.render(totalTime, suppressEvents, force);
2116              }
2117
2118              child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force || _reverting && (child._initted || child._startAt));
2119
2120              if (time !== this._time || !this._ts && !prevPaused) {
2121                pauseTween = 0;
2122                next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum);
2123                break;
2124              }
2125            }
2126
2127            child = next;
2128          }
2129        }
2130
2131        if (pauseTween && !suppressEvents) {
2132          this.pause();
2133          pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1;
2134
2135          if (this._ts) {
2136            this._start = prevStart;
2137
2138            _setEnd(this);
2139
2140            return this.render(totalTime, suppressEvents, force);
2141          }
2142        }
2143
2144        this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true);
2145        if (tTime === tDur && this._tTime >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) {
2146          (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
2147
2148          if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime || !tDur)) {
2149            _callback(this, tTime === tDur && totalTime >= 0 ? "onComplete" : "onReverseComplete", true);
2150
2151            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
2152          }
2153        }
2154      }
2155
2156      return this;
2157    };
2158
2159    _proto2.add = function add(child, position) {
2160      var _this2 = this;
2161
2162      _isNumber(position) || (position = _parsePosition(this, position, child));
2163
2164      if (!(child instanceof Animation)) {
2165        if (_isArray(child)) {
2166          child.forEach(function (obj) {
2167            return _this2.add(obj, position);
2168          });
2169          return this;
2170        }
2171
2172        if (_isString(child)) {
2173          return this.addLabel(child, position);
2174        }
2175
2176        if (_isFunction(child)) {
2177          child = Tween.delayedCall(0, child);
2178        } else {
2179          return this;
2180        }
2181      }
2182
2183      return this !== child ? _addToTimeline(this, child, position) : this;
2184    };
2185
2186    _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) {
2187      if (nested === void 0) {
2188        nested = true;
2189      }
2190
2191      if (tweens === void 0) {
2192        tweens = true;
2193      }
2194
2195      if (timelines === void 0) {
2196        timelines = true;
2197      }
2198
2199      if (ignoreBeforeTime === void 0) {
2200        ignoreBeforeTime = -_bigNum;
2201      }
2202
2203      var a = [],
2204          child = this._first;
2205
2206      while (child) {
2207        if (child._start >= ignoreBeforeTime) {
2208          if (child instanceof Tween) {
2209            tweens && a.push(child);
2210          } else {
2211            timelines && a.push(child);
2212            nested && a.push.apply(a, child.getChildren(true, tweens, timelines));
2213          }
2214        }
2215
2216        child = child._next;
2217      }
2218
2219      return a;
2220    };
2221
2222    _proto2.getById = function getById(id) {
2223      var animations = this.getChildren(1, 1, 1),
2224          i = animations.length;
2225
2226      while (i--) {
2227        if (animations[i].vars.id === id) {
2228          return animations[i];
2229        }
2230      }
2231    };
2232
2233    _proto2.remove = function remove(child) {
2234      if (_isString(child)) {
2235        return this.removeLabel(child);
2236      }
2237
2238      if (_isFunction(child)) {
2239        return this.killTweensOf(child);
2240      }
2241
2242      _removeLinkedListItem(this, child);
2243
2244      if (child === this._recent) {
2245        this._recent = this._last;
2246      }
2247
2248      return _uncache(this);
2249    };
2250
2251    _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) {
2252      if (!arguments.length) {
2253        return this._tTime;
2254      }
2255
2256      this._forcing = 1;
2257
2258      if (!this._dp && this._ts) {
2259        this._start = _roundPrecise(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts));
2260      }
2261
2262      _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents);
2263
2264      this._forcing = 0;
2265      return this;
2266    };
2267
2268    _proto2.addLabel = function addLabel(label, position) {
2269      this.labels[label] = _parsePosition(this, position);
2270      return this;
2271    };
2272
2273    _proto2.removeLabel = function removeLabel(label) {
2274      delete this.labels[label];
2275      return this;
2276    };
2277
2278    _proto2.addPause = function addPause(position, callback, params) {
2279      var t = Tween.delayedCall(0, callback || _emptyFunc, params);
2280      t.data = "isPause";
2281      this._hasPause = 1;
2282      return _addToTimeline(this, t, _parsePosition(this, position));
2283    };
2284
2285    _proto2.removePause = function removePause(position) {
2286      var child = this._first;
2287      position = _parsePosition(this, position);
2288
2289      while (child) {
2290        if (child._start === position && child.data === "isPause") {
2291          _removeFromParent(child);
2292        }
2293
2294        child = child._next;
2295      }
2296    };
2297
2298    _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) {
2299      var tweens = this.getTweensOf(targets, onlyActive),
2300          i = tweens.length;
2301
2302      while (i--) {
2303        _overwritingTween !== tweens[i] && tweens[i].kill(targets, props);
2304      }
2305
2306      return this;
2307    };
2308
2309    _proto2.getTweensOf = function getTweensOf(targets, onlyActive) {
2310      var a = [],
2311          parsedTargets = toArray(targets),
2312          child = this._first,
2313          isGlobalTime = _isNumber(onlyActive),
2314          children;
2315
2316      while (child) {
2317        if (child instanceof Tween) {
2318          if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) {
2319            a.push(child);
2320          }
2321        } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) {
2322          a.push.apply(a, children);
2323        }
2324
2325        child = child._next;
2326      }
2327
2328      return a;
2329    };
2330
2331    _proto2.tweenTo = function tweenTo(position, vars) {
2332      vars = vars || {};
2333
2334      var tl = this,
2335          endTime = _parsePosition(tl, position),
2336          _vars = vars,
2337          startAt = _vars.startAt,
2338          _onStart = _vars.onStart,
2339          onStartParams = _vars.onStartParams,
2340          immediateRender = _vars.immediateRender,
2341          initted,
2342          tween = Tween.to(tl, _setDefaults({
2343        ease: vars.ease || "none",
2344        lazy: false,
2345        immediateRender: false,
2346        time: endTime,
2347        overwrite: "auto",
2348        duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum,
2349        onStart: function onStart() {
2350          tl.pause();
2351
2352          if (!initted) {
2353            var duration = vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale());
2354            tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true);
2355            initted = 1;
2356          }
2357
2358          _onStart && _onStart.apply(tween, onStartParams || []);
2359        }
2360      }, vars));
2361
2362      return immediateRender ? tween.render(0) : tween;
2363    };
2364
2365    _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) {
2366      return this.tweenTo(toPosition, _setDefaults({
2367        startAt: {
2368          time: _parsePosition(this, fromPosition)
2369        }
2370      }, vars));
2371    };
2372
2373    _proto2.recent = function recent() {
2374      return this._recent;
2375    };
2376
2377    _proto2.nextLabel = function nextLabel(afterTime) {
2378      if (afterTime === void 0) {
2379        afterTime = this._time;
2380      }
2381
2382      return _getLabelInDirection(this, _parsePosition(this, afterTime));
2383    };
2384
2385    _proto2.previousLabel = function previousLabel(beforeTime) {
2386      if (beforeTime === void 0) {
2387        beforeTime = this._time;
2388      }
2389
2390      return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1);
2391    };
2392
2393    _proto2.currentLabel = function currentLabel(value) {
2394      return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum);
2395    };
2396
2397    _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) {
2398      if (ignoreBeforeTime === void 0) {
2399        ignoreBeforeTime = 0;
2400      }
2401
2402      var child = this._first,
2403          labels = this.labels,
2404          p;
2405
2406      while (child) {
2407        if (child._start >= ignoreBeforeTime) {
2408          child._start += amount;
2409          child._end += amount;
2410        }
2411
2412        child = child._next;
2413      }
2414
2415      if (adjustLabels) {
2416        for (p in labels) {
2417          if (labels[p] >= ignoreBeforeTime) {
2418            labels[p] += amount;
2419          }
2420        }
2421      }
2422
2423      return _uncache(this);
2424    };
2425
2426    _proto2.invalidate = function invalidate(soft) {
2427      var child = this._first;
2428      this._lock = 0;
2429
2430      while (child) {
2431        child.invalidate(soft);
2432        child = child._next;
2433      }
2434
2435      return _Animation.prototype.invalidate.call(this, soft);
2436    };
2437
2438    _proto2.clear = function clear(includeLabels) {
2439      if (includeLabels === void 0) {
2440        includeLabels = true;
2441      }
2442
2443      var child = this._first,
2444          next;
2445
2446      while (child) {
2447        next = child._next;
2448        this.remove(child);
2449        child = next;
2450      }
2451
2452      this._dp && (this._time = this._tTime = this._pTime = 0);
2453      includeLabels && (this.labels = {});
2454      return _uncache(this);
2455    };
2456
2457    _proto2.totalDuration = function totalDuration(value) {
2458      var max = 0,
2459          self = this,
2460          child = self._last,
2461          prevStart = _bigNum,
2462          prev,
2463          start,
2464          parent;
2465
2466      if (arguments.length) {
2467        return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value));
2468      }
2469
2470      if (self._dirty) {
2471        parent = self.parent;
2472
2473        while (child) {
2474          prev = child._prev;
2475          child._dirty && child.totalDuration();
2476          start = child._start;
2477
2478          if (start > prevStart && self._sort && child._ts && !self._lock) {
2479            self._lock = 1;
2480            _addToTimeline(self, child, start - child._delay, 1)._lock = 0;
2481          } else {
2482            prevStart = start;
2483          }
2484
2485          if (start < 0 && child._ts) {
2486            max -= start;
2487
2488            if (!parent && !self._dp || parent && parent.smoothChildTiming) {
2489              self._start += start / self._ts;
2490              self._time -= start;
2491              self._tTime -= start;
2492            }
2493
2494            self.shiftChildren(-start, false, -1e999);
2495            prevStart = 0;
2496          }
2497
2498          child._end > max && child._ts && (max = child._end);
2499          child = prev;
2500        }
2501
2502        _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1);
2503
2504        self._dirty = 0;
2505      }
2506
2507      return self._tDur;
2508    };
2509
2510    Timeline.updateRoot = function updateRoot(time) {
2511      if (_globalTimeline._ts) {
2512        _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline));
2513
2514        _lastRenderedFrame = _ticker.frame;
2515      }
2516
2517      if (_ticker.frame >= _nextGCFrame) {
2518        _nextGCFrame += _config.autoSleep || 120;
2519        var child = _globalTimeline._first;
2520        if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) {
2521          while (child && !child._ts) {
2522            child = child._next;
2523          }
2524
2525          child || _ticker.sleep();
2526        }
2527      }
2528    };
2529
2530    return Timeline;
2531  }(Animation);
2532
2533  _setDefaults(Timeline.prototype, {
2534    _lock: 0,
2535    _hasPause: 0,
2536    _forcing: 0
2537  });
2538
2539  var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) {
2540    var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter),
2541        index = 0,
2542        matchIndex = 0,
2543        result,
2544        startNums,
2545        color,
2546        endNum,
2547        chunk,
2548        startNum,
2549        hasRandom,
2550        a;
2551    pt.b = start;
2552    pt.e = end;
2553    start += "";
2554    end += "";
2555
2556    if (hasRandom = ~end.indexOf("random(")) {
2557      end = _replaceRandom(end);
2558    }
2559
2560    if (stringFilter) {
2561      a = [start, end];
2562      stringFilter(a, target, prop);
2563      start = a[0];
2564      end = a[1];
2565    }
2566
2567    startNums = start.match(_complexStringNumExp) || [];
2568
2569    while (result = _complexStringNumExp.exec(end)) {
2570      endNum = result[0];
2571      chunk = end.substring(index, result.index);
2572
2573      if (color) {
2574        color = (color + 1) % 5;
2575      } else if (chunk.substr(-5) === "rgba(") {
2576        color = 1;
2577      }
2578
2579      if (endNum !== startNums[matchIndex++]) {
2580        startNum = parseFloat(startNums[matchIndex - 1]) || 0;
2581        pt._pt = {
2582          _next: pt._pt,
2583          p: chunk || matchIndex === 1 ? chunk : ",",
2584          s: startNum,
2585          c: endNum.charAt(1) === "=" ? _parseRelative(startNum, endNum) - startNum : parseFloat(endNum) - startNum,
2586          m: color && color < 4 ? Math.round : 0
2587        };
2588        index = _complexStringNumExp.lastIndex;
2589      }
2590    }
2591
2592    pt.c = index < end.length ? end.substring(index, end.length) : "";
2593    pt.fp = funcParam;
2594
2595    if (_relExp.test(end) || hasRandom) {
2596      pt.e = 0;
2597    }
2598
2599    this._pt = pt;
2600    return pt;
2601  },
2602      _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam, optional) {
vendor: 9,749 bytes, lines 2603-2889
2603    _isFunction(end) && (end = end(index || 0, target, targets));
2604    var currentValue = target[prop],
2605        parsedStart = start !== "get" ? start : !_isFunction(currentValue) ? currentValue : funcParam ? target[prop.indexOf("set") || !_isFunction(target["get" + prop.substr(3)]) ? prop : "get" + prop.substr(3)](funcParam) : target[prop](),
2606        setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc,
2607        pt;
2608
2609    if (_isString(end)) {
2610      if (~end.indexOf("random(")) {
2611        end = _replaceRandom(end);
2612      }
2613
2614      if (end.charAt(1) === "=") {
2615        pt = _parseRelative(parsedStart, end) + (getUnit(parsedStart) || 0);
2616
2617        if (pt || pt === 0) {
2618          end = pt;
2619        }
2620      }
2621    }
2622
2623    if (!optional || parsedStart !== end || _forceAllPropTweens) {
2624      if (!isNaN(parsedStart * end) && end !== "") {
2625        pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter);
2626        funcParam && (pt.fp = funcParam);
2627        modifier && pt.modifier(modifier, this, target);
2628        return this._pt = pt;
2629      }
2630
2631      !currentValue && !(prop in target) && _missingPlugin(prop, end);
2632      return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam);
2633    }
2634  },
2635      _processVars = function _processVars(vars, index, target, targets, tween) {
2636    _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets));
2637
2638    if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) {
2639      return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars;
2640    }
2641
2642    var copy = {},
2643        p;
2644
2645    for (p in vars) {
2646      copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets);
2647    }
2648
2649    return copy;
2650  },
2651      _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) {
2652    var plugin, pt, ptLookup, i;
2653
2654    if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) {
2655      tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority);
2656
2657      if (tween !== _quickTween) {
2658        ptLookup = tween._ptLookup[tween._targets.indexOf(target)];
2659        i = plugin._props.length;
2660
2661        while (i--) {
2662          ptLookup[plugin._props[i]] = pt;
2663        }
2664      }
2665    }
2666
2667    return plugin;
2668  },
2669      _overwritingTween,
2670      _forceAllPropTweens,
2671      _initTween = function _initTween(tween, time, tTime) {
2672    var vars = tween.vars,
2673        ease = vars.ease,
2674        startAt = vars.startAt,
2675        immediateRender = vars.immediateRender,
2676        lazy = vars.lazy,
2677        onUpdate = vars.onUpdate,
2678        onUpdateParams = vars.onUpdateParams,
2679        callbackScope = vars.callbackScope,
2680        runBackwards = vars.runBackwards,
2681        yoyoEase = vars.yoyoEase,
2682        keyframes = vars.keyframes,
2683        autoRevert = vars.autoRevert,
2684        dur = tween._dur,
2685        prevStartAt = tween._startAt,
2686        targets = tween._targets,
2687        parent = tween.parent,
2688        fullTargets = parent && parent.data === "nested" ? parent.vars.targets : targets,
2689        autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites,
2690        tl = tween.timeline,
2691        cleanVars,
2692        i,
2693        p,
2694        pt,
2695        target,
2696        hasPriority,
2697        gsData,
2698        harness,
2699        plugin,
2700        ptLookup,
2701        index,
2702        harnessVars,
2703        overwritten;
2704    tl && (!keyframes || !ease) && (ease = "none");
2705    tween._ease = _parseEase(ease, _defaults.ease);
2706    tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0;
2707
2708    if (yoyoEase && tween._yoyo && !tween._repeat) {
2709      yoyoEase = tween._yEase;
2710      tween._yEase = tween._ease;
2711      tween._ease = yoyoEase;
2712    }
2713
2714    tween._from = !tl && !!vars.runBackwards;
2715
2716    if (!tl || keyframes && !vars.stagger) {
2717      harness = targets[0] ? _getCache(targets[0]).harness : 0;
2718      harnessVars = harness && vars[harness.prop];
2719      cleanVars = _copyExcluding(vars, _reservedProps);
2720
2721      if (prevStartAt) {
2722        prevStartAt._zTime < 0 && prevStartAt.progress(1);
2723        time < 0 && runBackwards && immediateRender && !autoRevert ? prevStartAt.render(-1, true) : prevStartAt.revert(runBackwards && dur ? _revertConfigNoKill : _startAtRevertConfig);
2724        prevStartAt._lazy = 0;
2725      }
2726
2727      if (startAt) {
2728        _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({
2729          data: "isStart",
2730          overwrite: false,
2731          parent: parent,
2732          immediateRender: true,
2733          lazy: _isNotFalse(lazy),
2734          startAt: null,
2735          delay: 0,
2736          onUpdate: onUpdate,
2737          onUpdateParams: onUpdateParams,
2738          callbackScope: callbackScope,
2739          stagger: 0
2740        }, startAt)));
2741
2742        tween._startAt._dp = 0;
2743        time < 0 && (_reverting || !immediateRender && !autoRevert) && tween._startAt.revert(_revertConfigNoKill);
2744
2745        if (immediateRender) {
2746          if (dur && time <= 0 && tTime <= 0) {
2747            time && (tween._zTime = time);
2748            return;
2749          }
2750        }
2751      } else if (runBackwards && dur) {
2752        if (!prevStartAt) {
2753          time && (immediateRender = false);
2754          p = _setDefaults({
2755            overwrite: false,
2756            data: "isFromStart",
2757            lazy: immediateRender && _isNotFalse(lazy),
2758            immediateRender: immediateRender,
2759            stagger: 0,
2760            parent: parent
2761          }, cleanVars);
2762          harnessVars && (p[harness.prop] = harnessVars);
2763
2764          _removeFromParent(tween._startAt = Tween.set(targets, p));
2765
2766          tween._startAt._dp = 0;
2767          time < 0 && (_reverting ? tween._startAt.revert(_revertConfigNoKill) : tween._startAt.render(-1, true));
2768          tween._zTime = time;
2769
2770          if (!immediateRender) {
2771            _initTween(tween._startAt, _tinyNum, _tinyNum);
2772          } else if (!time) {
2773            return;
2774          }
2775        }
2776      }
2777
2778      tween._pt = tween._ptCache = 0;
2779      lazy = dur && _isNotFalse(lazy) || lazy && !dur;
2780
2781      for (i = 0; i < targets.length; i++) {
2782        target = targets[i];
2783        gsData = target._gsap || _harness(targets)[i]._gsap;
2784        tween._ptLookup[i] = ptLookup = {};
2785        _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender();
2786        index = fullTargets === targets ? i : fullTargets.indexOf(target);
2787
2788        if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) {
2789          tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority);
2790
2791          plugin._props.forEach(function (name) {
2792            ptLookup[name] = pt;
2793          });
2794
2795          plugin.priority && (hasPriority = 1);
2796        }
2797
2798        if (!harness || harnessVars) {
2799          for (p in cleanVars) {
2800            if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) {
2801              plugin.priority && (hasPriority = 1);
2802            } else {
2803              ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter);
2804            }
2805          }
2806        }
2807
2808        tween._op && tween._op[i] && tween.kill(target, tween._op[i]);
2809
2810        if (autoOverwrite && tween._pt) {
2811          _overwritingTween = tween;
2812
2813          _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(time));
2814
2815          overwritten = !tween.parent;
2816          _overwritingTween = 0;
2817        }
2818
2819        tween._pt && lazy && (_lazyLookup[gsData.id] = 1);
2820      }
2821
2822      hasPriority && _sortPropTweensByPriority(tween);
2823      tween._onInit && tween._onInit(tween);
2824    }
2825
2826    tween._onUpdate = onUpdate;
2827    tween._initted = (!tween._op || tween._pt) && !overwritten;
2828    keyframes && time <= 0 && tl.render(_bigNum, true, true);
2829  },
2830      _updatePropTweens = function _updatePropTweens(tween, property, value, start, startIsRelative, ratio, time) {
2831    var ptCache = (tween._pt && tween._ptCache || (tween._ptCache = {}))[property],
2832        pt,
2833        rootPT,
2834        lookup,
2835        i;
2836
2837    if (!ptCache) {
2838      ptCache = tween._ptCache[property] = [];
2839      lookup = tween._ptLookup;
2840      i = tween._targets.length;
2841
2842      while (i--) {
2843        pt = lookup[i][property];
2844
2845        if (pt && pt.d && pt.d._pt) {
2846          pt = pt.d._pt;
2847
2848          while (pt && pt.p !== property && pt.fp !== property) {
2849            pt = pt._next;
2850          }
2851        }
2852
2853        if (!pt) {
2854          _forceAllPropTweens = 1;
2855          tween.vars[property] = "+=0";
2856
2857          _initTween(tween, time);
2858
2859          _forceAllPropTweens = 0;
2860          return 1;
2861        }
2862
2863        ptCache.push(pt);
2864      }
2865    }
2866
2867    i = ptCache.length;
2868
2869    while (i--) {
2870      rootPT = ptCache[i];
2871      pt = rootPT._pt || rootPT;
2872      pt.s = (start || start === 0) && !startIsRelative ? start : pt.s + (start || 0) + ratio * pt.c;
2873      pt.c = value - pt.s;
2874      rootPT.e && (rootPT.e = _round(value) + getUnit(rootPT.e));
2875      rootPT.b && (rootPT.b = pt.s + getUnit(rootPT.b));
2876    }
2877  },
2878      _addAliasesToVars = function _addAliasesToVars(targets, vars) {
2879    var harness = targets[0] ? _getCache(targets[0]).harness : 0,
2880        propertyAliases = harness && harness.aliases,
2881        copy,
2882        p,
2883        i,
2884        aliases;
2885
2886    if (!propertyAliases) {
2887      return vars;
2888    }
2889
vendor: 4,989 bytes, lines 2890-3032
2890    copy = _merge({}, vars);
2891
2892    for (p in propertyAliases) {
2893      if (p in copy) {
2894        aliases = propertyAliases[p].split(",");
2895        i = aliases.length;
2896
2897        while (i--) {
2898          copy[aliases[i]] = copy[p];
2899        }
2900      }
2901    }
2902
2903    return copy;
2904  },
2905      _parseKeyframe = function _parseKeyframe(prop, obj, allProps, easeEach) {
2906    var ease = obj.ease || easeEach || "power1.inOut",
2907        p,
2908        a;
2909
2910    if (_isArray(obj)) {
2911      a = allProps[prop] || (allProps[prop] = []);
2912      obj.forEach(function (value, i) {
2913        return a.push({
2914          t: i / (obj.length - 1) * 100,
2915          v: value,
2916          e: ease
2917        });
2918      });
2919    } else {
2920      for (p in obj) {
2921        a = allProps[p] || (allProps[p] = []);
2922        p === "ease" || a.push({
2923          t: parseFloat(prop),
2924          v: obj[p],
2925          e: ease
2926        });
2927      }
2928    }
2929  },
2930      _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) {
2931    return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value;
2932  },
2933      _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase,autoRevert",
2934      _staggerPropsToSkip = {};
2935
2936  _forEachName(_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger", function (name) {
2937    return _staggerPropsToSkip[name] = 1;
2938  });
2939
2940  var Tween = function (_Animation2) {
2941    _inheritsLoose(Tween, _Animation2);
2942
2943    function Tween(targets, vars, position, skipInherit) {
2944      var _this3;
2945
2946      if (typeof vars === "number") {
2947        position.duration = vars;
2948        vars = position;
2949        position = null;
2950      }
2951
2952      _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars)) || this;
2953      var _this3$vars = _this3.vars,
2954          duration = _this3$vars.duration,
2955          delay = _this3$vars.delay,
2956          immediateRender = _this3$vars.immediateRender,
2957          stagger = _this3$vars.stagger,
2958          overwrite = _this3$vars.overwrite,
2959          keyframes = _this3$vars.keyframes,
2960          defaults = _this3$vars.defaults,
2961          scrollTrigger = _this3$vars.scrollTrigger,
2962          yoyoEase = _this3$vars.yoyoEase,
2963          parent = vars.parent || _globalTimeline,
2964          parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets),
2965          tl,
2966          i,
2967          copy,
2968          l,
2969          p,
2970          curTarget,
2971          staggerFunc,
2972          staggerVarsToMerge;
2973      _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://greensock.com", !_config.nullTargetWarn) || [];
2974      _this3._ptLookup = [];
2975      _this3._overwrite = overwrite;
2976
2977      if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2978        vars = _this3.vars;
2979        tl = _this3.timeline = new Timeline({
2980          data: "nested",
2981          defaults: defaults || {},
2982          targets: parent && parent.data === "nested" ? parent.vars.targets : parsedTargets
2983        });
2984        tl.kill();
2985        tl.parent = tl._dp = _assertThisInitialized(_this3);
2986        tl._start = 0;
2987
2988        if (stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) {
2989          l = parsedTargets.length;
2990          staggerFunc = stagger && distribute(stagger);
2991
2992          if (_isObject(stagger)) {
2993            for (p in stagger) {
2994              if (~_staggerTweenProps.indexOf(p)) {
2995                staggerVarsToMerge || (staggerVarsToMerge = {});
2996                staggerVarsToMerge[p] = stagger[p];
2997              }
2998            }
2999          }
3000
3001          for (i = 0; i < l; i++) {
3002            copy = _copyExcluding(vars, _staggerPropsToSkip);
3003            copy.stagger = 0;
3004            yoyoEase && (copy.yoyoEase = yoyoEase);
3005            staggerVarsToMerge && _merge(copy, staggerVarsToMerge);
3006            curTarget = parsedTargets[i];
3007            copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets);
3008            copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay;
3009
3010            if (!stagger && l === 1 && copy.delay) {
3011              _this3._delay = delay = copy.delay;
3012              _this3._start += delay;
3013              copy.delay = 0;
3014            }
3015
3016            tl.to(curTarget, copy, staggerFunc ? staggerFunc(i, curTarget, parsedTargets) : 0);
3017            tl._ease = _easeMap.none;
3018          }
3019
3020          tl.duration() ? duration = delay = 0 : _this3.timeline = 0;
3021        } else if (keyframes) {
3022          _inheritDefaults(_setDefaults(tl.vars.defaults, {
3023            ease: "none"
3024          }));
3025
3026          tl._ease = _parseEase(keyframes.ease || vars.ease || "none");
3027          var time = 0,
3028              a,
3029              kf,
3030              v;
3031
3032          if (_isArray(keyframes)) {
vendor: 6,328 bytes, lines 3033-3239
3033            keyframes.forEach(function (frame) {
3034              return tl.to(parsedTargets, frame, ">");
3035            });
3036            tl.duration();
3037          } else {
3038            copy = {};
3039
3040            for (p in keyframes) {
3041              p === "ease" || p === "easeEach" || _parseKeyframe(p, keyframes[p], copy, keyframes.easeEach);
3042            }
3043
3044            for (p in copy) {
3045              a = copy[p].sort(function (a, b) {
3046                return a.t - b.t;
3047              });
3048              time = 0;
3049
3050              for (i = 0; i < a.length; i++) {
3051                kf = a[i];
3052                v = {
3053                  ease: kf.e,
3054                  duration: (kf.t - (i ? a[i - 1].t : 0)) / 100 * duration
3055                };
3056                v[p] = kf.v;
3057                tl.to(parsedTargets, v, time);
3058                time += v.duration;
3059              }
3060            }
3061
3062            tl.duration() < duration && tl.to({}, {
3063              duration: duration - tl.duration()
3064            });
3065          }
3066        }
3067
3068        duration || _this3.duration(duration = tl.duration());
3069      } else {
3070        _this3.timeline = 0;
3071      }
3072
3073      if (overwrite === true && !_suppressOverwrites) {
3074        _overwritingTween = _assertThisInitialized(_this3);
3075
3076        _globalTimeline.killTweensOf(parsedTargets);
3077
3078        _overwritingTween = 0;
3079      }
3080
3081      _addToTimeline(parent, _assertThisInitialized(_this3), position);
3082
3083      vars.reversed && _this3.reverse();
3084      vars.paused && _this3.paused(true);
3085
3086      if (immediateRender || !duration && !keyframes && _this3._start === _roundPrecise(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") {
3087        _this3._tTime = -_tinyNum;
3088
3089        _this3.render(Math.max(0, -delay) || 0);
3090      }
3091
3092      scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger);
3093      return _this3;
3094    }
3095
3096    var _proto3 = Tween.prototype;
3097
3098    _proto3.render = function render(totalTime, suppressEvents, force) {
3099      var prevTime = this._time,
3100          tDur = this._tDur,
3101          dur = this._dur,
3102          isNegative = totalTime < 0,
3103          tTime = totalTime > tDur - _tinyNum && !isNegative ? tDur : totalTime < _tinyNum ? 0 : totalTime,
3104          time,
3105          pt,
3106          iteration,
3107          cycleDuration,
3108          prevIteration,
3109          isYoyo,
3110          ratio,
3111          timeline,
3112          yoyoEase;
3113
3114      if (!dur) {
3115        _renderZeroDurationTween(this, totalTime, suppressEvents, force);
3116      } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== isNegative) {
3117        time = tTime;
3118        timeline = this.timeline;
3119
3120        if (this._repeat) {
3121          cycleDuration = dur + this._rDelay;
3122
3123          if (this._repeat < -1 && isNegative) {
3124            return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force);
3125          }
3126
3127          time = _roundPrecise(tTime % cycleDuration);
3128
3129          if (tTime === tDur) {
3130            iteration = this._repeat;
3131            time = dur;
3132          } else {
3133            iteration = ~~(tTime / cycleDuration);
3134
3135            if (iteration && iteration === tTime / cycleDuration) {
3136              time = dur;
3137              iteration--;
3138            }
3139
3140            time > dur && (time = dur);
3141          }
3142
3143          isYoyo = this._yoyo && iteration & 1;
3144
3145          if (isYoyo) {
3146            yoyoEase = this._yEase;
3147            time = dur - time;
3148          }
3149
3150          prevIteration = _animationCycle(this._tTime, cycleDuration);
3151
3152          if (time === prevTime && !force && this._initted) {
3153            this._tTime = tTime;
3154            return this;
3155          }
3156
3157          if (iteration !== prevIteration) {
3158            timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo);
3159
3160            if (this.vars.repeatRefresh && !isYoyo && !this._lock) {
3161              this._lock = force = 1;
3162              this.render(_roundPrecise(cycleDuration * iteration), true).invalidate()._lock = 0;
3163            }
3164          }
3165        }
3166
3167        if (!this._initted) {
3168          if (_attemptInitTween(this, isNegative ? totalTime : time, force, suppressEvents, tTime)) {
3169            this._tTime = 0;
3170            return this;
3171          }
3172
3173          if (prevTime !== this._time) {
3174            return this;
3175          }
3176
3177          if (dur !== this._dur) {
3178            return this.render(totalTime, suppressEvents, force);
3179          }
3180        }
3181
3182        this._tTime = tTime;
3183        this._time = time;
3184
3185        if (!this._act && this._ts) {
3186          this._act = 1;
3187          this._lazy = 0;
3188        }
3189
3190        this.ratio = ratio = (yoyoEase || this._ease)(time / dur);
3191
3192        if (this._from) {
3193          this.ratio = ratio = 1 - ratio;
3194        }
3195
3196        if (time && !prevTime && !suppressEvents) {
3197          _callback(this, "onStart");
3198
3199          if (this._tTime !== tTime) {
3200            return this;
3201          }
3202        }
3203
3204        pt = this._pt;
3205
3206        while (pt) {
3207          pt.r(ratio, pt.d);
3208          pt = pt._next;
3209        }
3210
3211        timeline && timeline.render(totalTime < 0 ? totalTime : !time && isYoyo ? -_tinyNum : timeline._dur * timeline._ease(time / this._dur), suppressEvents, force) || this._startAt && (this._zTime = totalTime);
3212
3213        if (this._onUpdate && !suppressEvents) {
3214          isNegative && _rewindStartAt(this, totalTime, suppressEvents, force);
3215
3216          _callback(this, "onUpdate");
3217        }
3218
3219        this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat");
3220
3221        if ((tTime === this._tDur || !tTime) && this._tTime === tTime) {
3222          isNegative && !this._onUpdate && _rewindStartAt(this, totalTime, true, true);
3223          (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1);
3224
3225          if (!suppressEvents && !(isNegative && !prevTime) && (tTime || prevTime || isYoyo)) {
3226            _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true);
3227
3228            this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom();
3229          }
3230        }
3231      }
3232
3233      return this;
3234    };
3235
3236    _proto3.targets = function targets() {
3237      return this._targets;
3238    };
3239
vendor: 1,277 bytes, lines 3240-3273
3240    _proto3.invalidate = function invalidate(soft) {
3241      (!soft || !this.vars.runBackwards) && (this._startAt = 0);
3242      this._pt = this._op = this._onUpdate = this._lazy = this.ratio = 0;
3243      this._ptLookup = [];
3244      this.timeline && this.timeline.invalidate(soft);
3245      return _Animation2.prototype.invalidate.call(this, soft);
3246    };
3247
3248    _proto3.resetTo = function resetTo(property, value, start, startIsRelative) {
3249      _tickerActive || _ticker.wake();
3250      this._ts || this.play();
3251      var time = Math.min(this._dur, (this._dp._time - this._start) * this._ts),
3252          ratio;
3253      this._initted || _initTween(this, time);
3254      ratio = this._ease(time / this._dur);
3255
3256      if (_updatePropTweens(this, property, value, start, startIsRelative, ratio, time)) {
3257        return this.resetTo(property, value, start, startIsRelative);
3258      }
3259
3260      _alignPlayhead(this, 0);
3261
3262      this.parent || _addLinkedListItem(this._dp, this, "_first", "_last", this._dp._sort ? "_start" : 0);
3263      return this.render(0);
3264    };
3265
3266    _proto3.kill = function kill(targets, vars) {
3267      if (vars === void 0) {
3268        vars = "all";
3269      }
3270
3271      if (!targets && (!vars || vars === "all")) {
3272        this._lazy = this._pt = 0;
3273        return this.parent ? _interrupt(this) :
vendor: 7,709 bytes, lines 3273-3553
3273 this;
3274      }
3275
3276      if (this.timeline) {
3277        var tDur = this.timeline.totalDuration();
3278        this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this);
3279        this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1);
3280        return this;
3281      }
3282
3283      var parsedTargets = this._targets,
3284          killingTargets = targets ? toArray(targets) : parsedTargets,
3285          propTweenLookup = this._ptLookup,
3286          firstPT = this._pt,
3287          overwrittenProps,
3288          curLookup,
3289          curOverwriteProps,
3290          props,
3291          p,
3292          pt,
3293          i;
3294
3295      if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) {
3296        vars === "all" && (this._pt = 0);
3297        return _interrupt(this);
3298      }
3299
3300      overwrittenProps = this._op = this._op || [];
3301
3302      if (vars !== "all") {
3303        if (_isString(vars)) {
3304          p = {};
3305
3306          _forEachName(vars, function (name) {
3307            return p[name] = 1;
3308          });
3309
3310          vars = p;
3311        }
3312
3313        vars = _addAliasesToVars(parsedTargets, vars);
3314      }
3315
3316      i = parsedTargets.length;
3317
3318      while (i--) {
3319        if (~killingTargets.indexOf(parsedTargets[i])) {
3320          curLookup = propTweenLookup[i];
3321
3322          if (vars === "all") {
3323            overwrittenProps[i] = vars;
3324            props = curLookup;
3325            curOverwriteProps = {};
3326          } else {
3327            curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {};
3328            props = vars;
3329          }
3330
3331          for (p in props) {
3332            pt = curLookup && curLookup[p];
3333
3334            if (pt) {
3335              if (!("kill" in pt.d) || pt.d.kill(p) === true) {
3336                _removeLinkedListItem(this, pt, "_pt");
3337              }
3338
3339              delete curLookup[p];
3340            }
3341
3342            if (curOverwriteProps !== "all") {
3343              curOverwriteProps[p] = 1;
3344            }
3345          }
3346        }
3347      }
3348
3349      this._initted && !this._pt && firstPT && _interrupt(this);
3350      return this;
3351    };
3352
3353    Tween.to = function to(targets, vars) {
3354      return new Tween(targets, vars, arguments[2]);
3355    };
3356
3357    Tween.from = function from(targets, vars) {
3358      return _createTweenType(1, arguments);
3359    };
3360
3361    Tween.delayedCall = function delayedCall(delay, callback, params, scope) {
3362      return new Tween(callback, 0, {
3363        immediateRender: false,
3364        lazy: false,
3365        overwrite: false,
3366        delay: delay,
3367        onComplete: callback,
3368        onReverseComplete: callback,
3369        onCompleteParams: params,
3370        onReverseCompleteParams: params,
3371        callbackScope: scope
3372      });
3373    };
3374
3375    Tween.fromTo = function fromTo(targets, fromVars, toVars) {
3376      return _createTweenType(2, arguments);
3377    };
3378
3379    Tween.set = function set(targets, vars) {
3380      vars.duration = 0;
3381      vars.repeatDelay || (vars.repeat = 0);
3382      return new Tween(targets, vars);
3383    };
3384
3385    Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) {
3386      return _globalTimeline.killTweensOf(targets, props, onlyActive);
3387    };
3388
3389    return Tween;
3390  }(Animation);
3391
3392  _setDefaults(Tween.prototype, {
3393    _targets: [],
3394    _lazy: 0,
3395    _startAt: 0,
3396    _op: 0,
3397    _onInit: 0
3398  });
3399
3400  _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) {
3401    Tween[name] = function () {
3402      var tl = new Timeline(),
3403          params = _slice.call(arguments, 0);
3404
3405      params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0);
3406      return tl[name].apply(tl, params);
3407    };
3408  });
3409
3410  var _setterPlain = function _setterPlain(target, property, value) {
3411    return target[property] = value;
3412  },
3413      _setterFunc = function _setterFunc(target, property, value) {
3414    return target[property](value);
3415  },
3416      _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) {
3417    return target[property](data.fp, value);
3418  },
3419      _setterAttribute = function _setterAttribute(target, property, value) {
3420    return target.setAttribute(property, value);
3421  },
3422      _getSetter = function _getSetter(target, property) {
3423    return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain;
3424  },
3425      _renderPlain = function _renderPlain(ratio, data) {
3426    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 1000000) / 1000000, data);
3427  },
3428      _renderBoolean = function _renderBoolean(ratio, data) {
3429    return data.set(data.t, data.p, !!(data.s + data.c * ratio), data);
3430  },
3431      _renderComplexString = function _renderComplexString(ratio, data) {
3432    var pt = data._pt,
3433        s = "";
3434
3435    if (!ratio && data.b) {
3436      s = data.b;
3437    } else if (ratio === 1 && data.e) {
3438      s = data.e;
3439    } else {
3440      while (pt) {
3441        s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s;
3442        pt = pt._next;
3443      }
3444
3445      s += data.c;
3446    }
3447
3448    data.set(data.t, data.p, s, data);
3449  },
3450      _renderPropTweens = function _renderPropTweens(ratio, data) {
3451    var pt = data._pt;
3452
3453    while (pt) {
3454      pt.r(ratio, pt.d);
3455      pt = pt._next;
3456    }
3457  },
3458      _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) {
3459    var pt = this._pt,
3460        next;
3461
3462    while (pt) {
3463      next = pt._next;
3464      pt.p === property && pt.modifier(modifier, tween, target);
3465      pt = next;
3466    }
3467  },
3468      _killPropTweensOf = function _killPropTweensOf(property) {
3469    var pt = this._pt,
3470        hasNonDependentRemaining,
3471        next;
3472
3473    while (pt) {
3474      next = pt._next;
3475
3476      if (pt.p === property && !pt.op || pt.op === property) {
3477        _removeLinkedListItem(this, pt, "_pt");
3478      } else if (!pt.dep) {
3479        hasNonDependentRemaining = 1;
3480      }
3481
3482      pt = next;
3483    }
3484
3485    return !hasNonDependentRemaining;
3486  },
3487      _setterWithModifier = function _setterWithModifier(target, property, value, data) {
3488    data.mSet(target, property, data.m.call(data.tween, value, data.mt), data);
3489  },
3490      _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) {
3491    var pt = parent._pt,
3492        next,
3493        pt2,
3494        first,
3495        last;
3496
3497    while (pt) {
3498      next = pt._next;
3499      pt2 = first;
3500
3501      while (pt2 && pt2.pr > pt.pr) {
3502        pt2 = pt2._next;
3503      }
3504
3505      if (pt._prev = pt2 ? pt2._prev : last) {
3506        pt._prev._next = pt;
3507      } else {
3508        first = pt;
3509      }
3510
3511      if (pt._next = pt2) {
3512        pt2._prev = pt;
3513      } else {
3514        last = pt;
3515      }
3516
3517      pt = next;
3518    }
3519
3520    parent._pt = first;
3521  };
3522
3523  var PropTween = function () {
3524    function PropTween(next, target, prop, start, change, renderer, data, setter, priority) {
3525      this.t = target;
3526      this.s = start;
3527      this.c = change;
3528      this.p = prop;
3529      this.r = renderer || _renderPlain;
3530      this.d = data || this;
3531      this.set = setter || _setterPlain;
3532      this.pr = priority || 0;
3533      this._next = next;
3534
3535      if (next) {
3536        next._prev = this;
3537      }
3538    }
3539
3540    var _proto4 = PropTween.prototype;
3541
3542    _proto4.modifier = function modifier(func, tween, target) {
3543      this.mSet = this.mSet || this.set;
3544      this.set = _setterWithModifier;
3545      this.m = func;
3546      this.mt = target;
3547      this.tween = tween;
3548    };
3549
3550    return PropTween;
3551  }();
3552
3553  _forEachName(_callbackNames + "parent,duration,ease,delay,overwrite,runBackwards,startAt,yoyo,immediateRender,repeat,repeatDelay,data,paused,reversed,lazy,callbackScope,stringFilter,id,yoyoEase,stagger,inherit,repeatRefresh,keyframes,autoRevert,scrollTrigger
vendor: 3,674 bytes, lines 3553-3696
3553", function (name) {
3554    return _reservedProps[name] = 1;
3555  });
3556
3557  _globals.TweenMax = _globals.TweenLite = Tween;
3558  _globals.TimelineLite = _globals.TimelineMax = Timeline;
3559  _globalTimeline = new Timeline({
3560    sortChildren: false,
3561    defaults: _defaults,
3562    autoRemoveChildren: true,
3563    id: "root",
3564    smoothChildTiming: true
3565  });
3566  _config.stringFilter = _colorStringFilter;
3567
3568  var _media = [],
3569      _listeners = {},
3570      _emptyArray = [],
3571      _lastMediaTime = 0,
3572      _dispatch = function _dispatch(type) {
3573    return (_listeners[type] || _emptyArray).map(function (f) {
3574      return f();
3575    });
3576  },
3577      _onMediaChange = function _onMediaChange() {
3578    var time = Date.now(),
3579        matches = [];
3580
3581    if (time - _lastMediaTime > 2) {
3582      _dispatch("matchMediaInit");
3583
3584      _media.forEach(function (c) {
3585        var queries = c.queries,
3586            conditions = c.conditions,
3587            match,
3588            p,
3589            anyMatch,
3590            toggled;
3591
3592        for (p in queries) {
3593          match = _win.matchMedia(queries[p]).matches;
3594          match && (anyMatch = 1);
3595
3596          if (match !== conditions[p]) {
3597            conditions[p] = match;
3598            toggled = 1;
3599          }
3600        }
3601
3602        if (toggled) {
3603          c.revert();
3604          anyMatch && matches.push(c);
3605        }
3606      });
3607
3608      _dispatch("matchMediaRevert");
3609
3610      matches.forEach(function (c) {
3611        return c.onMatch(c);
3612      });
3613      _lastMediaTime = time;
3614
3615      _dispatch("matchMedia");
3616    }
3617  };
3618
3619  var Context = function () {
3620    function Context(func, scope) {
3621      this.selector = scope && selector(scope);
3622      this.data = [];
3623      this._r = [];
3624      this.isReverted = false;
3625      func && this.add(func);
3626    }
3627
3628    var _proto5 = Context.prototype;
3629
3630    _proto5.add = function add(name, func, scope) {
3631      if (_isFunction(name)) {
3632        scope = func;
3633        func = name;
3634        name = _isFunction;
3635      }
3636
3637      var self = this,
3638          f = function f() {
3639        var prev = _context,
3640            prevSelector = self.selector,
3641            result;
3642        prev && prev !== self && prev.data.push(self);
3643        scope && (self.selector = selector(scope));
3644        _context = self;
3645        result = func.apply(self, arguments);
3646        _isFunction(result) && self._r.push(result);
3647        _context = prev;
3648        self.selector = prevSelector;
3649        self.isReverted = false;
3650        return result;
3651      };
3652
3653      self.last = f;
3654      return name === _isFunction ? f(self) : name ? self[name] = f : f;
3655    };
3656
3657    _proto5.ignore = function ignore(func) {
3658      var prev = _context;
3659      _context = null;
3660      func(this);
3661      _context = prev;
3662    };
3663
3664    _proto5.getTweens = function getTweens() {
3665      var a = [];
3666      this.data.forEach(function (e) {
3667        return e instanceof Context ? a.push.apply(a, e.getTweens()) : e instanceof Tween && !(e.parent && e.parent.data === "nested") && a.push(e);
3668      });
3669      return a;
3670    };
3671
3672    _proto5.clear = function clear() {
3673      this._r.length = this.data.length = 0;
3674    };
3675
3676    _proto5.kill = function kill(revert, matchMedia) {
3677      var _this4 = this;
3678
3679      if (revert) {
3680        var tweens = this.getTweens();
3681        this.data.forEach(function (t) {
3682          if (t.data === "isFlip") {
3683            t.revert();
3684            t.getChildren(true, true, false).forEach(function (tween) {
3685              return tweens.splice(tweens.indexOf(tween), 1);
3686            });
3687          }
3688        });
3689        tweens.map(function (t) {
3690          return {
3691            g: t.globalTime(0),
3692            t: t
3693          };
3694        }).sort(function (a, b) {
3695          return b.g - a.g || -1;
3696        }
3696).forEach(function (o) {
3697          return o.t.revert(revert);
3698        });
3699        this.data.forEach(function (e) {
3700          return !(e instanceof Animation) && e.revert && e.revert(revert);
3701        });
3702
3703        this._r.forEach(function (f) {
3704          return f(revert, _this4);
3705        });
3706
3707        this.isReverted = true;
3708      } else {
3709        this.data.forEach(function (e) {
3710          return e.kill && e.kill();
3711        });
3712      }
3713
3714      this.clear();
3715
3716      if (matchMedia) {
3717        var i = _media.indexOf(this);
3718
3719        !!~i && _media.splice(i, 1);
3720      }
3721    };
3722
3723    _proto5.revert = function revert(config) {
3724      this.kill(config || {});
3725    };
3726
3727    return Context;
3728  }();
3729
3730  var MatchMedia = function () {
3731    function MatchMedia(scope) {
3732      this.contexts = [];
3733      this.scope = scope;
3734    }
3735
3736    var _proto6 = MatchMedia.prototype;
3737
3738    _proto6.add = function add(conditions, func, scope) {
3739      _isObject(conditions) || (conditions = {
3740        matches: conditions
3741      });
3742      var context = new Context(0, scope || this.scope),
3743          cond = context.conditions = {},
3744          mq,
3745          p,
3746          active;
3747      this.contexts.push(context);
3748      func = context.add("onMatch", func);
3749      context.queries = conditions;
3750
3751      for (p in conditions) {
3752        if (p === "all") {
3753          active = 1;
3754        } else {
3755          mq = _win.matchMedia(conditions[p]);
3756
3757          if (mq) {
3758            _media.indexOf(context) < 0 && _media.push(context);
3759            (cond[p] = mq.matches) && (active = 1);
3760            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
3761          }
3762        }
3763      }
3764
3765      active && func(context);
3766      return this;
3767    };
3768
3769    _proto6.revert = function revert(config) {
3770      this.kill(config || {});
3771    };
3772
3773    _proto6.kill = function kill(revert) {
vendor: 2,486 bytes, lines 3774-3846
3774      this.contexts.forEach(function (c) {
3775        return c.kill(revert, true);
3776      });
3777    };
3778
3779    return MatchMedia;
3780  }();
3781
3782  var _gsap = {
3783    registerPlugin: function registerPlugin() {
3784      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
3785        args[_key2] = arguments[_key2];
3786      }
3787
3788      args.forEach(function (config) {
3789        return _createPlugin(config);
3790      });
3791    },
3792    timeline: function timeline(vars) {
3793      return new Timeline(vars);
3794    },
3795    getTweensOf: function getTweensOf(targets, onlyActive) {
3796      return _globalTimeline.getTweensOf(targets, onlyActive);
3797    },
3798    getProperty: function getProperty(target, property, unit, uncache) {
3799      _isString(target) && (target = toArray(target)[0]);
3800
3801      var getter = _getCache(target || {}).get,
3802          format = unit ? _passThrough : _numericIfPossible;
3803
3804      unit === "native" && (unit = "");
3805      return !target ? target : !property ? function (property, unit, uncache) {
3806        return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3807      } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache));
3808    },
3809    quickSetter: function quickSetter(target, property, unit) {
3810      target = toArray(target);
3811
3812      if (target.length > 1) {
3813        var setters = target.map(function (t) {
3814          return gsap.quickSetter(t, property, unit);
3815        }),
3816            l = setters.length;
3817        return function (value) {
3818          var i = l;
3819
3820          while (i--) {
3821            setters[i](value);
3822          }
3823        };
3824      }
3825
3826      target = target[0] || {};
3827
3828      var Plugin = _plugins[property],
3829          cache = _getCache(target),
3830          p = cache.harness && (cache.harness.aliases || {})[property] || property,
3831          setter = Plugin ? function (value) {
3832        var p = new Plugin();
3833        _quickTween._pt = 0;
3834        p.init(target, unit ? value + unit : value, _quickTween, 0, [target]);
3835        p.render(1, p);
3836        _quickTween._pt && _renderPropTweens(1, _quickTween);
3837      } : cache.set(target, p);
3838
3839      return Plugin ? setter : function (value) {
3840        return setter(target, p, unit ? value + unit : value, cache, 1);
3841      };
3842    },
3843    quickTo: function quickTo(target, property, vars) {
3844      var _merge2;
3845
3846      var tween = gsap.to(target, _merge((_merge2 = {}, _merge2[property] = "+=0.1", _merge2.paused = true, _merge
vendor: 5,649 bytes, lines 3846-4048
38462), vars || {})),
3847          func = function func(value, start, startIsRelative) {
3848        return tween.resetTo(property, value, start, startIsRelative);
3849      };
3850
3851      func.tween = tween;
3852      return func;
3853    },
3854    isTweening: function isTweening(targets) {
3855      return _globalTimeline.getTweensOf(targets, true).length > 0;
3856    },
3857    defaults: function defaults(value) {
3858      value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease));
3859      return _mergeDeep(_defaults, value || {});
3860    },
3861    config: function config(value) {
3862      return _mergeDeep(_config, value || {});
3863    },
3864    registerEffect: function registerEffect(_ref3) {
3865      var name = _ref3.name,
3866          effect = _ref3.effect,
3867          plugins = _ref3.plugins,
3868          defaults = _ref3.defaults,
3869          extendTimeline = _ref3.extendTimeline;
3870      (plugins || "").split(",").forEach(function (pluginName) {
3871        return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin.");
3872      });
3873
3874      _effects[name] = function (targets, vars, tl) {
3875        return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl);
3876      };
3877
3878      if (extendTimeline) {
3879        Timeline.prototype[name] = function (targets, vars, position) {
3880          return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position);
3881        };
3882      }
3883    },
3884    registerEase: function registerEase(name, ease) {
3885      _easeMap[name] = _parseEase(ease);
3886    },
3887    parseEase: function parseEase(ease, defaultEase) {
3888      return arguments.length ? _parseEase(ease, defaultEase) : _easeMap;
3889    },
3890    getById: function getById(id) {
3891      return _globalTimeline.getById(id);
3892    },
3893    exportRoot: function exportRoot(vars, includeDelayedCalls) {
3894      if (vars === void 0) {
3895        vars = {};
3896      }
3897
3898      var tl = new Timeline(vars),
3899          child,
3900          next;
3901      tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming);
3902
3903      _globalTimeline.remove(tl);
3904
3905      tl._dp = 0;
3906      tl._time = tl._tTime = _globalTimeline._time;
3907      child = _globalTimeline._first;
3908
3909      while (child) {
3910        next = child._next;
3911
3912        if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) {
3913          _addToTimeline(tl, child, child._start - child._delay);
3914        }
3915
3916        child = next;
3917      }
3918
3919      _addToTimeline(_globalTimeline, tl, 0);
3920
3921      return tl;
3922    },
3923    context: function context(func, scope) {
3924      return func ? new Context(func, scope) : _context;
3925    },
3926    matchMedia: function matchMedia(scope) {
3927      return new MatchMedia(scope);
3928    },
3929    matchMediaRefresh: function matchMediaRefresh() {
3930      return _media.forEach(function (c) {
3931        var cond = c.conditions,
3932            found,
3933            p;
3934
3935        for (p in cond) {
3936          if (cond[p]) {
3937            cond[p] = false;
3938            found = 1;
3939          }
3940        }
3941
3942        found && c.revert();
3943      }) || _onMediaChange();
3944    },
3945    addEventListener: function addEventListener(type, callback) {
3946      var a = _listeners[type] || (_listeners[type] = []);
3947      ~a.indexOf(callback) || a.push(callback);
3948    },
3949    removeEventListener: function removeEventListener(type, callback) {
3950      var a = _listeners[type],
3951          i = a && a.indexOf(callback);
3952      i >= 0 && a.splice(i, 1);
3953    },
3954    utils: {
3955      wrap: wrap,
3956      wrapYoyo: wrapYoyo,
3957      distribute: distribute,
3958      random: random,
3959      snap: snap,
3960      normalize: normalize,
3961      getUnit: getUnit,
3962      clamp: clamp,
3963      splitColor: splitColor,
3964      toArray: toArray,
3965      selector: selector,
3966      mapRange: mapRange,
3967      pipe: pipe,
3968      unitize: unitize,
3969      interpolate: interpolate,
3970      shuffle: shuffle
3971    },
3972    install: _install,
3973    effects: _effects,
3974    ticker: _ticker,
3975    updateRoot: Timeline.updateRoot,
3976    plugins: _plugins,
3977    globalTimeline: _globalTimeline,
3978    core: {
3979      PropTween: PropTween,
3980      globals: _addGlobal,
3981      Tween: Tween,
3982      Timeline: Timeline,
3983      Animation: Animation,
3984      getCache: _getCache,
3985      _removeLinkedListItem: _removeLinkedListItem,
3986      reverting: function reverting() {
3987        return _reverting;
3988      },
3989      context: function context(toAdd) {
3990        if (toAdd && _context) {
3991          _context.data.push(toAdd);
3992
3993          toAdd._ctx = _context;
3994        }
3995
3996        return _context;
3997      },
3998      suppressOverwrites: function suppressOverwrites(value) {
3999        return _suppressOverwrites = value;
4000      }
4001    }
4002  };
4003
4004  _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) {
4005    return _gsap[name] = Tween[name];
4006  });
4007
4008  _ticker.add(Timeline.updateRoot);
4009
4010  _quickTween = _gsap.to({}, {
4011    duration: 0
4012  });
4013
4014  var _getPluginPropTween = function _getPluginPropTween(plugin, prop) {
4015    var pt = plugin._pt;
4016
4017    while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) {
4018      pt = pt._next;
4019    }
4020
4021    return pt;
4022  },
4023      _addModifiers = function _addModifiers(tween, modifiers) {
4024    var targets = tween._targets,
4025        p,
4026        i,
4027        pt;
4028
4029    for (p in modifiers) {
4030      i = targets.length;
4031
4032      while (i--) {
4033        pt = tween._ptLookup[i][p];
4034
4035        if (pt && (pt = pt.d)) {
4036          if (pt._pt) {
4037            pt = _getPluginPropTween(pt, p);
4038          }
4039
4040          pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p);
4041        }
4042      }
4043    }
4044  },
4045      _buildModifierPlugin = function _buildModifierPlugin(name, modifier) {
4046    return {
4047      name: name,
4048      
vendor: 20,072 bytes, lines 4048-4675
4048rawVars: 1,
4049      init: function init(target, vars, tween) {
4050        tween._onInit = function (tween) {
4051          var temp, p;
4052
4053          if (_isString(vars)) {
4054            temp = {};
4055
4056            _forEachName(vars, function (name) {
4057              return temp[name] = 1;
4058            });
4059
4060            vars = temp;
4061          }
4062
4063          if (modifier) {
4064            temp = {};
4065
4066            for (p in vars) {
4067              temp[p] = modifier(vars[p]);
4068            }
4069
4070            vars = temp;
4071          }
4072
4073          _addModifiers(tween, vars);
4074        };
4075      }
4076    };
4077  };
4078
4079  var gsap = _gsap.registerPlugin({
4080    name: "attr",
4081    init: function init(target, vars, tween, index, targets) {
4082      var p, pt, v;
4083      this.tween = tween;
4084
4085      for (p in vars) {
4086        v = target.getAttribute(p) || "";
4087        pt = this.add(target, "setAttribute", (v || 0) + "", vars[p], index, targets, 0, 0, p);
4088        pt.op = p;
4089        pt.b = v;
4090
4091        this._props.push(p);
4092      }
4093    },
4094    render: function render(ratio, data) {
4095      var pt = data._pt;
4096
4097      while (pt) {
4098        _reverting ? pt.set(pt.t, pt.p, pt.b, pt) : pt.r(ratio, pt.d);
4099        pt = pt._next;
4100      }
4101    }
4102  }, {
4103    name: "endArray",
4104    init: function init(target, value) {
4105      var i = value.length;
4106
4107      while (i--) {
4108        this.add(target, i, target[i] || 0, value[i], 0, 0, 0, 0, 0, 1);
4109      }
4110    }
4111  }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap;
4112  Tween.version = Timeline.version = gsap.version = "3.11.3";
4113  _coreReady = 1;
4114  _windowExists() && _wake();
4115  var Power0 = _easeMap.Power0,
4116      Power1 = _easeMap.Power1,
4117      Power2 = _easeMap.Power2,
4118      Power3 = _easeMap.Power3,
4119      Power4 = _easeMap.Power4,
4120      Linear = _easeMap.Linear,
4121      Quad = _easeMap.Quad,
4122      Cubic = _easeMap.Cubic,
4123      Quart = _easeMap.Quart,
4124      Quint = _easeMap.Quint,
4125      Strong = _easeMap.Strong,
4126      Elastic = _easeMap.Elastic,
4127      Back = _easeMap.Back,
4128      SteppedEase = _easeMap.SteppedEase,
4129      Bounce = _easeMap.Bounce,
4130      Sine = _easeMap.Sine,
4131      Expo = _easeMap.Expo,
4132      Circ = _easeMap.Circ;
4133
4134  var _win$1,
4135      _doc$1,
4136      _docElement,
4137      _pluginInitted,
4138      _tempDiv,
4139      _tempDivStyler,
4140      _recentSetterPlugin,
4141      _reverting$1,
4142      _windowExists$1 = function _windowExists() {
4143    return typeof window !== "undefined";
4144  },
4145      _transformProps = {},
4146      _RAD2DEG = 180 / Math.PI,
4147      _DEG2RAD = Math.PI / 180,
4148      _atan2 = Math.atan2,
4149      _bigNum$1 = 1e8,
4150      _capsExp = /([A-Z])/g,
4151      _horizontalExp = /(left|right|width|margin|padding|x)/i,
4152      _complexExp = /[\s,\(]\S/,
4153      _propertyAliases = {
4154    autoAlpha: "opacity,visibility",
4155    scale: "scaleX,scaleY",
4156    alpha: "opacity"
4157  },
4158      _renderCSSProp = function _renderCSSProp(ratio, data) {
4159    return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
4160  },
4161      _renderPropWithEnd = function _renderPropWithEnd(ratio, data) {
4162    return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data);
4163  },
4164      _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) {
4165    return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data);
4166  },
4167      _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) {
4168    var value = data.s + data.c * ratio;
4169    data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data);
4170  },
4171      _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) {
4172    return data.set(data.t, data.p, ratio ? data.e : data.b, data);
4173  },
4174      _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) {
4175    return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data);
4176  },
4177      _setterCSSStyle = function _setterCSSStyle(target, property, value) {
4178    return target.style[property] = value;
4179  },
4180      _setterCSSProp = function _setterCSSProp(target, property, value) {
4181    return target.style.setProperty(property, value);
4182  },
4183      _setterTransform = function _setterTransform(target, property, value) {
4184    return target._gsap[property] = value;
4185  },
4186      _setterScale = function _setterScale(target, property, value) {
4187    return target._gsap.scaleX = target._gsap.scaleY = value;
4188  },
4189      _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) {
4190    var cache = target._gsap;
4191    cache.scaleX = cache.scaleY = value;
4192    cache.renderTransform(ratio, cache);
4193  },
4194      _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) {
4195    var cache = target._gsap;
4196    cache[property] = value;
4197    cache.renderTransform(ratio, cache);
4198  },
4199      _transformProp = "transform",
4200      _transformOriginProp = _transformProp + "Origin",
4201      _saveStyle = function _saveStyle(property, isNotCSS) {
4202    var _this = this;
4203
4204    var target = this.target,
4205        style = target.style;
4206
4207    if (property in _transformProps) {
4208      this.tfm = this.tfm || {};
4209
4210      if (property !== "transform") {
4211        property = _propertyAliases[property] || property;
4212        ~property.indexOf(",") ? property.split(",").forEach(function (a) {
4213          return _this.tfm[a] = _get(target, a);
4214        }) : this.tfm[property] = target._gsap.x ? target._gsap[property] : _get(target, property);
4215      }
4216
4217      if (this.props.indexOf(_transformProp) >= 0) {
4218        return;
4219      }
4220
4221      if (target._gsap.svg) {
4222        this.svgo = target.getAttribute("data-svg-origin");
4223        this.props.push(_transformOriginProp, isNotCSS, "");
4224      }
4225
4226      property = _transformProp;
4227    }
4228
4229    (style || isNotCSS) && this.props.push(property, isNotCSS, style[property]);
4230  },
4231      _removeIndependentTransforms = function _removeIndependentTransforms(style) {
4232    if (style.translate) {
4233      style.removeProperty("translate");
4234      style.removeProperty("scale");
4235      style.removeProperty("rotate");
4236    }
4237  },
4238      _revertStyle = function _revertStyle() {
4239    var props = this.props,
4240        target = this.target,
4241        style = target.style,
4242        cache = target._gsap,
4243        i,
4244        p;
4245
4246    for (i = 0; i < props.length; i += 3) {
4247      props[i + 1] ? target[props[i]] = props[i + 2] : props[i + 2] ? style[props[i]] = props[i + 2] : style.removeProperty(props[i].replace(_capsExp, "-$1").toLowerCase());
4248    }
4249
4250    if (this.tfm) {
4251      for (p in this.tfm) {
4252        cache[p] = this.tfm[p];
4253      }
4254
4255      if (cache.svg) {
4256        cache.renderTransform();
4257        target.setAttribute("data-svg-origin", this.svgo || "");
4258      }
4259
4260      i = _reverting$1();
4261
4262      if (i && !i.isStart && !style[_transformProp]) {
4263        _removeIndependentTransforms(style);
4264
4265        cache.uncache = 1;
4266      }
4267    }
4268  },
4269      _getStyleSaver = function _getStyleSaver(target, properties) {
4270    var saver = {
4271      target: target,
4272      props: [],
4273      revert: _revertStyle,
4274      save: _saveStyle
4275    };
4276    properties && properties.split(",").forEach(function (p) {
4277      return saver.save(p);
4278    });
4279    return saver;
4280  },
4281      _supports3D,
4282      _createElement = function _createElement(type, ns) {
4283    var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type);
4284    return e.style ? e : _doc$1.createElement(type);
4285  },
4286      _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) {
4287    var cs = getComputedStyle(target);
4288    return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || "";
4289  },
4290      _prefixes = "O,Moz,ms,Ms,Webkit".split(","),
4291      _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) {
4292    var e = element || _tempDiv,
4293        s = e.style,
4294        i = 5;
4295
4296    if (property in s && !preferPrefix) {
4297      return property;
4298    }
4299
4300    property = property.charAt(0).toUpperCase() + property.substr(1);
4301
4302    while (i-- && !(_prefixes[i] + property in s)) {}
4303
4304    return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property;
4305  },
4306      _initCore = function _initCore() {
4307    if (_windowExists$1() && window.document) {
4308      _win$1 = window;
4309      _doc$1 = _win$1.document;
4310      _docElement = _doc$1.documentElement;
4311      _tempDiv = _createElement("div") || {
4312        style: {}
4313      };
4314      _tempDivStyler = _createElement("div");
4315      _transformProp = _checkPropPrefix(_transformProp);
4316      _transformOriginProp = _transformProp + "Origin";
4317      _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0";
4318      _supports3D = !!_checkPropPrefix("perspective");
4319      _reverting$1 = gsap.core.reverting;
4320      _pluginInitted = 1;
4321    }
4322  },
4323      _getBBoxHack = function _getBBoxHack(swapIfPossible) {
4324    var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"),
4325        oldParent = this.parentNode,
4326        oldSibling = this.nextSibling,
4327        oldCSS = this.style.cssText,
4328        bbox;
4329
4330    _docElement.appendChild(svg);
4331
4332    svg.appendChild(this);
4333    this.style.display = "block";
4334
4335    if (swapIfPossible) {
4336      try {
4337        bbox = this.getBBox();
4338        this._gsapBBox = this.getBBox;
4339        this.getBBox = _getBBoxHack;
4340      } catch (e) {}
4341    } else if (this._gsapBBox) {
4342      bbox = this._gsapBBox();
4343    }
4344
4345    if (oldParent) {
4346      if (oldSibling) {
4347        oldParent.insertBefore(this, oldSibling);
4348      } else {
4349        oldParent.appendChild(this);
4350      }
4351    }
4352
4353    _docElement.removeChild(svg);
4354
4355    this.style.cssText = oldCSS;
4356    return bbox;
4357  },
4358      _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) {
4359    var i = attributesArray.length;
4360
4361    while (i--) {
4362      if (target.hasAttribute(attributesArray[i])) {
4363        return target.getAttribute(attributesArray[i]);
4364      }
4365    }
4366  },
4367      _getBBox = function _getBBox(target) {
4368    var bounds;
4369
4370    try {
4371      bounds = target.getBBox();
4372    } catch (error) {
4373      bounds = _getBBoxHack.call(target, true);
4374    }
4375
4376    bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true));
4377    return bounds && !bounds.width && !bounds.x && !bounds.y ? {
4378      x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0,
4379      y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0,
4380      width: 0,
4381      height: 0
4382    } : bounds;
4383  },
4384      _isSVG = function _isSVG(e) {
4385    return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e));
4386  },
4387      _removeProperty = function _removeProperty(target, property) {
4388    if (property) {
4389      var style = target.style;
4390
4391      if (property in _transformProps && property !== _transformOriginProp) {
4392        property = _transformProp;
4393      }
4394
4395      if (style.removeProperty) {
4396        if (property.substr(0, 2) === "ms" || property.substr(0, 6) === "webkit") {
4397          property = "-" + property;
4398        }
4399
4400        style.removeProperty(property.replace(_capsExp, "-$1").toLowerCase());
4401      } else {
4402        style.removeAttribute(property);
4403      }
4404    }
4405  },
4406      _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) {
4407    var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue);
4408    plugin._pt = pt;
4409    pt.b = beginning;
4410    pt.e = end;
4411
4412    plugin._props.push(property);
4413
4414    return pt;
4415  },
4416      _nonConvertibleUnits = {
4417    deg: 1,
4418    rad: 1,
4419    turn: 1
4420  },
4421      _nonStandardLayouts = {
4422    grid: 1,
4423    flex: 1
4424  },
4425      _convertToUnit = function _convertToUnit(target, property, value, unit) {
4426    var curValue = parseFloat(value) || 0,
4427        curUnit = (value + "").trim().substr((curValue + "").length) || "px",
4428        style = _tempDiv.style,
4429        horizontal = _horizontalExp.test(property),
4430        isRootSVG = target.tagName.toLowerCase() === "svg",
4431        measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"),
4432        amount = 100,
4433        toPixels = unit === "px",
4434        toPercent = unit === "%",
4435        px,
4436        parent,
4437        cache,
4438        isSVG;
4439
4440    if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) {
4441      return curValue;
4442    }
4443
4444    curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px"));
4445    isSVG = target.getCTM && _isSVG(target);
4446
4447    if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) {
4448      px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty];
4449      return _round(toPercent ? curValue / px * amount : curValue / 100 * px);
4450    }
4451
4452    style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit);
4453    parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode;
4454
4455    if (isSVG) {
4456      parent = (target.ownerSVGElement || {}).parentNode;
4457    }
4458
4459    if (!parent || parent === _doc$1 || !parent.appendChild) {
4460      parent = _doc$1.body;
4461    }
4462
4463    cache = parent._gsap;
4464
4465    if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time && !cache.uncache) {
4466      return _round(curValue / cache.width * amount);
4467    } else {
4468      (toPercent || curUnit === "%") && !_nonStandardLayouts[_getComputedProperty(parent, "display")] && (style.position = _getComputedProperty(target, "position"));
4469      parent === target && (style.position = "static");
4470      parent.appendChild(_tempDiv);
4471      px = _tempDiv[measureProperty];
4472      parent.removeChild(_tempDiv);
4473      style.position = "absolute";
4474
4475      if (horizontal && toPercent) {
4476        cache = _getCache(parent);
4477        cache.time = _ticker.time;
4478        cache.width = parent[measureProperty];
4479      }
4480    }
4481
4482    return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0);
4483  },
4484      _get = function _get(target, property, unit, uncache) {
4485    var value;
4486    _pluginInitted || _initCore();
4487
4488    if (property in _propertyAliases && property !== "transform") {
4489      property = _propertyAliases[property];
4490
4491      if (~property.indexOf(",")) {
4492        property = property.split(",")[0];
4493      }
4494    }
4495
4496    if (_transformProps[property] && property !== "transform") {
4497      value = _parseTransform(target, uncache);
4498      value = property !== "transformOrigin" ? value[property] : value.svg ? value.origin : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px";
4499    } else {
4500      value = target.style[property];
4501
4502      if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) {
4503        value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0);
4504      }
4505    }
4506
4507    return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value;
4508  },
4509      _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) {
4510    if (!start || start === "none") {
4511      var p = _checkPropPrefix(prop, target, 1),
4512          s = p && _getComputedProperty(target, p, 1);
4513
4514      if (s && s !== start) {
4515        prop = p;
4516        start = s;
4517      } else if (prop === "borderColor") {
4518        start = _getComputedProperty(target, "borderTopColor");
4519      }
4520    }
4521
4522    var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString),
4523        index = 0,
4524        matchIndex = 0,
4525        a,
4526        result,
4527        startValues,
4528        startNum,
4529        color,
4530        startValue,
4531        endValue,
4532        endNum,
4533        chunk,
4534        endUnit,
4535        startUnit,
4536        endValues;
4537    pt.b = start;
4538    pt.e = end;
4539    start += "";
4540    end += "";
4541
4542    if (end === "auto") {
4543      target.style[prop] = end;
4544      end = _getComputedProperty(target, prop) || end;
4545      target.style[prop] = start;
4546    }
4547
4548    a = [start, end];
4549
4550    _colorStringFilter(a);
4551
4552    start = a[0];
4553    end = a[1];
4554    startValues = start.match(_numWithUnitExp) || [];
4555    endValues = end.match(_numWithUnitExp) || [];
4556
4557    if (endValues.length) {
4558      while (result = _numWithUnitExp.exec(end)) {
4559        endValue = result[0];
4560        chunk = end.substring(index, result.index);
4561
4562        if (color) {
4563          color = (color + 1) % 5;
4564        } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") {
4565          color = 1;
4566        }
4567
4568        if (endValue !== (startValue = startValues[matchIndex++] || "")) {
4569          startNum = parseFloat(startValue) || 0;
4570          startUnit = startValue.substr((startNum + "").length);
4571          endValue.charAt(1) === "=" && (endValue = _parseRelative(startNum, endValue) + startUnit);
4572          endNum = parseFloat(endValue);
4573          endUnit = endValue.substr((endNum + "").length);
4574          index = _numWithUnitExp.lastIndex - endUnit.length;
4575
4576          if (!endUnit) {
4577            endUnit = endUnit || _config.units[prop] || startUnit;
4578
4579            if (index === end.length) {
4580              end += endUnit;
4581              pt.e += endUnit;
4582            }
4583          }
4584
4585          if (startUnit !== endUnit) {
4586            startNum = _convertToUnit(target, prop, startValue, endUnit) || 0;
4587          }
4588
4589          pt._pt = {
4590            _next: pt._pt,
4591            p: chunk || matchIndex === 1 ? chunk : ",",
4592            s: startNum,
4593            c: endNum - startNum,
4594            m: color && color < 4 || prop === "zIndex" ? Math.round : 0
4595          };
4596        }
4597      }
4598
4599      pt.c = index < end.length ? end.substring(index, end.length) : "";
4600    } else {
4601      pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue;
4602    }
4603
4604    _relExp.test(end) && (pt.e = 0);
4605    this._pt = pt;
4606    return pt;
4607  },
4608      _keywordToPercent = {
4609    top: "0%",
4610    bottom: "100%",
4611    left: "0%",
4612    right: "100%",
4613    center: "50%"
4614  },
4615      _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) {
4616    var split = value.split(" "),
4617        x = split[0],
4618        y = split[1] || "50%";
4619
4620    if (x === "top" || x === "bottom" || y === "left" || y === "right") {
4621      value = x;
4622      x = y;
4623      y = value;
4624    }
4625
4626    split[0] = _keywordToPercent[x] || x;
4627    split[1] = _keywordToPercent[y] || y;
4628    return split.join(" ");
4629  },
4630      _renderClearProps = function _renderClearProps(ratio, data) {
4631    if (data.tween && data.tween._time === data.tween._dur) {
4632      var target = data.t,
4633          style = target.style,
4634          props = data.u,
4635          cache = target._gsap,
4636          prop,
4637          clearTransforms,
4638          i;
4639
4640      if (props === "all" || props === true) {
4641        style.cssText = "";
4642        clearTransforms = 1;
4643      } else {
4644        props = props.split(",");
4645        i = props.length;
4646
4647        while (--i > -1) {
4648          prop = props[i];
4649
4650          if (_transformProps[prop]) {
4651            clearTransforms = 1;
4652            prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp;
4653          }
4654
4655          _removeProperty(target, prop);
4656        }
4657      }
4658
4659      if (clearTransforms) {
4660        _removeProperty(target, _transformProp);
4661
4662        if (cache) {
4663          cache.svg && target.removeAttribute("transform");
4664
4665          _parseTransform(target, 1);
4666
4667          cache.uncache = 1;
4668
4669          _removeIndependentTransforms(style);
4670        }
4671      }
4672    }
4673  },
4674      _specialProps = {
4675    clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 1,580 bytes, lines 4676-4716
4676      if (tween.data !== "isFromStart") {
4677        var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps);
4678        pt.u = endValue;
4679        pt.pr = -10;
4680        pt.tween = tween;
4681
4682        plugin._props.push(property);
4683
4684        return 1;
4685      }
4686    }
4687  },
4688      _identity2DMatrix = [1, 0, 0, 1, 0, 0],
4689      _rotationalProperties = {},
4690      _isNullTransform = function _isNullTransform(value) {
4691    return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value;
4692  },
4693      _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) {
4694    var matrixString = _getComputedProperty(target, _transformProp);
4695
4696    return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round);
4697  },
4698      _getMatrix = function _getMatrix(target, force2D) {
4699    var cache = target._gsap || _getCache(target),
4700        style = target.style,
4701        matrix = _getComputedTransformMatrixAsArray(target),
4702        parent,
4703        nextSibling,
4704        temp,
4705        addedToDOM;
4706
4707    if (cache.svg && target.getAttribute("transform")) {
4708      temp = target.transform.baseVal.consolidate().matrix;
4709      matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f];
4710      return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix;
4711    } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) {
4712      temp = style.display;
4713      style.display = "block";
4714      parent = target.parentNode;
4715
4716      if (!parent || !target.offsetParent
vendor: 18,897 bytes, lines 4716-5313
4716) {
4717        addedToDOM = 1;
4718        nextSibling = target.nextElementSibling;
4719
4720        _docElement.appendChild(target);
4721      }
4722
4723      matrix = _getComputedTransformMatrixAsArray(target);
4724      temp ? style.display = temp : _removeProperty(target, "display");
4725
4726      if (addedToDOM) {
4727        nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target);
4728      }
4729    }
4730
4731    return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix;
4732  },
4733      _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) {
4734    var cache = target._gsap,
4735        matrix = matrixArray || _getMatrix(target, true),
4736        xOriginOld = cache.xOrigin || 0,
4737        yOriginOld = cache.yOrigin || 0,
4738        xOffsetOld = cache.xOffset || 0,
4739        yOffsetOld = cache.yOffset || 0,
4740        a = matrix[0],
4741        b = matrix[1],
4742        c = matrix[2],
4743        d = matrix[3],
4744        tx = matrix[4],
4745        ty = matrix[5],
4746        originSplit = origin.split(" "),
4747        xOrigin = parseFloat(originSplit[0]) || 0,
4748        yOrigin = parseFloat(originSplit[1]) || 0,
4749        bounds,
4750        determinant,
4751        x,
4752        y;
4753
4754    if (!originIsAbsolute) {
4755      bounds = _getBBox(target);
4756      xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * bounds.width : xOrigin);
4757      yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin);
4758    } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) {
4759      x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant;
4760      y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant;
4761      xOrigin = x;
4762      yOrigin = y;
4763    }
4764
4765    if (smooth || smooth !== false && cache.smooth) {
4766      tx = xOrigin - xOriginOld;
4767      ty = yOrigin - yOriginOld;
4768      cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx;
4769      cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty;
4770    } else {
4771      cache.xOffset = cache.yOffset = 0;
4772    }
4773
4774    cache.xOrigin = xOrigin;
4775    cache.yOrigin = yOrigin;
4776    cache.smooth = !!smooth;
4777    cache.origin = origin;
4778    cache.originIsAbsolute = !!originIsAbsolute;
4779    target.style[_transformOriginProp] = "0px 0px";
4780
4781    if (pluginToAddPropTweensTo) {
4782      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin);
4783
4784      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin);
4785
4786      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset);
4787
4788      _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset);
4789    }
4790
4791    target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin);
4792  },
4793      _parseTransform = function _parseTransform(target, uncache) {
4794    var cache = target._gsap || new GSCache(target);
4795
4796    if ("x" in cache && !uncache && !cache.uncache) {
4797      return cache;
4798    }
4799
4800    var style = target.style,
4801        invertedScaleX = cache.scaleX < 0,
4802        px = "px",
4803        deg = "deg",
4804        cs = getComputedStyle(target),
4805        origin = _getComputedProperty(target, _transformOriginProp) || "0",
4806        x,
4807        y,
4808        z,
4809        scaleX,
4810        scaleY,
4811        rotation,
4812        rotationX,
4813        rotationY,
4814        skewX,
4815        skewY,
4816        perspective,
4817        xOrigin,
4818        yOrigin,
4819        matrix,
4820        angle,
4821        cos,
4822        sin,
4823        a,
4824        b,
4825        c,
4826        d,
4827        a12,
4828        a22,
4829        t1,
4830        t2,
4831        t3,
4832        a13,
4833        a23,
4834        a33,
4835        a42,
4836        a43,
4837        a32;
4838    x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0;
4839    scaleX = scaleY = 1;
4840    cache.svg = !!(target.getCTM && _isSVG(target));
4841
4842    if (cs.translate) {
4843      if (cs.translate !== "none" || cs.scale !== "none" || cs.rotate !== "none") {
4844        style[_transformProp] = (cs.translate !== "none" ? "translate3d(" + (cs.translate + " 0 0").split(" ").slice(0, 3).join(", ") + ") " : "") + (cs.rotate !== "none" ? "rotate(" + cs.rotate + ") " : "") + (cs.scale !== "none" ? "scale(" + cs.scale.split(" ").join(",") + ") " : "") + (cs[_transformProp] !== "none" ? cs[_transformProp] : "");
4845      }
4846
4847      style.scale = style.rotate = style.translate = "none";
4848    }
4849
4850    matrix = _getMatrix(target, cache.svg);
4851
4852    if (cache.svg) {
4853      if (cache.uncache) {
4854        t2 = target.getBBox();
4855        origin = cache.xOrigin - t2.x + "px " + (cache.yOrigin - t2.y) + "px";
4856        t1 = "";
4857      } else {
4858        t1 = !uncache && target.getAttribute("data-svg-origin");
4859      }
4860
4861      _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix);
4862    }
4863
4864    xOrigin = cache.xOrigin || 0;
4865    yOrigin = cache.yOrigin || 0;
4866
4867    if (matrix !== _identity2DMatrix) {
4868      a = matrix[0];
4869      b = matrix[1];
4870      c = matrix[2];
4871      d = matrix[3];
4872      x = a12 = matrix[4];
4873      y = a22 = matrix[5];
4874
4875      if (matrix.length === 6) {
4876        scaleX = Math.sqrt(a * a + b * b);
4877        scaleY = Math.sqrt(d * d + c * c);
4878        rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0;
4879        skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0;
4880        skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD)));
4881
4882        if (cache.svg) {
4883          x -= xOrigin - (xOrigin * a + yOrigin * c);
4884          y -= yOrigin - (xOrigin * b + yOrigin * d);
4885        }
4886      } else {
4887        a32 = matrix[6];
4888        a42 = matrix[7];
4889        a13 = matrix[8];
4890        a23 = matrix[9];
4891        a33 = matrix[10];
4892        a43 = matrix[11];
4893        x = matrix[12];
4894        y = matrix[13];
4895        z = matrix[14];
4896        angle = _atan2(a32, a33);
4897        rotationX = angle * _RAD2DEG;
4898
4899        if (angle) {
4900          cos = Math.cos(-angle);
4901          sin = Math.sin(-angle);
4902          t1 = a12 * cos + a13 * sin;
4903          t2 = a22 * cos + a23 * sin;
4904          t3 = a32 * cos + a33 * sin;
4905          a13 = a12 * -sin + a13 * cos;
4906          a23 = a22 * -sin + a23 * cos;
4907          a33 = a32 * -sin + a33 * cos;
4908          a43 = a42 * -sin + a43 * cos;
4909          a12 = t1;
4910          a22 = t2;
4911          a32 = t3;
4912        }
4913
4914        angle = _atan2(-c, a33);
4915        rotationY = angle * _RAD2DEG;
4916
4917        if (angle) {
4918          cos = Math.cos(-angle);
4919          sin = Math.sin(-angle);
4920          t1 = a * cos - a13 * sin;
4921          t2 = b * cos - a23 * sin;
4922          t3 = c * cos - a33 * sin;
4923          a43 = d * sin + a43 * cos;
4924          a = t1;
4925          b = t2;
4926          c = t3;
4927        }
4928
4929        angle = _atan2(b, a);
4930        rotation = angle * _RAD2DEG;
4931
4932        if (angle) {
4933          cos = Math.cos(angle);
4934          sin = Math.sin(angle);
4935          t1 = a * cos + b * sin;
4936          t2 = a12 * cos + a22 * sin;
4937          b = b * cos - a * sin;
4938          a22 = a22 * cos - a12 * sin;
4939          a = t1;
4940          a12 = t2;
4941        }
4942
4943        if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) {
4944          rotationX = rotation = 0;
4945          rotationY = 180 - rotationY;
4946        }
4947
4948        scaleX = _round(Math.sqrt(a * a + b * b + c * c));
4949        scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32));
4950        angle = _atan2(a12, a22);
4951        skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0;
4952        perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0;
4953      }
4954
4955      if (cache.svg) {
4956        t1 = target.getAttribute("transform");
4957        cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp));
4958        t1 && target.setAttribute("transform", t1);
4959      }
4960    }
4961
4962    if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) {
4963      if (invertedScaleX) {
4964        scaleX *= -1;
4965        skewX += rotation <= 0 ? 180 : -180;
4966        rotation += rotation <= 0 ? 180 : -180;
4967      } else {
4968        scaleY *= -1;
4969        skewX += skewX <= 0 ? 180 : -180;
4970      }
4971    }
4972
4973    uncache = uncache || cache.uncache;
4974    cache.x = x - ((cache.xPercent = x && (!uncache && cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px;
4975    cache.y = y - ((cache.yPercent = y && (!uncache && cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px;
4976    cache.z = z + px;
4977    cache.scaleX = _round(scaleX);
4978    cache.scaleY = _round(scaleY);
4979    cache.rotation = _round(rotation) + deg;
4980    cache.rotationX = _round(rotationX) + deg;
4981    cache.rotationY = _round(rotationY) + deg;
4982    cache.skewX = skewX + deg;
4983    cache.skewY = skewY + deg;
4984    cache.transformPerspective = perspective + px;
4985
4986    if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || 0) {
4987      style[_transformOriginProp] = _firstTwoOnly(origin);
4988    }
4989
4990    cache.xOffset = cache.yOffset = 0;
4991    cache.force3D = _config.force3D;
4992    cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms;
4993    cache.uncache = 0;
4994    return cache;
4995  },
4996      _firstTwoOnly = function _firstTwoOnly(value) {
4997    return (value = value.split(" "))[0] + " " + value[1];
4998  },
4999      _addPxTranslate = function _addPxTranslate(target, start, value) {
5000    var unit = getUnit(start);
5001    return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit;
5002  },
5003      _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) {
5004    cache.z = "0px";
5005    cache.rotationY = cache.rotationX = "0deg";
5006    cache.force3D = 0;
5007
5008    _renderCSSTransforms(ratio, cache);
5009  },
5010      _zeroDeg = "0deg",
5011      _zeroPx = "0px",
5012      _endParenthesis = ") ",
5013      _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) {
5014    var _ref = cache || this,
5015        xPercent = _ref.xPercent,
5016        yPercent = _ref.yPercent,
5017        x = _ref.x,
5018        y = _ref.y,
5019        z = _ref.z,
5020        rotation = _ref.rotation,
5021        rotationY = _ref.rotationY,
5022        rotationX = _ref.rotationX,
5023        skewX = _ref.skewX,
5024        skewY = _ref.skewY,
5025        scaleX = _ref.scaleX,
5026        scaleY = _ref.scaleY,
5027        transformPerspective = _ref.transformPerspective,
5028        force3D = _ref.force3D,
5029        target = _ref.target,
5030        zOrigin = _ref.zOrigin,
5031        transforms = "",
5032        use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true;
5033
5034    if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) {
5035      var angle = parseFloat(rotationY) * _DEG2RAD,
5036          a13 = Math.sin(angle),
5037          a33 = Math.cos(angle),
5038          cos;
5039
5040      angle = parseFloat(rotationX) * _DEG2RAD;
5041      cos = Math.cos(angle);
5042      x = _addPxTranslate(target, x, a13 * cos * -zOrigin);
5043      y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin);
5044      z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin);
5045    }
5046
5047    if (transformPerspective !== _zeroPx) {
5048      transforms += "perspective(" + transformPerspective + _endParenthesis;
5049    }
5050
5051    if (xPercent || yPercent) {
5052      transforms += "translate(" + xPercent + "%, " + yPercent + "%) ";
5053    }
5054
5055    if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) {
5056      transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis;
5057    }
5058
5059    if (rotation !== _zeroDeg) {
5060      transforms += "rotate(" + rotation + _endParenthesis;
5061    }
5062
5063    if (rotationY !== _zeroDeg) {
5064      transforms += "rotateY(" + rotationY + _endParenthesis;
5065    }
5066
5067    if (rotationX !== _zeroDeg) {
5068      transforms += "rotateX(" + rotationX + _endParenthesis;
5069    }
5070
5071    if (skewX !== _zeroDeg || skewY !== _zeroDeg) {
5072      transforms += "skew(" + skewX + ", " + skewY + _endParenthesis;
5073    }
5074
5075    if (scaleX !== 1 || scaleY !== 1) {
5076      transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis;
5077    }
5078
5079    target.style[_transformProp] = transforms || "translate(0, 0)";
5080  },
5081      _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) {
5082    var _ref2 = cache || this,
5083        xPercent = _ref2.xPercent,
5084        yPercent = _ref2.yPercent,
5085        x = _ref2.x,
5086        y = _ref2.y,
5087        rotation = _ref2.rotation,
5088        skewX = _ref2.skewX,
5089        skewY = _ref2.skewY,
5090        scaleX = _ref2.scaleX,
5091        scaleY = _ref2.scaleY,
5092        target = _ref2.target,
5093        xOrigin = _ref2.xOrigin,
5094        yOrigin = _ref2.yOrigin,
5095        xOffset = _ref2.xOffset,
5096        yOffset = _ref2.yOffset,
5097        forceCSS = _ref2.forceCSS,
5098        tx = parseFloat(x),
5099        ty = parseFloat(y),
5100        a11,
5101        a21,
5102        a12,
5103        a22,
5104        temp;
5105
5106    rotation = parseFloat(rotation);
5107    skewX = parseFloat(skewX);
5108    skewY = parseFloat(skewY);
5109
5110    if (skewY) {
5111      skewY = parseFloat(skewY);
5112      skewX += skewY;
5113      rotation += skewY;
5114    }
5115
5116    if (rotation || skewX) {
5117      rotation *= _DEG2RAD;
5118      skewX *= _DEG2RAD;
5119      a11 = Math.cos(rotation) * scaleX;
5120      a21 = Math.sin(rotation) * scaleX;
5121      a12 = Math.sin(rotation - skewX) * -scaleY;
5122      a22 = Math.cos(rotation - skewX) * scaleY;
5123
5124      if (skewX) {
5125        skewY *= _DEG2RAD;
5126        temp = Math.tan(skewX - skewY);
5127        temp = Math.sqrt(1 + temp * temp);
5128        a12 *= temp;
5129        a22 *= temp;
5130
5131        if (skewY) {
5132          temp = Math.tan(skewY);
5133          temp = Math.sqrt(1 + temp * temp);
5134          a11 *= temp;
5135          a21 *= temp;
5136        }
5137      }
5138
5139      a11 = _round(a11);
5140      a21 = _round(a21);
5141      a12 = _round(a12);
5142      a22 = _round(a22);
5143    } else {
5144      a11 = scaleX;
5145      a22 = scaleY;
5146      a21 = a12 = 0;
5147    }
5148
5149    if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) {
5150      tx = _convertToUnit(target, "x", x, "px");
5151      ty = _convertToUnit(target, "y", y, "px");
5152    }
5153
5154    if (xOrigin || yOrigin || xOffset || yOffset) {
5155      tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset);
5156      ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset);
5157    }
5158
5159    if (xPercent || yPercent) {
5160      temp = target.getBBox();
5161      tx = _round(tx + xPercent / 100 * temp.width);
5162      ty = _round(ty + yPercent / 100 * temp.height);
5163    }
5164
5165    temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")";
5166    target.setAttribute("transform", temp);
5167    forceCSS && (target.style[_transformProp] = temp);
5168  },
5169      _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue) {
5170    var cap = 360,
5171        isString = _isString(endValue),
5172        endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1),
5173        change = endNum - startNum,
5174        finalValue = startNum + change + "deg",
5175        direction,
5176        pt;
5177
5178    if (isString) {
5179      direction = endValue.split("_")[1];
5180
5181      if (direction === "short") {
5182        change %= cap;
5183
5184        if (change !== change % (cap / 2)) {
5185          change += change < 0 ? cap : -cap;
5186        }
5187      }
5188
5189      if (direction === "cw" && change < 0) {
5190        change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap;
5191      } else if (direction === "ccw" && change > 0) {
5192        change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap;
5193      }
5194    }
5195
5196    plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd);
5197    pt.e = finalValue;
5198    pt.u = "deg";
5199
5200    plugin._props.push(property);
5201
5202    return pt;
5203  },
5204      _assign = function _assign(target, source) {
5205    for (var p in source) {
5206      target[p] = source[p];
5207    }
5208
5209    return target;
5210  },
5211      _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) {
5212    var startCache = _assign({}, target._gsap),
5213        exclude = "perspective,force3D,transformOrigin,svgOrigin",
5214        style = target.style,
5215        endCache,
5216        p,
5217        startValue,
5218        endValue,
5219        startNum,
5220        endNum,
5221        startUnit,
5222        endUnit;
5223
5224    if (startCache.svg) {
5225      startValue = target.getAttribute("transform");
5226      target.setAttribute("transform", "");
5227      style[_transformProp] = transforms;
5228      endCache = _parseTransform(target, 1);
5229
5230      _removeProperty(target, _transformProp);
5231
5232      target.setAttribute("transform", startValue);
5233    } else {
5234      startValue = getComputedStyle(target)[_transformProp];
5235      style[_transformProp] = transforms;
5236      endCache = _parseTransform(target, 1);
5237      style[_transformProp] = startValue;
5238    }
5239
5240    for (p in _transformProps) {
5241      startValue = startCache[p];
5242      endValue = endCache[p];
5243
5244      if (startValue !== endValue && exclude.indexOf(p) < 0) {
5245        startUnit = getUnit(startValue);
5246        endUnit = getUnit(endValue);
5247        startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue);
5248        endNum = parseFloat(endValue);
5249        plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp);
5250        plugin._pt.u = endUnit || 0;
5251
5252        plugin._props.push(p);
5253      }
5254    }
5255
5256    _assign(endCache, startCache);
5257  };
5258
5259  _forEachName("padding,margin,Width,Radius", function (name, index) {
5260    var t = "Top",
5261        r = "Right",
5262        b = "Bottom",
5263        l = "Left",
5264        props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) {
5265      return index < 2 ? name + side : "border" + side + name;
5266    });
5267
5268    _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) {
5269      var a, vars;
5270
5271      if (arguments.length < 4) {
5272        a = props.map(function (prop) {
5273          return _get(plugin, prop, property);
5274        });
5275        vars = a.join(" ");
5276        return vars.split(a[0]).length === 5 ? a[0] : vars;
5277      }
5278
5279      a = (endValue + "").split(" ");
5280      vars = {};
5281      props.forEach(function (prop, i) {
5282        return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0];
5283      });
5284      plugin.init(target, vars, tween);
5285    };
5286  });
5287
5288  var CSSPlugin = {
5289    name: "css",
5290    register: _initCore,
5291    targetTest: function targetTest(target) {
5292      return target.style && target.nodeType;
5293    },
5294    init: function init(target, vars, tween, index, targets) {
5295      var props = this._props,
5296          style = target.style,
5297          startAt = tween.vars.startAt,
5298          startValue,
5299          endValue,
5300          endNum,
5301          startNum,
5302          type,
5303          specialProp,
5304          p,
5305          startUnit,
5306          endUnit,
5307          relative,
5308          isTransformRelated,
5309          transformPropTween,
5310          cache,
5311          smooth,
5312          hasPriority,
5313          inlineProps
vendor: 7,960 bytes, lines 5313-5500
5313;
5314      _pluginInitted || _initCore();
5315      this.styles = this.styles || _getStyleSaver(target);
5316      inlineProps = this.styles.props;
5317      this.tween = tween;
5318
5319      for (p in vars) {
5320        if (p === "autoRound") {
5321          continue;
5322        }
5323
5324        endValue = vars[p];
5325
5326        if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) {
5327          continue;
5328        }
5329
5330        type = typeof endValue;
5331        specialProp = _specialProps[p];
5332
5333        if (type === "function") {
5334          endValue = endValue.call(tween, index, target, targets);
5335          type = typeof endValue;
5336        }
5337
5338        if (type === "string" && ~endValue.indexOf("random(")) {
5339          endValue = _replaceRandom(endValue);
5340        }
5341
5342        if (specialProp) {
5343          specialProp(this, target, p, endValue, tween) && (hasPriority = 1);
5344        } else if (p.substr(0, 2) === "--") {
5345          startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim();
5346          endValue += "";
5347          _colorExp.lastIndex = 0;
5348
5349          if (!_colorExp.test(startValue)) {
5350            startUnit = getUnit(startValue);
5351            endUnit = getUnit(endValue);
5352          }
5353
5354          endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit);
5355          this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p);
5356          props.push(p);
5357          inlineProps.push(p, 0, style[p]);
5358        } else if (type !== "undefined") {
5359          if (startAt && p in startAt) {
5360            startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p];
5361            _isString(startValue) && ~startValue.indexOf("random(") && (startValue = _replaceRandom(startValue));
5362            getUnit(startValue + "") || (startValue += _config.units[p] || getUnit(_get(target, p)) || "");
5363            (startValue + "").charAt(1) === "=" && (startValue = _get(target, p));
5364          } else {
5365            startValue = _get(target, p);
5366          }
5367
5368          startNum = parseFloat(startValue);
5369          relative = type === "string" && endValue.charAt(1) === "=" && endValue.substr(0, 2);
5370          relative && (endValue = endValue.substr(2));
5371          endNum = parseFloat(endValue);
5372
5373          if (p in _propertyAliases) {
5374            if (p === "autoAlpha") {
5375              if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) {
5376                startNum = 0;
5377              }
5378
5379              inlineProps.push("visibility", 0, style.visibility);
5380
5381              _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum);
5382            }
5383
5384            if (p !== "scale" && p !== "transform") {
5385              p = _propertyAliases[p];
5386              ~p.indexOf(",") && (p = p.split(",")[0]);
5387            }
5388          }
5389
5390          isTransformRelated = p in _transformProps;
5391
5392          if (isTransformRelated) {
5393            this.styles.save(p);
5394
5395            if (!transformPropTween) {
5396              cache = target._gsap;
5397              cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform);
5398              smooth = vars.smoothOrigin !== false && cache.smooth;
5399              transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1);
5400              transformPropTween.dep = 1;
5401            }
5402
5403            if (p === "scale") {
5404              this._pt = new PropTween(this._pt, cache, "scaleY", startNum, (relative ? _parseRelative(startNum, relative + endNum) : endNum) - startNum || 0, _renderCSSProp);
5405              this._pt.u = 0;
5406              props.push("scaleY", p);
5407              p += "X";
5408            } else if (p === "transformOrigin") {
5409              inlineProps.push(_transformOriginProp, 0, style[_transformOriginProp]);
5410              endValue = _convertKeywordsToPercentages(endValue);
5411
5412              if (cache.svg) {
5413                _applySVGOrigin(target, endValue, 0, smooth, 0, this);
5414              } else {
5415                endUnit = parseFloat(endValue.split(" ")[2]) || 0;
5416                endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit);
5417
5418                _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue));
5419              }
5420
5421              continue;
5422            } else if (p === "svgOrigin") {
5423              _applySVGOrigin(target, endValue, 1, smooth, 0, this);
5424
5425              continue;
5426            } else if (p in _rotationalProperties) {
5427              _addRotationalPropTween(this, cache, p, startNum, relative ? _parseRelative(startNum, relative + endValue) : endValue);
5428
5429              continue;
5430            } else if (p === "smoothOrigin") {
5431              _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue);
5432
5433              continue;
5434            } else if (p === "force3D") {
5435              cache[p] = endValue;
5436              continue;
5437            } else if (p === "transform") {
5438              _addRawTransformPTs(this, endValue, target);
5439
5440              continue;
5441            }
5442          } else if (!(p in style)) {
5443            p = _checkPropPrefix(p) || p;
5444          }
5445
5446          if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) {
5447            startUnit = (startValue + "").substr((startNum + "").length);
5448            endNum || (endNum = 0);
5449            endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit);
5450            startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit));
5451            this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, (relative ? _parseRelative(startNum, relative + endNum) : endNum) - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp);
5452            this._pt.u = endUnit || 0;
5453
5454            if (startUnit !== endUnit && endUnit !== "%") {
5455              this._pt.b = startValue;
5456              this._pt.r = _renderCSSPropWithBeginning;
5457            }
5458          } else if (!(p in style)) {
5459            if (p in target) {
5460              this.add(target, p, startValue || target[p], relative ? relative + endValue : endValue, index, targets);
5461            } else {
5462              _missingPlugin(p, endValue);
5463
5464              continue;
5465            }
5466          } else {
5467            _tweenComplexCSSString.call(this, target, p, startValue, relative ? relative + endValue : endValue);
5468          }
5469
5470          isTransformRelated || (p in style ? inlineProps.push(p, 0, style[p]) : inlineProps.push(p, 1, startValue || target[p]));
5471          props.push(p);
5472        }
5473      }
5474
5475      hasPriority && _sortPropTweensByPriority(this);
5476    },
5477    render: function render(ratio, data) {
5478      if (data.tween._time || !_reverting$1()) {
5479        var pt = data._pt;
5480
5481        while (pt) {
5482          pt.r(ratio, pt.d);
5483          pt = pt._next;
5484        }
5485      } else {
5486        data.styles.revert();
5487      }
5488    },
5489    get: _get,
5490    aliases: _propertyAliases,
5491    getSetter: function getSetter(target, property, plugin) {
5492      var p = _propertyAliases[property];
5493      p && p.indexOf(",") < 0 && (property = p);
5494      return property in _transformProps && property !== _transformOriginProp && (target._gsap.x || _get(target, "x")) ? plugin && _recentSetterPlugin === plugin ? property === "scale" ? _setterScale : _setterTransform : (_recentSetterPlugin = plugin || {}) && (property === "scale" ? _setterScaleWithRender : _setterTransformWithRender) : target.style && !_isUndefined(target.style[property]) ? _setterCSSStyle : ~property.indexOf("-") ? _setterCSSProp : _getSetter(target, property);
5495    },
5496    core: {
5497      _removeProperty: _removeProperty,
5498      _getMatrix: _getMatrix
5499    }
5500  };
5501  gsap.utils.checkPrefix = _checkPropPrefix;
5502  gsap.core.getStyleSaver = _getStyleSaver;
5503
5504  (function (positionAndScale, rotation, others, aliases) {
5505    var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) {
5506      _transformProps[name] = 1;
5507    });
5508
5509    _forEachName(rotation, function (name) {
5510      _config.units[name] = "deg";
5511      _rotationalProperties[name] = 1;
5512    });
5513
5514    _propertyAliases[all[13]] = positionAndScale + "," + rotation;
5515
5516    _forEachName(aliases, function (name) {
5517      var split = name.split(":");
5518      _propertyAliases[split[1]] = all[split[0]];
5519    });
5520  })("x,y,z,scale,scaleX,scaleY,xPercent,yPercent", "rotation,rotationX,rotationY,skewX,skewY", "transform,transformOrigin,svgOrigin,force3D,smoothOrigin,transformPerspective", "0:translateX,1:translateY,2:translateZ,8:rotate,8:rotationZ,8:rotateZ,9:rotateX,10:rotateY");
5521
5522  _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) {
5523    _config.units[name] = "px";
5524  });
5525
5526  gsap.registerPlugin(CSSPlugin);
5527
5528  var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap,
5529      TweenMaxWithCSS = gsapWithCSS.core.Tween;
5530
5531  exports.Back = Back;
5532  exports.Bounce = Bounce;
5533  exports.CSSPlugin = CSSPlugin;
5534  exports.Circ = Circ;
5535  exports.Cubic = Cubic;
5536  exports.Elastic = Elastic;
5537  exports.Expo = Expo;
5538  exports.Linear = Linear;
5539  exports.Power0 = Power0;
5540  exports.Power1 = Power1;
5541  exports.Power2 = Power2;
5542  exports.Power3 = Power3;
5543  exports.Power4 = Power4;
5544  exports.Quad = Quad;
5545  exports.Quart = Quart;
5546  exports.Quint = Quint;
5547  exports.Sine = Sine;
5548  exports.SteppedEase = SteppedEase;
5549  exports.Strong = Strong;
5550  exports.TimelineLite = Timeline;
5551  exports.TimelineMax = Timeline;
5552  exports.TweenLite = Tween;
5553  exports.TweenMax = TweenMaxWithCSS;
5554  exports.default = gsapWithCSS;
5555  exports.gsap = gsapWithCSS;
5556
5557  if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;}
5558
5559})));
5560
5561(function(window, $) {
5562  'use strict';
5563  var counter = 0,
5564    $headCache = $('head'),
5565    oldBigText = window.BigText,
5566    oldjQueryMethod = $.fn.bigtext,
5567    BigText = {
5568      DEBUG_MODE: false,
5569      DEFAULT_MIN_FONT_SIZE_PX: null,
5570      DEFAULT_MAX_FONT_SIZE_PX: 528,
5571      GLOBAL_STYLE_ID: 'bigtext-style',
5572      STYLE_ID: 'bigtext-id',
5573      LINE_CLASS_PREFIX: 'bigtext-line',
5574      EXEMPT_CLASS: 'bigtext-exempt',
5575      noConflict: function(restore)
5576      {
5577        if(restore) {
5578          $.fn.bigtext = oldjQueryMethod;
5579          window.BigText = oldBigText;
5580        }
5581        return BigText;
5582      },
5583      supports: {
5584        wholeNumberFontSizeOnly: (function() {
5585          if( !( 'getComputedStyle' in window ) ) {
5586            return true;
5587          }
5588          var test = $('<div/>').css({
5589              position: 'absolute',
5590              'font-size': '14.1px'
5591            }).insertBefore( $('script').eq(0) ),
5592            computedStyle = window.getComputedStyle( test[0], null );
5593
5594          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
5595          test.remove();
5596          return ret;
5597        })()
5598      },
5599      init: function() {
5600        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
5601          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
5602                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
5603        }
5604      },
5605      bindResize: function(eventName, resizeFunction) {
5606        var timeoutId;
5607        $(window).unbind(eventName).bind(eventName, function() {
5608          if( timeoutId ) {
5609            clearTimeout( timeoutId );
5610          }
5611          timeoutId = setTimeout( resizeFunction, 300 );
5612        });
5613      },
5614      getStyleId: function(id)
5615      {
5616        return BigText.STYLE_ID + '-' + id;
5617      },
5618      generateStyleTag: function(id, css)
5619      {
5620        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
5621      },
5622      clearCss: function(id)
5623      {
5624        var styleId = BigText.getStyleId(id);
5625        $('#' + styleId).remove();
5626      },
5627      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
5628      {
5629        var css = [];
5630
5631        BigText.clearCss(id);
5632
5633        for(var j=0, k=linesFontSizes.length; j<k; j++) {
5634          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
5635            (minFontSizes[j] ? ' white-space: normal;' : '') +
5636            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
5637            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
5638            '}');
5639        }
5640
5641        return BigText.generateStyleTag(BigText.getStyleId(id), css);
5642      },
5643      jQueryMethod: function(options)
5644      {
5645        BigText.init();
5646
5647        options = $.extend({
5648          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
5649          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
5650          childSelector: '',
5651          resize: true
5652        }, options || {});
5653
5654        this.each(function()
5655        {
5656          var $t = $(this).addClass('bigtext'),
5657            maxWidth = $t.width(),
5658            id = $t.attr('id'),
5659            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
5660
5661          if(!id) {
5662            id = 'bigtext-id' + (counter++);
5663            $t.attr('id', id);
5664          }
5665
5666          if(options.resize) {
5667            BigText.bindResize('resize.bigtext-event-' + id, function()
5668            {
5669              // TODO only call this if the width has changed.
5670              BigText.jQueryMethod.call($('#' + id), options);
5671            });
5672          }
5673
5674          BigText.clearCss(id);
5675
5676          $children.addClass(function(lineNumber, className)
5677          {
5678            // remove existing line classes.
5679            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
5680                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
5681          });
5682
5683          var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
5684          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
5685        });
5686
5687        return this.trigger('bigtext:complete');
5688      }
5689    };
5690
5691  function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth)
5692  {
5693    var width;
5694    previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
5695    $line.css(property, size + units);
5696
5697    width = $line.width();
5698
5699    if(width >= maxWidth) {
5700
5701      $line.css(property, '');
5702
5703      if(width === maxWidth) {
5704        return {
5705          match: 'exact',
5706          size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
5707        };
5708      }
5709
5710      // Since this is an estimate, we calculate how far over the width we went with the new value.
5711      // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
5712      // Otherwise, we revert to the underestimate.
5713      var under = maxWidth - previousWidth,
5714        over = width - maxWidth;
5715
5716      return {
5717        match: 'estimate',
5718        size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
5719      };
5720    }
5721
5722    return width;
5723  }
5724
5725  function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize)
5726  {
5727    var $c = $t.clone(true)
5728      .addClass('bigtext-cloned')
5729      .css({
5730        fontFamily: $t.css('font-family'),
5731        textTransform: $t.css('text-transform'),
5732        wordSpacing: $t.css('word-spacing'),
5733        letterSpacing: $t.css('letter-spacing'),
5734        position: 'absolute',
5735        left: BigText.DEBUG_MODE ? 0 : -9999,
5736        top: BigText.DEBUG_MODE ? 0 : -9999
5737      })
5738      .appendTo(document.body);
5739
5740    // font-size isn't the only thing we can modify, we can also mess with:
5741    // word-spacing and letter-spacing. WebKit does not respect subpixel
5742    // letter-spacing, word-spacing, or font-size.
5743    // TODO try -webkit-transform: scale() as a workaround.
5744    var fontSizes = [],
5745      wordSpacings = [],
5746      minFontSizes = [],
5747      ratios = [];
5748
5749    $children.css('float', 'left').each(function() {
5750      var $line = $(this),
5751        // TODO replace 8, 4 with a proportional size to the calculated font-size.
5752        intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
5753        lineMax,
5754        newFontSize;
5755
5756      if($line.hasClass(BigText.EXEMPT_CLASS)) {
5757        fontSizes.push(null);
5758        ratios.push(null);
5759        minFontSizes.push(false);
5760        return;
5761      }
5762
5763      // TODO we can cache this ratio?
5764      var autoGuessSubtraction = 32, // font size in px
5765        currentFontSize = parseFloat($line.css('font-size')),
5766        ratio = ( $line.width() / currentFontSize ).toFixed(6);
5767
5768      newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
5769
5770      outer: for(var m=0, n=intervals.length; m<n; m++) {
5771        inner: for(var j=1, k=10; j<=k; j++) {
5772          if(newFontSize + j*intervals[m] > maxFontSize) {
5773            newFontSize = maxFontSize;
5774            break outer;
5775          }
5776
5777          lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
5778          if(typeof lineMax !== 'number') {
5779            newFontSize = lineMax.size;
5780
5781            if(lineMax.match === 'exact') {
5782              break outer;
5783            }
5784            break inner;
5785          }
5786        }
5787      }
5788
5789      ratios.push(maxWidth / newFontSize);
5790
5791      if(newFontSize > maxFontSize) {
5792        fontSizes.push(maxFontSize);
5793        minFontSizes.push(false);
5794      } else if(!!minFontSize && newFontSize < minFontSize) {
5795        fontSizes.push(minFontSize);
5796        minFontSizes.push(true);
5797      } else {
5798        fontSizes.push(newFontSize);
5799        minFontSizes.push(false);
5800      }
5801    }).each(function(lineNumber) {
5802      var $line = $(this),
5803        wordSpacing = 0,
5804        interval = 1,
5805        maxWordSpacing;
5806
5807      if($line.hasClass(BigText.EXEMPT_CLASS)) {
5808        wordSpacings.push(null);
5809        return;
5810      }
5811
5812      // must re-use font-size, even though it was removed above.
5813      $line.css('font-size', fontSizes[lineNumber] + 'px');
5814
5815      for(var m=1, n=3; m<n; m+=interval) {
5816        maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
5817        if(typeof maxWordSpacing !== 'number') {
5818          wordSpacing = maxWordSpacing.size;
5819          break;
5820        }
5821      }
5822
5823      $line.css('font-size', '');
5824      wordSpacings.push(wordSpacing);
5825    }).removeAttr('style');
5826
5827    if( !BigText.DEBUG_MODE ) {
5828      $c.remove();
5829    } else {
5830      $c.css({
5831        'background-color': 'rgba(255,255,255,.4)'
5832      });
5833    }
5834
5835    return {
5836      fontSizes: fontSizes,
5837      wordSpacings: wordSpacings,
5838      ratios: ratios,
5839      minFontSizes: minFontSizes
5840    };
5841  }
5842
5843  $.fn.bigtext = BigText.jQueryMethod;
5844  window.BigText = BigText;
5845
5846})(this, jQuery);
5847/*!
5848 * Isotope PACKAGED v3.0.6
5849 *
5850 * Licensed GPLv3 for open source use
5851 * or Isotope Commercial License for commercial use
5852 *
5853 * https://isotope.metafizzy.co
5854 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 5854-6504
5854
5855 */
5856
5857/**
5858 * Bridget makes jQuery widgets
5859 * v2.0.1
5860 * MIT license
5861 */
5862
5863/* jshint browser: true, strict: true, undef: true, unused: true */
5864
5865( function( window, factory ) {
5866  // universal module definition
5867  /*jshint strict: false */ /* globals define, module, require */
5868  if ( typeof define == 'function' && define.amd ) {
5869    // AMD
5870    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
5871      return factory( window, jQuery );
5872    });
5873  } else if ( typeof module == 'object' && module.exports ) {
5874    // CommonJS
5875    module.exports = factory(
5876      window,
5877      require('jquery')
5878    );
5879  } else {
5880    // browser global
5881    window.jQueryBridget = factory(
5882      window,
5883      window.jQuery
5884    );
5885  }
5886
5887}( window, function factory( window, jQuery ) {
5888'use strict';
5889
5890// ----- utils ----- //
5891
5892var arraySlice = Array.prototype.slice;
5893
5894// helper function for logging errors
5895// $.error breaks jQuery chaining
5896var console = window.console;
5897var logError = typeof console == 'undefined' ? function() {} :
5898  function( message ) {
5899    console.error( message );
5900  };
5901
5902// ----- jQueryBridget ----- //
5903
5904function jQueryBridget( namespace, PluginClass, $ ) {
5905  $ = $ || jQuery || window.jQuery;
5906  if ( !$ ) {
5907    return;
5908  }
5909
5910  // add option method -> $().plugin('option', {...})
5911  if ( !PluginClass.prototype.option ) {
5912    // option setter
5913    PluginClass.prototype.option = function( opts ) {
5914      // bail out if not an object
5915      if ( !$.isPlainObject( opts ) ){
5916        return;
5917      }
5918      this.options = $.extend( true, this.options, opts );
5919    };
5920  }
5921
5922  // make jQuery plugin
5923  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
5924    if ( typeof arg0 == 'string' ) {
5925      // method call $().plugin( 'methodName', { options } )
5926      // shift arguments by 1
5927      var args = arraySlice.call( arguments, 1 );
5928      return methodCall( this, arg0, args );
5929    }
5930    // just $().plugin({ options })
5931    plainCall( this, arg0 );
5932    return this;
5933  };
5934
5935  // $().plugin('methodName')
5936  function methodCall( $elems, methodName, args ) {
5937    var returnValue;
5938    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
5939
5940    $elems.each( function( i, elem ) {
5941      // get instance
5942      var instance = $.data( elem, namespace );
5943      if ( !instance ) {
5944        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
5945          pluginMethodStr );
5946        return;
5947      }
5948
5949      var method = instance[ methodName ];
5950      if ( !method || methodName.charAt(0) == '_' ) {
5951        logError( pluginMethodStr + ' is not a valid method' );
5952        return;
5953      }
5954
5955      // apply method, get return value
5956      var value = method.apply( instance, args );
5957      // set return value if value is returned, use only first value
5958      returnValue = returnValue === undefined ? value : returnValue;
5959    });
5960
5961    return returnValue !== undefined ? returnValue : $elems;
5962  }
5963
5964  function plainCall( $elems, options ) {
5965    $elems.each( function( i, elem ) {
5966      var instance = $.data( elem, namespace );
5967      if ( instance ) {
5968        // set options & init
5969        instance.option( options );
5970        instance._init();
5971      } else {
5972        // initialize new instance
5973        instance = new PluginClass( elem, options );
5974        $.data( elem, namespace, instance );
5975      }
5976    });
5977  }
5978
5979  updateJQuery( $ );
5980
5981}
5982
5983// ----- updateJQuery ----- //
5984
5985// set $.bridget for v1 backwards compatibility
5986function updateJQuery( $ ) {
5987  if ( !$ || ( $ && $.bridget ) ) {
5988    return;
5989  }
5990  $.bridget = jQueryBridget;
5991}
5992
5993updateJQuery( jQuery || window.jQuery );
5994
5995// -----  ----- //
5996
5997return jQueryBridget;
5998
5999}));
6000
6001/**
6002 * EvEmitter v1.1.0
6003 * Lil' event emitter
6004 * MIT License
6005 */
6006
6007/* jshint unused: true, undef: true, strict: true */
6008
6009( function( global, factory ) {
6010  // universal module definition
6011  /* jshint strict: false */ /* globals define, module, window */
6012  if ( typeof define == 'function' && define.amd ) {
6013    // AMD - RequireJS
6014    define( 'ev-emitter/ev-emitter',factory );
6015  } else if ( typeof module == 'object' && module.exports ) {
6016    // CommonJS - Browserify, Webpack
6017    module.exports = factory();
6018  } else {
6019    // Browser globals
6020    global.EvEmitter = factory();
6021  }
6022
6023}( typeof window != 'undefined' ? window : this, function() {
6024
6025
6026
6027function EvEmitter() {}
6028
6029var proto = EvEmitter.prototype;
6030
6031proto.on = function( eventName, listener ) {
6032  if ( !eventName || !listener ) {
6033    return;
6034  }
6035  // set events hash
6036  var events = this._events = this._events || {};
6037  // set listeners array
6038  var listeners = events[ eventName ] = events[ eventName ] || [];
6039  // only add once
6040  if ( listeners.indexOf( listener ) == -1 ) {
6041    listeners.push( listener );
6042  }
6043
6044  return this;
6045};
6046
6047proto.once = function( eventName, listener ) {
6048  if ( !eventName || !listener ) {
6049    return;
6050  }
6051  // add event
6052  this.on( eventName, listener );
6053  // set once flag
6054  // set onceEvents hash
6055  var onceEvents = this._onceEvents = this._onceEvents || {};
6056  // set onceListeners object
6057  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
6058  // set flag
6059  onceListeners[ listener ] = true;
6060
6061  return this;
6062};
6063
6064proto.off = function( eventName, listener ) {
6065  var listeners = this._events && this._events[ eventName ];
6066  if ( !listeners || !listeners.length ) {
6067    return;
6068  }
6069  var index = listeners.indexOf( listener );
6070  if ( index != -1 ) {
6071    listeners.splice( index, 1 );
6072  }
6073
6074  return this;
6075};
6076
6077proto.emitEvent = function( eventName, args ) {
6078  var listeners = this._events && this._events[ eventName ];
6079  if ( !listeners || !listeners.length ) {
6080    return;
6081  }
6082  // copy over to avoid interference if .off() in listener
6083  listeners = listeners.slice(0);
6084  args = args || [];
6085  // once stuff
6086  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
6087
6088  for ( var i=0; i < listeners.length; i++ ) {
6089    var listener = listeners[i]
6090    var isOnce = onceListeners && onceListeners[ listener ];
6091    if ( isOnce ) {
6092      // remove listener
6093      // remove before trigger to prevent recursion
6094      this.off( eventName, listener );
6095      // unset once flag
6096      delete onceListeners[ listener ];
6097    }
6098    // trigger listener
6099    listener.apply( this, args );
6100  }
6101
6102  return this;
6103};
6104
6105proto.allOff = function() {
6106  delete this._events;
6107  delete this._onceEvents;
6108};
6109
6110return EvEmitter;
6111
6112}));
6113
6114/*!
6115 * getSize v2.0.3
6116 * measure size of elements
6117 * MIT license
6118 */
6119
6120/* jshint browser: true, strict: true, undef: true, unused: true */
6121/* globals console: false */
6122
6123( function( window, factory ) {
6124  /* jshint strict: false */ /* globals define, module */
6125  if ( typeof define == 'function' && define.amd ) {
6126    // AMD
6127    define( 'get-size/get-size',factory );
6128  } else if ( typeof module == 'object' && module.exports ) {
6129    // CommonJS
6130    module.exports = factory();
6131  } else {
6132    // browser global
6133    window.getSize = factory();
6134  }
6135
6136})( window, function factory() {
6137'use strict';
6138
6139// -------------------------- helpers -------------------------- //
6140
6141// get a number from a string, not a percentage
6142function getStyleSize( value ) {
6143  var num = parseFloat( value );
6144  // not a percent like '100%', and a number
6145  var isValid = value.indexOf('%') == -1 && !isNaN( num );
6146  return isValid && num;
6147}
6148
6149function noop() {}
6150
6151var logError = typeof console == 'undefined' ? noop :
6152  function( message ) {
6153    console.error( message );
6154  };
6155
6156// -------------------------- measurements -------------------------- //
6157
6158var measurements = [
6159  'paddingLeft',
6160  'paddingRight',
6161  'paddingTop',
6162  'paddingBottom',
6163  'marginLeft',
6164  'marginRight',
6165  'marginTop',
6166  'marginBottom',
6167  'borderLeftWidth',
6168  'borderRightWidth',
6169  'borderTopWidth',
6170  'borderBottomWidth'
6171];
6172
6173var measurementsLength = measurements.length;
6174
6175function getZeroSize() {
6176  var size = {
6177    width: 0,
6178    height: 0,
6179    innerWidth: 0,
6180    innerHeight: 0,
6181    outerWidth: 0,
6182    outerHeight: 0
6183  };
6184  for ( var i=0; i < measurementsLength; i++ ) {
6185    var measurement = measurements[i];
6186    size[ measurement ] = 0;
6187  }
6188  return size;
6189}
6190
6191// -------------------------- getStyle -------------------------- //
6192
6193/**
6194 * getStyle, get style of element, check for Firefox bug
6195 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
6196 */
6197function getStyle( elem ) {
6198  var style = getComputedStyle( elem );
6199  if ( !style ) {
6200    logError( 'Style returned ' + style +
6201      '. Are you running this code in a hidden iframe on Firefox? ' +
6202      'See https://bit.ly/getsizebug1' );
6203  }
6204  return style;
6205}
6206
6207// -------------------------- setup -------------------------- //
6208
6209var isSetup = false;
6210
6211var isBoxSizeOuter;
6212
6213/**
6214 * setup
6215 * check isBoxSizerOuter
6216 * do on first getSize() rather than on page load for Firefox bug
6217 */
6218function setup() {
6219  // setup once
6220  if ( isSetup ) {
6221    return;
6222  }
6223  isSetup = true;
6224
6225  // -------------------------- box sizing -------------------------- //
6226
6227  /**
6228   * Chrome & Safari measure the outer-width on style.width on border-box elems
6229   * IE11 & Firefox<29 measures the inner-width
6230   */
6231  var div = document.createElement('div');
6232  div.style.width = '200px';
6233  div.style.padding = '1px 2px 3px 4px';
6234  div.style.borderStyle = 'solid';
6235  div.style.borderWidth = '1px 2px 3px 4px';
6236  div.style.boxSizing = 'border-box';
6237
6238  var body = document.body || document.documentElement;
6239  body.appendChild( div );
6240  var style = getStyle( div );
6241  // round value for browser zoom. desandro/masonry#928
6242  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
6243  getSize.isBoxSizeOuter = isBoxSizeOuter;
6244
6245  body.removeChild( div );
6246}
6247
6248// -------------------------- getSize -------------------------- //
6249
6250function getSize( elem ) {
6251  setup();
6252
6253  // use querySeletor if elem is string
6254  if ( typeof elem == 'string' ) {
6255    elem = document.querySelector( elem );
6256  }
6257
6258  // do not proceed on non-objects
6259  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
6260    return;
6261  }
6262
6263  var style = getStyle( elem );
6264
6265  // if hidden, everything is 0
6266  if ( style.display == 'none' ) {
6267    return getZeroSize();
6268  }
6269
6270  var size = {};
6271  size.width = elem.offsetWidth;
6272  size.height = elem.offsetHeight;
6273
6274  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
6275
6276  // get all measurements
6277  for ( var i=0; i < measurementsLength; i++ ) {
6278    var measurement = measurements[i];
6279    var value = style[ measurement ];
6280    var num = parseFloat( value );
6281    // any 'auto', 'medium' value will be 0
6282    size[ measurement ] = !isNaN( num ) ? num : 0;
6283  }
6284
6285  var paddingWidth = size.paddingLeft + size.paddingRight;
6286  var paddingHeight = size.paddingTop + size.paddingBottom;
6287  var marginWidth = size.marginLeft + size.marginRight;
6288  var marginHeight = size.marginTop + size.marginBottom;
6289  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
6290  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
6291
6292  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
6293
6294  // overwrite width and height if we can get it from style
6295  var styleWidth = getStyleSize( style.width );
6296  if ( styleWidth !== false ) {
6297    size.width = styleWidth +
6298      // add padding and border unless it's already including it
6299      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
6300  }
6301
6302  var styleHeight = getStyleSize( style.height );
6303  if ( styleHeight !== false ) {
6304    size.height = styleHeight +
6305      // add padding and border unless it's already including it
6306      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
6307  }
6308
6309  size.innerWidth = size.width - ( paddingWidth + borderWidth );
6310  size.innerHeight = size.height - ( paddingHeight + borderHeight );
6311
6312  size.outerWidth = size.width + marginWidth;
6313  size.outerHeight = size.height + marginHeight;
6314
6315  return size;
6316}
6317
6318return getSize;
6319
6320});
6321
6322/**
6323 * matchesSelector v2.0.2
6324 * matchesSelector( element, '.selector' )
6325 * MIT license
6326 */
6327
6328/*jshint browser: true, strict: true, undef: true, unused: true */
6329
6330( function( window, factory ) {
6331  /*global define: false, module: false */
6332  'use strict';
6333  // universal module definition
6334  if ( typeof define == 'function' && define.amd ) {
6335    // AMD
6336    define( 'desandro-matches-selector/matches-selector',factory );
6337  } else if ( typeof module == 'object' && module.exports ) {
6338    // CommonJS
6339    module.exports = factory();
6340  } else {
6341    // browser global
6342    window.matchesSelector = factory();
6343  }
6344
6345}( window, function factory() {
6346  'use strict';
6347
6348  var matchesMethod = ( function() {
6349    var ElemProto = window.Element.prototype;
6350    // check for the standard method name first
6351    if ( ElemProto.matches ) {
6352      return 'matches';
6353    }
6354    // check un-prefixed
6355    if ( ElemProto.matchesSelector ) {
6356      return 'matchesSelector';
6357    }
6358    // check vendor prefixes
6359    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
6360
6361    for ( var i=0; i < prefixes.length; i++ ) {
6362      var prefix = prefixes[i];
6363      var method = prefix + 'MatchesSelector';
6364      if ( ElemProto[ method ] ) {
6365        return method;
6366      }
6367    }
6368  })();
6369
6370  return function matchesSelector( elem, selector ) {
6371    return elem[ matchesMethod ]( selector );
6372  };
6373
6374}));
6375
6376/**
6377 * Fizzy UI utils v2.0.7
6378 * MIT license
6379 */
6380
6381/*jshint browser: true, undef: true, unused: true, strict: true */
6382
6383( function( window, factory ) {
6384  // universal module definition
6385  /*jshint strict: false */ /*globals define, module, require */
6386
6387  if ( typeof define == 'function' && define.amd ) {
6388    // AMD
6389    define( 'fizzy-ui-utils/utils',[
6390      'desandro-matches-selector/matches-selector'
6391    ], function( matchesSelector ) {
6392      return factory( window, matchesSelector );
6393    });
6394  } else if ( typeof module == 'object' && module.exports ) {
6395    // CommonJS
6396    module.exports = factory(
6397      window,
6398      require('desandro-matches-selector')
6399    );
6400  } else {
6401    // browser global
6402    window.fizzyUIUtils = factory(
6403      window,
6404      window.matchesSelector
6405    );
6406  }
6407
6408}( window, function factory( window, matchesSelector ) {
6409
6410
6411
6412var utils = {};
6413
6414// ----- extend ----- //
6415
6416// extends objects
6417utils.extend = function( a, b ) {
6418  for ( var prop in b ) {
6419    a[ prop ] = b[ prop ];
6420  }
6421  return a;
6422};
6423
6424// ----- modulo ----- //
6425
6426utils.modulo = function( num, div ) {
6427  return ( ( num % div ) + div ) % div;
6428};
6429
6430// ----- makeArray ----- //
6431
6432var arraySlice = Array.prototype.slice;
6433
6434// turn element or nodeList into an array
6435utils.makeArray = function( obj ) {
6436  if ( Array.isArray( obj ) ) {
6437    // use object if already an array
6438    return obj;
6439  }
6440  // return empty array if undefined or null. #6
6441  if ( obj === null || obj === undefined ) {
6442    return [];
6443  }
6444
6445  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
6446  if ( isArrayLike ) {
6447    // convert nodeList to array
6448    return arraySlice.call( obj );
6449  }
6450
6451  // array of single index
6452  return [ obj ];
6453};
6454
6455// ----- removeFrom ----- //
6456
6457utils.removeFrom = function( ary, obj ) {
6458  var index = ary.indexOf( obj );
6459  if ( index != -1 ) {
6460    ary.splice( index, 1 );
6461  }
6462};
6463
6464// ----- getParent ----- //
6465
6466utils.getParent = function( elem, selector ) {
6467  while ( elem.parentNode && elem != document.body ) {
6468    elem = elem.parentNode;
6469    if ( matchesSelector( elem, selector ) ) {
6470      return elem;
6471    }
6472  }
6473};
6474
6475// ----- getQueryElement ----- //
6476
6477// use element as selector string
6478utils.getQueryElement = function( elem ) {
6479  if ( typeof elem == 'string' ) {
6480    return document.querySelector( elem );
6481  }
6482  return elem;
6483};
6484
6485// ----- handleEvent ----- //
6486
6487// enable .ontype to trigger from .addEventListener( elem, 'type' )
6488utils.handleEvent = function( event ) {
6489  var method = 'on' + event.type;
6490  if ( this[ method ] ) {
6491    this[ method ]( event );
6492  }
6493};
6494
6495// ----- filterFindElements ----- //
6496
6497utils.filterFindElements = function( elems, selector ) {
6498  // make array of elems
6499  elems = utils.makeArray( elems );
6500  var ffElems = [];
6501
6502  elems.forEach( function( elem ) {
6503    // check that elem is an actual element
6504    
6504// START UNCODE EDIT
6505    // if ( !( elem instanceof HTMLElement ) ) {
6506    if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) {
6507    // END UNCODE EDIT
vendor: 23,480 bytes, lines 6507-7419
6507
6508      return;
6509    }
6510    // add elem if no selector
6511    if ( !selector ) {
6512      ffElems.push( elem );
6513      return;
6514    }
6515    // filter & find items if we have a selector
6516    // filter
6517    if ( matchesSelector( elem, selector ) ) {
6518      ffElems.push( elem );
6519    }
6520    // find children
6521    var childElems = elem.querySelectorAll( selector );
6522    // concat childElems to filterFound array
6523    for ( var i=0; i < childElems.length; i++ ) {
6524      ffElems.push( childElems[i] );
6525    }
6526  });
6527
6528  return ffElems;
6529};
6530
6531// ----- debounceMethod ----- //
6532
6533utils.debounceMethod = function( _class, methodName, threshold ) {
6534  threshold = threshold || 100;
6535  // original method
6536  var method = _class.prototype[ methodName ];
6537  var timeoutName = methodName + 'Timeout';
6538
6539  _class.prototype[ methodName ] = function() {
6540    var timeout = this[ timeoutName ];
6541    clearTimeout( timeout );
6542
6543    var args = arguments;
6544    var _this = this;
6545    this[ timeoutName ] = setTimeout( function() {
6546      method.apply( _this, args );
6547      delete _this[ timeoutName ];
6548    }, threshold );
6549  };
6550};
6551
6552// ----- docReady ----- //
6553
6554utils.docReady = function( callback ) {
6555  var readyState = document.readyState;
6556  if ( readyState == 'complete' || readyState == 'interactive' ) {
6557    // do async to allow for other scripts to run. metafizzy/flickity#441
6558    setTimeout( callback );
6559  } else {
6560    document.addEventListener( 'DOMContentLoaded', callback );
6561  }
6562};
6563
6564// ----- htmlInit ----- //
6565
6566// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
6567utils.toDashed = function( str ) {
6568  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
6569    return $1 + '-' + $2;
6570  }).toLowerCase();
6571};
6572
6573var console = window.console;
6574/**
6575 * allow user to initialize classes via [data-namespace] or .js-namespace class
6576 * htmlInit( Widget, 'widgetName' )
6577 * options are parsed from data-namespace-options
6578 */
6579utils.htmlInit = function( WidgetClass, namespace ) {
6580  utils.docReady( function() {
6581    var dashedNamespace = utils.toDashed( namespace );
6582    var dataAttr = 'data-' + dashedNamespace;
6583    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
6584    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
6585    var elems = utils.makeArray( dataAttrElems )
6586      .concat( utils.makeArray( jsDashElems ) );
6587    var dataOptionsAttr = dataAttr + '-options';
6588    var jQuery = window.jQuery;
6589
6590    elems.forEach( function( elem ) {
6591      var attr = elem.getAttribute( dataAttr ) ||
6592        elem.getAttribute( dataOptionsAttr );
6593      var options;
6594      try {
6595        options = attr && JSON.parse( attr );
6596      } catch ( error ) {
6597        // log error, do not initialize
6598        if ( console ) {
6599          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
6600          ': ' + error );
6601        }
6602        return;
6603      }
6604      // initialize
6605      var instance = new WidgetClass( elem, options );
6606      // make available via $().data('namespace')
6607      if ( jQuery ) {
6608        jQuery.data( elem, namespace, instance );
6609      }
6610    });
6611
6612  });
6613};
6614
6615// -----  ----- //
6616
6617return utils;
6618
6619}));
6620
6621/**
6622 * Outlayer Item
6623 */
6624
6625( function( window, factory ) {
6626  // universal module definition
6627  /* jshint strict: false */ /* globals define, module, require */
6628  if ( typeof define == 'function' && define.amd ) {
6629    // AMD - RequireJS
6630    define( 'outlayer/item',[
6631        'ev-emitter/ev-emitter',
6632        'get-size/get-size'
6633      ],
6634      factory
6635    );
6636  } else if ( typeof module == 'object' && module.exports ) {
6637    // CommonJS - Browserify, Webpack
6638    module.exports = factory(
6639      require('ev-emitter'),
6640      require('get-size')
6641    );
6642  } else {
6643    // browser global
6644    window.Outlayer = {};
6645    window.Outlayer.Item = factory(
6646      window.EvEmitter,
6647      window.getSize
6648    );
6649  }
6650
6651}( window, function factory( EvEmitter, getSize ) {
6652'use strict';
6653
6654// ----- helpers ----- //
6655
6656function isEmptyObj( obj ) {
6657  for ( var prop in obj ) {
6658    return false;
6659  }
6660  prop = null;
6661  return true;
6662}
6663
6664// -------------------------- CSS3 support -------------------------- //
6665
6666
6667var docElemStyle = document.documentElement.style;
6668
6669var transitionProperty = typeof docElemStyle.transition == 'string' ?
6670  'transition' : 'WebkitTransition';
6671var transformProperty = typeof docElemStyle.transform == 'string' ?
6672  'transform' : 'WebkitTransform';
6673
6674var transitionEndEvent = {
6675  WebkitTransition: 'webkitTransitionEnd',
6676  transition: 'transitionend'
6677}[ transitionProperty ];
6678
6679// cache all vendor properties that could have vendor prefix
6680var vendorProperties = {
6681  transform: transformProperty,
6682  transition: transitionProperty,
6683  transitionDuration: transitionProperty + 'Duration',
6684  transitionProperty: transitionProperty + 'Property',
6685  transitionDelay: transitionProperty + 'Delay'
6686};
6687
6688// -------------------------- Item -------------------------- //
6689
6690function Item( element, layout ) {
6691  if ( !element ) {
6692    return;
6693  }
6694
6695  this.element = element;
6696  // parent layout class, i.e. Masonry, Isotope, or Packery
6697  this.layout = layout;
6698  this.position = {
6699    x: 0,
6700    y: 0
6701  };
6702
6703  this._create();
6704}
6705
6706// inherit EvEmitter
6707var proto = Item.prototype = Object.create( EvEmitter.prototype );
6708proto.constructor = Item;
6709
6710proto._create = function() {
6711  // transition objects
6712  this._transn = {
6713    ingProperties: {},
6714    clean: {},
6715    onEnd: {}
6716  };
6717
6718  this.css({
6719    position: 'absolute'
6720  });
6721};
6722
6723// trigger specified handler for event type
6724proto.handleEvent = function( event ) {
6725  var method = 'on' + event.type;
6726  if ( this[ method ] ) {
6727    this[ method ]( event );
6728  }
6729};
6730
6731proto.getSize = function() {
6732  this.size = getSize( this.element );
6733};
6734
6735/**
6736 * apply CSS styles to element
6737 * @param {Object} style
6738 */
6739proto.css = function( style ) {
6740  var elemStyle = this.element.style;
6741
6742  for ( var prop in style ) {
6743    // use vendor property if available
6744    var supportedProp = vendorProperties[ prop ] || prop;
6745    elemStyle[ supportedProp ] = style[ prop ];
6746  }
6747};
6748
6749 // measure position, and sets it
6750proto.getPosition = function() {
6751  var style = getComputedStyle( this.element );
6752  var isOriginLeft = this.layout._getOption('originLeft');
6753  var isOriginTop = this.layout._getOption('originTop');
6754  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
6755  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
6756  var x = parseFloat( xValue );
6757  var y = parseFloat( yValue );
6758  // convert percent to pixels
6759  var layoutSize = this.layout.size;
6760  if ( xValue.indexOf('%') != -1 ) {
6761    x = ( x / 100 ) * layoutSize.width;
6762  }
6763  if ( yValue.indexOf('%') != -1 ) {
6764    y = ( y / 100 ) * layoutSize.height;
6765  }
6766  // clean up 'auto' or other non-integer values
6767  x = isNaN( x ) ? 0 : x;
6768  y = isNaN( y ) ? 0 : y;
6769  // remove padding from measurement
6770  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
6771  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
6772
6773  this.position.x = x;
6774  this.position.y = y;
6775};
6776
6777// set settled position, apply padding
6778proto.layoutPosition = function() {
6779  var layoutSize = this.layout.size;
6780  var style = {};
6781  var isOriginLeft = this.layout._getOption('originLeft');
6782  var isOriginTop = this.layout._getOption('originTop');
6783
6784  // x
6785  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
6786  var xProperty = isOriginLeft ? 'left' : 'right';
6787  var xResetProperty = isOriginLeft ? 'right' : 'left';
6788
6789  var x = this.position.x + layoutSize[ xPadding ];
6790  // set in percentage or pixels
6791  style[ xProperty ] = this.getXValue( x );
6792  // reset other property
6793  style[ xResetProperty ] = '';
6794
6795  // y
6796  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
6797  var yProperty = isOriginTop ? 'top' : 'bottom';
6798  var yResetProperty = isOriginTop ? 'bottom' : 'top';
6799
6800  var y = this.position.y + layoutSize[ yPadding ];
6801  // set in percentage or pixels
6802  style[ yProperty ] = this.getYValue( y );
6803  // reset other property
6804  style[ yResetProperty ] = '';
6805
6806  this.css( style );
6807  this.emitEvent( 'layout', [ this ] );
6808};
6809
6810proto.getXValue = function( x ) {
6811  var isHorizontal = this.layout._getOption('horizontal');
6812  return this.layout.options.percentPosition && !isHorizontal ?
6813    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
6814};
6815
6816proto.getYValue = function( y ) {
6817  var isHorizontal = this.layout._getOption('horizontal');
6818  return this.layout.options.percentPosition && isHorizontal ?
6819    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
6820};
6821
6822proto._transitionTo = function( x, y ) {
6823  this.getPosition();
6824  // get current x & y from top/left
6825  var curX = this.position.x;
6826  var curY = this.position.y;
6827
6828  var didNotMove = x == this.position.x && y == this.position.y;
6829
6830  // save end position
6831  this.setPosition( x, y );
6832
6833  // if did not move and not transitioning, just go to layout
6834  if ( didNotMove && !this.isTransitioning ) {
6835    this.layoutPosition();
6836    return;
6837  }
6838
6839  var transX = x - curX;
6840  var transY = y - curY;
6841  var transitionStyle = {};
6842  transitionStyle.transform = this.getTranslate( transX, transY );
6843
6844  this.transition({
6845    to: transitionStyle,
6846    onTransitionEnd: {
6847      transform: this.layoutPosition
6848    },
6849    isCleaning: true
6850  });
6851};
6852
6853proto.getTranslate = function( x, y ) {
6854  // flip cooridinates if origin on right or bottom
6855  var isOriginLeft = this.layout._getOption('originLeft');
6856  var isOriginTop = this.layout._getOption('originTop');
6857  x = isOriginLeft ? x : -x;
6858  y = isOriginTop ? y : -y;
6859  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
6860};
6861
6862// non transition + transform support
6863proto.goTo = function( x, y ) {
6864  this.setPosition( x, y );
6865  this.layoutPosition();
6866};
6867
6868proto.moveTo = proto._transitionTo;
6869
6870proto.setPosition = function( x, y ) {
6871  this.position.x = parseFloat( x );
6872  this.position.y = parseFloat( y );
6873};
6874
6875// ----- transition ----- //
6876
6877/**
6878 * @param {Object} style - CSS
6879 * @param {Function} onTransitionEnd
6880 */
6881
6882// non transition, just trigger callback
6883proto._nonTransition = function( args ) {
6884  this.css( args.to );
6885  if ( args.isCleaning ) {
6886    this._removeStyles( args.to );
6887  }
6888  for ( var prop in args.onTransitionEnd ) {
6889    args.onTransitionEnd[ prop ].call( this );
6890  }
6891};
6892
6893/**
6894 * proper transition
6895 * @param {Object} args - arguments
6896 *   @param {Object} to - style to transition to
6897 *   @param {Object} from - style to start transition from
6898 *   @param {Boolean} isCleaning - removes transition styles after transition
6899 *   @param {Function} onTransitionEnd - callback
6900 */
6901proto.transition = function( args ) {
6902  // redirect to nonTransition if no transition duration
6903  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
6904    this._nonTransition( args );
6905    return;
6906  }
6907
6908  var _transition = this._transn;
6909  // keep track of onTransitionEnd callback by css property
6910  for ( var prop in args.onTransitionEnd ) {
6911    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
6912  }
6913  // keep track of properties that are transitioning
6914  for ( prop in args.to ) {
6915    _transition.ingProperties[ prop ] = true;
6916    // keep track of properties to clean up when transition is done
6917    if ( args.isCleaning ) {
6918      _transition.clean[ prop ] = true;
6919    }
6920  }
6921
6922  // set from styles
6923  if ( args.from ) {
6924    this.css( args.from );
6925    // force redraw. http://blog.alexmaccaw.com/css-transitions
6926    var h = this.element.offsetHeight;
6927    // hack for JSHint to hush about unused var
6928    h = null;
6929  }
6930  // enable transition
6931  this.enableTransition( args.to );
6932  // set styles that are transitioning
6933  this.css( args.to );
6934
6935  this.isTransitioning = true;
6936
6937};
6938
6939// dash before all cap letters, including first for
6940// WebkitTransform => -webkit-transform
6941function toDashedAll( str ) {
6942  return str.replace( /([A-Z])/g, function( $1 ) {
6943    return '-' + $1.toLowerCase();
6944  });
6945}
6946
6947var transitionProps = 'opacity,' + toDashedAll( transformProperty );
6948
6949proto.enableTransition = function(/* style */) {
6950  // HACK changing transitionProperty during a transition
6951  // will cause transition to jump
6952  if ( this.isTransitioning ) {
6953    return;
6954  }
6955
6956  // make `transition: foo, bar, baz` from style object
6957  // HACK un-comment this when enableTransition can work
6958  // while a transition is happening
6959  // var transitionValues = [];
6960  // for ( var prop in style ) {
6961  //   // dash-ify camelCased properties like WebkitTransition
6962  //   prop = vendorProperties[ prop ] || prop;
6963  //   transitionValues.push( toDashedAll( prop ) );
6964  // }
6965  // munge number to millisecond, to match stagger
6966  var duration = this.layout.options.transitionDuration;
6967  duration = typeof duration == 'number' ? duration + 'ms' : duration;
6968  // enable transition styles
6969  this.css({
6970    transitionProperty: transitionProps,
6971    transitionDuration: duration,
6972    transitionDelay: this.staggerDelay || 0
6973  });
6974  // listen for transition end event
6975  this.element.addEventListener( transitionEndEvent, this, false );
6976};
6977
6978// ----- events ----- //
6979
6980proto.onwebkitTransitionEnd = function( event ) {
6981  this.ontransitionend( event );
6982};
6983
6984proto.onotransitionend = function( event ) {
6985  this.ontransitionend( event );
6986};
6987
6988// properties that I munge to make my life easier
6989var dashedVendorProperties = {
6990  '-webkit-transform': 'transform'
6991};
6992
6993proto.ontransitionend = function( event ) {
6994  // disregard bubbled events from children
6995  if ( event.target !== this.element ) {
6996    return;
6997  }
6998  var _transition = this._transn;
6999  // get property name of transitioned property, convert to prefix-free
7000  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
7001
7002  // remove property that has completed transitioning
7003  delete _transition.ingProperties[ propertyName ];
7004  // check if any properties are still transitioning
7005  if ( isEmptyObj( _transition.ingProperties ) ) {
7006    // all properties have completed transitioning
7007    this.disableTransition();
7008  }
7009  // clean style
7010  if ( propertyName in _transition.clean ) {
7011    // clean up style
7012    this.element.style[ event.propertyName ] = '';
7013    delete _transition.clean[ propertyName ];
7014  }
7015  // trigger onTransitionEnd callback
7016  if ( propertyName in _transition.onEnd ) {
7017    var onTransitionEnd = _transition.onEnd[ propertyName ];
7018    onTransitionEnd.call( this );
7019    delete _transition.onEnd[ propertyName ];
7020  }
7021
7022  this.emitEvent( 'transitionEnd', [ this ] );
7023};
7024
7025proto.disableTransition = function() {
7026  this.removeTransitionStyles();
7027  this.element.removeEventListener( transitionEndEvent, this, false );
7028  this.isTransitioning = false;
7029};
7030
7031/**
7032 * removes style property from element
7033 * @param {Object} style
7034**/
7035proto._removeStyles = function( style ) {
7036  // clean up transition styles
7037  var cleanStyle = {};
7038  for ( var prop in style ) {
7039    cleanStyle[ prop ] = '';
7040  }
7041  this.css( cleanStyle );
7042};
7043
7044var cleanTransitionStyle = {
7045  transitionProperty: '',
7046  transitionDuration: '',
7047  transitionDelay: ''
7048};
7049
7050proto.removeTransitionStyles = function() {
7051  // remove transition
7052  this.css( cleanTransitionStyle );
7053};
7054
7055// ----- stagger ----- //
7056
7057proto.stagger = function( delay ) {
7058  delay = isNaN( delay ) ? 0 : delay;
7059  this.staggerDelay = delay + 'ms';
7060};
7061
7062// ----- show/hide/remove ----- //
7063
7064// remove element from DOM
7065proto.removeElem = function() {
7066  this.element.parentNode.removeChild( this.element );
7067  // remove display: none
7068  this.css({ display: '' });
7069  this.emitEvent( 'remove', [ this ] );
7070};
7071
7072proto.remove = function() {
7073  // just remove element if no transition support or no transition
7074  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
7075    this.removeElem();
7076    return;
7077  }
7078
7079  // start transition
7080  this.once( 'transitionEnd', function() {
7081    this.removeElem();
7082  });
7083  this.hide();
7084};
7085
7086proto.reveal = function() {
7087  delete this.isHidden;
7088  // remove display: none
7089  this.css({ display: '' });
7090
7091  var options = this.layout.options;
7092
7093  var onTransitionEnd = {};
7094  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
7095  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
7096
7097  this.transition({
7098    from: options.hiddenStyle,
7099    to: options.visibleStyle,
7100    isCleaning: true,
7101    onTransitionEnd: onTransitionEnd
7102  });
7103};
7104
7105proto.onRevealTransitionEnd = function() {
7106  // check if still visible
7107  // during transition, item may have been hidden
7108  if ( !this.isHidden ) {
7109    this.emitEvent('reveal');
7110  }
7111};
7112
7113/**
7114 * get style property use for hide/reveal transition end
7115 * @param {String} styleProperty - hiddenStyle/visibleStyle
7116 * @returns {String}
7117 */
7118proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
7119  var optionStyle = this.layout.options[ styleProperty ];
7120  // use opacity
7121  if ( optionStyle.opacity ) {
7122    return 'opacity';
7123  }
7124  // get first property
7125  for ( var prop in optionStyle ) {
7126    return prop;
7127  }
7128};
7129
7130proto.hide = function() {
7131  // set flag
7132  this.isHidden = true;
7133  // remove display: none
7134  this.css({ display: '' });
7135
7136  var options = this.layout.options;
7137
7138  var onTransitionEnd = {};
7139  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
7140  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
7141
7142  this.transition({
7143    from: options.visibleStyle,
7144    to: options.hiddenStyle,
7145    // keep hidden stuff hidden
7146    isCleaning: true,
7147    onTransitionEnd: onTransitionEnd
7148  });
7149};
7150
7151proto.onHideTransitionEnd = function() {
7152  // check if still hidden
7153  // during transition, item may have been un-hidden
7154  if ( this.isHidden ) {
7155    this.css({ display: 'none' });
7156    this.emitEvent('hide');
7157  }
7158};
7159
7160proto.destroy = function() {
7161  this.css({
7162    position: '',
7163    left: '',
7164    right: '',
7165    top: '',
7166    bottom: '',
7167    transition: '',
7168    transform: ''
7169  });
7170};
7171
7172return Item;
7173
7174}));
7175
7176/*!
7177 * Outlayer v2.1.1
7178 * the brains and guts of a layout library
7179 * MIT license
7180 */
7181
7182( function( window, factory ) {
7183  'use strict';
7184  // universal module definition
7185  /* jshint strict: false */ /* globals define, module, require */
7186  if ( typeof define == 'function' && define.amd ) {
7187    // AMD - RequireJS
7188    define( 'outlayer/outlayer',[
7189        'ev-emitter/ev-emitter',
7190        'get-size/get-size',
7191        'fizzy-ui-utils/utils',
7192        './item'
7193      ],
7194      function( EvEmitter, getSize, utils, Item ) {
7195        return factory( window, EvEmitter, getSize, utils, Item);
7196      }
7197    );
7198  } else if ( typeof module == 'object' && module.exports ) {
7199    // CommonJS - Browserify, Webpack
7200    module.exports = factory(
7201      window,
7202      require('ev-emitter'),
7203      require('get-size'),
7204      require('fizzy-ui-utils'),
7205      require('./item')
7206    );
7207  } else {
7208    // browser global
7209    window.Outlayer = factory(
7210      window,
7211      window.EvEmitter,
7212      window.getSize,
7213      window.fizzyUIUtils,
7214      window.Outlayer.Item
7215    );
7216  }
7217
7218}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
7219'use strict';
7220
7221// ----- vars ----- //
7222
7223var console = window.console;
7224var jQuery = window.jQuery;
7225var noop = function() {};
7226
7227// -------------------------- Outlayer -------------------------- //
7228
7229// globally unique identifiers
7230var GUID = 0;
7231// internal store of all Outlayer intances
7232var instances = {};
7233
7234
7235/**
7236 * @param {Element, String} element
7237 * @param {Object} options
7238 * @constructor
7239 */
7240function Outlayer( element, options ) {
7241  var queryElement = utils.getQueryElement( element );
7242  if ( !queryElement ) {
7243    if ( console ) {
7244      console.error( 'Bad element for ' + this.constructor.namespace +
7245        ': ' + ( queryElement || element ) );
7246    }
7247    return;
7248  }
7249  this.element = queryElement;
7250  // add jQuery
7251  if ( jQuery ) {
7252    this.$element = jQuery( this.element );
7253  }
7254
7255  // options
7256  this.options = utils.extend( {}, this.constructor.defaults );
7257  this.option( options );
7258
7259  // add id for Outlayer.getFromElement
7260  var id = ++GUID;
7261  this.element.outlayerGUID = id; // expando
7262  instances[ id ] = this; // associate via id
7263
7264  // kick it off
7265  this._create();
7266
7267  var isInitLayout = this._getOption('initLayout');
7268  if ( isInitLayout ) {
7269    this.layout();
7270  }
7271}
7272
7273// settings are for internal use only
7274Outlayer.namespace = 'outlayer';
7275Outlayer.Item = Item;
7276
7277// default options
7278Outlayer.defaults = {
7279  containerStyle: {
7280    position: 'relative'
7281  },
7282  initLayout: true,
7283  originLeft: true,
7284  originTop: true,
7285  resize: true,
7286  resizeContainer: true,
7287  // item options
7288  transitionDuration: '0.4s',
7289  hiddenStyle: {
7290    opacity: 0,
7291    transform: 'scale(0.001)'
7292  },
7293  visibleStyle: {
7294    opacity: 1,
7295    transform: 'scale(1)'
7296  }
7297};
7298
7299var proto = Outlayer.prototype;
7300// inherit EvEmitter
7301utils.extend( proto, EvEmitter.prototype );
7302
7303/**
7304 * set options
7305 * @param {Object} opts
7306 */
7307proto.option = function( opts ) {
7308  utils.extend( this.options, opts );
7309};
7310
7311/**
7312 * get backwards compatible option value, check old name
7313 */
7314proto._getOption = function( option ) {
7315  var oldOption = this.constructor.compatOptions[ option ];
7316  return oldOption && this.options[ oldOption ] !== undefined ?
7317    this.options[ oldOption ] : this.options[ option ];
7318};
7319
7320Outlayer.compatOptions = {
7321  // currentName: oldName
7322  initLayout: 'isInitLayout',
7323  horizontal: 'isHorizontal',
7324  layoutInstant: 'isLayoutInstant',
7325  originLeft: 'isOriginLeft',
7326  originTop: 'isOriginTop',
7327  resize: 'isResizeBound',
7328  resizeContainer: 'isResizingContainer'
7329};
7330
7331proto._create = function() {
7332  // get items from children
7333  this.reloadItems();
7334  // elements that affect layout, but are not laid out
7335  this.stamps = [];
7336  this.stamp( this.options.stamp );
7337  // set container style
7338  utils.extend( this.element.style, this.options.containerStyle );
7339
7340  // bind resize method
7341  var canBindResize = this._getOption('resize');
7342  if ( canBindResize ) {
7343    this.bindResize();
7344  }
7345};
7346
7347// goes through all children again and gets bricks in proper order
7348proto.reloadItems = function() {
7349  // collection of item elements
7350  this.items = this._itemize( this.element.children );
7351};
7352
7353
7354/**
7355 * turn elements into Outlayer.Items to be used in layout
7356 * @param {Array or NodeList or HTMLElement} elems
7357 * @returns {Array} items - collection of new Outlayer Items
7358 */
7359proto._itemize = function( elems ) {
7360
7361  var itemElems = this._filterFindItemElements( elems );
7362  var Item = this.constructor.Item;
7363
7364  // create new Outlayer Items for collection
7365  var items = [];
7366  for ( var i=0; i < itemElems.length; i++ ) {
7367    var elem = itemElems[i];
7368    var item = new Item( elem, this );
7369    items.push( item );
7370  }
7371
7372  return items;
7373};
7374
7375/**
7376 * get item elements to be used in layout
7377 * @param {Array or NodeList or HTMLElement} elems
7378 * @returns {Array} items - item elements
7379 */
7380proto._filterFindItemElements = function( elems ) {
7381  return utils.filterFindElements( elems, this.options.itemSelector );
7382};
7383
7384/**
7385 * getter method for getting item elements
7386 * @returns {Array} elems - collection of item elements
7387 */
7388proto.getItemElements = function() {
7389  return this.items.map( function( item ) {
7390    return item.element;
7391  });
7392};
7393
7394// ----- init & layout ----- //
7395
7396/**
7397 * lays out all items
7398 */
7399proto.layout = function() {
7400  this._resetLayout();
7401  this._manageStamps();
7402
7403  // don't animate first layout
7404  var layoutInstant = this._getOption('layoutInstant');
7405  var isInstant = layoutInstant !== undefined ?
7406    layoutInstant : !this._isLayoutInited;
7407  this.layoutItems( this.items, isInstant );
7408
7409  // flag for initalized
7410  this._isLayoutInited = true;
7411};
7412
7413// _init is alias for layout
7414proto._init = proto.layout;
7415
7416/**
7417 * logic before any new layout
7418 */
7419proto._resetLayout = function() {
vendor: 13,499 bytes, lines 7420-7988
7420  this.getSize();
7421};
7422
7423
7424proto.getSize = function() {
7425  this.size = getSize( this.element );
7426};
7427
7428/**
7429 * get measurement from option, for columnWidth, rowHeight, gutter
7430 * if option is String -> get element from selector string, & get size of element
7431 * if option is Element -> get size of element
7432 * else use option as a number
7433 *
7434 * @param {String} measurement
7435 * @param {String} size - width or height
7436 * @private
7437 */
7438proto._getMeasurement = function( measurement, size ) {
7439  var option = this.options[ measurement ];
7440  var elem;
7441  if ( !option ) {
7442    // default to 0
7443    this[ measurement ] = 0;
7444  } else {
7445    // use option as an element
7446    if ( typeof option == 'string' ) {
7447      elem = this.element.querySelector( option );
7448    } else if ( option instanceof HTMLElement ) {
7449      elem = option;
7450    }
7451    // use size of element, if element
7452    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
7453  }
7454};
7455
7456/**
7457 * layout a collection of item elements
7458 * @api public
7459 */
7460proto.layoutItems = function( items, isInstant ) {
7461  items = this._getItemsForLayout( items );
7462
7463  this._layoutItems( items, isInstant );
7464
7465  this._postLayout();
7466};
7467
7468/**
7469 * get the items to be laid out
7470 * you may want to skip over some items
7471 * @param {Array} items
7472 * @returns {Array} items
7473 */
7474proto._getItemsForLayout = function( items ) {
7475  return items.filter( function( item ) {
7476    return !item.isIgnored;
7477  });
7478};
7479
7480/**
7481 * layout items
7482 * @param {Array} items
7483 * @param {Boolean} isInstant
7484 */
7485proto._layoutItems = function( items, isInstant ) {
7486  this._emitCompleteOnItems( 'layout', items );
7487
7488  if ( !items || !items.length ) {
7489    // no items, emit event with empty array
7490    return;
7491  }
7492
7493  var queue = [];
7494
7495  items.forEach( function( item ) {
7496    // get x/y object from method
7497    var position = this._getItemLayoutPosition( item );
7498    // enqueue
7499    position.item = item;
7500    position.isInstant = isInstant || item.isLayoutInstant;
7501    queue.push( position );
7502  }, this );
7503
7504  this._processLayoutQueue( queue );
7505};
7506
7507/**
7508 * get item layout position
7509 * @param {Outlayer.Item} item
7510 * @returns {Object} x and y position
7511 */
7512proto._getItemLayoutPosition = function( /* item */ ) {
7513  return {
7514    x: 0,
7515    y: 0
7516  };
7517};
7518
7519/**
7520 * iterate over array and position each item
7521 * Reason being - separating this logic prevents 'layout invalidation'
7522 * thx @paul_irish
7523 * @param {Array} queue
7524 */
7525proto._processLayoutQueue = function( queue ) {
7526  this.updateStagger();
7527  queue.forEach( function( obj, i ) {
7528    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
7529  }, this );
7530};
7531
7532// set stagger from option in milliseconds number
7533proto.updateStagger = function() {
7534  var stagger = this.options.stagger;
7535  if ( stagger === null || stagger === undefined ) {
7536    this.stagger = 0;
7537    return;
7538  }
7539  this.stagger = getMilliseconds( stagger );
7540  return this.stagger;
7541};
7542
7543/**
7544 * Sets position of item in DOM
7545 * @param {Outlayer.Item} item
7546 * @param {Number} x - horizontal position
7547 * @param {Number} y - vertical position
7548 * @param {Boolean} isInstant - disables transitions
7549 */
7550proto._positionItem = function( item, x, y, isInstant, i ) {
7551  if ( isInstant ) {
7552    // if not transition, just set CSS
7553    item.goTo( x, y );
7554  } else {
7555    item.stagger( i * this.stagger );
7556    item.moveTo( x, y );
7557  }
7558};
7559
7560/**
7561 * Any logic you want to do after each layout,
7562 * i.e. size the container
7563 */
7564proto._postLayout = function() {
7565  this.resizeContainer();
7566};
7567
7568proto.resizeContainer = function() {
7569  var isResizingContainer = this._getOption('resizeContainer');
7570  if ( !isResizingContainer ) {
7571    return;
7572  }
7573  var size = this._getContainerSize();
7574  if ( size ) {
7575    this._setContainerMeasure( size.width, true );
7576    this._setContainerMeasure( size.height, false );
7577  }
7578};
7579
7580/**
7581 * Sets width or height of container if returned
7582 * @returns {Object} size
7583 *   @param {Number} width
7584 *   @param {Number} height
7585 */
7586proto._getContainerSize = noop;
7587
7588/**
7589 * @param {Number} measure - size of width or height
7590 * @param {Boolean} isWidth
7591 */
7592proto._setContainerMeasure = function( measure, isWidth ) {
7593  if ( measure === undefined ) {
7594    return;
7595  }
7596
7597  var elemSize = this.size;
7598  // add padding and border width if border box
7599  if ( elemSize.isBorderBox ) {
7600    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
7601      elemSize.borderLeftWidth + elemSize.borderRightWidth :
7602      elemSize.paddingBottom + elemSize.paddingTop +
7603      elemSize.borderTopWidth + elemSize.borderBottomWidth;
7604  }
7605
7606  measure = Math.max( measure, 0 );
7607  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
7608};
7609
7610/**
7611 * emit eventComplete on a collection of items events
7612 * @param {String} eventName
7613 * @param {Array} items - Outlayer.Items
7614 */
7615proto._emitCompleteOnItems = function( eventName, items ) {
7616  var _this = this;
7617  function onComplete() {
7618    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
7619  }
7620
7621  var count = items.length;
7622  if ( !items || !count ) {
7623    onComplete();
7624    return;
7625  }
7626
7627  var doneCount = 0;
7628  function tick() {
7629    doneCount++;
7630    if ( doneCount == count ) {
7631      onComplete();
7632    }
7633  }
7634
7635  // bind callback
7636  items.forEach( function( item ) {
7637    item.once( eventName, tick );
7638  });
7639};
7640
7641/**
7642 * emits events via EvEmitter and jQuery events
7643 * @param {String} type - name of event
7644 * @param {Event} event - original event
7645 * @param {Array} args - extra arguments
7646 */
7647proto.dispatchEvent = function( type, event, args ) {
7648  // add original event to arguments
7649  var emitArgs = event ? [ event ].concat( args ) : args;
7650  this.emitEvent( type, emitArgs );
7651
7652  if ( jQuery ) {
7653    // set this.$element
7654    this.$element = this.$element || jQuery( this.element );
7655    if ( event ) {
7656      // create jQuery event
7657      var $event = jQuery.Event( event );
7658      $event.type = type;
7659      this.$element.trigger( $event, args );
7660    } else {
7661      // just trigger with type if no event available
7662      this.$element.trigger( type, args );
7663    }
7664  }
7665};
7666
7667// -------------------------- ignore & stamps -------------------------- //
7668
7669
7670/**
7671 * keep item in collection, but do not lay it out
7672 * ignored items do not get skipped in layout
7673 * @param {Element} elem
7674 */
7675proto.ignore = function( elem ) {
7676  var item = this.getItem( elem );
7677  if ( item ) {
7678    item.isIgnored = true;
7679  }
7680};
7681
7682/**
7683 * return item to layout collection
7684 * @param {Element} elem
7685 */
7686proto.unignore = function( elem ) {
7687  var item = this.getItem( elem );
7688  if ( item ) {
7689    delete item.isIgnored;
7690  }
7691};
7692
7693/**
7694 * adds elements to stamps
7695 * @param {NodeList, Array, Element, or String} elems
7696 */
7697proto.stamp = function( elems ) {
7698  elems = this._find( elems );
7699  if ( !elems ) {
7700    return;
7701  }
7702
7703  this.stamps = this.stamps.concat( elems );
7704  // ignore
7705  elems.forEach( this.ignore, this );
7706};
7707
7708/**
7709 * removes elements to stamps
7710 * @param {NodeList, Array, or Element} elems
7711 */
7712proto.unstamp = function( elems ) {
7713  elems = this._find( elems );
7714  if ( !elems ){
7715    return;
7716  }
7717
7718  elems.forEach( function( elem ) {
7719    // filter out removed stamp elements
7720    utils.removeFrom( this.stamps, elem );
7721    this.unignore( elem );
7722  }, this );
7723};
7724
7725/**
7726 * finds child elements
7727 * @param {NodeList, Array, Element, or String} elems
7728 * @returns {Array} elems
7729 */
7730proto._find = function( elems ) {
7731  if ( !elems ) {
7732    return;
7733  }
7734  // if string, use argument as selector string
7735  if ( typeof elems == 'string' ) {
7736    elems = this.element.querySelectorAll( elems );
7737  }
7738  elems = utils.makeArray( elems );
7739  return elems;
7740};
7741
7742proto._manageStamps = function() {
7743  if ( !this.stamps || !this.stamps.length ) {
7744    return;
7745  }
7746
7747  this._getBoundingRect();
7748
7749  this.stamps.forEach( this._manageStamp, this );
7750};
7751
7752// update boundingLeft / Top
7753proto._getBoundingRect = function() {
7754  // get bounding rect for container element
7755  var boundingRect = this.element.getBoundingClientRect();
7756  var size = this.size;
7757  this._boundingRect = {
7758    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
7759    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
7760    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
7761    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
7762  };
7763};
7764
7765/**
7766 * @param {Element} stamp
7767**/
7768proto._manageStamp = noop;
7769
7770/**
7771 * get x/y position of element relative to container element
7772 * @param {Element} elem
7773 * @returns {Object} offset - has left, top, right, bottom
7774 */
7775proto._getElementOffset = function( elem ) {
7776  var boundingRect = elem.getBoundingClientRect();
7777  var thisRect = this._boundingRect;
7778  var size = getSize( elem );
7779  var offset = {
7780    left: boundingRect.left - thisRect.left - size.marginLeft,
7781    top: boundingRect.top - thisRect.top - size.marginTop,
7782    right: thisRect.right - boundingRect.right - size.marginRight,
7783    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
7784  };
7785  return offset;
7786};
7787
7788// -------------------------- resize -------------------------- //
7789
7790// enable event handlers for listeners
7791// i.e. resize -> onresize
7792proto.handleEvent = utils.handleEvent;
7793
7794/**
7795 * Bind layout to window resizing
7796 */
7797proto.bindResize = function() {
7798  window.addEventListener( 'resize', this );
7799  this.isResizeBound = true;
7800};
7801
7802/**
7803 * Unbind layout to window resizing
7804 */
7805proto.unbindResize = function() {
7806  window.removeEventListener( 'resize', this );
7807  this.isResizeBound = false;
7808};
7809
7810proto.onresize = function() {
7811  this.resize();
7812};
7813
7814utils.debounceMethod( Outlayer, 'onresize', 100 );
7815
7816proto.resize = function() {
7817  // don't trigger if size did not change
7818  // or if resize was unbound. See #9
7819  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
7820    return;
7821  }
7822
7823  this.layout();
7824};
7825
7826/**
7827 * check if layout is needed post layout
7828 * @returns Boolean
7829 */
7830proto.needsResizeLayout = function() {
7831  var size = getSize( this.element );
7832  // check that this.size and size are there
7833  // IE8 triggers resize on body size change, so they might not be
7834  var hasSizes = this.size && size;
7835  return hasSizes && size.innerWidth !== this.size.innerWidth;
7836};
7837
7838// -------------------------- methods -------------------------- //
7839
7840/**
7841 * add items to Outlayer instance
7842 * @param {Array or NodeList or Element} elems
7843 * @returns {Array} items - Outlayer.Items
7844**/
7845proto.addItems = function( elems ) {
7846  var items = this._itemize( elems );
7847  // add items to collection
7848  if ( items.length ) {
7849    this.items = this.items.concat( items );
7850  }
7851  return items;
7852};
7853
7854/**
7855 * Layout newly-appended item elements
7856 * @param {Array or NodeList or Element} elems
7857 */
7858proto.appended = function( elems ) {
7859  var items = this.addItems( elems );
7860  if ( !items.length ) {
7861    return;
7862  }
7863  // layout and reveal just the new items
7864  this.layoutItems( items, true );
7865  this.reveal( items );
7866};
7867
7868/**
7869 * Layout prepended elements
7870 * @param {Array or NodeList or Element} elems
7871 */
7872proto.prepended = function( elems ) {
7873  var items = this._itemize( elems );
7874  if ( !items.length ) {
7875    return;
7876  }
7877  // add items to beginning of collection
7878  var previousItems = this.items.slice(0);
7879  this.items = items.concat( previousItems );
7880  // start new layout
7881  this._resetLayout();
7882  this._manageStamps();
7883  // layout new stuff without transition
7884  this.layoutItems( items, true );
7885  this.reveal( items );
7886  // layout previous items
7887  this.layoutItems( previousItems );
7888};
7889
7890/**
7891 * reveal a collection of items
7892 * @param {Array of Outlayer.Items} items
7893 */
7894proto.reveal = function( items ) {
7895  this._emitCompleteOnItems( 'reveal', items );
7896  if ( !items || !items.length ) {
7897    return;
7898  }
7899  var stagger = this.updateStagger();
7900  items.forEach( function( item, i ) {
7901    item.stagger( i * stagger );
7902    item.reveal();
7903  });
7904};
7905
7906/**
7907 * hide a collection of items
7908 * @param {Array of Outlayer.Items} items
7909 */
7910proto.hide = function( items ) {
7911  this._emitCompleteOnItems( 'hide', items );
7912  if ( !items || !items.length ) {
7913    return;
7914  }
7915  var stagger = this.updateStagger();
7916  items.forEach( function( item, i ) {
7917    item.stagger( i * stagger );
7918    item.hide();
7919  });
7920};
7921
7922/**
7923 * reveal item elements
7924 * @param {Array}, {Element}, {NodeList} items
7925 */
7926proto.revealItemElements = function( elems ) {
7927  var items = this.getItems( elems );
7928  this.reveal( items );
7929};
7930
7931/**
7932 * hide item elements
7933 * @param {Array}, {Element}, {NodeList} items
7934 */
7935proto.hideItemElements = function( elems ) {
7936  var items = this.getItems( elems );
7937  this.hide( items );
7938};
7939
7940/**
7941 * get Outlayer.Item, given an Element
7942 * @param {Element} elem
7943 * @param {Function} callback
7944 * @returns {Outlayer.Item} item
7945 */
7946proto.getItem = function( elem ) {
7947  // loop through items to get the one that matches
7948  for ( var i=0; i < this.items.length; i++ ) {
7949    var item = this.items[i];
7950    if ( item.element == elem ) {
7951      // return item
7952      return item;
7953    }
7954  }
7955};
7956
7957/**
7958 * get collection of Outlayer.Items, given Elements
7959 * @param {Array} elems
7960 * @returns {Array} items - Outlayer.Items
7961 */
7962proto.getItems = function( elems ) {
7963  elems = utils.makeArray( elems );
7964  var items = [];
7965  elems.forEach( function( elem ) {
7966    var item = this.getItem( elem );
7967    if ( item ) {
7968      items.push( item );
7969    }
7970  }, this );
7971
7972  return items;
7973};
7974
7975/**
7976 * remove element(s) from instance and DOM
7977 * @param {Array or NodeList or Element} elems
7978 */
7979proto.remove = function( elems ) {
7980  var removeItems = this.getItems( elems );
7981
7982  this._emitCompleteOnItems( 'remove', removeItems );
7983
7984  // bail if no items to remove
7985  if ( !removeItems || !removeItems.length ) {
7986    return;
7987  }
7988
vendor: 38,285 bytes, lines 7989-9412
7989  removeItems.forEach( function( item ) {
7990    item.remove();
7991    // remove item from collection
7992    utils.removeFrom( this.items, item );
7993  }, this );
7994};
7995
7996// ----- destroy ----- //
7997
7998// remove and disable Outlayer instance
7999proto.destroy = function() {
8000  // clean up dynamic styles
8001  var style = this.element.style;
8002  style.height = '';
8003  style.position = '';
8004  style.width = '';
8005  // destroy items
8006  this.items.forEach( function( item ) {
8007    item.destroy();
8008  });
8009
8010  this.unbindResize();
8011
8012  var id = this.element.outlayerGUID;
8013  delete instances[ id ]; // remove reference to instance by id
8014  delete this.element.outlayerGUID;
8015  // remove data for jQuery
8016  if ( jQuery ) {
8017    jQuery.removeData( this.element, this.constructor.namespace );
8018  }
8019
8020};
8021
8022// -------------------------- data -------------------------- //
8023
8024/**
8025 * get Outlayer instance from element
8026 * @param {Element} elem
8027 * @returns {Outlayer}
8028 */
8029Outlayer.data = function( elem ) {
8030  elem = utils.getQueryElement( elem );
8031  var id = elem && elem.outlayerGUID;
8032  return id && instances[ id ];
8033};
8034
8035
8036// -------------------------- create Outlayer class -------------------------- //
8037
8038/**
8039 * create a layout class
8040 * @param {String} namespace
8041 */
8042Outlayer.create = function( namespace, options ) {
8043  // sub-class Outlayer
8044  var Layout = subclass( Outlayer );
8045  // apply new options and compatOptions
8046  Layout.defaults = utils.extend( {}, Outlayer.defaults );
8047  utils.extend( Layout.defaults, options );
8048  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
8049
8050  Layout.namespace = namespace;
8051
8052  Layout.data = Outlayer.data;
8053
8054  // sub-class Item
8055  Layout.Item = subclass( Item );
8056
8057  // -------------------------- declarative -------------------------- //
8058
8059  utils.htmlInit( Layout, namespace );
8060
8061  // -------------------------- jQuery bridge -------------------------- //
8062
8063  // make into jQuery plugin
8064  if ( jQuery && jQuery.bridget ) {
8065    jQuery.bridget( namespace, Layout );
8066  }
8067
8068  return Layout;
8069};
8070
8071function subclass( Parent ) {
8072  function SubClass() {
8073    Parent.apply( this, arguments );
8074  }
8075
8076  SubClass.prototype = Object.create( Parent.prototype );
8077  SubClass.prototype.constructor = SubClass;
8078
8079  return SubClass;
8080}
8081
8082// ----- helpers ----- //
8083
8084// how many milliseconds are in each unit
8085var msUnits = {
8086  ms: 1,
8087  s: 1000
8088};
8089
8090// munge time-like parameter into millisecond number
8091// '0.4s' -> 40
8092function getMilliseconds( time ) {
8093  if ( typeof time == 'number' ) {
8094    return time;
8095  }
8096  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
8097  var num = matches && matches[1];
8098  var unit = matches && matches[2];
8099  if ( !num.length ) {
8100    return 0;
8101  }
8102  num = parseFloat( num );
8103  var mult = msUnits[ unit ] || 1;
8104  return num * mult;
8105}
8106
8107// ----- fin ----- //
8108
8109// back in global
8110Outlayer.Item = Item;
8111
8112return Outlayer;
8113
8114}));
8115
8116/**
8117 * Isotope Item
8118**/
8119
8120( function( window, factory ) {
8121  // universal module definition
8122  /* jshint strict: false */ /*globals define, module, require */
8123  if ( typeof define == 'function' && define.amd ) {
8124    // AMD
8125    define( 'isotope-layout/js/item',[
8126        'outlayer/outlayer'
8127      ],
8128      factory );
8129  } else if ( typeof module == 'object' && module.exports ) {
8130    // CommonJS
8131    module.exports = factory(
8132      require('outlayer')
8133    );
8134  } else {
8135    // browser global
8136    window.Isotope = window.Isotope || {};
8137    window.Isotope.Item = factory(
8138      window.Outlayer
8139    );
8140  }
8141
8142}( window, function factory( Outlayer ) {
8143'use strict';
8144
8145// -------------------------- Item -------------------------- //
8146
8147// sub-class Outlayer Item
8148function Item() {
8149  Outlayer.Item.apply( this, arguments );
8150}
8151
8152var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
8153
8154var _create = proto._create;
8155proto._create = function() {
8156  // assign id, used for original-order sorting
8157  this.id = this.layout.itemGUID++;
8158  _create.call( this );
8159  this.sortData = {};
8160};
8161
8162proto.updateSortData = function() {
8163  if ( this.isIgnored ) {
8164    return;
8165  }
8166  // default sorters
8167  this.sortData.id = this.id;
8168  // for backward compatibility
8169  this.sortData['original-order'] = this.id;
8170  this.sortData.random = Math.random();
8171  // go thru getSortData obj and apply the sorters
8172  var getSortData = this.layout.options.getSortData;
8173  var sorters = this.layout._sorters;
8174  for ( var key in getSortData ) {
8175    var sorter = sorters[ key ];
8176    this.sortData[ key ] = sorter( this.element, this );
8177  }
8178};
8179
8180var _destroy = proto.destroy;
8181proto.destroy = function() {
8182  // call super
8183  _destroy.apply( this, arguments );
8184  // reset display, #741
8185  this.css({
8186    display: ''
8187  });
8188};
8189
8190return Item;
8191
8192}));
8193
8194/**
8195 * Isotope LayoutMode
8196 */
8197
8198( function( window, factory ) {
8199  // universal module definition
8200  /* jshint strict: false */ /*globals define, module, require */
8201  if ( typeof define == 'function' && define.amd ) {
8202    // AMD
8203    define( 'isotope-layout/js/layout-mode',[
8204        'get-size/get-size',
8205        'outlayer/outlayer'
8206      ],
8207      factory );
8208  } else if ( typeof module == 'object' && module.exports ) {
8209    // CommonJS
8210    module.exports = factory(
8211      require('get-size'),
8212      require('outlayer')
8213    );
8214  } else {
8215    // browser global
8216    window.Isotope = window.Isotope || {};
8217    window.Isotope.LayoutMode = factory(
8218      window.getSize,
8219      window.Outlayer
8220    );
8221  }
8222
8223}( window, function factory( getSize, Outlayer ) {
8224  'use strict';
8225
8226  // layout mode class
8227  function LayoutMode( isotope ) {
8228    this.isotope = isotope;
8229    // link properties
8230    if ( isotope ) {
8231      this.options = isotope.options[ this.namespace ];
8232      this.element = isotope.element;
8233      this.items = isotope.filteredItems;
8234      this.size = isotope.size;
8235    }
8236  }
8237
8238  var proto = LayoutMode.prototype;
8239
8240  /**
8241   * some methods should just defer to default Outlayer method
8242   * and reference the Isotope instance as `this`
8243  **/
8244  var facadeMethods = [
8245    '_resetLayout',
8246    '_getItemLayoutPosition',
8247    '_manageStamp',
8248    '_getContainerSize',
8249    '_getElementOffset',
8250    'needsResizeLayout',
8251    '_getOption'
8252  ];
8253
8254  facadeMethods.forEach( function( methodName ) {
8255    proto[ methodName ] = function() {
8256      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
8257    };
8258  });
8259
8260  // -----  ----- //
8261
8262  // for horizontal layout modes, check vertical size
8263  proto.needsVerticalResizeLayout = function() {
8264    // don't trigger if size did not change
8265    var size = getSize( this.isotope.element );
8266    // check that this.size and size are there
8267    // IE8 triggers resize on body size change, so they might not be
8268    var hasSizes = this.isotope.size && size;
8269    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
8270  };
8271
8272  // ----- measurements ----- //
8273
8274  proto._getMeasurement = function() {
8275    this.isotope._getMeasurement.apply( this, arguments );
8276  };
8277
8278  proto.getColumnWidth = function() {
8279    this.getSegmentSize( 'column', 'Width' );
8280  };
8281
8282  proto.getRowHeight = function() {
8283    this.getSegmentSize( 'row', 'Height' );
8284  };
8285
8286  /**
8287   * get columnWidth or rowHeight
8288   * segment: 'column' or 'row'
8289   * size 'Width' or 'Height'
8290  **/
8291  proto.getSegmentSize = function( segment, size ) {
8292    var segmentName = segment + size;
8293    var outerSize = 'outer' + size;
8294    // columnWidth / outerWidth // rowHeight / outerHeight
8295    this._getMeasurement( segmentName, outerSize );
8296    // got rowHeight or columnWidth, we can chill
8297    if ( this[ segmentName ] ) {
8298      return;
8299    }
8300    // fall back to item of first element
8301    var firstItemSize = this.getFirstItemSize();
8302    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
8303      // or size of container
8304      this.isotope.size[ 'inner' + size ];
8305  };
8306
8307  proto.getFirstItemSize = function() {
8308    var firstItem = this.isotope.filteredItems[0];
8309    return firstItem && firstItem.element && getSize( firstItem.element );
8310  };
8311
8312  // ----- methods that should reference isotope ----- //
8313
8314  proto.layout = function() {
8315    this.isotope.layout.apply( this.isotope, arguments );
8316  };
8317
8318  proto.getSize = function() {
8319    this.isotope.getSize();
8320    this.size = this.isotope.size;
8321  };
8322
8323  // -------------------------- create -------------------------- //
8324
8325  LayoutMode.modes = {};
8326
8327  LayoutMode.create = function( namespace, options ) {
8328
8329    function Mode() {
8330      LayoutMode.apply( this, arguments );
8331    }
8332
8333    Mode.prototype = Object.create( proto );
8334    Mode.prototype.constructor = Mode;
8335
8336    // default options
8337    if ( options ) {
8338      Mode.options = options;
8339    }
8340
8341    Mode.prototype.namespace = namespace;
8342    // register in Isotope
8343    LayoutMode.modes[ namespace ] = Mode;
8344
8345    return Mode;
8346  };
8347
8348  return LayoutMode;
8349
8350}));
8351
8352/*!
8353 * Masonry v4.2.1
8354 * Cascading grid layout library
8355 * https://masonry.desandro.com
8356 * MIT License
8357 * by David DeSandro
8358 */
8359
8360( function( window, factory ) {
8361  // universal module definition
8362  /* jshint strict: false */ /*globals define, module, require */
8363  if ( typeof define == 'function' && define.amd ) {
8364    // AMD
8365    define( 'masonry-layout/masonry',[
8366        'outlayer/outlayer',
8367        'get-size/get-size'
8368      ],
8369      factory );
8370  } else if ( typeof module == 'object' && module.exports ) {
8371    // CommonJS
8372    module.exports = factory(
8373      require('outlayer'),
8374      require('get-size')
8375    );
8376  } else {
8377    // browser global
8378    window.Masonry = factory(
8379      window.Outlayer,
8380      window.getSize
8381    );
8382  }
8383
8384}( window, function factory( Outlayer, getSize ) {
8385
8386
8387
8388// -------------------------- masonryDefinition -------------------------- //
8389
8390  // create an Outlayer layout class
8391  var Masonry = Outlayer.create('masonry');
8392  // isFitWidth -> fitWidth
8393  Masonry.compatOptions.fitWidth = 'isFitWidth';
8394
8395  var proto = Masonry.prototype;
8396
8397  proto._resetLayout = function() {
8398    this.getSize();
8399    this._getMeasurement( 'columnWidth', 'outerWidth' );
8400    this._getMeasurement( 'gutter', 'outerWidth' );
8401    this.measureColumns();
8402
8403    // reset column Y
8404    this.colYs = [];
8405    for ( var i=0; i < this.cols; i++ ) {
8406      this.colYs.push( 0 );
8407    }
8408
8409    this.maxY = 0;
8410    this.horizontalColIndex = 0;
8411  };
8412
8413  proto.measureColumns = function() {
8414    this.getContainerWidth();
8415    // if columnWidth is 0, default to outerWidth of first item
8416    if ( !this.columnWidth ) {
8417      var firstItem = this.items[0];
8418      var firstItemElem = firstItem && firstItem.element;
8419      // columnWidth fall back to item of first element
8420      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
8421        // if first elem has no width, default to size of container
8422        this.containerWidth;
8423    }
8424
8425    var columnWidth = this.columnWidth += this.gutter;
8426
8427    // calculate columns
8428    var containerWidth = this.containerWidth + this.gutter;
8429    var cols = containerWidth / columnWidth;
8430    // fix rounding errors, typically with gutters
8431    var excess = columnWidth - containerWidth % columnWidth;
8432    // if overshoot is less than a pixel, round up, otherwise floor it
8433    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
8434    cols = Math[ mathMethod ]( cols );
8435    this.cols = Math.max( cols, 1 );
8436  };
8437
8438  proto.getContainerWidth = function() {
8439    // container is parent if fit width
8440    var isFitWidth = this._getOption('fitWidth');
8441    var container = isFitWidth ? this.element.parentNode : this.element;
8442    // check that this.size and size are there
8443    // IE8 triggers resize on body size change, so they might not be
8444    var size = getSize( container );
8445    this.containerWidth = size && size.innerWidth;
8446  };
8447
8448  proto._getItemLayoutPosition = function( item ) {
8449    item.getSize();
8450    // how many columns does this brick span
8451    var remainder = item.size.outerWidth % this.columnWidth;
8452    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
8453    // round if off by 1 pixel, otherwise use ceil
8454    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
8455    colSpan = Math.min( colSpan, this.cols );
8456    // use horizontal or top column position
8457    var colPosMethod = this.options.horizontalOrder ?
8458      '_getHorizontalColPosition' : '_getTopColPosition';
8459    var colPosition = this[ colPosMethod ]( colSpan, item );
8460    // position the brick
8461    var position = {
8462      x: this.columnWidth * colPosition.col,
8463      y: colPosition.y
8464    };
8465    // apply setHeight to necessary columns
8466    var setHeight = colPosition.y + item.size.outerHeight;
8467    var setMax = colSpan + colPosition.col;
8468    for ( var i = colPosition.col; i < setMax; i++ ) {
8469      this.colYs[i] = setHeight;
8470    }
8471
8472    return position;
8473  };
8474
8475  proto._getTopColPosition = function( colSpan ) {
8476    var colGroup = this._getTopColGroup( colSpan );
8477    // get the minimum Y value from the columns
8478    var minimumY = Math.min.apply( Math, colGroup );
8479
8480    return {
8481      col: colGroup.indexOf( minimumY ),
8482      y: minimumY,
8483    };
8484  };
8485
8486  /**
8487   * @param {Number} colSpan - number of columns the element spans
8488   * @returns {Array} colGroup
8489   */
8490  proto._getTopColGroup = function( colSpan ) {
8491    if ( colSpan < 2 ) {
8492      // if brick spans only one column, use all the column Ys
8493      return this.colYs;
8494    }
8495
8496    var colGroup = [];
8497    // how many different places could this brick fit horizontally
8498    var groupCount = this.cols + 1 - colSpan;
8499    // for each group potential horizontal position
8500    for ( var i = 0; i < groupCount; i++ ) {
8501      colGroup[i] = this._getColGroupY( i, colSpan );
8502    }
8503    return colGroup;
8504  };
8505
8506  proto._getColGroupY = function( col, colSpan ) {
8507    if ( colSpan < 2 ) {
8508      return this.colYs[ col ];
8509    }
8510    // make an array of colY values for that one group
8511    var groupColYs = this.colYs.slice( col, col + colSpan );
8512    // and get the max value of the array
8513    return Math.max.apply( Math, groupColYs );
8514  };
8515
8516  // get column position based on horizontal index. #873
8517  proto._getHorizontalColPosition = function( colSpan, item ) {
8518    var col = this.horizontalColIndex % this.cols;
8519    var isOver = colSpan > 1 && col + colSpan > this.cols;
8520    // shift to next row if item can't fit on current row
8521    col = isOver ? 0 : col;
8522    // don't let zero-size items take up space
8523    var hasSize = item.size.outerWidth && item.size.outerHeight;
8524    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
8525
8526    return {
8527      col: col,
8528      y: this._getColGroupY( col, colSpan ),
8529    };
8530  };
8531
8532  proto._manageStamp = function( stamp ) {
8533    var stampSize = getSize( stamp );
8534    var offset = this._getElementOffset( stamp );
8535    // get the columns that this stamp affects
8536    var isOriginLeft = this._getOption('originLeft');
8537    var firstX = isOriginLeft ? offset.left : offset.right;
8538    var lastX = firstX + stampSize.outerWidth;
8539    var firstCol = Math.floor( firstX / this.columnWidth );
8540    firstCol = Math.max( 0, firstCol );
8541    var lastCol = Math.floor( lastX / this.columnWidth );
8542    // lastCol should not go over if multiple of columnWidth #425
8543    lastCol -= lastX % this.columnWidth ? 0 : 1;
8544    lastCol = Math.min( this.cols - 1, lastCol );
8545    // set colYs to bottom of the stamp
8546
8547    var isOriginTop = this._getOption('originTop');
8548    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
8549      stampSize.outerHeight;
8550    for ( var i = firstCol; i <= lastCol; i++ ) {
8551      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
8552    }
8553  };
8554
8555  proto._getContainerSize = function() {
8556    this.maxY = Math.max.apply( Math, this.colYs );
8557    var size = {
8558      height: this.maxY
8559    };
8560
8561    if ( this._getOption('fitWidth') ) {
8562      size.width = this._getContainerFitWidth();
8563    }
8564
8565    return size;
8566  };
8567
8568  proto._getContainerFitWidth = function() {
8569    var unusedCols = 0;
8570    // count unused columns
8571    var i = this.cols;
8572    while ( --i ) {
8573      if ( this.colYs[i] !== 0 ) {
8574        break;
8575      }
8576      unusedCols++;
8577    }
8578    // fit container to columns that have been used
8579    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
8580  };
8581
8582  proto.needsResizeLayout = function() {
8583    var previousWidth = this.containerWidth;
8584    this.getContainerWidth();
8585    return previousWidth != this.containerWidth;
8586  };
8587
8588  return Masonry;
8589
8590}));
8591
8592/*!
8593 * Masonry layout mode
8594 * sub-classes Masonry
8595 * https://masonry.desandro.com
8596 */
8597
8598( function( window, factory ) {
8599  // universal module definition
8600  /* jshint strict: false */ /*globals define, module, require */
8601  if ( typeof define == 'function' && define.amd ) {
8602    // AMD
8603    define( 'isotope-layout/js/layout-modes/masonry',[
8604        '../layout-mode',
8605        'masonry-layout/masonry'
8606      ],
8607      factory );
8608  } else if ( typeof module == 'object' && module.exports ) {
8609    // CommonJS
8610    module.exports = factory(
8611      require('../layout-mode'),
8612      require('masonry-layout')
8613    );
8614  } else {
8615    // browser global
8616    factory(
8617      window.Isotope.LayoutMode,
8618      window.Masonry
8619    );
8620  }
8621
8622}( window, function factory( LayoutMode, Masonry ) {
8623'use strict';
8624
8625// -------------------------- masonryDefinition -------------------------- //
8626
8627  // create an Outlayer layout class
8628  var MasonryMode = LayoutMode.create('masonry');
8629
8630  var proto = MasonryMode.prototype;
8631
8632  var keepModeMethods = {
8633    _getElementOffset: true,
8634    layout: true,
8635    _getMeasurement: true
8636  };
8637
8638  // inherit Masonry prototype
8639  for ( var method in Masonry.prototype ) {
8640    // do not inherit mode methods
8641    if ( !keepModeMethods[ method ] ) {
8642      proto[ method ] = Masonry.prototype[ method ];
8643    }
8644  }
8645
8646  var measureColumns = proto.measureColumns;
8647  proto.measureColumns = function() {
8648    // set items, used if measuring first item
8649    this.items = this.isotope.filteredItems;
8650    measureColumns.call( this );
8651  };
8652
8653  // point to mode options for fitWidth
8654  var _getOption = proto._getOption;
8655  proto._getOption = function( option ) {
8656    if ( option == 'fitWidth' ) {
8657      return this.options.isFitWidth !== undefined ?
8658        this.options.isFitWidth : this.options.fitWidth;
8659    }
8660    return _getOption.apply( this.isotope, arguments );
8661  };
8662
8663  return MasonryMode;
8664
8665}));
8666
8667/**
8668 * fitRows layout mode
8669 */
8670
8671( function( window, factory ) {
8672  // universal module definition
8673  /* jshint strict: false */ /*globals define, module, require */
8674  if ( typeof define == 'function' && define.amd ) {
8675    // AMD
8676    define( 'isotope-layout/js/layout-modes/fit-rows',[
8677        '../layout-mode'
8678      ],
8679      factory );
8680  } else if ( typeof exports == 'object' ) {
8681    // CommonJS
8682    module.exports = factory(
8683      require('../layout-mode')
8684    );
8685  } else {
8686    // browser global
8687    factory(
8688      window.Isotope.LayoutMode
8689    );
8690  }
8691
8692}( window, function factory( LayoutMode ) {
8693'use strict';
8694
8695var FitRows = LayoutMode.create('fitRows');
8696
8697var proto = FitRows.prototype;
8698
8699proto._resetLayout = function() {
8700  this.x = 0;
8701  this.y = 0;
8702  this.maxY = 0;
8703  this._getMeasurement( 'gutter', 'outerWidth' );
8704};
8705
8706proto._getItemLayoutPosition = function( item ) {
8707  item.getSize();
8708
8709  var itemWidth = item.size.outerWidth + this.gutter;
8710  // if this element cannot fit in the current row
8711  var containerWidth = this.isotope.size.innerWidth + this.gutter;
8712  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
8713    this.x = 0;
8714    this.y = this.maxY;
8715  }
8716
8717  var position = {
8718    x: this.x,
8719    y: this.y
8720  };
8721
8722  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
8723  this.x += itemWidth;
8724
8725  return position;
8726};
8727
8728proto._getContainerSize = function() {
8729  return { height: this.maxY };
8730};
8731
8732return FitRows;
8733
8734}));
8735
8736/**
8737 * vertical layout mode
8738 */
8739
8740( function( window, factory ) {
8741  // universal module definition
8742  /* jshint strict: false */ /*globals define, module, require */
8743  if ( typeof define == 'function' && define.amd ) {
8744    // AMD
8745    define( 'isotope-layout/js/layout-modes/vertical',[
8746        '../layout-mode'
8747      ],
8748      factory );
8749  } else if ( typeof module == 'object' && module.exports ) {
8750    // CommonJS
8751    module.exports = factory(
8752      require('../layout-mode')
8753    );
8754  } else {
8755    // browser global
8756    factory(
8757      window.Isotope.LayoutMode
8758    );
8759  }
8760
8761}( window, function factory( LayoutMode ) {
8762'use strict';
8763
8764var Vertical = LayoutMode.create( 'vertical', {
8765  horizontalAlignment: 0
8766});
8767
8768var proto = Vertical.prototype;
8769
8770proto._resetLayout = function() {
8771  this.y = 0;
8772};
8773
8774proto._getItemLayoutPosition = function( item ) {
8775  item.getSize();
8776  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
8777    this.options.horizontalAlignment;
8778  var y = this.y;
8779  this.y += item.size.outerHeight;
8780  return { x: x, y: y };
8781};
8782
8783proto._getContainerSize = function() {
8784  return { height: this.y };
8785};
8786
8787return Vertical;
8788
8789}));
8790
8791/*!
8792 * Isotope v3.0.6
8793 *
8794 * Licensed GPLv3 for open source use
8795 * or Isotope Commercial License for commercial use
8796 *
8797 * https://isotope.metafizzy.co
8798 * Copyright 2010-2018 Metafizzy
8799 */
8800
8801( function( window, factory ) {
8802  // universal module definition
8803  /* jshint strict: false */ /*globals define, module, require */
8804  if ( typeof define == 'function' && define.amd ) {
8805    // AMD
8806    define( [
8807        'outlayer/outlayer',
8808        'get-size/get-size',
8809        'desandro-matches-selector/matches-selector',
8810        'fizzy-ui-utils/utils',
8811        'isotope-layout/js/item',
8812        'isotope-layout/js/layout-mode',
8813        // include default layout modes
8814        'isotope-layout/js/layout-modes/masonry',
8815        'isotope-layout/js/layout-modes/fit-rows',
8816        'isotope-layout/js/layout-modes/vertical'
8817      ],
8818      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
8819        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
8820      });
8821  } else if ( typeof module == 'object' && module.exports ) {
8822    // CommonJS
8823    module.exports = factory(
8824      window,
8825      require('outlayer'),
8826      require('get-size'),
8827      require('desandro-matches-selector'),
8828      require('fizzy-ui-utils'),
8829      require('isotope-layout/js/item'),
8830      require('isotope-layout/js/layout-mode'),
8831      // include default layout modes
8832      require('isotope-layout/js/layout-modes/masonry'),
8833      require('isotope-layout/js/layout-modes/fit-rows'),
8834      require('isotope-layout/js/layout-modes/vertical')
8835    );
8836  } else {
8837    // browser global
8838    window.Isotope = factory(
8839      window,
8840      window.Outlayer,
8841      window.getSize,
8842      window.matchesSelector,
8843      window.fizzyUIUtils,
8844      window.Isotope.Item,
8845      window.Isotope.LayoutMode
8846    );
8847  }
8848
8849}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
8850  Item, LayoutMode ) {
8851
8852
8853
8854// -------------------------- vars -------------------------- //
8855
8856var jQuery = window.jQuery;
8857
8858// -------------------------- helpers -------------------------- //
8859
8860var trim = String.prototype.trim ?
8861  function( str ) {
8862    return str.trim();
8863  } :
8864  function( str ) {
8865    return str.replace( /^\s+|\s+$/g, '' );
8866  };
8867
8868// -------------------------- isotopeDefinition -------------------------- //
8869
8870  // create an Outlayer layout class
8871  var Isotope = Outlayer.create( 'isotope', {
8872    layoutMode: 'masonry',
8873    isJQueryFiltering: true,
8874    sortAscending: true
8875  });
8876
8877  Isotope.Item = Item;
8878  Isotope.LayoutMode = LayoutMode;
8879
8880  var proto = Isotope.prototype;
8881
8882  proto._create = function() {
8883    this.itemGUID = 0;
8884    // functions that sort items
8885    this._sorters = {};
8886    this._getSorters();
8887    // call super
8888    Outlayer.prototype._create.call( this );
8889
8890    // create layout modes
8891    this.modes = {};
8892    // start filteredItems with all items
8893    this.filteredItems = this.items;
8894    // keep of track of sortBys
8895    this.sortHistory = [ 'original-order' ];
8896    // create from registered layout modes
8897    for ( var name in LayoutMode.modes ) {
8898      this._initLayoutMode( name );
8899    }
8900  };
8901
8902  proto.reloadItems = function() {
8903    // reset item ID counter
8904    this.itemGUID = 0;
8905    // call super
8906    Outlayer.prototype.reloadItems.call( this );
8907  };
8908
8909  proto._itemize = function() {
8910    var items = Outlayer.prototype._itemize.apply( this, arguments );
8911    // assign ID for original-order
8912    for ( var i=0; i < items.length; i++ ) {
8913      var item = items[i];
8914      item.id = this.itemGUID++;
8915    }
8916    this._updateItemsSortData( items );
8917    return items;
8918  };
8919
8920
8921  // -------------------------- layout -------------------------- //
8922
8923  proto._initLayoutMode = function( name ) {
8924    var Mode = LayoutMode.modes[ name ];
8925    // set mode options
8926    // HACK extend initial options, back-fill in default options
8927    var initialOpts = this.options[ name ] || {};
8928    this.options[ name ] = Mode.options ?
8929      utils.extend( Mode.options, initialOpts ) : initialOpts;
8930    // init layout mode instance
8931    this.modes[ name ] = new Mode( this );
8932  };
8933
8934
8935  proto.layout = function() {
8936    // if first time doing layout, do all magic
8937    if ( !this._isLayoutInited && this._getOption('initLayout') ) {
8938      this.arrange();
8939      return;
8940    }
8941    this._layout();
8942  };
8943
8944  // private method to be used in layout() & magic()
8945  proto._layout = function() {
8946    // don't animate first layout
8947    var isInstant = this._getIsInstant();
8948    // layout flow
8949    this._resetLayout();
8950    this._manageStamps();
8951    this.layoutItems( this.filteredItems, isInstant );
8952
8953    // flag for initalized
8954    this._isLayoutInited = true;
8955  };
8956
8957  // filter + sort + layout
8958  proto.arrange = function( opts ) {
8959    // set any options pass
8960    this.option( opts );
8961    this._getIsInstant();
8962    // filter, sort, and layout
8963
8964    // filter
8965    var filtered = this._filter( this.items );
8966    this.filteredItems = filtered.matches;
8967
8968    this._bindArrangeComplete();
8969
8970    if ( this._isInstant ) {
8971      this._noTransition( this._hideReveal, [ filtered ] );
8972    } else {
8973      this._hideReveal( filtered );
8974    }
8975
8976    this._sort();
8977    this._layout();
8978  };
8979  // alias to _init for main plugin method
8980  proto._init = proto.arrange;
8981
8982  proto._hideReveal = function( filtered ) {
8983    this.reveal( filtered.needReveal );
8984    this.hide( filtered.needHide );
8985  };
8986
8987  // HACK
8988  // Don't animate/transition first layout
8989  // Or don't animate/transition other layouts
8990  proto._getIsInstant = function() {
8991    var isLayoutInstant = this._getOption('layoutInstant');
8992    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
8993      !this._isLayoutInited;
8994    this._isInstant = isInstant;
8995    return isInstant;
8996  };
8997
8998  // listen for layoutComplete, hideComplete and revealComplete
8999  // to trigger arrangeComplete
9000  proto._bindArrangeComplete = function() {
9001    // listen for 3 events to trigger arrangeComplete
9002    var isLayoutComplete, isHideComplete, isRevealComplete;
9003    var _this = this;
9004    function arrangeParallelCallback() {
9005      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
9006        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
9007      }
9008    }
9009    this.once( 'layoutComplete', function() {
9010      isLayoutComplete = true;
9011      arrangeParallelCallback();
9012    });
9013    this.once( 'hideComplete', function() {
9014      isHideComplete = true;
9015      arrangeParallelCallback();
9016    });
9017    this.once( 'revealComplete', function() {
9018      isRevealComplete = true;
9019      arrangeParallelCallback();
9020    });
9021  };
9022
9023  // -------------------------- filter -------------------------- //
9024
9025  proto._filter = function( items ) {
9026    var filter = this.options.filter;
9027    filter = filter || '*';
9028    var matches = [];
9029    var hiddenMatched = [];
9030    var visibleUnmatched = [];
9031
9032    var test = this._getFilterTest( filter );
9033
9034    // test each item
9035    for ( var i=0; i < items.length; i++ ) {
9036      var item = items[i];
9037      if ( item.isIgnored ) {
9038        continue;
9039      }
9040      // add item to either matched or unmatched group
9041      var isMatched = test( item );
9042      // item.isFilterMatched = isMatched;
9043      // add to matches if its a match
9044      if ( isMatched ) {
9045        matches.push( item );
9046      }
9047      // add to additional group if item needs to be hidden or revealed
9048      if ( isMatched && item.isHidden ) {
9049        hiddenMatched.push( item );
9050      } else if ( !isMatched && !item.isHidden ) {
9051        visibleUnmatched.push( item );
9052      }
9053    }
9054
9055    // return collections of items to be manipulated
9056    return {
9057      matches: matches,
9058      needReveal: hiddenMatched,
9059      needHide: visibleUnmatched
9060    };
9061  };
9062
9063  // get a jQuery, function, or a matchesSelector test given the filter
9064  proto._getFilterTest = function( filter ) {
9065    if ( jQuery && this.options.isJQueryFiltering ) {
9066      // use jQuery
9067      return function( item ) {
9068        return jQuery( item.element ).is( filter );
9069      };
9070    }
9071    if ( typeof filter == 'function' ) {
9072      // use filter as function
9073      return function( item ) {
9074        return filter( item.element );
9075      };
9076    }
9077    // default, use filter as selector string
9078    return function( item ) {
9079      return matchesSelector( item.element, filter );
9080    };
9081  };
9082
9083  // -------------------------- sorting -------------------------- //
9084
9085  /**
9086   * @params {Array} elems
9087   * @public
9088   */
9089  proto.updateSortData = function( elems ) {
9090    // get items
9091    var items;
9092    if ( elems ) {
9093      elems = utils.makeArray( elems );
9094      items = this.getItems( elems );
9095    } else {
9096      // update all items if no elems provided
9097      items = this.items;
9098    }
9099
9100    this._getSorters();
9101    this._updateItemsSortData( items );
9102  };
9103
9104  proto._getSorters = function() {
9105    var getSortData = this.options.getSortData;
9106    for ( var key in getSortData ) {
9107      var sorter = getSortData[ key ];
9108      this._sorters[ key ] = mungeSorter( sorter );
9109    }
9110  };
9111
9112  /**
9113   * @params {Array} items - of Isotope.Items
9114   * @private
9115   */
9116  proto._updateItemsSortData = function( items ) {
9117    // do not update if no items
9118    var len = items && items.length;
9119
9120    for ( var i=0; len && i < len; i++ ) {
9121      var item = items[i];
9122      item.updateSortData();
9123    }
9124  };
9125
9126  // ----- munge sorter ----- //
9127
9128  // encapsulate this, as we just need mungeSorter
9129  // other functions in here are just for munging
9130  var mungeSorter = ( function() {
9131    // add a magic layer to sorters for convienent shorthands
9132    // `.foo-bar` will use the text of .foo-bar querySelector
9133    // `[foo-bar]` will use attribute
9134    // you can also add parser
9135    // `.foo-bar parseInt` will parse that as a number
9136    function mungeSorter( sorter ) {
9137      // if not a string, return function or whatever it is
9138      if ( typeof sorter != 'string' ) {
9139        return sorter;
9140      }
9141      // parse the sorter string
9142      var args = trim( sorter ).split(' ');
9143      var query = args[0];
9144      // check if query looks like [an-attribute]
9145      var attrMatch = query.match( /^\[(.+)\]$/ );
9146      var attr = attrMatch && attrMatch[1];
9147      var getValue = getValueGetter( attr, query );
9148      // use second argument as a parser
9149      var parser = Isotope.sortDataParsers[ args[1] ];
9150      // parse the value, if there was a parser
9151      sorter = parser ? function( elem ) {
9152        return elem && parser( getValue( elem ) );
9153      } :
9154      // otherwise just return value
9155      function( elem ) {
9156        return elem && getValue( elem );
9157      };
9158
9159      return sorter;
9160    }
9161
9162    // get an attribute getter, or get text of the querySelector
9163    function getValueGetter( attr, query ) {
9164      // if query looks like [foo-bar], get attribute
9165      if ( attr ) {
9166        return function getAttribute( elem ) {
9167          return elem.getAttribute( attr );
9168        };
9169      }
9170
9171      // otherwise, assume its a querySelector, and get its text
9172      return function getChildText( elem ) {
9173        var child = elem.querySelector( query );
9174        return child && child.textContent;
9175      };
9176    }
9177
9178    return mungeSorter;
9179  })();
9180
9181  // parsers used in getSortData shortcut strings
9182  Isotope.sortDataParsers = {
9183    'parseInt': function( val ) {
9184      return parseInt( val, 10 );
9185    },
9186    'parseFloat': function( val ) {
9187      return parseFloat( val );
9188    }
9189  };
9190
9191  // ----- sort method ----- //
9192
9193  // sort filteredItem order
9194  proto._sort = function() {
9195    if ( !this.options.sortBy ) {
9196      return;
9197    }
9198    // keep track of sortBy History
9199    var sortBys = utils.makeArray( this.options.sortBy );
9200    if ( !this._getIsSameSortBy( sortBys ) ) {
9201      // concat all sortBy and sortHistory, add to front, oldest goes in last
9202      this.sortHistory = sortBys.concat( this.sortHistory );
9203    }
9204    // sort magic
9205    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
9206    this.filteredItems.sort( itemSorter );
9207  };
9208
9209  // check if sortBys is same as start of sortHistory
9210  proto._getIsSameSortBy = function( sortBys ) {
9211    for ( var i=0; i < sortBys.length; i++ ) {
9212      if ( sortBys[i] != this.sortHistory[i] ) {
9213        return false;
9214      }
9215    }
9216    return true;
9217  };
9218
9219  // returns a function used for sorting
9220  function getItemSorter( sortBys, sortAsc ) {
9221    return function sorter( itemA, itemB ) {
9222      // cycle through all sortKeys
9223      for ( var i = 0; i < sortBys.length; i++ ) {
9224        var sortBy = sortBys[i];
9225        var a = itemA.sortData[ sortBy ];
9226        var b = itemB.sortData[ sortBy ];
9227        if ( a > b || a < b ) {
9228          // if sortAsc is an object, use the value given the sortBy key
9229          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
9230          var direction = isAscending ? 1 : -1;
9231          return ( a > b ? 1 : -1 ) * direction;
9232        }
9233      }
9234      return 0;
9235    };
9236  }
9237
9238  // -------------------------- methods -------------------------- //
9239
9240  // get layout mode
9241  proto._mode = function() {
9242    var layoutMode = this.options.layoutMode;
9243    var mode = this.modes[ layoutMode ];
9244    if ( !mode ) {
9245      // TODO console.error
9246      throw new Error( 'No layout mode: ' + layoutMode );
9247    }
9248    // HACK sync mode's options
9249    // any options set after init for layout mode need to be synced
9250    mode.options = this.options[ layoutMode ];
9251    return mode;
9252  };
9253
9254  proto._resetLayout = function() {
9255    // trigger original reset layout
9256    Outlayer.prototype._resetLayout.call( this );
9257    this._mode()._resetLayout();
9258  };
9259
9260  proto._getItemLayoutPosition = function( item  ) {
9261    return this._mode()._getItemLayoutPosition( item );
9262  };
9263
9264  proto._manageStamp = function( stamp ) {
9265    this._mode()._manageStamp( stamp );
9266  };
9267
9268  proto._getContainerSize = function() {
9269    return this._mode()._getContainerSize();
9270  };
9271
9272  proto.needsResizeLayout = function() {
9273    return this._mode().needsResizeLayout();
9274  };
9275
9276  // -------------------------- adding & removing -------------------------- //
9277
9278  // HEADS UP overwrites default Outlayer appended
9279  proto.appended = function( elems ) {
9280    var items = this.addItems( elems );
9281    if ( !items.length ) {
9282      return;
9283    }
9284    // filter, layout, reveal new items
9285    var filteredItems = this._filterRevealAdded( items );
9286    // add to filteredItems
9287    this.filteredItems = this.filteredItems.concat( filteredItems );
9288  };
9289
9290  // HEADS UP overwrites default Outlayer prepended
9291  proto.prepended = function( elems ) {
9292    var items = this._itemize( elems );
9293    if ( !items.length ) {
9294      return;
9295    }
9296    // start new layout
9297    this._resetLayout();
9298    this._manageStamps();
9299    // filter, layout, reveal new items
9300    var filteredItems = this._filterRevealAdded( items );
9301    // layout previous items
9302    this.layoutItems( this.filteredItems );
9303    // add to items and filteredItems
9304    this.filteredItems = filteredItems.concat( this.filteredItems );
9305    this.items = items.concat( this.items );
9306  };
9307
9308  proto._filterRevealAdded = function( items ) {
9309    var filtered = this._filter( items );
9310    this.hide( filtered.needHide );
9311    // reveal all new items
9312    this.reveal( filtered.matches );
9313    // layout new items, no transition
9314    this.layoutItems( filtered.matches, true );
9315    return filtered.matches;
9316  };
9317
9318  /**
9319   * Filter, sort, and layout newly-appended item elements
9320   * @param {Array or NodeList or Element} elems
9321   */
9322  proto.insert = function( elems ) {
9323    var items = this.addItems( elems );
9324    if ( !items.length ) {
9325      return;
9326    }
9327    // append item elements
9328    var i, item;
9329    var len = items.length;
9330    for ( i=0; i < len; i++ ) {
9331      item = items[i];
9332      this.element.appendChild( item.element );
9333    }
9334    // filter new stuff
9335    var filteredInsertItems = this._filter( items ).matches;
9336    // set flag
9337    for ( i=0; i < len; i++ ) {
9338      items[i].isLayoutInstant = true;
9339    }
9340    this.arrange();
9341    // reset flag
9342    for ( i=0; i < len; i++ ) {
9343      delete items[i].isLayoutInstant;
9344    }
9345    this.reveal( filteredInsertItems );
9346  };
9347
9348  var _remove = proto.remove;
9349  proto.remove = function( elems ) {
9350    elems = utils.makeArray( elems );
9351    var removeItems = this.getItems( elems );
9352    // do regular thing
9353    _remove.call( this, elems );
9354    // bail if no items to remove
9355    var len = removeItems && removeItems.length;
9356    // remove elems from filteredItems
9357    for ( var i=0; len && i < len; i++ ) {
9358      var item = removeItems[i];
9359      // remove item from collection
9360      utils.removeFrom( this.filteredItems, item );
9361    }
9362  };
9363
9364  proto.shuffle = function() {
9365    // update random sortData
9366    for ( var i=0; i < this.items.length; i++ ) {
9367      var item = this.items[i];
9368      item.sortData.random = Math.random();
9369    }
9370    this.options.sortBy = 'random';
9371    this._sort();
9372    this._layout();
9373  };
9374
9375  /**
9376   * trigger fn without transition
9377   * kind of hacky to have this in the first place
9378   * @param {Function} fn
9379   * @param {Array} args
9380   * @returns ret
9381   * @private
9382   */
9383  proto._noTransition = function( fn, args ) {
9384    // save transitionDuration before disabling
9385    var transitionDuration = this.options.transitionDuration;
9386    // disable transition
9387    this.options.transitionDuration = 0;
9388    // do it
9389    var returnValue = fn.apply( this, args );
9390    // re-enable transition for reveal
9391    this.options.transitionDuration = transitionDuration;
9392    return returnValue;
9393  };
9394
9395  // ----- helper methods ----- //
9396
9397  /**
9398   * getter method for getting filtered item elements
9399   * @returns {Array} elems - collection of item elements
9400   */
9401  proto.getFilteredItemElements = function() {
9402    return this.filteredItems.map( function( item ) {
9403      return item.element;
9404    });
9405  };
9406
9407  // -----  ----- //
9408
9409  return Isotope;
9410
9411}));
9412
vendor: 29,252 bytes, lines 9413-10569
9413/*!
9414 * Packery layout mode PACKAGED v2.0.1
9415 * sub-classes Packery
9416 */
9417
9418/**
9419 * Rect
9420 * low-level utility class for basic geometry
9421 */
9422
9423( function( window, factory ) {
9424  // universal module definition
9425  /* jshint strict: false */ /* globals define, module */
9426  if ( typeof define == 'function' && define.amd ) {
9427    // AMD
9428    define( 'packery/js/rect',factory );
9429  } else if ( typeof module == 'object' && module.exports ) {
9430    // CommonJS
9431    module.exports = factory();
9432  } else {
9433    // browser global
9434    window.Packery = window.Packery || {};
9435    window.Packery.Rect = factory();
9436  }
9437
9438}( window, function factory() {
9439
9440
9441// -------------------------- Rect -------------------------- //
9442
9443function Rect( props ) {
9444  // extend properties from defaults
9445  for ( var prop in Rect.defaults ) {
9446    this[ prop ] = Rect.defaults[ prop ];
9447  }
9448
9449  for ( prop in props ) {
9450    this[ prop ] = props[ prop ];
9451  }
9452
9453}
9454
9455Rect.defaults = {
9456  x: 0,
9457  y: 0,
9458  width: 0,
9459  height: 0
9460};
9461
9462var proto = Rect.prototype;
9463
9464/**
9465 * Determines whether or not this rectangle wholly encloses another rectangle or point.
9466 * @param {Rect} rect
9467 * @returns {Boolean}
9468**/
9469proto.contains = function( rect ) {
9470  // points don't have width or height
9471  var otherWidth = rect.width || 0;
9472  var otherHeight = rect.height || 0;
9473  return this.x <= rect.x &&
9474    this.y <= rect.y &&
9475    this.x + this.width >= rect.x + otherWidth &&
9476    this.y + this.height >= rect.y + otherHeight;
9477};
9478
9479/**
9480 * Determines whether or not the rectangle intersects with another.
9481 * @param {Rect} rect
9482 * @returns {Boolean}
9483**/
9484proto.overlaps = function( rect ) {
9485  var thisRight = this.x + this.width;
9486  var thisBottom = this.y + this.height;
9487  var rectRight = rect.x + rect.width;
9488  var rectBottom = rect.y + rect.height;
9489
9490  // http://stackoverflow.com/a/306332
9491  return this.x < rectRight &&
9492    thisRight > rect.x &&
9493    this.y < rectBottom &&
9494    thisBottom > rect.y;
9495};
9496
9497/**
9498 * @param {Rect} rect - the overlapping rect
9499 * @returns {Array} freeRects - rects representing the area around the rect
9500**/
9501proto.getMaximalFreeRects = function( rect ) {
9502
9503  // if no intersection, return false
9504  if ( !this.overlaps( rect ) ) {
9505    return false;
9506  }
9507
9508  var freeRects = [];
9509  var freeRect;
9510
9511  var thisRight = this.x + this.width;
9512  var thisBottom = this.y + this.height;
9513  var rectRight = rect.x + rect.width;
9514  var rectBottom = rect.y + rect.height;
9515
9516  // top
9517  if ( this.y < rect.y ) {
9518    freeRect = new Rect({
9519      x: this.x,
9520      y: this.y,
9521      width: this.width,
9522      height: rect.y - this.y
9523    });
9524    freeRects.push( freeRect );
9525  }
9526
9527  // right
9528  if ( thisRight > rectRight ) {
9529    freeRect = new Rect({
9530      x: rectRight,
9531      y: this.y,
9532      width: thisRight - rectRight,
9533      height: this.height
9534    });
9535    freeRects.push( freeRect );
9536  }
9537
9538  // bottom
9539  if ( thisBottom > rectBottom ) {
9540    freeRect = new Rect({
9541      x: this.x,
9542      y: rectBottom,
9543      width: this.width,
9544      height: thisBottom - rectBottom
9545    });
9546    freeRects.push( freeRect );
9547  }
9548
9549  // left
9550  if ( this.x < rect.x ) {
9551    freeRect = new Rect({
9552      x: this.x,
9553      y: this.y,
9554      width: rect.x - this.x,
9555      height: this.height
9556    });
9557    freeRects.push( freeRect );
9558  }
9559
9560  return freeRects;
9561};
9562
9563proto.canFit = function( rect ) {
9564  return this.width >= rect.width && this.height >= rect.height;
9565};
9566
9567return Rect;
9568
9569}));
9570
9571/**
9572 * Packer
9573 * bin-packing algorithm
9574 */
9575
9576( function( window, factory ) {
9577  // universal module definition
9578  /* jshint strict: false */ /* globals define, module, require */
9579  if ( typeof define == 'function' && define.amd ) {
9580    // AMD
9581    define( 'packery/js/packer',[ './rect' ], factory );
9582  } else if ( typeof module == 'object' && module.exports ) {
9583    // CommonJS
9584    module.exports = factory(
9585      require('./rect')
9586    );
9587  } else {
9588    // browser global
9589    var Packery = window.Packery = window.Packery || {};
9590    Packery.Packer = factory( Packery.Rect );
9591  }
9592
9593}( window, function factory( Rect ) {
9594
9595
9596// -------------------------- Packer -------------------------- //
9597
9598/**
9599 * @param {Number} width
9600 * @param {Number} height
9601 * @param {String} sortDirection
9602 *   topLeft for vertical, leftTop for horizontal
9603 */
9604function Packer( width, height, sortDirection ) {
9605  this.width = width || 0;
9606  this.height = height || 0;
9607  this.sortDirection = sortDirection || 'downwardLeftToRight';
9608
9609  this.reset();
9610}
9611
9612var proto = Packer.prototype;
9613
9614proto.reset = function() {
9615  this.spaces = [];
9616
9617  var initialSpace = new Rect({
9618    x: 0,
9619    y: 0,
9620    width: this.width,
9621    height: this.height
9622  });
9623
9624  this.spaces.push( initialSpace );
9625  // set sorter
9626  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
9627};
9628
9629// change x and y of rect to fit with in Packer's available spaces
9630proto.pack = function( rect ) {
9631  for ( var i=0; i < this.spaces.length; i++ ) {
9632    var space = this.spaces[i];
9633    if ( space.canFit( rect ) ) {
9634      this.placeInSpace( rect, space );
9635      break;
9636    }
9637  }
9638};
9639
9640proto.columnPack = function( rect ) {
9641  for ( var i=0; i < this.spaces.length; i++ ) {
9642    var space = this.spaces[i];
9643    var canFitInSpaceColumn = space.x <= rect.x &&
9644      space.x + space.width >= rect.x + rect.width &&
9645      space.height >= rect.height - 0.01; // fudge number for rounding error
9646    if ( canFitInSpaceColumn ) {
9647      rect.y = space.y;
9648      this.placed( rect );
9649      break;
9650    }
9651  }
9652};
9653
9654proto.rowPack = function( rect ) {
9655  for ( var i=0; i < this.spaces.length; i++ ) {
9656    var space = this.spaces[i];
9657    var canFitInSpaceRow = space.y <= rect.y &&
9658      space.y + space.height >= rect.y + rect.height &&
9659      space.width >= rect.width - 0.01; // fudge number for rounding error
9660    if ( canFitInSpaceRow ) {
9661      rect.x = space.x;
9662      this.placed( rect );
9663      break;
9664    }
9665  }
9666};
9667
9668proto.placeInSpace = function( rect, space ) {
9669  // place rect in space
9670  rect.x = space.x;
9671  rect.y = space.y;
9672
9673  this.placed( rect );
9674};
9675
9676// update spaces with placed rect
9677proto.placed = function( rect ) {
9678  // update spaces
9679  var revisedSpaces = [];
9680  for ( var i=0; i < this.spaces.length; i++ ) {
9681    var space = this.spaces[i];
9682    var newSpaces = space.getMaximalFreeRects( rect );
9683    // add either the original space or the new spaces to the revised spaces
9684    if ( newSpaces ) {
9685      revisedSpaces.push.apply( revisedSpaces, newSpaces );
9686    } else {
9687      revisedSpaces.push( space );
9688    }
9689  }
9690
9691  this.spaces = revisedSpaces;
9692
9693  this.mergeSortSpaces();
9694};
9695
9696proto.mergeSortSpaces = function() {
9697  // remove redundant spaces
9698  Packer.mergeRects( this.spaces );
9699  this.spaces.sort( this.sorter );
9700};
9701
9702// add a space back
9703proto.addSpace = function( rect ) {
9704  this.spaces.push( rect );
9705  this.mergeSortSpaces();
9706};
9707
9708// -------------------------- utility functions -------------------------- //
9709
9710/**
9711 * Remove redundant rectangle from array of rectangles
9712 * @param {Array} rects: an array of Rects
9713 * @returns {Array} rects: an array of Rects
9714**/
9715Packer.mergeRects = function( rects ) {
9716  var i = 0;
9717  var rect = rects[i];
9718
9719  rectLoop:
9720  while ( rect ) {
9721    var j = 0;
9722    var compareRect = rects[ i + j ];
9723
9724    while ( compareRect ) {
9725      if  ( compareRect == rect ) {
9726        j++; // next
9727      } else if ( compareRect.contains( rect ) ) {
9728        // remove rect
9729        rects.splice( i, 1 );
9730        rect = rects[i]; // set next rect
9731        continue rectLoop; // bail on compareLoop
9732      } else if ( rect.contains( compareRect ) ) {
9733        // remove compareRect
9734        rects.splice( i + j, 1 );
9735      } else {
9736        j++;
9737      }
9738      compareRect = rects[ i + j ]; // set next compareRect
9739    }
9740    i++;
9741    rect = rects[i];
9742  }
9743
9744  return rects;
9745};
9746
9747
9748// -------------------------- sorters -------------------------- //
9749
9750// functions for sorting rects in order
9751var sorters = {
9752  // top down, then left to right
9753  downwardLeftToRight: function( a, b ) {
9754    return a.y - b.y || a.x - b.x;
9755  },
9756  // left to right, then top down
9757  rightwardTopToBottom: function( a, b ) {
9758    return a.x - b.x || a.y - b.y;
9759  }
9760};
9761
9762
9763// --------------------------  -------------------------- //
9764
9765return Packer;
9766
9767}));
9768
9769/**
9770 * Packery Item Element
9771**/
9772
9773( function( window, factory ) {
9774  // universal module definition
9775  /* jshint strict: false */ /* globals define, module, require */
9776  if ( typeof define == 'function' && define.amd ) {
9777    // AMD
9778    define( 'packery/js/item',[
9779        'outlayer/outlayer',
9780        './rect'
9781      ],
9782      factory );
9783  } else if ( typeof module == 'object' && module.exports ) {
9784    // CommonJS
9785    module.exports = factory(
9786      require('outlayer'),
9787      require('./rect')
9788    );
9789  } else {
9790    // browser global
9791    window.Packery.Item = factory(
9792      window.Outlayer,
9793      window.Packery.Rect
9794    );
9795  }
9796
9797}( window, function factory( Outlayer, Rect ) {
9798
9799
9800// -------------------------- Item -------------------------- //
9801
9802var docElemStyle = document.documentElement.style;
9803
9804var transformProperty = typeof docElemStyle.transform == 'string' ?
9805  'transform' : 'WebkitTransform';
9806
9807// sub-class Item
9808var Item = function PackeryItem() {
9809  Outlayer.Item.apply( this, arguments );
9810};
9811
9812var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
9813
9814var __create = proto._create;
9815proto._create = function() {
9816  // call default _create logic
9817  __create.call( this );
9818  this.rect = new Rect();
9819};
9820
9821var _moveTo = proto.moveTo;
9822proto.moveTo = function( x, y ) {
9823  // don't shift 1px while dragging
9824  var dx = Math.abs( this.position.x - x );
9825  var dy = Math.abs( this.position.y - y );
9826
9827  var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&
9828    !this.isTransitioning && dx < 1 && dy < 1;
9829  if ( canHackGoTo ) {
9830    this.goTo( x, y );
9831    return;
9832  }
9833  _moveTo.apply( this, arguments );
9834};
9835
9836// -------------------------- placing -------------------------- //
9837
9838proto.enablePlacing = function() {
9839  this.removeTransitionStyles();
9840  // remove transform property from transition
9841  if ( this.isTransitioning && transformProperty ) {
9842    this.element.style[ transformProperty ] = 'none';
9843  }
9844  this.isTransitioning = false;
9845  this.getSize();
9846  this.layout._setRectSize( this.element, this.rect );
9847  this.isPlacing = true;
9848};
9849
9850proto.disablePlacing = function() {
9851  this.isPlacing = false;
9852};
9853
9854// -----  ----- //
9855
9856// remove element from DOM
9857proto.removeElem = function() {
9858  this.element.parentNode.removeChild( this.element );
9859  // add space back to packer
9860  this.layout.packer.addSpace( this.rect );
9861  this.emitEvent( 'remove', [ this ] );
9862};
9863
9864// ----- dropPlaceholder ----- //
9865
9866proto.showDropPlaceholder = function() {
9867  var dropPlaceholder = this.dropPlaceholder;
9868  if ( !dropPlaceholder ) {
9869    // create dropPlaceholder
9870    dropPlaceholder = this.dropPlaceholder = document.createElement('div');
9871    dropPlaceholder.className = 'packery-drop-placeholder';
9872    dropPlaceholder.style.position = 'absolute';
9873  }
9874
9875  dropPlaceholder.style.width = this.size.width + 'px';
9876  dropPlaceholder.style.height = this.size.height + 'px';
9877  this.positionDropPlaceholder();
9878  this.layout.element.appendChild( dropPlaceholder );
9879};
9880
9881proto.positionDropPlaceholder = function() {
9882  this.dropPlaceholder.style[ transformProperty ] = 'translate(' +
9883    this.rect.x + 'px, ' + this.rect.y + 'px)';
9884};
9885
9886proto.hideDropPlaceholder = function() {
9887  this.layout.element.removeChild( this.dropPlaceholder );
9888};
9889
9890// -----  ----- //
9891
9892return Item;
9893
9894}));
9895
9896/*!
9897 * Packery v2.0.0
9898 * Gapless, draggable grid layouts
9899 *
9900 * Licensed GPLv3 for open source use
9901 * or Packery Commercial License for commercial use
9902 *
9903 * http://packery.metafizzy.co
9904 * Copyright 2016 Metafizzy
9905 */
9906
9907( function( window, factory ) {
9908  // universal module definition
9909  /* jshint strict: false */ /* globals define, module, require */
9910  if ( typeof define == 'function' && define.amd ) {
9911    // AMD
9912    define( 'packery/js/packery',[
9913        'get-size/get-size',
9914        'outlayer/outlayer',
9915        './rect',
9916        './packer',
9917        './item'
9918      ],
9919      factory );
9920  } else if ( typeof module == 'object' && module.exports ) {
9921    // CommonJS
9922    module.exports = factory(
9923      require('get-size'),
9924      require('outlayer'),
9925      require('./rect'),
9926      require('./packer'),
9927      require('./item')
9928    );
9929  } else {
9930    // browser global
9931    window.Packery = factory(
9932      window.getSize,
9933      window.Outlayer,
9934      window.Packery.Rect,
9935      window.Packery.Packer,
9936      window.Packery.Item
9937    );
9938  }
9939
9940}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {
9941
9942
9943// ----- Rect ----- //
9944
9945// allow for pixel rounding errors IE8-IE11 & Firefox; #227
9946Rect.prototype.canFit = function( rect ) {
9947  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
9948};
9949
9950// -------------------------- Packery -------------------------- //
9951
9952// create an Outlayer layout class
9953var Packery = Outlayer.create('packery');
9954Packery.Item = Item;
9955
9956var proto = Packery.prototype;
9957
9958proto._create = function() {
9959  // call super
9960  Outlayer.prototype._create.call( this );
9961
9962  // initial properties
9963  this.packer = new Packer();
9964  // packer for drop targets
9965  this.shiftPacker = new Packer();
9966  this.isEnabled = true;
9967
9968  this.dragItemCount = 0;
9969
9970  // create drag handlers
9971  var _this = this;
9972  this.handleDraggabilly = {
9973    dragStart: function() {
9974      _this.itemDragStart( this.element );
9975    },
9976    dragMove: function() {
9977      _this.itemDragMove( this.element, this.position.x, this.position.y );
9978    },
9979    dragEnd: function() {
9980      _this.itemDragEnd( this.element );
9981    }
9982  };
9983
9984  this.handleUIDraggable = {
9985    start: function handleUIDraggableStart( event, ui ) {
9986      // HTML5 may trigger dragstart, dismiss HTML5 dragging
9987      if ( !ui ) {
9988        return;
9989      }
9990      _this.itemDragStart( event.currentTarget );
9991    },
9992    drag: function handleUIDraggableDrag( event, ui ) {
9993      if ( !ui ) {
9994        return;
9995      }
9996      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
9997    },
9998    stop: function handleUIDraggableStop( event, ui ) {
9999      if ( !ui ) {
10000        return;
10001      }
10002      _this.itemDragEnd( event.currentTarget );
10003    }
10004  };
10005
10006};
10007
10008
10009// ----- init & layout ----- //
10010
10011/**
10012 * logic before any new layout
10013 */
10014proto._resetLayout = function() {
10015  this.getSize();
10016
10017  this._getMeasurements();
10018
10019  // reset packer
10020  var width, height, sortDirection;
10021  // packer settings, if horizontal or vertical
10022  if ( this._getOption('horizontal') ) {
10023    width = Infinity;
10024    height = this.size.innerHeight + this.gutter;
10025    sortDirection = 'rightwardTopToBottom';
10026  } else {
10027    width = this.size.innerWidth + this.gutter;
10028    height = Infinity;
10029    sortDirection = 'downwardLeftToRight';
10030  }
10031
10032  this.packer.width = this.shiftPacker.width = width;
10033  this.packer.height = this.shiftPacker.height = height;
10034  this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;
10035
10036  this.packer.reset();
10037
10038  // layout
10039  this.maxY = 0;
10040  this.maxX = 0;
10041};
10042
10043/**
10044 * update columnWidth, rowHeight, & gutter
10045 * @private
10046 */
10047proto._getMeasurements = function() {
10048  this._getMeasurement( 'columnWidth', 'width' );
10049  this._getMeasurement( 'rowHeight', 'height' );
10050  this._getMeasurement( 'gutter', 'width' );
10051};
10052
10053proto._getItemLayoutPosition = function( item ) {
10054  this._setRectSize( item.element, item.rect );
10055  if ( this.isShifting || this.dragItemCount > 0 ) {
10056    var packMethod = this._getPackMethod();
10057    this.packer[ packMethod ]( item.rect );
10058  } else {
10059    this.packer.pack( item.rect );
10060  }
10061
10062  this._setMaxXY( item.rect );
10063  return item.rect;
10064};
10065
10066proto.shiftLayout = function() {
10067  this.isShifting = true;
10068  this.layout();
10069  delete this.isShifting;
10070};
10071
10072proto._getPackMethod = function() {
10073  return this._getOption('horizontal') ? 'rowPack' : 'columnPack';
10074};
10075
10076
10077/**
10078 * set max X and Y value, for size of container
10079 * @param {Packery.Rect} rect
10080 * @private
10081 */
10082proto._setMaxXY = function( rect ) {
10083  this.maxX = Math.max( rect.x + rect.width, this.maxX );
10084  this.maxY = Math.max( rect.y + rect.height, this.maxY );
10085};
10086
10087/**
10088 * set the width and height of a rect, applying columnWidth and rowHeight
10089 * @param {Element} elem
10090 * @param {Packery.Rect} rect
10091 */
10092proto._setRectSize = function( elem, rect ) {
10093  var size = getSize( elem );
10094  var w = size.outerWidth;
10095  var h = size.outerHeight;
10096  // size for columnWidth and rowHeight, if available
10097  // only check if size is non-zero, #177
10098  if ( w || h ) {
10099    w = this._applyGridGutter( w, this.columnWidth );
10100    h = this._applyGridGutter( h, this.rowHeight );
10101  }
10102  // rect must fit in packer
10103  rect.width = Math.min( w, this.packer.width );
10104  rect.height = Math.min( h, this.packer.height );
10105};
10106
10107/**
10108 * fits item to columnWidth/rowHeight and adds gutter
10109 * @param {Number} measurement - item width or height
10110 * @param {Number} gridSize - columnWidth or rowHeight
10111 * @returns measurement
10112 */
10113proto._applyGridGutter = function( measurement, gridSize ) {
10114  // just add gutter if no gridSize
10115  if ( !gridSize ) {
10116    return measurement + this.gutter;
10117  }
10118  gridSize += this.gutter;
10119  // fit item to columnWidth/rowHeight
10120  var remainder = measurement % gridSize;
10121  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
10122  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
10123  return measurement;
10124};
10125
10126proto._getContainerSize = function() {
10127  if ( this._getOption('horizontal') ) {
10128    return {
10129      width: this.maxX - this.gutter
10130    };
10131  } else {
10132    return {
10133      height: this.maxY - this.gutter
10134    };
10135  }
10136};
10137
10138
10139// -------------------------- stamp -------------------------- //
10140
10141/**
10142 * makes space for element
10143 * @param {Element} elem
10144 */
10145proto._manageStamp = function( elem ) {
10146
10147  var item = this.getItem( elem );
10148  var rect;
10149  if ( item && item.isPlacing ) {
10150    rect = item.rect;
10151  } else {
10152    var offset = this._getElementOffset( elem );
10153    rect = new Rect({
10154      x: this._getOption('originLeft') ? offset.left : offset.right,
10155      y: this._getOption('originTop') ? offset.top : offset.bottom
10156    });
10157  }
10158
10159  this._setRectSize( elem, rect );
10160  // save its space in the packer
10161  this.packer.placed( rect );
10162  this._setMaxXY( rect );
10163};
10164
10165// -------------------------- methods -------------------------- //
10166
10167function verticalSorter( a, b ) {
10168  return a.position.y - b.position.y || a.position.x - b.position.x;
10169}
10170
10171function horizontalSorter( a, b ) {
10172  return a.position.x - b.position.x || a.position.y - b.position.y;
10173}
10174
10175proto.sortItemsByPosition = function() {
10176  var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;
10177  this.items.sort( sorter );
10178};
10179
10180/**
10181 * Fit item element in its current position
10182 * Packery will position elements around it
10183 * useful for expanding elements
10184 *
10185 * @param {Element} elem
10186 * @param {Number} x - horizontal destination position, optional
10187 * @param {Number} y - vertical destination position, optional
10188 */
10189proto.fit = function( elem, x, y ) {
10190  var item = this.getItem( elem );
10191  if ( !item ) {
10192    return;
10193  }
10194
10195  // stamp item to get it out of layout
10196  this.stamp( item.element );
10197  // set placing flag
10198  item.enablePlacing();
10199  this.updateShiftTargets( item );
10200  // fall back to current position for fitting
10201  x = x === undefined ? item.rect.x: x;
10202  y = y === undefined ? item.rect.y: y;
10203  // position it best at its destination
10204  this.shift( item, x, y );
10205  this._bindFitEvents( item );
10206  item.moveTo( item.rect.x, item.rect.y );
10207  // layout everything else
10208  this.shiftLayout();
10209  // return back to regularly scheduled programming
10210  this.unstamp( item.element );
10211  this.sortItemsByPosition();
10212  item.disablePlacing();
10213};
10214
10215/**
10216 * emit event when item is fit and other items are laid out
10217 * @param {Packery.Item} item
10218 * @private
10219 */
10220proto._bindFitEvents = function( item ) {
10221  var _this = this;
10222  var ticks = 0;
10223  function onLayout() {
10224    ticks++;
10225    if ( ticks != 2 ) {
10226      return;
10227    }
10228    _this.dispatchEvent( 'fitComplete', null, [ item ] );
10229  }
10230  // when item is laid out
10231  item.once( 'layout', onLayout );
10232  // when all items are laid out
10233  this.once( 'layoutComplete', onLayout );
10234};
10235
10236// -------------------------- resize -------------------------- //
10237
10238// debounced, layout on resize
10239proto.resize = function() {
10240  // don't trigger if size did not change
10241  // or if resize was unbound. See #285, outlayer#9
10242  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
10243    return;
10244  }
10245
10246  if ( this.options.shiftPercentResize ) {
10247    this.resizeShiftPercentLayout();
10248  } else {
10249    this.layout();
10250  }
10251};
10252
10253/**
10254 * check if layout is needed post layout
10255 * @returns Boolean
10256 */
10257proto.needsResizeLayout = function() {
10258  var size = getSize( this.element );
10259  var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';
10260  return size[ innerSize ] != this.size[ innerSize ];
10261};
10262
10263proto.resizeShiftPercentLayout = function() {
10264  var items = this._getItemsForLayout( this.items );
10265
10266  var isHorizontal = this._getOption('horizontal');
10267  var coord = isHorizontal ? 'y' : 'x';
10268  var measure = isHorizontal ? 'height' : 'width';
10269  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
10270  var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';
10271
10272  // proportional re-align items
10273  var previousSegment = this[ segmentName ];
10274  previousSegment = previousSegment && previousSegment + this.gutter;
10275
10276  if ( previousSegment ) {
10277    this._getMeasurements();
10278    var currentSegment = this[ segmentName ] + this.gutter;
10279    items.forEach( function( item ) {
10280      var seg = Math.round( item.rect[ coord ] / previousSegment );
10281      item.rect[ coord ] = seg * currentSegment;
10282    });
10283  } else {
10284    var currentSize = getSize( this.element )[ innerSize ] + this.gutter;
10285    var previousSize = this.packer[ measure ];
10286    items.forEach( function( item ) {
10287      item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;
10288    });
10289  }
10290
10291  this.shiftLayout();
10292};
10293
10294// -------------------------- drag -------------------------- //
10295
10296/**
10297 * handle an item drag start event
10298 * @param {Element} elem
10299 */
10300proto.itemDragStart = function( elem ) {
10301  if ( !this.isEnabled ) {
10302    return;
10303  }
10304  this.stamp( elem );
10305  // this.ignore( elem );
10306  var item = this.getItem( elem );
10307  if ( !item ) {
10308    return;
10309  }
10310
10311  item.enablePlacing();
10312  item.showDropPlaceholder();
10313  this.dragItemCount++;
10314  this.updateShiftTargets( item );
10315};
10316
10317proto.updateShiftTargets = function( dropItem ) {
10318  this.shiftPacker.reset();
10319
10320  // pack stamps
10321  this._getBoundingRect();
10322  var isOriginLeft = this._getOption('originLeft');
10323  var isOriginTop = this._getOption('originTop');
10324  this.stamps.forEach( function( stamp ) {
10325    // ignore dragged item
10326    var item = this.getItem( stamp );
10327    if ( item && item.isPlacing ) {
10328      return;
10329    }
10330    var offset = this._getElementOffset( stamp );
10331    var rect = new Rect({
10332      x: isOriginLeft ? offset.left : offset.right,
10333      y: isOriginTop ? offset.top : offset.bottom
10334    });
10335    this._setRectSize( stamp, rect );
10336    // save its space in the packer
10337    this.shiftPacker.placed( rect );
10338  }, this );
10339
10340  // reset shiftTargets
10341  var isHorizontal = this._getOption('horizontal');
10342  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
10343  var measure = isHorizontal ? 'height' : 'width';
10344
10345  this.shiftTargetKeys = [];
10346  this.shiftTargets = [];
10347  var boundsSize;
10348  var segment = this[ segmentName ];
10349  segment = segment && segment + this.gutter;
10350
10351  if ( segment ) {
10352    var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );
10353    var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );
10354    boundsSize = ( segs - segmentSpan ) * segment;
10355    // add targets on top
10356    for ( var i=0; i < segs; i++ ) {
10357      this._addShiftTarget( i * segment, 0, boundsSize );
10358    }
10359  } else {
10360    boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];
10361    this._addShiftTarget( 0, 0, boundsSize );
10362  }
10363
10364  // pack each item to measure where shiftTargets are
10365  var items = this._getItemsForLayout( this.items );
10366  var packMethod = this._getPackMethod();
10367  items.forEach( function( item ) {
10368    var rect = item.rect;
10369    this._setRectSize( item.element, rect );
10370    this.shiftPacker[ packMethod ]( rect );
10371
10372    // add top left corner
10373    this._addShiftTarget( rect.x, rect.y, boundsSize );
10374    // add bottom left / top right corner
10375    var cornerX = isHorizontal ? rect.x + rect.width : rect.x;
10376    var cornerY = isHorizontal ? rect.y : rect.y + rect.height;
10377    this._addShiftTarget( cornerX, cornerY, boundsSize );
10378
10379    if ( segment ) {
10380      // add targets for each column on bottom / row on right
10381      var segSpan = Math.round( rect[ measure ] / segment );
10382      for ( var i=1; i < segSpan; i++ ) {
10383        var segX = isHorizontal ? cornerX : rect.x + segment * i;
10384        var segY = isHorizontal ? rect.y + segment * i : cornerY;
10385        this._addShiftTarget( segX, segY, boundsSize );
10386      }
10387    }
10388  }, this );
10389
10390};
10391
10392proto._addShiftTarget = function( x, y, boundsSize ) {
10393  var checkCoord = this._getOption('horizontal') ? y : x;
10394  if ( checkCoord !== 0 && checkCoord > boundsSize ) {
10395    return;
10396  }
10397  // create string for a key, easier to keep track of what targets
10398  var key = x + ',' + y;
10399  var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;
10400  if ( hasKey ) {
10401    return;
10402  }
10403  this.shiftTargetKeys.push( key );
10404  this.shiftTargets.push({ x: x, y: y });
10405};
10406
10407// -------------------------- drop -------------------------- //
10408
10409proto.shift = function( item, x, y ) {
10410  var shiftPosition;
10411  var minDistance = Infinity;
10412  var position = { x: x, y: y };
10413  this.shiftTargets.forEach( function( target ) {
10414    var distance = getDistance( target, position );
10415    if ( distance < minDistance ) {
10416      shiftPosition = target;
10417      minDistance = distance;
10418    }
10419  });
10420  item.rect.x = shiftPosition.x;
10421  item.rect.y = shiftPosition.y;
10422};
10423
10424function getDistance( a, b ) {
10425  var dx = b.x - a.x;
10426  var dy = b.y - a.y;
10427  return Math.sqrt( dx * dx + dy * dy );
10428}
10429
10430// -------------------------- drag move -------------------------- //
10431
10432var DRAG_THROTTLE_TIME = 120;
10433
10434/**
10435 * handle an item drag move event
10436 * @param {Element} elem
10437 * @param {Number} x - horizontal change in position
10438 * @param {Number} y - vertical change in position
10439 */
10440proto.itemDragMove = function( elem, x, y ) {
10441  var item = this.isEnabled && this.getItem( elem );
10442  if ( !item ) {
10443    return;
10444  }
10445
10446  x -= this.size.paddingLeft;
10447  y -= this.size.paddingTop;
10448
10449  var _this = this;
10450  function onDrag() {
10451    _this.shift( item, x, y );
10452    item.positionDropPlaceholder();
10453    _this.layout();
10454  }
10455
10456  // throttle
10457  var now = new Date();
10458  if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {
10459    clearTimeout( this.dragTimeout );
10460    this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );
10461  } else {
10462    onDrag();
10463    this._itemDragTime = now;
10464  }
10465};
10466
10467// -------------------------- drag end -------------------------- //
10468
10469/**
10470 * handle an item drag end event
10471 * @param {Element} elem
10472 */
10473proto.itemDragEnd = function( elem ) {
10474  var item = this.isEnabled && this.getItem( elem );
10475  if ( !item ) {
10476    return;
10477  }
10478
10479  clearTimeout( this.dragTimeout );
10480  item.element.classList.add('is-positioning-post-drag');
10481
10482  var completeCount = 0;
10483  var _this = this;
10484  function onDragEndLayoutComplete() {
10485    completeCount++;
10486    if ( completeCount != 2 ) {
10487      return;
10488    }
10489    // reset drag item
10490    item.element.classList.remove('is-positioning-post-drag');
10491    item.hideDropPlaceholder();
10492    _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
10493  }
10494
10495  item.once( 'layout', onDragEndLayoutComplete );
10496  this.once( 'layoutComplete', onDragEndLayoutComplete );
10497  item.moveTo( item.rect.x, item.rect.y );
10498  this.layout();
10499  this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );
10500  this.sortItemsByPosition();
10501  item.disablePlacing();
10502  this.unstamp( item.element );
10503};
10504
10505/**
10506 * binds Draggabilly events
10507 * @param {Draggabilly} draggie
10508 */
10509proto.bindDraggabillyEvents = function( draggie ) {
10510  this._bindDraggabillyEvents( draggie, 'on' );
10511};
10512
10513proto.unbindDraggabillyEvents = function( draggie ) {
10514  this._bindDraggabillyEvents( draggie, 'off' );
10515};
10516
10517proto._bindDraggabillyEvents = function( draggie, method ) {
10518  var handlers = this.handleDraggabilly;
10519  draggie[ method ]( 'dragStart', handlers.dragStart );
10520  draggie[ method ]( 'dragMove', handlers.dragMove );
10521  draggie[ method ]( 'dragEnd', handlers.dragEnd );
10522};
10523
10524/**
10525 * binds jQuery UI Draggable events
10526 * @param {jQuery} $elems
10527 */
10528proto.bindUIDraggableEvents = function( $elems ) {
10529  this._bindUIDraggableEvents( $elems, 'on' );
10530};
10531
10532proto.unbindUIDraggableEvents = function( $elems ) {
10533  this._bindUIDraggableEvents( $elems, 'off' );
10534};
10535
10536proto._bindUIDraggableEvents = function( $elems, method ) {
10537  var handlers = this.handleUIDraggable;
10538  $elems
10539    [ method ]( 'dragstart', handlers.start )
10540    [ method ]( 'drag', handlers.drag )
10541    [ method ]( 'dragstop', handlers.stop );
10542};
10543
10544// ----- destroy ----- //
10545
10546var _destroy = proto.destroy;
10547proto.destroy = function() {
10548  _destroy.apply( this, arguments );
10549  // disable flag; prevent drag events from triggering. #72
10550  this.isEnabled = false;
10551};
10552
10553// -----  ----- //
10554
10555Packery.Rect = Rect;
10556Packery.Packer = Packer;
10557
10558return Packery;
10559
10560}));
10561
10562/*!
10563 * Packery layout mode v2.0.1
10564 * sub-classes Packery
10565 */
10566
10567/*jshint browser: true, strict: true, undef: true, unused: true */
10568
10569( function( window, factory ) {
10570
10571  // universal module definition
10572  if ( typeof define == 'function' && define.amd ) {
10573    // AMD
10574    define( [
10575        'isotope-layout/js/layout-mode',
10576        'packery/js/packery'
10577      ],
10578      factory );
10579  } else if ( typeof module == 'object' && module.exports ) {
10580    // CommonJS
10581    module.exports = factory(
10582      require('isotope-layout/js/layout-mode'),
10583      require('packery')
10584    );
10585  } else {
10586    // browser global
10587    factory(
10588      window.Isotope.LayoutMode,
10589      window.Packery
10590    );
10591  }
10592
10593}( window, function factor( LayoutMode, Packery ) {
10594
10595
10596  // create an Outlayer layout class
10597  var PackeryMode = LayoutMode.create('packery');
10598  var proto = PackeryMode.prototype;
10599
10600  var keepModeMethods = {
10601    _getElementOffset: true,
10602    _getMeasurement: true
10603  };
10604
10605  // inherit Packery prototype
10606  for ( var method in Packery.prototype ) {
10607    // do not inherit mode methods
10608    if ( !keepModeMethods[ method ] ) {
10609      proto[ method ] = Packery.prototype[ method ];
10610    }
10611  }
10612
10613  // set packer in _resetLayout
10614  var _resetLayout = proto._resetLayout;
10615  proto._resetLayout = function() {
10616    this.packer = this.packer || new Packery.Packer();
10617    this.shiftPacker = this.shiftPacker || new Packery.Packer();
10618    _resetLayout.apply( this, arguments );
10619  };
10620
10621  var _getItemLayoutPosition = proto._getItemLayoutPosition;
10622  proto._getItemLayoutPosition = function( item ) {
10623    // set packery rect
10624    item.rect = item.rect || new Packery.Rect();
10625    return _getItemLayoutPosition.call( this, item );
10626  };
10627
10628  // needsResizeLayout for vertical or horizontal
10629  var _needsResizeLayout = proto.needsResizeLayout;
10630  proto.needsResizeLayout = function() {
10631    if ( this._getOption('horizontal') ) {
10632      return this.needsVerticalResizeLayout();
10633    } else {
10634      return _needsResizeLayout.call( this );
10635    }
10636  };
10637
10638  // point to mode options for horizontal
10639  var _getOption = proto._getOption;
10640  proto._getOption = function( option ) {
10641    if ( option == 'horizontal' ) {
10642      return this.options.isHorizontal !== undefined ?
10643        this.options.isHorizontal : this.options.horizontal;
10644    }
10645    return _getOption.apply( this.isotope, arguments );
10646  };
10647
10648  return PackeryMode;
10649
10650}));
10651
10652/*!
10653 * cellsByRows layout mode for Isotope
10654 * v1.1.3
10655 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
10656 */
10657
10658/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
10659
10660( function( window, factory ) {
10661  // universal module definition
10662  /* jshint strict: false */ /*globals define, module, require */
10663  if ( typeof define === 'function' && define.amd ) {
10664    // AMD
10665    define( [
10666        'isotope/js/layout-mode'
10667      ],
10668      factory );
10669  } else if ( typeof exports === 'object' ) {
10670    // CommonJS
10671    module.exports = factory(
10672      require('isotope-layout/js/layout-mode')
10673    );
10674  } else {
10675    // browser global
10676    factory(
10677      window.Isotope.LayoutMode
10678    );
10679  }
10680
10681}( window, function factory( LayoutMode ) {
10682  'use strict';
10683
10684  var CellsByRow = LayoutMode.create( 'cellsByRow' );
10685  var proto = CellsByRow.prototype;
10686
10687  proto._resetLayout = function() {
10688    // reset properties
10689    this.itemIndex = 0;
10690    // measurements
10691    this.getColumnWidth();
10692    this.getRowHeight();
10693    // set cols
10694    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
10695    this.cols = Math.max( this.cols, 1 );
10696  };
10697
10698  proto._getItemLayoutPosition = function( item ) {
10699    item.getSize();
10700    var col = this.itemIndex % this.cols;
10701    var row = Math.floor( this.itemIndex / this.cols );
10702    // center item within cell
10703    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
10704    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
10705    this.itemIndex++;
10706    return { x: x, y: y };
10707  };
10708
10709  proto._getContainerSize = function() {
10710    return {
10711      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
10712    };
10713  };
10714
10715  return CellsByRow;
10716
10717}));
10718/*global jQuery: true */
10719
10720/*!
10721   --------------------------------
10722   Infinite Scroll
10723   --------------------------------
10724   + https://github.com/paulirish/infinite-scroll
10725   + version 2.1.0
10726   + Copyright 2011/12 Paul Irish & Luke Shumard
10727   + Licensed under the MIT license
10728
10729   + Documentation: http://infinite-scroll.com/
10730*/
10731
10732// Uses AMD or browser globals to create a jQuery plugin.
10733(function (factory) {
10734    if (typeof define === 'function' && define.amd) {
10735        // AMD. Register as an anonymous module.
10736        define(['jquery'], factory);
10737    } else {
10738        // Browser globals
10739        factory(jQuery);
10740    }
10741}(function ($, undefined) {
10742    'use strict';
10743
10744    $.infinitescroll = function infscr(options, callback, element) {
10745        this.element = $(element);
10746
10747        // Flag the object in the event of a failed creation
10748        if (!this._create(options, callback)) {
10749            this.failed = true;
10750        }
10751    };
10752
10753    $.infinitescroll.defaults = {
10754        loading: {
10755            finished: undefined,
10756            finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
10757            img: 'data:image/gif;base64,R0lGODlh3AATAPQeAPDy+MnQ6LW/4N3h8MzT6rjC4sTM5r/I5NHX7N7j8c7U6tvg8OLl8uXo9Ojr9b3G5MfP6Ovu9tPZ7PT1+vX2+tbb7vf4+8/W69jd7rC73vn5/O/x+K243ai02////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQECgD/ACwAAAAA3AATAAAF/6AnjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEj0BAScpHLJbDqf0Kh0Sq1ar9isdioItAKGw+MAKYMFhbF63CW438f0mg1R2O8EuXj/aOPtaHx7fn96goR4hmuId4qDdX95c4+RBIGCB4yAjpmQhZN0YGYGXitdZBIVGAsLoq4BBKQDswm1CQRkcG6ytrYKubq8vbfAcMK9v7q7EMO1ycrHvsW6zcTKsczNz8HZw9vG3cjTsMIYqQkCLBwHCgsMDQ4RDAYIqfYSFxDxEfz88/X38Onr16+Bp4ADCco7eC8hQYMAEe57yNCew4IVBU7EGNDiRn8Z831cGLHhSIgdFf9chIeBg7oA7gjaWUWTVQAGE3LqBDCTlc9WOHfm7PkTqNCh54rePDqB6M+lR536hCpUqs2gVZM+xbrTqtGoWqdy1emValeXKzggYBBB5y1acFNZmEvXAoN2cGfJrTv3bl69Ffj2xZt3L1+/fw3XRVw4sGDGcR0fJhxZsF3KtBTThZxZ8mLMgC3fRatCbYMNFCzwLEqLgE4NsDWs/tvqdezZf13Hvk2A9Szdu2X3pg18N+68xXn7rh1c+PLksI/Dhe6cuO3ow3NfV92bdArTqC2Ebd3A8vjf5QWfH6Bg7Nz17c2fj69+fnq+8N2Lty+fuP78/eV2X13neIcCeBRwxorbZrA1ANoCDGrgoG8RTshahQ9iSKEEzUmYIYfNWViUhheCGJyIP5E4oom7WWjgCeBFAJNv1DVV01MAdJhhjdkplWNzO/5oXI846njjVEIqR2OS2B1pE5PVscajkxhMycqLJghQSwT40PgfAl4GqNSXYdZXJn5gSkmmmmJu1aZYb14V51do+pTOCmA40AqVCIhG5IJ9PvYnhIFOxmdqhpaI6GeHCtpooisuutmg+Eg62KOMKuqoTaXgicQWoIYq6qiklmoqFV0UoeqqrLbq6quwxirrrLTWauutJ4QAACH5BAUKABwALAcABADOAAsAAAX/IPd0D2dyRCoUp/k8gpHOKtseR9yiSmGbuBykler9XLAhkbDavXTL5k2oqFqNOxzUZPU5YYZd1XsD72rZpBjbeh52mSNnMSC8lwblKZGwi+0QfIJ8CncnCoCDgoVnBHmKfByGJimPkIwtiAeBkH6ZHJaKmCeVnKKTHIihg5KNq4uoqmEtcRUtEREMBggtEr4QDrjCuRC8h7/BwxENeicSF8DKy82pyNLMOxzWygzFmdvD2L3P0dze4+Xh1Arkyepi7dfFvvTtLQkZBC0T/FX3CRgCMOBHsJ+EHYQY7OinAGECgQsB+Lu3AOK+CewcWjwxQeJBihtNGHSoQOE+iQ3//4XkwBBhRZMcUS6YSXOAwIL8PGqEaSJCiYt9SNoCmnJPAgUVLChdaoFBURN8MAzl2PQphwQLfDFd6lTowglHve6rKpbjhK7/pG5VinZP1qkiz1rl4+tr2LRwWU64cFEihwEtZgbgR1UiHaMVvxpOSwBA37kzGz9e8G+B5MIEKLutOGEsAH2ATQwYfTmuX8aETWdGPZmiZcccNSzeTCA1Sw0bdiitC7LBWgu8jQr8HRzqgpK6gX88QbrB14z/kF+ELpwB8eVQj/JkqdylAudji/+ts3039vEEfK8Vz2dlvxZKG0CmbkKDBvllRd6fCzDvBLKBDSCeffhRJEFebFk1k/Mv9jVIoIJZSeBggwUaNeB+Qk34IE0cXlihcfRxkOAJFFhwGmKlmWDiakZhUJtnLBpnWWcnKaAZcxI0piFGGLBm1mc90kajSCveeBVWKeYEoU2wqeaQi0PetoE+rr14EpVC7oAbAUHqhYExbn2XHHsVqbcVew9tx8+XJKk5AZsqqdlddGpqAKdbAYBn1pcczmSTdWvdmZ17c1b3FZ99vnTdCRFM8OEcAhLwm1NdXnWcBBSMRWmfkWZqVlsmLIiAp/o1gGV2vpS4lalGYsUOqXrddcKCmK61aZ8SjEpUpVFVoCpTj4r661Km7kBHjrDyc1RAIQAAIfkEBQoAGwAsBwAEAM4ACwAABf/gtmUCd4goQQgFKj6PYKi0yrrbc8i4ohQt12EHcal+MNSQiCP8gigdz7iCioaCIvUmZLp8QBzW0EN2vSlCuDtFKaq4RyHzQLEKZNdiQDhRDVooCwkbfm59EAmKi4SGIm+AjIsKjhsqB4mSjT2IOIOUnICeCaB/mZKFNTSRmqVpmJqklSqskq6PfYYCDwYHDC4REQwGCBLGxxIQDsHMwhAIX8bKzcENgSLGF9PU1j3Sy9zX2NrgzQziChLk1BHWxcjf7N046tvN82715czn9Pryz6Ilc4ACj4EBOCZM8KEnAYYADBRKnACAYUMFv1wotIhCEcaJCisqwJFgAUSQGyX/kCSVUUTIdKMwJlyo0oXHlhskwrTJciZHEXsgaqS4s6PJiCAr1uzYU8kBBSgnWFqpoMJMUjGtDmUwkmfVmVypakWhEKvXsS4nhLW5wNjVroJIoc05wSzTr0PtiigpYe4EC2vj4iWrFu5euWIMRBhacaVJhYQBEFjA9jHjyQ0xEABwGceGAZYjY0YBOrRLCxUp29QM+bRkx5s7ZyYgVbTqwwti2ybJ+vLtDYpycyZbYOlptxdx0kV+V7lC5iJAyyRrwYKxAdiz82ng0/jnAdMJFz0cPi104Ec1Vj9/M6F173vKL/feXv156dw11tlqeMMnv4V5Ap53GmjQQH97nFfg+IFiucfgRX5Z8KAgbUlQ4IULIlghhhdOSB6AgX0IVn8eReghen3NRIBsRgnH4l4LuEidZBjwRpt6NM5WGwoW0KSjCwX6yJSMab2GwwAPDXfaBCtWpluRTQqC5JM5oUZAjUNS+VeOLWpJEQ7VYQANW0INJSZVDFSnZphjSikfmzE5N4EEbQI1QJmnWXCmHulRp2edwDXF43txukenJwvI9xyg9Q26Z3MzGUcBYFEChZh6DVTq34AU8Iflh51Sd+CnKFYQ6mmZkhqfBKfSxZWqA9DZanWjxmhrWwi0qtCrt/43K6WqVjjpmhIqgEGvculaGKklKstAACEAACH5BAUKABwALAcABADOAAsAAAX/ICdyQmaMYyAUqPgIBiHPxNpy79kqRXH8wAPsRmDdXpAWgWdEIYm2llCHqjVHU+jjJkwqBTecwItShMXkEfNWSh8e1NGAcLgpDGlRgk7EJ/6Ae3VKfoF/fDuFhohVeDeCfXkcCQqDVQcQhn+VNDOYmpSWaoqBlUSfmowjEA+iEAEGDRGztAwGCDcXEA60tXEiCrq8vREMEBLIyRLCxMWSH
10757MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/Cpk3ABwSLQkYAQwT/P309vcI7OvXr94jBQMJ/nskkGA/BQBRLNDncAIAiDcG6LsxAWOLiQzmeURBKWSLCQbv/1F0eDGinJUKR47YY1IEgQASKk7Yc7ACRwZm7mHweRJoz59BJUogisKCUaFMR0x4SlJBVBFTk8pZivTR0K73rN5wqlXEAq5Fy3IYgHbEzQ0nLy4QSoCjXLoom96VOJEeCosK5n4kkFfqXjl94wa+l1gvAcGICbewAOAxY8l/Ky/QhAGz4cUkGxu2HNozhwMGBnCUqUdBg9UuW9eUynqSwLHIBujePef1ZGQZXcM+OFuEBeBhi3OYgLyqcuaxbT9vLkf4SeqyWxSQpKGB2gQpm1KdWbu72rPRzR9Ne2Nu9Kzr/1Jqj0yD/fvqP4aXOt5sW/5qsXXVcv1Nsp8IBUAmgswGF3llGgeU1YVXXKTN1FlhWFXW3gIE+DVChApysACHHo7Q4A35lLichh+ROBmLKAzgYmYEYDAhCgxKGOOMn4WR4kkDaoBBOxJtdNKQxFmg5JIWIBnQc07GaORfUY4AEkdV6jHlCEISSZ5yTXpp1pbGZbkWmcuZmQCaE6iJ0FhjMaDjTMsgZaNEHFRAQVp3bqXnZED1qYcECOz5V6BhSWCoVJQIKuKQi2KFKEkEFAqoAo7uYSmO3jk61wUUMKmknJ4SGimBmAa0qVQBhAAAIfkEBQoAGwAsBwAEAM4ACwAABf/gJm5FmRlEqhJC+bywgK5pO4rHI0D3pii22+Mg6/0Ej96weCMAk7cDkXf7lZTTnrMl7eaYoy10JN0ZFdco0XAuvKI6qkgVFJXYNwjkIBcNBgR8TQoGfRsJCRuCYYQQiI+ICosiCoGOkIiKfSl8mJkHZ4U9kZMbKaI3pKGXmJKrngmug4WwkhA0lrCBWgYFCCMQFwoQDRHGxwwGCBLMzRLEx8iGzMMO0cYNeCMKzBDW19lnF9DXDIY/48Xg093f0Q3s1dcR8OLe8+Y91OTv5wrj7o7B+7VNQqABIoRVCMBggsOHE36kSoCBIcSH3EbFangxogJYFi8CkJhqQciLJEf/LDDJEeJIBT0GsOwYUYJGBS0fjpQAMidGmyVP6sx4Y6VQhzs9VUwkwqaCCh0tmKoFtSMDmBOf9phg4SrVrROuasRQAaxXpVUhdsU6IsECZlvX3kwLUWzRt0BHOLTbNlbZG3vZinArge5Dvn7wbqtQkSYAAgtKmnSsYKVKo2AfW048uaPmG386i4Q8EQMBAIAnfB7xBxBqvapJ9zX9WgRS2YMpnvYMGdPK3aMjt/3dUcNI4blpj7iwkMFWDXDvSmgAlijrt9RTR78+PS6z1uAJZIe93Q8g5zcsWCi/4Y+C8bah5zUv3vv89uft30QP23punGCx5954oBBwnwYaNCDY/wYrsYeggnM9B2Fpf8GG2CEUVWhbWAtGouEGDy7Y4IEJVrbSiXghqGKIo7z1IVcXIkKWWR361QOLWWnIhwERpLaaCCee5iMBGJQmJGyPFTnbkfHVZGRtIGrg5HALEJAZbu39BuUEUmq1JJQIPtZilY5hGeSWsSk52G9XqsmgljdIcABytq13HyIM6RcUA+r1qZ4EBF3WHWB29tBgAzRhEGhig8KmqKFv8SeCeo+mgsF7YFXa1qWSbkDpom/mqR1PmHCqJ3fwNRVXjC7S6CZhFVCQ2lWvZiirhQq42SACt25IK2hv8TprriUV1usGgeka7LFcNmCldMLi6qZMgFLgpw16Cipb7bC1knXsBiEAACH5BAUKABsALAcABADOAAsAAAX/4FZsJPkUmUGsLCEUTywXglFuSg7fW1xAvNWLF6sFFcPb42C8EZCj24EJdCp2yoegWsolS0Uu6fmamg8n8YYcLU2bXSiRaXMGvqV6/KAeJAh8VgZqCX+BexCFioWAYgqNi4qAR4ORhRuHY408jAeUhAmYYiuVlpiflqGZa5CWkzc5fKmbbhIpsAoQDRG8vQwQCBLCwxK6vb5qwhfGxxENahvCEA7NzskSy7vNzzzK09W/PNHF1NvX2dXcN8K55cfh69Luveol3vO8zwi4Yhj+AQwmCBw4IYclDAAJDlQggVOChAoLKkgFkSCAHDwWLKhIEOONARsDKryogFPIiAUb/95gJNIiw4wnI778GFPhzBKFOAq8qLJEhQpiNArjMcHCmlTCUDIouTKBhApELSxFWiGiVKY4E2CAekPgUphDu0742nRrVLJZnyrFSqKQ2ohoSYAMW6IoDpNJ4bLdILTnAj8KUF7UeENjAKuDyxIgOuGiOI0EBBMgLNew5AUrDTMGsFixwBIaNCQuAXJB57qNJ2OWm2Aj4skwCQCIyNkhhtMkdsIuodE0AN4LJDRgfLPtn5YDLdBlraAByuUbBgxQwICxMOnYpVOPej074OFdlfc0TqC62OIbcppHjV4o+LrieWhfT8JC/I/T6W8oCl29vQ0XjLdBaA3s1RcPBO7lFvpX8BVoG4O5jTXRQRDuJ6FDTzEWF1/BCZhgbyAKE9qICYLloQYOFtahVRsWYlZ4KQJHlwHS/IYaZ6sZd9tmu5HQm2xi1UaTbzxYwJk/wBF5g5EEYOBZeEfGZmNdFyFZmZIR4jikbLThlh5kUUVJGmRT7sekkziRWUIACABk3T4qCsedgO4xhgGcY7q5pHJ4klBBTQRJ0CeHcoYHHUh6wgfdn9uJdSdMiebGJ0zUPTcoS286FCkrZxnYoYYKWLkBowhQoBeaOlZAgVhLidrXqg2G
10757iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/oGFw2WZuT5oZROsSQnGaKjRvilI893MItlNOJ5v5gDcFrHhKIWcEYu/xFEqNv6B1N62aclysF7fsZYe5aOx2yL5aAUGSaT1oTYMBwQ5VGCAJgYIJCnx1gIOBhXdwiIl7d0p2iYGQUAQBjoOFSQR/lIQHnZ+Ue6OagqYzSqSJi5eTpTxGcjcSChANEbu8DBAIEsHBChe5vL13G7fFuscRDcnKuM3H0La3EA7Oz8kKEsXazr7Cw9/Gztar5uHHvte47MjktznZ2w0G1+D3BgirAqJmJMAQgMGEgwgn5Ei0gKDBhBMALGRYEOJBb5QcWlQo4cbAihZz3GgIMqFEBSM1/4ZEOWPAgpIIJXYU+PIhRG8ja1qU6VHlzZknJNQ6UanCjQkWCIGSUGEjAwVLjc44+DTqUQtPPS5gejUrTa5TJ3g9sWCr1BNUWZI161StiQUDmLYdGfesibQ3XMq1OPYthrwuA2yU2LBs2cBHIypYQPPlYAKFD5cVvNPtW8eVGbdcQADATsiNO4cFAPkvHpedPzc8kUcPgNGgZ5RNDZG05reoE9s2vSEP79MEGiQGy1qP8LA4ZcdtsJE48ONoLTBtTV0B9LsTnPceoIDBDQvS7W7vfjVY3q3eZ4A339J4eaAmKqU/sV58HvJh2RcnIBsDUw0ABqhBA5aV5V9XUFGiHfVeAiWwoFgJJrIXRH1tEMiDFV4oHoAEGlaWhgIGSGBO2nFomYY3mKjVglidaNYJGJDkWW2xxTfbjCbVaOGNqoX2GloR8ZeTaECS9pthRGJH2g0b3Agbk6hNANtteHD2GJUucfajCQBy5OOTQ25ZgUPvaVVQmbKh9510/qQpwXx3SQdfk8tZJOd5b6JJFplT3ZnmmX3qd5l1eg5q00HrtUkUn0AKaiGjClSAgKLYZcgWXwocGRcCFGCKwSB6ceqphwmYRUFYT/1WKlOdUpipmxW0mlCqHjYkAaeoZlqrqZ4qd+upQKaapn/AmgAegZ8KUtYtFAQQAgAh+QQFCgAbACwHAAQAzgALAAAF/+C2PUcmiCiZGUTrEkKBis8jQEquKwU5HyXIbEPgyX7BYa5wTNmEMwWsSXsqFbEh8DYs9mrgGjdK6GkPY5GOeU6ryz7UFopSQEzygOGhJBjoIgMDBAcBM0V/CYqLCQqFOwobiYyKjn2TlI6GKC2YjJZknouaZAcQlJUHl6eooJwKooobqoewrJSEmyKdt59NhRKFMxLEEA4RyMkMEAjDEhfGycqAG8TQx9IRDRDE3d3R2ctD1RLg0ttKEnbY5wZD3+zJ6M7X2RHi9Oby7u/r9g38UFjTh2xZJBEBMDAboogAgwkQI07IMUORwocSJwCgWDFBAIwZOaJIsOBjRogKJP8wTODw5ESVHVtm3AhzpEeQElOuNDlTZ0ycEUWKWFASqEahGwYUPbnxoAgEdlYSqDBkgoUNClAlIHbSAoOsqCRQnQHxq1axVb06FWFxLIqyaze0Tft1JVqyE+pWXMD1pF6bYl3+HTqAWNW8cRUFzmih0ZAAB2oGKukSAAGGRHWJgLiR6AylBLpuHKKUMlMCngMpDSAa9QIUggZVVvDaJobLeC3XZpvgNgCmtPcuwP3WgmXSq4do0DC6o2/guzcseECtUoO0hmcsGKDgOt7ssBd07wqesAIGZC1YIBa7PQHvb1+SFo+++HrJSQfB33xfav3i5eX3Hnb4CTJgegEq8tH/YQEOcIJzbm2G2EoYRLgBXFpVmFYDcREV4HIcnmUhiGBRouEMJGJGzHIspqgdXxK0yCKHRNXoIX4uorCdTyjkyNtdPWrA4Up82EbAbzMRxxZRR54WXVLDIRmRcag5d2R6ugl3ZXzNhTecchpMhIGVAKAYpgJjjsSklBEd99maZoo535ZvdamjBEpusJyctg3h4X8XqodBMx0tiNeg/oGJaKGABpogS40KSqiaEgBqlQWLUtqoVQnytekEjzo0hHqhRorppOZt2p923M2AAV+oBtpAnnPNoB6HaU6mAAIU+IXmi3j2mtFXuUoHKwXpzVrsjcgGOauKEjQrwq157hitGq2NoWmjh7z6Wmxb0m5w66+2VRAuXN/yFUAIACH5BAUKABsALAcABADOAAsAAAX/4CZuRiaM45MZqBgIRbs9AqTcuFLE7VHLOh7KB5ERdjJaEaU4ClO/lgKWjKKcMiJQ8KgumcieVdQMD8cbBeuAkkC6LYLhOxoQ2PF5Ys9PKPBMen17f0CCg4VSh32JV4t8jSNqEIOEgJKPlkYBlJWRInKdiJdkmQlvKAsLBxdABA4RsbIMBggtEhcQsLKxDBC2TAS6vLENdJLDxMZAubu8vjIbzcQRtMzJz79S08oQEt/guNiyy7fcvMbh4OezdAvGrakLAQwyABsELQkY9BP+//ckyPDD4J9BfAMh1GsBoImMeQUN+lMgUJ9CiRMa5msxoB9Gh/o8GmxYMZXIgxtR/yQ46S/gQAURR0pDwYDfywoyLPip5AdnCwsMFPBU4BPFhKBDi444quCmDKZOfwZ9KEGpCKgcN1jdALSpPqIYsabS+nSqvqplvYqQYAeDPgwKwjaMtiDl0oaqUAyo+3TuWwUAMPpVCfee0cEjVBGQq2ABx7oTWmQk4FglZMGN9fGVDMCuiH2AOVOu/PmyxM630gwM0CCn6q8LjVJ8GXvpa5Uwn95OTC/nNxkda1/dLSK475IjCD6dHbK1ZOa4hXP9DXs5chJ00UpVm5xo2qRpoxptwF2E4/IbJpB/SDz9+q9b1aNfQH08+p4a8uvX8B53fLP+ycAfemjsRUBgp1H20K+BghHgVgt1GXZXZpZ5lt4ECjxYR4ScUWiShEtZqBiIInRGWnERNnjiBglw+JyGnxUmGowsyiiZg189lNtPGACjV2+S9UjbU0JWF6SPvEk3QZEqsZYTk3UAaRSUnznJI5LmESCdBVSyaOWUWLK4I5gDUYVeV1T9l+FZClCAUVA09uSmRHBCKAECFEhW51ht6rnmWBXkaR+NjuHpJ40D3DmnQXt2F+ihZxlqVKOfQRACACH5BAUKABwALAcABADOAAsAAAX/ICdyUCkUo/g8mUG8MCGkKgspeC6j6XEIEBpBUeCNfECaglBcOVfJFK7YQwZHQ6JRZBUqTrSuVEuD3nI45pYjFuWKvjjSkCoRaBUMWxkwBGgJCXspQ36Bh4EEB0oKhoiBgyNLjo8Ki4QElIiWfJqHnISNEI+Ql5J9o6SgkqKkgqYihamPkW6oNBgSfiMMDQkGCBLCwxIQDhHIyQwQCGMKxsnKVyPCF9DREQ3MxMPX0cu4wt7J2uHWx9jlKd3o39MiuefYEcvNkuLt5O8c1ePI2tyELXGQwoGDAQf+iEC2xByDCRAjTlAgIUWCBRgCPJQ4AQBFXAs0coT40WLIjRxL/47AcHLkxIomRXL0CHPERZkpa4q4iVKiyp0tR/7kwHMkTUBBJR5dOCEBAVcKKtCAyOHpowXCpk7goABqBZdcvWploACpBKkpIJI1q5OD2rIWE0R1uTZu1LFwbWL9OlKuWb4c6+o9i3dEgw0RCGDUG9KlRw56gDY2qmCByZBaASi+TACA0TucAaTteCcy0ZuOK3N2vJlx58+LRQyY3Xm0ZsgjZg+oPQLi7dUcNXi0LOJw1pgNtB7XG6CBy+U75SYfPTSQAgZTNUDnQHt67wnbZyvwLgKiMN3oCZB3C76tdewpLFgIP2C88rbi4Y+QT3+8S5USMICZXWj1pkEDeUU3lOYGB3alSoEiMIjgX4WlgNF2EibIwQIXauWXSRg2SAOHIU5IIIMoZkhhWiJaiFVbKo6AQEgQXrTAazO1JhkBrBG3Y2Y6EsUhaGn95hprSN0oWpFE7rhkeaQBchGOEWnwEmc0uKWZj0LeuNV3W4Y2lZHFlQCSRjTIl8uZ+kG5HU/3sRlnTG2ytyadytnD3HrmuRcSn+0h1dycexIK1KCjYaCnjCCVqOFFJTZ5GkUUjESWaUIKU2lgCmAKKQIUjHapXRKE+t2og1VgankNYnohqKJ2CmKplso6GKz7WYCgqxeuyoF8u9IQAgA7',
10758            msg: null,
10759            msgText: '<em>Loading the next set of posts...</em>',
10760            selector: null,
10761            speed: 'fast',
10762            start: undefined
10763        },
10764        state: {
10765            isDuringAjax: false,
10766            isInvalidPage: false,
10767            isDestroyed: false,
10768            isDone: false, // For when it goes all the way through the archive.
10769            isPaused: false,
10770            isBeyondMaxPage: false,
10771            currPage: 1
10772        },
10773        debug: false,
10774        behavior: undefined,
10775        binder: $(window), // used to cache the selector
10776        nextSelector: 'div.navigation a:first',
10777        navSelector: 'div.navigation',
10778        contentSelector: null, // rename to pageFragment
10779        extraScrollPx: 150,
10780        itemSelector: 'div.post',
10781        animate: false,
10782        pathParse: undefined,
10783        dataType: 'html',
10784        appendCallback: true,
10785        bufferPx: 40,
10786        errorCallback: function () { },
10787        infid: 0, //Instance ID
10788        pixelsFromNavToBottom: undefined,
10789        path: undefined, // Either parts of a URL as an array (e.g. ["/page/", "/"] or a function that takes in the page number and returns a URL
10790        prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
10791        maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
10792    };
10793
10794    $.infinitescroll.prototype = {
10795
10796        /*
10797            ----------------------------
10798            Private methods
10799            ----------------------------
10800            */
10801
10802        // Bind or unbind from scroll
10803        _binding: function infscr_binding(binding) {
10804
10805            var instance = this,
10806            opts = instance.options;
10807
10808            opts.v = '2.0b2.120520';
10809
10810            // if behavior is defined and this function is extended, call that instead of default
10811            if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) {
10812                this['_binding_'+opts.behavior].call(this);
10813                return;
10814            }
10815
10816            if (binding !== 'bind' && binding !== 'unbind') {
10817                this._debug('Binding value  ' + binding + ' not valid');
10818                return false;
10819            }
10820
10821            if (binding === 'unbind') {
10822                (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
10823            } else {
10824                (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
10825                    instance.scroll();
10826                });
10827            }
10828
10829            this._debug('Binding', binding);
10830        },
10831
10832        // Fundamental aspects of the plugin are initialized
10833        _create: function infscr_create(options, callback) {
10834
10835            // Add custom options to defaults
10836            var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
10837            this.options = opts;
10838            var $window = $(window);
10839            var instance = this;
10840
10841            // Validate selectors
10842            if (!instance._validate(options)) {
10843                return false;
10844            }
10845
10846            // Validate page fragment path
10847            var path = $(opts.nextSelector).attr('href');
10848            if (!path) {
10849                this._debug('Navigation selector not found');
10850                return false;
10851            }
10852
10853            // Set the path to be a relative URL from root.
10854            opts.path = opts.path || this._determinepath(path);
10855
10856            // contentSelector is 'page fragment' option for .load() / .ajax() calls
10857            opts.contentSelector = opts.contentSelector || this.element;
10858
10859            // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
10860            opts.loading.selector = opts.loading.selector || opts.contentSelector;
10861
10862            // Define loading.msg
10863            opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
10864
10865            // Preload loading.img
10866            (new Image()).src = opts.loading.img;
10867
10868            // distance from nav links to bottom
10869            // computed as: height of the document + top offset of container - top offset of nav link
10870            if(opts.pixelsFromNavToBottom === undefined) {
10871                opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
10872                this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
10873            }
10874
10875            var self = this;
10876
10877            // determine loading.start actions
10878            opts.loading.start = opts.loading.start || function() {
10879                $(opts.navSelector).hide();
10880                opts.loading.msg
10881                .appendTo(opts.loading.selector)
10882                .show(opts.loading.speed, $.proxy(function() {
10883                    this.beginAjax(opts);
10884                }, self));
10885            };
10886
10887            // determine loading.finished actions
10888            opts.loading.finished = opts.loading.finished || function() {
10889                if (!opts.state.isBeyondMaxPage)
10890                    opts.loading.msg.fadeOut(opts.loading.speed);
10891            };
10892
10893            // callback loading
10894            opts.callback = function(instance, data, url) {
10895                if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) {
10896                    instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url);
10897                }
10898
10899                if (callback) {
10900                    callback.call($(opts.contentSelector)[0], data, opts, url);
10901                }
10902
10903                if (opts.prefill) {
10904                    $window.bind('resize.infinite-scroll', instance._prefill);
10905                }
10906            };
10907
10908            if (options.debug) {
10909                // Tell IE9 to use its built-in console
10910                if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
10911                    ['log','info','warn','error','assert','dir','clear','profile','profileEnd']
10912                        .forEach(function (method) {
10913                            console[method] = this.call(console[method], console);
10914                        }, Function.prototype.bind);
10915                }
10916            }
10917
10918            this._setup();
10919
10920            // Setups the prefill method for use
10921            if (opts.prefill) {
10922                this._prefill();
10923            }
10924
10925            // Return true to indicate successful creation
10926            return true;
10927        },
10928
10929        _prefill: function infscr_prefill() {
10930            var instance = this;
10931            var $window = $(window);
10932
10933            function needsPrefill() {
10934                return ( $(instance.options.contentSelector).height() <= $window.height() );
10935            }
10936
10937            this._prefill = function() {
10938                if (needsPrefill()) {
10939                    instance.scroll();
10940                }
10941
10942                $window.bind('resize.infinite-scroll', function() {
10943                    if (needsPrefill()) {
10944                        $window.unbind('resize.infinite-scroll');
10945                        instance.scroll();
10946                    }
10947                });
10948            };
10949
10950            // Call self after setting up the new function
10951            this._prefill();
10952        },
10953
10954        // Console log wrapper
10955        _debug: function infscr_debug() {
10956            if (true !== this.options.debug) {
10957                return;
10958            }
10959
10960            if (typeof console !== 'undefined' && typeof console.log === 'function') {
10961                // Modern browsers
10962                // Single argument, which is a string
10963                if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
10964                    console.log( (Array.prototype.slice.call(arguments)).toString() );
10965                } else {
10966                    console.log( Array.prototype.slice.call(arguments) );
10967                }
10968            } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
10969                // IE8
10970                Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
10971            }
10972        },
10973
10974        // find the number to increment in the path.
10975        _determinepath: function infscr_determinepath(path) {
10976
10977            var opts = this.options;
10978
10979            // if behavior is defined and this function is extended, call that instead of default
10980            if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) {
10981                return this['_determinepath_'+opts.behavior].call(this,path);
10982            }
10983
10984            if (!!opts.pathParse) {
10985
10986                this._debug('pathParse manual');
10987                return opts.pathParse(path, this.options.state.currPage+1);
10988
10989            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
10990                path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
10991
10992                // if there is any 2 in the url at all.
10993            } else if (path.match(/^(.*?)2(.*?$)/)) {
10994
10995                // page= is used in django:
10996                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
10997                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
10998                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
10999                    return path;
11000                }
11001
11002                path = path.match(/^(.*?)2(.*?$)/).slice(1);
11003
11004            } else {
11005
11006                // page= is used in drupal too but second page is page=1 not page=2:
11007                // thx Jerod Fritz, vladikoff
11008                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
11009                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
11010                    return path;
11011                } else {
11012                    this._debug("Sorry, we couldn't parse your Next (Previous Posts) URL. Verify your the css selector points to the correct A tag. If you still get this error: yell, scream, and kindly ask for help at infinite-scroll.com.");
11013                    // Get rid of isInvalidPage to allow permalink to state
11014                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
11015                }
11016            }
11017            this._debug('determinePath', path);
11018            return path;
11019
11020        },
11021
11022        // Custom error
11023        _error: function infscr_error(xhr) {
11024
11025            var opts = this.options;
11026
11027            // if behavior is defined and this function is extended, call that instead of default
11028            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
11029                this['_error_'+opts.behavior].call(this,xhr);
11030                return;
11031            }
11032
11033            if (xhr !== 'destroy' && xhr !== 'end') {
11034                xhr = 'unknown';
11035            }
11036
11037            this._debug('Error', xhr);
11038
11039            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
11040                this._showdonemsg();
11041            }
11042
11043            opts.state.isDone = true;
11044            opts.state.currPage = 1; // if you need to go back to this instance
11045            opts.state.isPaused = false;
11046            opts.state.isBeyondMaxPage = false;
11047            this._binding('unbind');
11048
11049        },
11050
11051        // Load Callback
11052        _loadcallback: function infscr_loadcallback(box, data, url) {
11053            var opts = this.options,
11054            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
11055            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
11056            frag;
11057
11058            // if behavior is defined and this function is extended, call that instead of default
11059            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
11060                this['_loadcallback_'+opts.behavior].call(this,box,data);
11061                return;
11062            }
11063
11064            switch (result) {
11065                case 'done':
11066                    this._showdonemsg();
11067                    return false;
11068
11069                case 'no-append':
11070                    if (opts.dataType === 'html') {
11071                        data = '<div>' + data + '</div>';
11072                        data = $(data).find(opts.itemSelector);
11073                    }
11074
11075                    // if it didn't return anything
11076                    if (data.length === 0) {
11077                        return this._error('end');
11078                    }
11079
11080                    break;
11081
11082                case 'append':
11083                    var children = box.children();
11084                    // if it didn't return anything
11085                    if (children.length === 0) {
11086                        return this._error('end');
11087                    }
11088
11089                    // use a documentFragment because it works when content is going into a table or UL
11090                    frag = document.createDocumentFragment();
11091                    while (box[0].firstChild) {
11092                        frag.appendChild(box[0].firstChild);
11093                    }
11094
11095                    this._debug('contentSelector', $(opts.contentSelector)[0]);
11096                    $(opts.contentSelector)[0].appendChild(frag);
11097                    // previously, we would pass in the new DOM element as context for the callback
11098                    // however we're now using a documentfragment, which doesn't have parents or children,
11099                    // so the context is the contentContainer guy, and we pass in an array
11100                    // of the elements collected as the first argument.
11101
11102                    data = children.get();
11103                    break;
11104            }
11105
11106            // loadingEnd function
11107            opts.loading.finished.call($(opts.contentSelector)[0],opts);
11108
11109            // smooth scroll to ease in the new content
11110            if (opts.animate) {
11111                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
11112                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
11113            }
11114
11115            if (!opts.animate) {
11116                // once the call is done, we can allow it again.
11117                opts.state.isDuringAjax = false;
11118            }
11119
11120            callback(this, data, url);
11121
11122            if (opts.prefill) {
11123                this._prefill();
11124            }
11125        },
11126
11127        _nearbottom: function infscr_nearbottom() {
11128
11129            var opts = this.options,
11130            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
11131
11132            // if behavior is defined and this function is extended, call that instead of default
11133            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
11134                return this['_nearbottom_'+opts.behavior].call(this);
11135            }
11136
11137            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
11138
11139            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
11140            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
11141
11142        },
11143
11144        // Pause / temporarily disable plugin from firing
11145        _pausing: function infscr_pausing(pause) {
11146
11147            var opts = this.options;
11148
11149            // if behavior is defined and this function is extended, call that instead of default
11150            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
11151                this['_pausing_'+opts.behavior].call(this,pause);
11152                return;
11153            }
11154
11155            // If pause is not 'pause' or 'resume', toggle it's value
11156            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
11157                this._debug('Invalid argument. Toggling pause value instead');
11158            }
11159
11160            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
11161
11162            switch (pause) {
11163                case 'pause':
11164                    opts.state.isPaused = true;
11165                break;
11166
11167                case 'resume':
11168                    opts.state.isPaused = false;
11169                break;
11170
11171                case 'toggle':
11172                    opts.state.isPaused = !opts.state.isPaused;
11173                break;
11174            }
11175
11176            this._debug('Paused', opts.state.isPaused);
11177            return false;
11178
11179        },
11180
11181        // Behavior is determined
11182        // If the behavior option is undefined, it will set to default and bind to scroll
11183        _setup: function infscr_setup() {
11184
11185            var opts = this.options;
11186
11187            // if behavior is defined and this function is extended, call that instead of default
11188            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
11189                this['_setup_'+opts.behavior].call(this);
11190                return;
11191            }
11192
11193            this._binding('bind');
11194
11195            return false;
11196
11197        },
11198
11199        // Show done message
11200        _showdonemsg: function infscr_showdonemsg() {
11201
11202            var opts = this.options;
11203
11204            // if behavior is defined and this function is extended, call that instead of default
11205            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
11206                this['_showdonemsg_'+opts.behavior].call(this);
11207                return;
11208            }
11209
11210            opts.loading.msg
11211            .find('img')
11212            .hide()
11213            .parent()
11214            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
11215                $(this).parent().fadeOut(opts.loading.speed);
11216            });
11217
11218            // user provided callback when done
11219            opts.errorCallback.call($(opts.contentSelector)[0],'done');
11220        },
11221
11222        // grab each selector option and see if any fail
11223        _validate: function infscr_validate(opts) {
11224            for (var key in opts) {
11225                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
11226                    this._debug('Your ' + key + ' found no elements.');
11227                    return false;
11228                }
11229            }
11230
11231            return true;
11232        },
11233
11234        /*
11235            ----------------------------
11236            Public methods
11237            ----------------------------
11238            */
11239
11240        // Bind to scroll
11241        bind: function infscr_bind() {
11242            this._binding('bind');
11243        },
11244
11245        // Destroy current instance of plugin
11246        destroy: function infscr_destroy() {
11247            this.options.state.isDestroyed = true;
11248            this.options.loading.finished();
11249            return this._error('destroy');
11250        },
11251
11252        // Set pause value to false
11253        pause: function infscr_pause() {
11254            this._pausing('pause');
11255        },
11256
11257        // Set pause value to false
11258        resume: function infscr_resume() {
11259            this._pausing('resume');
11260        },
11261
11262        beginAjax: function infscr_ajax(opts) {
11263            var instance = this,
11264                path = opts.path,
11265                box, desturl, method, condition;
11266
11267            // increment the URL bit. e.g. /page/3/
11268            opts.state.currPage++;
11269
11270            // Manually control maximum page
11271            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
11272                opts.state.isBeyondMaxPage = true;
11273                this.destroy();
11274                return;
11275            }
11276
11277            // if we're dealing with a table we can't use DIVs
11278            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
11279
11280            desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
11281            instance._debug('heading into ajax', desturl);
11282
11283            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
11284            if (opts.appendCallback && opts.dataType === 'html') {
11285                method += '+callback';
11286            }
11287
11288            switch (method) {
11289                case 'html+callback':
11290                    instance._debug('Using HTML via .load() method');
11291                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
11292                        instance._loadcallback(box, responseText, desturl);
11293                    });
11294
11295                    break;
11296
11297                case 'html':
11298                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
11299                    $.ajax({
11300                        // params
11301                        url: desturl,
11302                        dataType: opts.dataType,
11303                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
11304                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
11305                            if (condition) {
11306                                instance._loadcallback(box, jqXHR.responseText, desturl);
11307                            } else {
11308                                instance._error('end');
11309                            }
11310                        }
11311                    });
11312
11313                    break;
11314                case 'json':
11315                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
11316                    $.ajax({
11317                        dataType: 'json',
11318                        type: 'GET',
11319                        url: desturl,
11320                        success: function (data, textStatus, jqXHR) {
11321                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
11322                            if (opts.appendCallback) {
11323                                // if appendCallback is true, you must defined template in options.
11324                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
11325                                if (opts.template !== undefined) {
11326                                    var theData = opts.template(data);
11327                                    box.append(theData);
11328                                    if (condition) {
11329                                        instance._loadcallback(box, theData);
11330                                    } else {
11331                                        instance._error('end');
11332                                    }
11333                                } else {
11334                                    instance._debug('template must be defined.');
11335                                    instance._error('end');
11336                                }
11337                            } else {
11338                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
11339                                if (condition) {
11340                                    instance._loadcallback(box, data, desturl);
11341                                } else {
11342                                    instance._error('end');
11343                                }
11344                            }
11345                        },
11346                        error: function() {
11347                            instance._debug('JSON ajax request failed.');
11348                            instance._error('end');
11349                        }
11350                    });
11351
11352                    break;
11353            }
11354        },
11355
11356        // Retrieve next set of content items
11357        retrieve: function infscr_retrieve(pageNum) {
11358            pageNum = pageNum || null;
11359
11360            var instance = this,
11361            opts = instance.options;
11362
11363            // if behavior is defined and this function is extended, call that instead of default
11364            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
11365                this['retrieve_'+opts.behavior].call(this,pageNum);
11366                return;
11367            }
11368
11369            // for manual triggers, if destroyed, get out of here
11370            if (opts.state.isDestroyed) {
11371                this._debug('Instance is destroyed');
11372                return false;
11373            }
11374
11375            // we dont want to fire the ajax multiple times
11376            opts.state.isDuringAjax = true;
11377
11378            opts.loading.start.call($(opts.contentSelector)[0],opts);
11379        },
11380
11381        // Check to see next page is needed
11382        scroll: function infscr_scroll() {
11383
11384            var opts = this.options,
11385            state = opts.state;
11386
11387            // if behavior is defined and this function is extended, call that instead of default
11388            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
11389                this['scroll_'+opts.behavior].call(this);
11390                return;
11391            }
11392
11393            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
11394                return;
11395            }
11396
11397            if (!this._nearbottom()) {
11398                return;
11399            }
11400
11401            this.retrieve();
11402
11403        },
11404
11405        // Toggle pause value
11406        toggle: function infscr_toggle() {
11407            this._pausing();
11408        },
11409
11410        // Unbind from scroll
11411        unbind: function infscr_unbind() {
11412            this._binding('unbind');
11413        },
11414
11415        // update options
11416        update: function infscr_options(key) {
11417            if ($.isPlainObject(key)) {
11418                this.options = $.extend(true,this.options,key);
11419            }
11420        }
11421    };
11422
11423
11424    /*
11425        ----------------------------
11426        Infinite Scroll function
11427        ----------------------------
11428
11429        Borrowed logic from the following...
11430
11431        jQuery UI
11432        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
11433
11434        jCarousel
11435        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
11436
11437        Masonry
11438        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
11439
11440*/
11441
11442    $.fn.infinitescroll = function infscr_init(options, callback) {
11443
11444
11445        var thisCall = typeof options;
11446
11447        switch (thisCall) {
11448
11449            // method
11450            case 'string':
11451                var args = Array.prototype.slice.call(arguments, 1);
11452
11453                this.each(function () {
11454                    var instance = $.data(this, 'infinitescroll');
11455
11456                    if (!instance) {
11457                        // not setup yet
11458                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
11459                        return false;
11460                    }
11461
11462                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
11463                        // return $.error('No such method ' + options + ' for Infinite Scroll');
11464                        return false;
11465                    }
11466
11467                    // no errors!
11468                    instance[options].apply(instance, args);
11469                });
11470
11471            break;
11472
11473            // creation
11474            case 'object':
11475
11476                this.each(function () {
11477
11478                var instance = $.data(this, 'infinitescroll');
11479
11480                if (instance) {
11481
11482                    // update options of current instance
11483                    instance.update(options);
11484
11485                } else {
11486
11487                    // initialize new instance
11488                    instance = new $.infinitescroll(options, callback, this);
11489
11490                    // don't attach if instantiation failed
11491                    if (!instance.failed) {
11492                        $.data(this, 'infinitescroll', instance);
11493                    }
11494
11495                }
11496
11497            });
11498
11499            break;
11500
11501        }
11502
11503        return this;
11504    };
11505
11506
11507
11508    /*
11509     * smartscroll: debounced scroll event for jQuery *
11510     * https://github.com/lukeshumard/smartscroll
11511     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
11512     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
11513     */
11514
11515    var event = $.event,
11516    scrollTimeout;
11517
11518    event.special.smartscroll = {
11519        setup: function () {
11520            $(this).bind('scroll', event.special.smartscroll.handler);
11521        },
11522        teardown: function () {
11523            $(this).unbind('scroll', event.special.smartscroll.handler);
11524        },
11525        handler: function (event, execAsap) {
11526            // Save the context
11527            var context = this,
11528            args = arguments;
11529
11530            // set correct event type
11531            event.type = 'smartscroll';
11532
11533            if (scrollTimeout) { clearTimeout(scrollTimeout); }
11534            scrollTimeout = setTimeout(function () {
11535                $(context).trigger('smartscroll', args);
11536            }, execAsap === 'execAsap' ? 0 : 100);
11537        }
11538    };
11539
11540    $.fn.smartscroll = function (fn) {
11541        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
11542    };
11543
11544}));
11545
11546/*!
11547Waypoints - 4.0.1
11548Copyright © 2011-2016 Caleb Troughton
11549Licensed under the MIT license.
11550https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
11551*/
11552(function() {
11553  'use strict'
11554
11555  var keyCounter = 0
11556  var allWaypoints = {}
11557
11558  /* http://imakewebthings.com/waypoints/api/waypoint */
11559  function Waypoint(options) {
11560    if (!options) {
11561      throw new Error('No options passed to Waypoint constructor')
11562    }
11563    if (!options.element) {
11564      throw new Error('No element option passed to Waypoint constructor')
11565    }
11566    if (!options.handler) {
11567      throw new Error('No handler option passed to Waypoint constructor')
11568    }
11569
11570    this.key = 'waypoint-' + keyCounter
11571    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
11572    this.element = this.options.element
11573    this.adapter = new Waypoint.Adapter(this.element)
11574    this.callback = options.handler
11575    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
11576    this.enabled = this.options.enabled
11577    this.triggerPoint = null
11578    this.group = Waypoint.Group.findOrCreate({
11579      name: this.options.group,
11580      axis: this.axis
11581    })
11582    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
11583
11584    if (Waypoint.offsetAliases[this.options.offset]) {
11585      this.options.offset = Waypoint.offsetAliases[this.options.offset]
11586    }
11587    this.group.add(this)
11588    this.context.add(this)
11589    allWaypoints[this.key] = this
11590    keyCounter += 1
11591  }
11592
11593  /* Private */
11594  Waypoint.prototype.queueTrigger = function(direction) {
11595    this.group.queueTrigger(this, direction)
11596  }
11597
11598  /* Private */
11599  Waypoint.prototype.trigger = function(args) {
11600    if (!this.enabled) {
11601      return
11602    }
11603    if (this.callback) {
11604      this.callback.apply(this, args)
11605    }
11606  }
11607
11608  /* Public */
11609  /* http://imakewebthings.com/waypoints/api/destroy */
11610  Waypoint.prototype.destroy = function() {
11611    this.context.remove(this)
11612    this.group.remove(this)
11613    delete allWaypoints[this.key]
11614  }
11615
11616  /* Public */
11617  /* http://imakewebthings.com/waypoints/api/disable */
11618  Waypoint.prototype.disable = function() {
11619    this.enabled = false
11620    return this
11621  }
11622
11623  /* Public */
11624  /* http://imakewebthings.com/waypoints/api/enable */
11625  Waypoint.prototype.enable = function() {
11626    this.context.refresh()
11627    this.enabled = true
11628    return this
11629  }
11630
11631  /* Public */
11632  /* http://imakewebthings.com/waypoints/api/next */
11633  Waypoint.prototype.next = function() {
11634    return this.group.next(this)
11635  }
11636
11637  /* Public */
11638  /* http://imakewebthings.com/waypoints/api/previous */
11639  Waypoint.prototype.previous = function() {
11640    return this.group.previous(this)
11641  }
11642
11643  /* Private */
11644  Waypoint.invokeAll = function(method) {
11645    var allWaypointsArray = []
11646    for (var waypointKey in allWaypoints) {
11647      allWaypointsArray.push(allWaypoints[waypointKey])
11648    }
11649    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
11650      allWaypointsArray[i][method]()
11651    }
11652  }
11653
11654  /* Public */
11655  /* http://imakewebthings.com/waypoints/api/destroy-all */
11656  Waypoint.destroyAll = function() {
11657    Waypoint.invokeAll('destroy')
11658  }
11659
11660  /* Public */
11661  /* http://imakewebthings.com/waypoints/api/disable-all */
11662  Waypoint.disableAll = function() {
11663    Waypoint.invokeAll('disable')
11664  }
11665
11666  /* Public */
11667  /* http://imakewebthings.com/waypoints/api/enable-all */
11668  Waypoint.enableAll = function() {
11669    Waypoint.Context.refreshAll()
11670    for (var waypointKey in allWaypoints) {
11671      allWaypoints[waypointKey].enabled = true
11672    }
11673    return this
11674  }
11675
11676  /* Public */
11677  /* http://imakewebthings.com/waypoints/api/refresh-all */
11678  Waypoint.refreshAll = function() {
11679    Waypoint.Context.refreshAll()
11680  }
11681
11682  /* Public */
11683  /* http://imakewebthings.com/waypoints/api/viewport-height */
11684  Waypoint.viewportHeight = function() {
11685    return window.innerHeight || document.documentElement.clientHeight
11686  }
11687
11688  /* Public */
11689  /* http://imakewebthings.com/waypoints/api/viewport-width */
11690  Waypoint.viewportWidth = function() {
11691    return document.documentElement.clientWidth
11692  }
11693
11694  Waypoint.adapters = []
11695
11696  Waypoint.defaults = {
11697    context: window,
11698    continuous: true,
11699    enabled: true,
11700    group: 'default',
11701    horizontal: false,
11702    offset: 0
11703  }
11704
11705  Waypoint.offsetAliases = {
11706    'bottom-in-view': function() {
11707      return this.context.innerHeight() - this.adapter.outerHeight()
11708    },
11709    'right-in-view': function() {
11710      return this.context.innerWidth() - this.adapter.outerWidth()
11711    }
11712  }
11713
11714  window.Waypoint = Waypoint
11715}())
11716;(function() {
11717  'use strict'
11718
11719  function requestAnimationFrameShim(callback) {
11720    window.setTimeout(callback, 1000 / 60)
11721  }
11722
11723  var keyCounter = 0
11724  var contexts = {}
11725  var Waypoint = window.Waypoint
11726  var oldWindowLoad = window.onload
11727
11728  /* http://imakewebthings.com/waypoints/api/context */
11729  function Context(element) {
11730    this.element = element
11731    this.Adapter = Waypoint.Adapter
11732    this.adapter = new this.Adapter(element)
11733    this.key = 'waypoint-context-' + keyCounter
11734    this.didScroll = false
11735    this.didResize = false
11736    this.oldScroll = {
11737      x: this.adapter.scrollLeft(),
11738      y: this.adapter.scrollTop()
11739    }
11740    this.waypoints = {
11741      vertical: {},
11742      horizontal: {}
11743    }
11744
11745    element.waypointContextKey = this.key
11746    contexts[element.waypointContextKey] = this
11747    keyCounter += 1
11748    if (!Waypoint.windowContext) {
11749      Waypoint.windowContext = true
11750      Waypoint.windowContext = new Context(window)
11751    }
11752
11753    this.createThrottledScrollHandler()
11754    this.createThrottledResizeHandler()
11755  }
11756
11757  /* Private */
11758  Context.prototype.add = function(waypoint) {
11759    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
11760    this.waypoints[axis][waypoint.key] = waypoint
11761    this.refresh()
11762  }
11763
11764  /* Private */
11765  Context.prototype.checkEmpty = function() {
11766    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
11767    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
11768    var isWindow = this.element == this.element.window
11769    if (horizontalEmpty && verticalEmpty && !isWindow) {
11770      this.adapter.off('.waypoints')
11771      delete contexts[this.key]
11772    }
11773  }
11774
11775  /* Private */
11776  Context.prototype.createThrottledResizeHandler = function() {
11777    var self = this
11778
11779    function resizeHandler() {
11780      self.handleResize()
11781      self.didResize = false
11782    }
11783
11784    this.adapter.on('resize.waypoints', function() {
11785      if (!self.didResize) {
11786        self.didResize = true
11787        Waypoint.requestAnimationFrame(resizeHandler)
11788      }
11789    })
11790  }
11791
11792  /* Private */
11793  Context.prototype.createThrottledScrollHandler = function() {
11794    var self = this
11795    function scrollHandler() {
11796      self.handleScroll()
11797      self.didScroll = false
11798    }
11799
11800    this.adapter.on('scroll.waypoints', function() {
11801      if (!self.didScroll || Waypoint.isTouch) {
11802        self.didScroll = true
11803        Waypoint.requestAnimationFrame(scrollHandler)
11804      }
11805    })
11806  }
11807
11808  /* Private */
11809  Context.prototype.handleResize = function() {
11810    Waypoint.Context.refreshAll()
11811  }
11812
11813  /* Private */
11814  Context.prototype.handleScroll = function() {
11815    var triggeredGroups = {}
11816    var axes = {
11817      horizontal: {
11818        newScroll: this.adapter.scrollLeft(),
11819        oldScroll: this.oldScroll.x,
11820        forward: 'right',
11821        backward: 'left'
11822      },
11823      vertical: {
11824        newScroll: this.adapter.scrollTop(),
11825        oldScroll: this.oldScroll.y,
11826        forward: 'down',
11827        backward: 'up'
11828      }
11829    }
11830
11831    for (var axisKey in axes) {
11832      var axis = axes[axisKey]
11833      var isForward = axis.newScroll > axis.oldScroll
11834      var direction = isForward ? axis.forward : axis.backward
11835
11836      for (var waypointKey in this.waypoints[axisKey]) {
11837        var waypoint = this.waypoints[axisKey][waypointKey]
11838        if (waypoint.triggerPoint === null) {
11839          continue
11840        }
11841        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
11842        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
11843        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
11844        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
11845        if (crossedForward || crossedBackward) {
11846          waypoint.queueTrigger(direction)
11847          triggeredGroups[waypoint.group.id] = waypoint.group
11848        }
11849      }
11850    }
11851
11852    for (var groupKey in triggeredGroups) {
11853      triggeredGroups[groupKey].flushTriggers()
11854    }
11855
11856    this.oldScroll = {
11857      x: axes.horizontal.newScroll,
11858      y: axes.vertical.newScroll
11859    }
11860  }
11861
11862  /* Private */
11863  Context.prototype.innerHeight = function() {
11864    /*eslint-disable eqeqeq */
11865    if (this.element == this.element.window) {
11866      return Waypoint.viewportHeight()
11867    }
11868    /*eslint-enable eqeqeq */
11869    return this.adapter.innerHeight()
11870  }
11871
11872  /* Private */
11873  Context.prototype.remove = function(waypoint) {
11874    delete this.waypoints[waypoint.axis][waypoint.key]
11875    this.checkEmpty()
11876  }
11877
11878  /* Private */
11879  Context.prototype.innerWidth = function() {
11880    /*eslint-disable eqeqeq */
11881    if (this.element == this.element.window) {
11882      return Waypoint.viewportWidth()
11883    }
11884    /*eslint-enable eqeqeq */
11885    return this.adapter.innerWidth()
11886  }
11887
11888  /* Public */
11889  /* http://imakewebthings.com/waypoints/api/context-destroy */
11890  Context.prototype.destroy = function() {
11891    var allWaypoints = []
11892    for (var axis in this.waypoints) {
11893      for (var waypointKey in this.waypoints[axis]) {
11894        allWaypoints.push(this.waypoints[axis][waypointKey])
11895      }
11896    }
11897    for (var i = 0, end = allWaypoints.length; i < end; i++) {
11898      allWaypoints[i].destroy()
11899    }
11900  }
11901
11902  /* Public */
11903  /* http://imakewebthings.com/waypoints/api/context-refresh */
11904  Context.prototype.refresh = function() {
11905    /*eslint-disable eqeqeq */
11906    var isWindow = this.element == this.element.window
11907    /*eslint-enable eqeqeq */
11908    var contextOffset = isWindow ? undefined : this.adapter.offset()
11909    var triggeredGroups = {}
11910    var axes
11911
11912    this.handleScroll()
11913    axes = {
11914      horizontal: {
11915        contextOffset: isWindow ? 0 : contextOffset.left,
11916        contextScroll: isWindow ? 0 : this.oldScroll.x,
11917        contextDimension: this.innerWidth(),
11918        oldScroll: this.oldScroll.x,
11919        forward: 'right',
11920        backward: 'left',
11921        offsetProp: 'left'
11922      },
11923      vertical: {
11924        contextOffset: isWindow ? 0 : contextOffset.top,
11925        contextScroll: isWindow ? 0 : this.oldScroll.y,
11926        contextDimension: this.innerHeight(),
11927        oldScroll: this.oldScroll.y,
11928        forward: 'down',
11929        backward: 'up',
11930        offsetProp: 'top'
11931      }
11932    }
11933
11934    for (var axisKey in axes) {
11935      var axis = axes[axisKey]
11936      for (var waypointKey in this.waypoints[axisKey]) {
11937        var waypoint = this.waypoints[axisKey][waypointKey]
11938        var adjustment = waypoint.options.offset
11939        var oldTriggerPoint = waypoint.triggerPoint
11940        var elementOffset = 0
11941        var freshWaypoint = oldTriggerPoint == null
11942        var contextModifier, wasBeforeScroll, nowAfterScroll
11943        var triggeredBackward, triggeredForward
11944
11945        if (waypoint.element !== waypoint.element.window) {
11946          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
11947        }
11948
11949        if (typeof adjustment === 'function') {
11950          adjustment = adjustment.apply(waypoint)
11951        }
11952        else if (typeof adjustment === 'string') {
11953          adjustment = parseFloat(adjustment)
11954          if (waypoint.options.offset.indexOf('%') > - 1) {
11955            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
11956          }
11957        }
11958
11959        contextModifier = axis.contextScroll - axis.contextOffset
11960        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
11961        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
11962        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
11963        triggeredBackward = wasBeforeScroll && nowAfterScroll
11964        triggeredForward = !wasBeforeScroll && !nowAfterScroll
11965
11966        if (!freshWaypoint && triggeredBackward) {
11967          waypoint.queueTrigger(axis.backward)
11968          triggeredGroups[waypoint.group.id] = waypoint.group
11969        }
11970        else if (!freshWaypoint && triggeredForward) {
11971          waypoint.queueTrigger(axis.forward)
11972          triggeredGroups[waypoint.group.id] = waypoint.group
11973        }
11974        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
11975          waypoint.queueTrigger(axis.forward)
11976          triggeredGroups[waypoint.group.id] = waypoint.group
11977        }
11978      }
11979    }
11980
11981    Waypoint.requestAnimationFrame(function() {
11982      for (var groupKey in triggeredGroups) {
11983        triggeredGroups[groupKey].flushTriggers()
11984      }
11985    })
11986
11987    return this
11988  }
11989
11990  /* Private */
11991  Context.findOrCreateByElement = function(element) {
11992    return Context.findByElement(element) || new Context(element)
11993  }
11994
11995  /* Private */
11996  Context.refreshAll = function() {
11997    for (var contextId in contexts) {
11998      contexts[contextId].refresh()
11999    }
12000  }
12001
12002  /* Public */
12003  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
12004  Context.findByElement = function(element) {
12005    return contexts[element.waypointContextKey]
12006  }
12007
12008  window.onload = function() {
12009    if (oldWindowLoad) {
12010      oldWindowLoad()
12011    }
12012    Context.refreshAll()
12013  }
12014
12015
12016  Waypoint.requestAnimationFrame = function(callback) {
12017    var requestFn = window.requestAnimationFrame ||
12018      window.mozRequestAnimationFrame ||
12019      window.webkitRequestAnimationFrame ||
12020      requestAnimationFrameShim
12021    requestFn.call(window, callback)
12022  }
12023  Waypoint.Context = Context
12024}())
12025;(function() {
12026  'use strict'
12027
12028  function byTriggerPoint(a, b) {
12029    return a.triggerPoint - b.triggerPoint
12030  }
12031
12032  function byReverseTriggerPoint(a, b) {
12033    return b.triggerPoint - a.triggerPoint
12034  }
12035
12036  var groups = {
12037    vertical: {},
12038    horizontal: {}
12039  }
12040  var Waypoint = window.Waypoint
12041
12042  /* http://imakewebthings.com/waypoints/api/group */
12043  function Group(options) {
12044    this.name = options.name
12045    this.axis = options.axis
12046    this.id = this.name + '-' + this.axis
12047    this.waypoints = []
12048    this.clearTriggerQueues()
12049    groups[this.axis][this.name] = this
12050  }
12051
12052  /* Private */
12053  Group.prototype.add = function(waypoint) {
12054    this.waypoints.push(waypoint)
12055  }
12056
12057  /* Private */
12058  Group.prototype.clearTriggerQueues = function() {
12059    this.triggerQueues = {
12060      up: [],
12061      down: [],
12062      left: [],
12063      right: []
12064    }
12065  }
12066
12067  /* Private */
12068  Group.prototype.flushTriggers = function() {
12069    for (var direction in this.triggerQueues) {
12070      var waypoints = this.triggerQueues[direction]
12071      var reverse = direction === 'up' || direction === 'left'
12072      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
12073      for (var i = 0, end = waypoints.length; i < end; i += 1) {
12074        var waypoint = waypoints[i]
12075        if (waypoint.options.continuous || i === waypoints.length - 1) {
12076          waypoint.trigger([direction])
12077        }
12078      }
12079    }
12080    this.clearTriggerQueues()
12081  }
12082
12083  /* Private */
12084  Group.prototype.next = function(waypoint) {
12085    this.waypoints.sort(byTriggerPoint)
12086    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12087    var isLast = index === this.waypoints.length - 1
12088    return isLast ? null : this.waypoints[index + 1]
12089  }
12090
12091  /* Private */
12092  Group.prototype.previous = function(waypoint) {
12093    this.waypoints.sort(byTriggerPoint)
12094    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12095    return index ? this.waypoints[index - 1] : null
12096  }
12097
12098  /* Private */
12099  Group.prototype.queueTrigger = function(waypoint, direction) {
12100    this.triggerQueues[direction].push(waypoint)
12101  }
12102
12103  /* Private */
12104  Group.prototype.remove = function(waypoint) {
12105    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12106    if (index > -1) {
12107      this.waypoints.splice(index, 1)
12108    }
12109  }
12110
12111  /* Public */
12112  /* http://imakewebthings.com/waypoints/api/first */
12113  Group.prototype.first = function() {
12114    return this.waypoints[0]
12115  }
12116
12117  /* Public */
12118  /* http://imakewebthings.com/waypoints/api/last */
12119  Group.prototype.last = function() {
12120    return this.waypoints[this.waypoints.length - 1]
12121  }
12122
12123  /* Private */
12124  Group.findOrCreate = function(options) {
12125    return groups[options.axis][options.name] || new Group(options)
12126  }
12127
12128  Waypoint.Group = Group
12129}())
12130;(function() {
12131  'use strict'
12132
12133  var $ = window.jQuery
12134  var Waypoint = window.Waypoint
12135
12136  function JQueryAdapter(element) {
12137    this.$element = $(element)
12138  }
12139
12140  $.each([
12141    'innerHeight',
12142    'innerWidth',
12143    'off',
12144    'offset',
12145    'on',
12146    'outerHeight',
12147    'outerWidth',
12148    'scrollLeft',
12149    'scrollTop'
12150  ], function(i, method) {
12151    JQueryAdapter.prototype[method] = function() {
12152      var args = Array.prototype.slice.call(arguments)
12153      return this.$element[method].apply(this.$element, args)
12154    }
12155  })
12156
12157  $.each([
12158    'extend',
12159    'inArray',
12160    'isEmptyObject'
12161  ], function(i, method) {
12162    JQueryAdapter[method] = $[method]
12163  })
12164
12165  Waypoint.adapters.push({
12166    name: 'jquery',
12167    Adapter: JQueryAdapter
12168  })
12169  Waypoint.Adapter = JQueryAdapter
12170}())
12171;(function() {
12172  'use strict'
12173
12174  var Waypoint = window.Waypoint
12175
12176  function createExtension(framework) {
12177    return function() {
12178      var waypoints = []
12179      var overrides = arguments[0]
12180
12181      if (framework.isFunction(arguments[0])) {
12182        overrides = framework.extend({}, arguments[1])
12183        overrides.handler = arguments[0]
12184      }
12185
12186      this.each(function() {
12187        var options = framework.extend({}, overrides, {
12188          element: this
12189        })
12190        if (typeof options.context === 'string') {
12191          options.context = framework(this).closest(options.context)[0]
12192        }
12193        waypoints.push(new Waypoint(options))
12194      })
12195
12196      return waypoints
12197    }
12198  }
12199
12200  if (window.jQuery) {
12201    window.jQuery.fn.waypoint = createExtension(window.jQuery)
12202  }
12203  if (window.Zepto) {
12204    window.Zepto.fn.waypoint = createExtension(window.Zepto)
12205  }
12206}())
12207;
12208/*!
12209Waypoints Inview Shortcut - 4.0.1
12210Copyright © 2011-2016 Caleb Troughton
12211Licensed under the MIT license.
12212https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
12213*/
12214(function() {
12215  'use strict'
12216
12217  function noop() {}
12218
12219  var Waypoint = window.Waypoint
12220
12221  /* http://imakewebthings.com/waypoints/shortcuts/inview */
12222  function Inview(options) {
12223    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
12224    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
12225    this.waypoints = []
12226    this.element = this.options.element
12227    this.createWaypoints()
12228  }
12229
12230  /* Private */
12231  Inview.prototype.createWaypoints = function() {
12232    var configs = {
12233      vertical: [{
12234        down: 'enter',
12235        up: 'exited',
12236        offset: '100%'
12237      }, {
12238        down: 'entered',
12239        up: 'exit',
12240        offset: 'bottom-in-view'
12241      }, {
12242        down: 'exit',
12243        up: 'entered',
12244        offset: 0
12245      }, {
12246        down: 'exited',
12247        up: 'enter',
12248        offset: function() {
12249          return -this.adapter.outerHeight()
12250        }
12251      }],
12252      horizontal: [{
12253        right: 'enter',
12254        left: 'exited',
12255        offset: '100%'
12256      }, {
12257        right: 'entered',
12258        left: 'exit',
12259        offset: 'right-in-view'
12260      }, {
12261        right: 'exit',
12262        left: 'entered',
12263        offset: 0
12264      }, {
12265        right: 'exited',
12266        left: 'enter',
12267        offset: function() {
12268          return -this.adapter.outerWidth()
12269        }
12270      }]
12271    }
12272
12273    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
12274      var config = configs[this.axis][i]
12275      this.createWaypoint(config)
12276    }
12277  }
12278
12279  /* Private */
12280  Inview.prototype.createWaypoint = function(config) {
12281    var self = this
12282    this.waypoints.push(new Waypoint({
12283      context: this.options.context,
12284      element: this.options.element,
12285      enabled: this.options.enabled,
12286      handler: (function(config) {
12287        return function(direction) {
12288          self.options[config[direction]].call(self, direction)
12289        }
12290      }(config)),
12291      offset: config.offset,
12292      horizontal: this.options.horizontal
12293    }))
12294  }
12295
12296  /* Public */
12297  Inview.prototype.destroy = function() {
12298    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12299      this.waypoints[i].destroy()
12300    }
12301    this.waypoints = []
12302  }
12303
12304  Inview.prototype.disable = function() {
12305    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12306      this.waypoints[i].disable()
12307    }
12308  }
12309
12310  Inview.prototype.enable = function() {
12311    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12312      this.waypoints[i].enable()
12313    }
12314  }
12315
12316  Inview.defaults = {
12317    context: window,
12318    enabled: true,
12319    enter: noop,
12320    entered: noop,
12321    exit: noop,
12322    exited: noop
12323  }
12324
12325  Waypoint.Inview = Inview
12326}())
12327;
12328
12329/*
12330 * SmartMenus jQuery v0.9.6
12331 * http://www.smartmenus.org/
12332 *
12333 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
12334 * http://vadikom.com/
12335 *
12336 * Released under the MIT license:
12337 * http://www.opensource.org/licenses/MIT
12338 */
12339
12340(function($) {
12341
12342	var menuTrees = [],
12343		IE = !!window.createPopup, // we need to detect it, unfortunately
12344		IElt9 = IE && !document.defaultView,
12345		IElt8 = IE && !document.querySelector,
12346		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
12347		mouse = false, // optimize for touch by default - we will detect for mouse input
12348		mouseDetectionEnabled = false;
12349
12350	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
12351	function initMouseDetection(disable) {
12352		if (!mouseDetectionEnabled && !disable) {
12353			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
12354			// in practice, this seems like impossible to trick unintentianally with a real mouse and a pretty safe detection on touch devices (even with older browsers that do not support touch events)
12355			var firstTime = true,
12356				lastMove = null;
12357			$(document).bind({
12358				'mousemove.smartmenus_mouse': function(e) {
12359					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
12360					if (lastMove) {
12361						var deltaX = Math.abs(lastMove.x - thisMove.x),
12362							deltaY = Math.abs(lastMove.y - thisMove.y);
12363	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
12364							mouse = true;
12365							// if this is the first check after page load, check if we are not over some item by chance and call the mouseenter handler if yes
12366							if (firstTime) {
12367								var $a = $(e.target).closest('a');
12368								if ($a.is('a')) {
12369									$.each(menuTrees, function() {
12370										if ($.contains(this.$root[0], $a[0])) {
12371											this.itemEnter({ currentTarget: $a[0] });
12372											return false;
12373										}
12374									});
12375								}
12376								firstTime = false;
12377							}
12378						}
12379					}
12380					lastMove = thisMove;
12381				},
12382				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
12383					if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) {
12384						mouse = false;
12385					}
12386				}
12387			});
12388			mouseDetectionEnabled = true;
12389		} else if (mouseDetectionEnabled && disable) {
12390			$(document).unbind('.smartmenus_mouse');
12391			mouseDetectionEnabled = false;
12392		}
12393	};
12394
12395	$.SmartMenus = function(elm, options) {
12396		this.$root = $(elm);
12397		this.opts = options;
12398		this.rootId = ''; // internal
12399		this.$subArrow = null;
12400		this.subMenus = []; // all sub menus in the tree (UL elms) in no particular order (only real - e.g. UL's in mega sub menus won't be counted)
12401		this.activatedItems = []; // stores last activated A's for each level
12402		this.visibleSubMenus = []; // stores visible sub menus UL's
12403		this.showTimeout = 0;
12404		this.hideTimeout = 0;
12405		this.scrollTimeout = 0;
12406		this.clickActivated = false;
12407		this.zIndexInc = 0;
12408		this.$firstLink = null; // we'll use these for some tests
12409		this.$firstSub = null; // at runtime so we'll cache them
12410		this.disabled = false;
12411		this.$disableOverlay = null;
12412		this.init();
12413	};
12414
12415	$.extend($.SmartMenus, {
12416		hideAll: function() {
12417			$.each(menuTrees, function() {
12418				this.menuHideAll();
12419			});
12420		},
12421		destroy: function() {
12422			while (menuTrees.length) {
12423				menuTrees[0].destroy();
12424			}
12425			initMouseDetection(true);
12426		},
12427		prototype: {
12428			init: function(refresh) {
12429				var self = this;
12430
12431				if (!refresh) {
12432					menuTrees.push(this);
12433
12434					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
12435
12436					if (this.$root.hasClass('sm-rtl')) {
12437						this.opts.rightToLeftSubMenus = true;
12438					}
12439
12440					// init root (main menu)
12441					this.$root
12442						.data('smartmenus', this)
12443						.attr('data-smartmenus-id', this.rootId)
12444						.dataSM('level', 1)
12445						.bind({
12446							'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
12447							'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
12448						})
12449						.delegate('a, div.logo-container', {
12450							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
12451							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
12452							'mousedown.smartmenus': $.proxy(this.itemDown, this),
12453							'focus.smartmenus': $.proxy(this.itemFocus, this),
12454							'blur.smartmenus': $.proxy(this.itemBlur, this),
12455							'click.smartmenus': $.proxy(this.itemClick, this),
12456							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
12457						});
12458
12459					var eNamespace = '.smartmenus' + this.rootId;
12460					// hide menus on tap or click outside the root UL
12461					if (this.opts.hideOnClick) {
12462							$(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
12463								.on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
12464								.on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
12465								// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
12466								.on('click' + eNamespace, $.proxy(this.docClick, this));
12467					}
12468					// hide sub menus on resize
12469					$(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12470					$(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12471
12472					if (this.opts.subIndicators) {
12473						this.$subArrow = $('<span/>').addClass('sub-arrow');
12474						if (this.opts.subIndicatorsText) {
12475							this.$subArrow.html(this.opts.subIndicatorsText);
12476						}
12477					}
12478
12479					// make sure mouse detection is enabled
12480					initMouseDetection();
12481				}
12482
12483				// init sub menus
12484				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
12485
12486				this.$firstLink = this.$root.find('a').eq(0);
12487
12488				// find current item
12489				if (this.opts.markCurrentItem) {
12490					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
12491						reHash = /#.*/,
12492						locHref = window.location.href.replace(reDefaultDoc, ''),
12493						locHrefNoHash = locHref.replace(reHash, '');
12494					this.$root.find('a').each(function() {
12495						var href = this.href.replace(reDefaultDoc, ''),
12496							$this = $(this);
12497						if (href == locHref || href == locHrefNoHash) {
12498							$this.addClass('current');
12499							if (self.opts.markCurrentTree) {
12500								$this.parents('li').each(function() {
12501									var $this = $(this);
12502									if ($this.dataSM('sub')) {
12503										$this.children('a').addClass('current');
12504									}
12505								});
12506							}
12507						}
12508					});
12509				}
12510			},
12511			destroy: function() {
12512				this.menuHideAll();
12513				this.$root
12514					.removeData('smartmenus')
12515					.removeAttr('data-smartmenus-id')
12516					.removeDataSM('level')
12517					.unbind('.smartmenus')
12518					.undelegate('.smartmenus');
12519				var eNamespace = '.smartmenus' + this.rootId;
12520				$(document).unbind(eNamespace);
12521				$(window).unbind(eNamespace);
12522				if (this.opts.subIndicators) {
12523					this.$subArrow = null;
12524				}
12525				var self = this;
12526				$.each(this.subMenus, function() {
12527					if (this.hasClass('mega-menu')) {
12528						this.find('ul').removeDataSM('in-mega');
12529					}
12530					if (this.dataSM('shown-before')) {
12531						if (IElt8) {
12532							this.children().css({ styleFloat: '', width: '' });
12533						}
12534						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
12535							if (!IE6) {
12536								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
12537							} else {
12538								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
12539							}
12540						}
12541						if (this.dataSM('scroll-arrows')) {
12542							this.dataSM('scroll-arrows').remove();
12543						}
12544						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
12545					}
12546					if (self.opts.subIndicators) {
12547						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
12548					}
12549					this.removeDataSM('shown-before')
12550						.removeDataSM('ie-shim')
12551						.removeDataSM('scroll-arrows')
12552						.removeDataSM('parent-a')
12553						.removeDataSM('level')
12554						.removeDataSM('beforefirstshowfired')
12555						.parent().removeDataSM('sub');
12556				});
12557				if (this.opts.markCurrentItem) {
12558					this.$root.find('a.current').removeClass('current');
12559				}
12560				this.$root = null;
12561				this.$firstLink = null;
12562				this.$firstSub = null;
12563				if (this.$disableOverlay) {
12564					this.$disableOverlay.remove();
12565					this.$disableOverlay = null;
12566				}
12567				menuTrees.splice($.inArray(this, menuTrees), 1);
12568			},
12569			disable: function(noOverlay) {
12570				if (!this.disabled) {
12571					this.menuHideAll();
12572					// display overlay over the menu to prevent interaction
12573					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
12574						var pos = this.$root.offset();
12575						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
12576							position: 'absolute',
12577							top: pos.top,
12578							left: pos.left,
12579							width: this.$root.outerWidth(),
12580							height: this.$root.outerHeight(),
12581							zIndex: this.getStartZIndex() + 1,
12582							opacity: 0
12583						}).appendTo(document.body);
12584					}
12585					this.disabled = true;
12586				}
12587			},
12588			docClick: function(e) {
12589				// hide on any click outside the menu or on a menu link
12590				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
12591					this.menuHideAll($(e.target));
12592				}
12593			},
12594			docTouchEnd: function(e) {
12595				if (!this.lastTouch) {
12596					return;
12597				}
12598				if (this.visibleSubMenus.length && (this.lastTouch.x2 === undefined || this.lastTouch.x1 == this.lastTouch.x2) && (this.lastTouch.y2 === undefined || this.lastTouch.y1 == this.lastTouch.y2) && (!this.lastTouch.target || !$.contains(this.$root[0], this.lastTouch.target))) {
12599					if (this.hideTimeout) {
12600						clearTimeout(this.hideTimeout);
12601						this.hideTimeout = 0;
12602					}
12603					// hide with a delay to prevent triggering accidental unwanted click on some page element
12604					var self = this;
12605					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
12606				}
12607				this.lastTouch = null;
12608			},
12609			docTouchMove: function(e) {
12610				if (!this.lastTouch) {
12611					return;
12612				}
12613				var touchPoint = e.originalEvent.touches[0];
12614				this.lastTouch.x2 = touchPoint.pageX;
12615				this.lastTouch.y2 = touchPoint.pageY;
12616			},
12617			docTouchStart: function(e) {
12618				var touchPoint = e.originalEvent.touches[0];
12619				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
12620			},
12621			enable: function() {
12622				if (this.disabled) {
12623					if (this.$disableOverlay) {
12624						this.$disableOverlay.remove();
12625						this.$disableOverlay = null;
12626					}
12627					this.disabled = false;
12628				}
12629			},
12630			getHeight: function($elm) {
12631				return this.getOffset($elm, true);
12632			},
12633			// returns precise width/height float values in IE9+, FF4+, recent WebKit
12634			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
12635			getOffset: function($elm, height) {
12636				var old,
12637					$win = $(window),
12638					winW = $win.width();
12639				if ($elm.css('display') == 'none') {
12640					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
12641					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
12642					if ( 
12643						($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length)
12644						||
12645						($('body').hasClass('vmenu-offcanvas-overlay') && winW >= 960 && $elm.closest('.main-menu-container').length)
12646					) {
12647						$elm.closest('li').addClass('smartmenu-open-item');
12648					}
12649				}
12650				var defaultView = $elm[0].ownerDocument.defaultView,
12651					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
12652					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
12653				if (val) {
12654					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
12655	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
12656	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
12657	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
12658				} else {
12659					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
12660				}
12661				if (old) {
12662					$elm.hide().css(old);
12663				}
12664				return val;
12665			},
12666			getWidth: function($elm) {
12667				return this.getOffset($elm);
12668			},
12669			getStartZIndex: function() {
12670				var zIndex = parseInt(this.$root.css('z-index'));
12671				return !isNaN(zIndex) ? zIndex : 1;
12672			},
12673			handleEvents: function() {
12674				return !this.disabled && this.isCSSOn();
12675			},
12676			handleItemEvents: function($a) {
12677				return this.handleEvents() && !this.isLinkInMegaMenu($a);
12678			},
12679			isCollapsible: function() {
12680				return this.$firstSub.css('position') == 'static';
12681			},
12682			isCSSOn: function() {
12683				return this.$firstLink.css('display') == 'block' || this.$firstLink.css('display') == 'flex' || this.$firstLink.css('display') == 'inline-flex' || this.$firstLink.css('display') == 'table-cell' || this.$firstLink.css('display') == 'inline';
12684			},
12685			isFixed: function() {
12686				return this.$root.css('position') == 'fixed';
12687			},
12688			isLinkInMegaMenu: function($a) {
12689				return !$a.parent().parent().dataSM('level');
12690			},
12691			isTouchMode: function() {
12692				return !mouse || this.isCollapsible();
12693			},
12694			itemActivate: function($a) {
12695				var $li = $a.parent(),
12696					$ul = $li.parent(),
12697					level = $ul.dataSM('level');
12698				// if for some reason the parent item is not activated (e.g. this is an API call to activate the item), activate all parent items first
12699				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
12700					var self = this;
12701					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
12702						self.itemActivate($(this).dataSM('parent-a'));
12703					});
12704				}
12705				// hide any visible deeper level sub menus
12706				if (this.visibleSubMenus.length > level) {
12707					for (var i = this.visibleSubMenus.length - 1, l = !this.activatedItems[level - 1] || this.activatedItems[level - 1][0] != $a[0] ? level - 1 : level; i > l; i--) {
12708						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12709							this.menuHide(this.visibleSubMenus[i]);
12710						//}
12711					}
12712				}
12713				// save new active item and sub menu for this level
12714				this.activatedItems[level - 1] = $a;
12715				this.visibleSubMenus[level - 1] = $ul;
12716				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
12717					return;
12718				}
12719				// show the sub menu if this item has one
12720				var $sub = $li.dataSM('sub');
12721				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
12722					this.menuShow($sub);
12723				}
12724			},
12725			itemBlur: function(e) {
12726				var $a = $(e.currentTarget);
12727				if (!this.handleItemEvents($a)) {
12728					return;
12729				}
12730				this.$root.triggerHandler('blur.smapi', $a[0]);
12731			},
12732			itemClick: function(e) {
12733				var $a = $(e.currentTarget);
12734
12735				if (!this.handleItemEvents($a)) {
12736					return;
12737				}
12738				$a.removeDataSM('mousedown');
12739				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
12740					return false;
12741				}
12742				var $sub = $a.parent().dataSM('sub');
12743				if (this.isTouchMode()) {
12744					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
12745					if ($a.dataSM('href')) {
12746						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
12747					}
12748					// if the sub is not visible
12749					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12750						// try to activate the item and show the sub
12751						this.itemActivate($a);
12752						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
12753						// if it couldn't show it, then the sub menus are disabled with an !important declaration (e.g. via mobile styles) so let the link get loaded
12754						if ($sub.is(':visible')) {
12755							return false;
12756						}
12757					}
12758				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
12759					this.clickActivated = true;
12760					this.menuShow($sub);
12761					return false;
12762				}
12763				if ($a.hasClass('disabled')) {
12764					return false;
12765				}
12766				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
12767					return false;
12768				}
12769			},
12770			itemDown: function(e) {
12771				var $a = $(e.currentTarget);
12772				if (!this.handleItemEvents($a)) {
12773					return;
12774				}
12775				$a.dataSM('mousedown', true);
12776			},
12777			itemEnter: function(e) {
12778				var $a = $(e.currentTarget);
12779				if (!this.handleItemEvents($a)) {
12780					return;
12781				}
12782				if (!this.isTouchMode()) {
12783					if (this.showTimeout) {
12784						clearTimeout(this.showTimeout);
12785						this.showTimeout = 0;
12786					}
12787					var self = this;
12788					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
12789				}
12790				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
12791			},
12792			itemFocus: function(e) {
12793				var $a = $(e.currentTarget);
12794				if (!this.handleItemEvents($a)) {
12795					return;
12796				}
12797				// fix (the mousedown check): in some browsers a tap/click produces consecutive focus + click events so we don't need to activate the item on focus
12798				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
12799					this.itemActivate($a);
12800				}
12801				this.$root.triggerHandler('focus.smapi', $a[0]);
12802			},
12803			itemLeave: function(e) {
12804				var $a = $(e.currentTarget);
12805				if (!this.handleItemEvents($a)) {
12806					return;
12807				}
12808				if (!this.isTouchMode()) {
12809					if ($a[0].blur) {
12810						$a[0].blur();
12811					}
12812					if (this.showTimeout) {
12813						clearTimeout(this.showTimeout);
12814						this.showTimeout = 0;
12815					}
12816				}
12817				$a.removeDataSM('mousedown');
12818				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
12819			},
12820			itemTouchEnd: function(e) {
12821				var $a = $(e.currentTarget);
12822				if (!this.handleItemEvents($a)) {
12823					return;
12824				}
12825				// prevent the address bar on iPhone from sliding down when expanding a sub menu
12826				var $sub = $a.parent().dataSM('sub');
12827				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12828					$a.dataSM('href', $a.attr('href'));
12829					$a.attr('href', '#');
12830				}
12831			},
12832			menuFixLayout: function($ul) {
12833				// fixes a menu that is being shown for the first time
12834				if (!$ul.dataSM('shown-before')) {
12835					$ul.hide().dataSM('shown-before', true);
12836					// fix the layout of the items in IE<8
12837					if (IElt8) {
12838						$ul.children().css({ styleFloat: 'left', width: '100%' });
12839					}
12840				}
12841			},
12842			menuHide: function($sub) {
12843				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
12844					return;
12845				}
12846				$sub.stop(true, true);
12847				if ($sub.is(':visible')) {
12848					var complete = function() {
12849						// unset z-index
12850						if (IElt9) {
12851							$sub.parent().css('z-index', '');
12852						} else {
12853							$sub.css('z-index', '');
12854						}
12855					};
12856					// if sub is collapsible (mobile view)
12857					if (this.isCollapsible()) {
12858						if (this.opts.collapsibleHideFunction) {
12859							this.opts.collapsibleHideFunction.call(this, $sub, complete);
12860						} else {
12861							$sub.hide(this.opts.collapsibleHideDuration, complete);
12862						}
12863					} else {
12864						if (this.opts.hideFunction) {
12865							this.opts.hideFunction.call(this, $sub, complete);
12866						} else {
12867							$sub.hide(this.opts.hideDuration, complete);
12868						}
12869					}
12870					// remove IE iframe shim
12871					if ($sub.dataSM('ie-shim')) {
12872						$sub.dataSM('ie-shim').remove();
12873					}
12874					// deactivate scrolling if it is activated for this sub
12875					if ($sub.dataSM('scroll')) {
12876						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
12877					}
12878					// unhighlight parent item
12879					$sub.dataSM('parent-a').removeClass('highlighted');
12880					var level = $sub.dataSM('level');
12881					this.activatedItems.splice(level - 1, 1);
12882					this.visibleSubMenus.splice(level - 1, 1);
12883					this.$root.triggerHandler('hide.smapi', $sub[0]);
12884				}
12885			},
12886			menuHideAll: function($item) {
12887				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
12888				var $win = $(window),
12889					winW = $win.width();
12890				if (this.showTimeout) {
12891					clearTimeout(this.showTimeout);
12892					this.showTimeout = 0;
12893				}
12894				// hide all subs
12895				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
12896					if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) {
12897						if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) {
12898							this.menuHide(this.visibleSubMenus[i]);
12899							$(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item');
12900						} else {
12901							return;
12902						}
12903					} else {
12904						this.menuHide(this.visibleSubMenus[i]);
12905					}
12906				}
12907				// hide root if it's popup
12908				if (this.opts.isPopup) {
12909					this.$root.stop(true, true);
12910					if (this.$root.is(':visible')) {
12911						if (this.opts.hideFunction) {
12912							this.opts.hideFunction.call(this, this.$root);
12913						} else {
12914							this.$root.hide(this.opts.hideDuration);
12915						}
12916						// remove IE iframe shim
12917						if (this.$root.dataSM('ie-shim')) {
12918							this.$root.dataSM('ie-shim').remove();
12919						}
12920					}
12921				}
12922				this.activatedItems = [];
12923				this.visibleSubMenus = [];
12924				this.clickActivated = false;
12925				// reset z-index increment
12926				this.zIndexInc = 0;
12927			},
12928			menuIframeShim: function($ul) {
12929				// create iframe shim for the menu
12930				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
12931					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
12932						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
12933					);
12934				}
12935			},
12936			menuInit: function($ul) {
12937				if (!$ul.dataSM('in-mega')) {
12938					this.subMenus.push($ul);
12939					// mark UL's in mega drop downs (if any) so we can neglect them
12940					if ($ul.hasClass('mega-menu')) {
12941						$ul.find('ul').dataSM('in-mega', true);
12942					}
12943					// get level (much faster than, for example, using parentsUntil)
12944					var level = 2,
12945						par = $ul[0];
12946					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
12947						level++;
12948					}
12949					// cache stuff
12950					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
12951						.dataSM('level', level)
12952						.parent().dataSM('sub', $ul);
12953					// add sub indicator to parent item
12954					if (this.opts.subIndicators) {
12955						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
12956					}
12957				}
12958			},
12959			menuPosition: function($sub) {
12960				var fixIE = $('html.ie').length;
12961				// if (fixIE) {
12962				// 	var $rowParent = $($sub).closest('.main-menu-container');
12963				// 	$rowParent.height($rowParent.height());
12964				// }
12965				var $a = $sub.dataSM('parent-a'),
12966					$li = $sub.parent(),
12967					$ul = $sub.parent().parent(),
12968					// $container = $ul.closest('.row-menu-inner').length ? ( $('body').hasClass('megamenu-side-to-side') ? ( $('body').hasClass('boxed-width') ? $ul.closest('.row-menu') : $(window) ) : $ul.closest('.row-menu-inner') ) : $ul.closest('.uncol'),
12969					$container = $ul.closest('.row-menu-inner').length ? ( $('body').hasClass('megamenu-side-to-side') ? $ul.closest('.row-menu') : $ul.closest('.row-menu-inner') ) : $ul.closest('.uncol'),
12970					level = $sub.dataSM('level'),
12971					subW = this.getWidth($sub),
12972					subH = this.getHeight($sub),
12973					itemOffset = $a.offset(),
12974					itemX = itemOffset.left,
12975					itemY = itemOffset.top,
12976					itemW = this.getWidth($a),
12977					itemH = this.getHeight($a),
12978					$win = $(window),
12979					winX = $win.scrollLeft(),
12980					winY = $win.scrollTop(),
12981					winW = $win.width(),
12982					winH = $win.height(),
12983					containerW = $container.width(),
12984					containerOffsetX = containerW + ((winW - containerW) / 2),
12985					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
12986					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
12987					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
12988					x, y, leftPos;
12989
12990				if (horizontalParent) {
12991					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
12992					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
12993				} else {
12994					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
12995					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
12996				}
12997				if (this.opts.keepInViewport && !this.isCollapsible()) {
12998					if (this.isFixed()) {
12999						itemX -= winX;
13000						itemY -= winY;
13001						winX = winY = 0;
13002					}
13003					var absX = itemX + x,
13004						absY = itemY + y;
13005					if (this.opts.rightToLeftSubMenus && absX < winX) {
13006						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
13007					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
13008						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
13009					}
13010					if (!horizontalParent) {
13011						if (subH < winH && absY + subH > winY + winH) {
13012							y += winY + winH - subH - absY;
13013						} else if (subH >= winH || absY < winY) {
13014							y += winY - absY;
13015						}
13016					}
13017					// do we need scrolling?
13018					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
13019					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
13020						var self = this;
13021						if (!$sub.dataSM('scroll-arrows')) {
13022							$sub.dataSM('scroll-arrows', $([$('<span class="scroll-up"><span class="scroll-up-arrow"></span></span>')[0], $('<span class="scroll-down"><span class="scroll-down-arrow"></span></span>')[0]])
13023								.bind({
13024									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
13025									mouseleave: function(e) {
13026										self.menuScrollStop($sub);
13027										self.menuScrollOut($sub, e);
13028									},
13029									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
13030								})
13031								.insertAfter($sub)
13032							);
13033						}
13034						// bind events to show/hide arrows on hover and save scrolling data for this sub
13035						var vportY = winY - (itemY + itemH);
13036						$sub.dataSM('scroll', {
13037								vportY: vportY,
13038								subH: subH,
13039								winH: winH,
13040								step: 1
13041							})
13042							.bind({
13043								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
13044								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
13045								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
13046							})
13047							.dataSM('scroll-arrows').css({ top: 'auto', left: '0', marginLeft: x + (parseInt($sub.css('border-left-width')) || 0), width: this.getWidth($sub) - (parseInt($sub.css('border-left-width')) || 0) - (parseInt($sub.css('border-right-width')) || 0), zIndex: this.get
13047StartZIndex() + this.zIndexInc })
13048							.eq(0).css('margin-top', vportY).end()
13049							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
13050							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
13051					}
13052				}
13053				if ( !$sub.closest('.menu-accordion').length ) {
13054					var rightPos = 'auto';
13055					if ( $sub.closest('.grid-filters').length ) {
13056						if ( $sub.closest('.text-right').length ) {
13057							leftPos = '0px';
13058							rightPos = 'auto';
13059						} else {
13060							leftPos = 'auto';
13061							rightPos = '0px';
13062						}
13063						x = 0;
13064					} else {
13065						if ( $sub.hasClass('mega-menu-inner') ) {
13066							$sub.css({ width: containerW});
13067							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
13068							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
13069								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
13070							}
13071							x = 0;
13072						} else {
13073							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
13074							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
13075						}
13076					}
13077				}
13078
13079				// $sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-borders').length ? 1 : 0) });
13080				$sub.css({ top: (level > 2) ? $a[0].offsetTop : (fixIE ? itemH : '100%'), left: leftPos, right: rightPos, marginLeft: x, marginTop: (level > 2) ? 0 : y - itemH + ($sub.closest('.menu-borders').length && !$sub.closest('.menu-borders.needs-after').length ? 1 : 0) });
13081				// IE iframe shim
13082				this.menuIframeShim($sub);
13083				if ($sub.dataSM('ie-shim')) {
13084					$sub.dataSM('ie-shim').css({ zIndex: $sub.css('z-index'), width: subW, height: subH, marginLeft: x, marginTop: y - itemH + ($sub.closest('.menu-mini').length ? 0 : 1) });
13085				}
13086			},
13087			menuScroll: function($sub, up, wheel) {
13088				var y = parseFloat($sub.css('margin-top')),
13089					scroll = $sub.dataSM('scroll'),
13090					end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH),
13091					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
13092				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
13093				y = parseFloat($sub.css('margin-top'));
13094				// show opposite arrow if appropriate
13095				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
13096					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
13097				}
13098				// accelerate when not using mousewheel to scroll
13099				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
13100					$sub.dataSM('scroll').step += 0.5;
13101				}
13102				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
13103				if (Math.abs(y - end) < 1) {
13104					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
13105					$sub.dataSM('scroll').step = 1;
13106				} else if (!wheel) {
13107					var self = this;
13108					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
13109				}
13110			},
13111			menuScrollMousewheel: function($sub, e) {
13112				var $closestSub = $(e.target).closest('ul');
13113				while ($closestSub.dataSM('in-mega')) {
13114					$closestSub = $closestSub.parent().closest('ul');
13115				}
13116				if ($closestSub[0] == $sub[0]) {
13117					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
13118					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
13119						this.menuScroll($sub, up, true);
13120					}
13121				}
13122				e.preventDefault();
13123			},
13124			menuScrollOut: function($sub, e) {
13125				var reClass = /^scroll-(up|down)/,
13126					$closestSub = $(e.relatedTarget).closest('ul');
13127				while ($closestSub.dataSM('in-mega')) {
13128					$closestSub = $closestSub.parent().closest('ul');
13129				}
13130				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
13131					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
13132				}
13133			},
13134			menuScrollOver: function($sub, e) {
13135				var reClass = /^scroll-(up|down)/,
13136					$closestSub = $(e.target).closest('ul');
13137				while ($closestSub.dataSM('in-mega')) {
13138					$closestSub = $closestSub.parent().closest('ul');
13139				}
13140				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
13141					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
13142				}
13143			},
13144			menuScrollStop: function($sub) {
13145				if (this.scrollTimeout) {
13146					clearTimeout(this.scrollTimeout);
13147					this.scrollTimeout = 0;
13148					$sub.dataSM('scroll').step = 1;
13149				}
13150			},
13151			menuShow: function($sub) {
13152				if (!$sub.dataSM('beforefirstshowfired')) {
13153					$sub.dataSM('beforefirstshowfired', true);
13154					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
13155						return;
13156					}
13157				}
13158				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
13159					return;
13160				}
13161				this.menuFixLayout($sub);
13162				$sub.stop(true, true);
13163				if (!$sub.is(':visible')) {
13164					$sub.css({
13165						'visibility': 'visible',
13166						'pointer-events': 'auto',
13167					});
13168					// set z-index - for IE < 9 set it to the parent LI
13169					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
13170					if (IElt9) {
13171						$sub.parent().css('z-index', zIndex);
13172					} else {
13173						$sub.css('z-index', zIndex);
13174					}
13175					// highlight parent item
13176					if (this.opts.keepHighlighted || this.isCollapsible()) {
13177						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
13178							$sub.dataSM('parent-a').addClass('highlighted');
13179					}
13180					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
13181					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
13182						if (!IElt8) {
13183							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13184							if (this.opts.subMenusMinWidth) {
13185							 	$sub.css('min-width', this.opts.subMenusMinWidth);
13186							}
13187							if (this.opts.subMenusMaxWidth) {
13188							 	var noMaxWidth = this.getWidth($sub);
13189							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13190								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13191							 	}
13192								if (noMaxWidth > this.getWidth($sub)) {
13193									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13194								}
13195							}
13196						// IE6,7
13197 						} else {
13198							$sub.children().css('styleFloat', 'none');
13199							if (IE6) {
13200								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
13201									.children().children('a').css('white-space', 'nowrap');
13202							} else { // IE7
13203								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13204								if (this.opts.subMenusMinWidth) {
13205									$sub.css('min-width', this.opts.subMenusMinWidth);
13206								}
13207							}
13208							if (this.opts.subMenusMaxWidth) {
13209								var noMaxWidth = $sub.width();
13210								if (IE6) {
13211							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
13212									if (noMaxWidth > maxWidth) {
13213										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
13214									} else {
13215										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
13216									}
13217								} else { // IE7
13218								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13219									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13220								 	}
13221									if (noMaxWidth > $sub.width()) {
13222										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13223									} else {
13224										$sub.width(noMaxWidth);
13225									}
13226								}
13227							} else {
13228							 	$sub.width($sub.width());
13229							}
13230							$sub.children().css('styleFloat', 'left');
13231						}
13232					}
13233					this.menuPosition($sub);
13234					// insert IE iframe shim
13235					if ($sub.dataSM('ie-shim')) {
13236						$sub.dataSM('ie-shim').insertBefore($sub);
13237					}
13238					var complete = function() {
13239						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
13240						$sub.css('overflow', '');
13241					};
13242					// if sub is collapsible (mobile view)
13243					if (this.isCollapsible()) {
13244						if (this.opts.collapsibleShowFunction) {
13245							this.opts.collapsibleShowFunction.call(this, $sub, complete);
13246						} else {
13247							$sub.show(this.opts.collapsibleShowDuration, complete);
13248						}
13249					} else {
13250						if (this.opts.showFunction) {
13251							this.opts.showFunction.call(this, $sub, complete);
13252						} else {
13253							$sub.show(this.opts.showDuration, complete);
13254						}
13255					}
13256					// save new sub menu for this level
13257					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
13258					this.$root.triggerHandler('show.smapi', $sub[0]);
13259				}
13260			},
13261			popupHide: function(noHideTimeout) {
13262				if (this.hideTimeout) {
13263					clearTimeout(this.hideTimeout);
13264					this.hideTimeout = 0;
13265				}
13266				var self = this;
13267				this.hideTimeout = setTimeout(function() {
13268					self.menuHideAll();
13269				}, noHideTimeout ? 1 : this.opts.hideTimeout);
13270			},
13271			popupShow: function(left, top) {
13272				if (!this.opts.isPopup) {
13273					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
13274					return;
13275				}
13276				if (this.hideTimeout) {
13277					clearTimeout(this.hideTimeout);
13278					this.hideTimeout = 0;
13279				}
13280				this.menuFixLayout(this.$root);
13281				this.$root.stop(true, true);
13282				if (!this.$root.is(':visible')) {
13283					this.$root.css({ left: left, top: top });
13284					// IE iframe shim
13285					this.menuIframeShim(this.$root);
13286					if (this.$root.dataSM('ie-shim')) {
13287						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
13287: left, top: top }).insertBefore(this.$root);
13288					}
13289					// show menu
13290					if (this.opts.showFunction) {
13291						this.opts.showFunction.call(this, this.$root);
13292					} else {
13293						this.$root.show(this.opts.showDuration);
13294					}
13295					this.visibleSubMenus[0] = this.$root;
13296				}
13297			},
13298			refresh: function() {
13299				this.menuHideAll();
13300				this.$root.find('ul').each(function() {
13301						var $this = $(this);
13302						if ($this.dataSM('scroll-arrows')) {
13303							$this.dataSM('scroll-arrows').remove();
13304						}
13305					})
13306					.removeDataSM('in-mega')
13307					.removeDataSM('shown-before')
13308					.removeDataSM('ie-shim')
13309					.removeDataSM('scroll-arrows')
13310					.removeDataSM('parent-a')
13311					.removeDataSM('level')
13312					.removeDataSM('beforefirstshowfired');
13313				this.$root.find('a.has-submenu').removeClass('has-submenu')
13314					.parent().removeDataSM('sub');
13315				if (this.opts.subIndicators) {
13316					this.$root.find('span.sub-arrow').remove();
13317				}
13318				if (this.opts.markCurrentItem) {
13319					this.$root.find('a.current').removeClass('current');
13320				}
13321				this.subMenus = [];
13322				this.init(true);
13323			},
13324			rootOut: function(e) {
13325				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13326					return;
13327				}
13328				if (this.hideTimeout) {
13329					clearTimeout(this.hideTimeout);
13330					this.hideTimeout = 0;
13331				}
13332				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
13333					var self = this;
13334					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
13335				}
13336			},
13337			rootOver: function(e) {
13338				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13339					return;
13340				}
13341				if (this.hideTimeout) {
13342					clearTimeout(this.hideTimeout);
13343					this.hideTimeout = 0;
13344				}
13345			},
13346			winResize: function(e) {
13347				if (!this.handleEvents()) {
13348					// we still need to resize the disable overlay if it's visible
13349					if (this.$disableOverlay) {
13350						var pos = this.$root.offset();
13351	 					this.$disableOverlay.css({
13352							top: pos.top,
13353							left: pos.left,
13354							width: this.$root.outerWidth(),
13355							height: this.$root.outerHeight()
13356						});
13357					}
13358					return;
13359				}
13360				// hide sub menus on resize - on mobile do it only on orientation change
13361				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
13362					if (this.activatedItems.length) {
13363						this.activatedItems[this.activatedItems.length - 1][0].blur();
13364					}
13365					this.menuHideAll();
13366				}
13367			}
13368		}
13369	});
13370
13371	$.fn.dataSM = function(key, val) {
13372		if (val) {
13373			return this.data(key + '_smartmenus', val);
13374		}
13375		return this.data(key + '_smartmenus');
13376	}
13377
13378	$.fn.removeDataSM = function(key) {
13379		return this.removeData(key + '_smartmenus');
13380	}
13381
13382	$.fn.smartmenus = function(options) {
13383		if (typeof options == 'string') {
13384			var args = arguments,
13385				method = options;
13386			Array.prototype.shift.call(args);
13387			return this.each(function() {
13388				var smartmenus = $(this).data('smartmenus');
13389				if (smartmenus && smartmenus[method]) {
13390					smartmenus[method].apply(smartmenus, args);
13391				}
13392			});
13393		}
13394		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
13395		return this.each(function() {
13396			new $.SmartMenus(this, opts);
13397		});
13398	}
13399
13400	// default settings
13401	$.fn.smartmenus.defaults = {
13402		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
13403		mainMenuSubOffsetX:	0,		// pixels offset from default position
13404		mainMenuSubOffsetY:	0,		// pixels offset from default position
13405		subMenusSubOffsetX:	0,		// pixels offset from default position
13406		subMenusSubOffsetY:	0,		// pixels offset from default position
13407		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13408		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13409		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
13410		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
13411		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
13412		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
13413		scrollInterval:		30,		// interval between each scrolling step
13414		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
13415		showTimeout:		250,		// timeout before showing the sub menus
13416		hideTimeout:		500,		// timeout before hiding the sub menus
13417		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
13418		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
13419							// don't forget to call complete() at the end of whatever you do
13420							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
13421		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
13422		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
13423							// don't forget to call complete() at the end of whatever you do
13424							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
13425		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
13426		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
13427							// (i.e. when mobile styles are used to make the sub menus collapsible)
13428		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
13429		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
13430							// (i.e. when mobile styles are used to make the sub menus collapsible)
13431		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
13432		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
13433		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
13434		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
13435		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
13436		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
13437		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
13438		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
13439		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
13440	};
13441
13442})(jQuery);
13443/*
13444 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
13445 * Open source under the BSD License.
13446 * Copyright © 2008 George McGinley Smith
13447 * All rights reserved.
13448 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
13449*/
13450
13451/* globals jQuery, define, module, require */
13452(function (factory) {
13453	if (typeof define === "function" && define.amd) {
13454		define(['jquery'], function ($) {
13455			return factory($);
13456		});
13457	} else if (typeof module === "object" && typeof module.exports === "object") {
13458		module.exports = factory(require('jquery'));
13459	} else {
13460		factory(jQuery);
13461	}
13462})(function($){
13463
13464	// Preserve the original jQuery "swing" easing as "jswing"
13465	if (typeof $.easing !== 'undefined') {
13466		$.easing['jswing'] = $.easing['swing'];
13467	}
13468
13469	var pow = Math.pow,
13470		sqrt = Math.sqrt,
13471		sin = Math.sin,
13472		cos = Math.cos,
13473		PI = Math.PI,
13474		c1 = 1.70158,
13475		c2 = c1 * 1.525,
13476		c3 = c1 + 1,
13477		c4 = ( 2 * PI ) / 3,
13478		c5 = ( 2 * PI ) / 4.5;
13479
13480	// x is the fraction of animation progress, in the range 0..1
13481	function bounceOut(x) {
13482		var n1 = 7.5625,
13483			d1 = 2.75;
13484		if ( x < 1/d1 ) {
13485			return n1*x*x;
13486		} else if ( x < 2/d1 ) {
13487			return n1*(x-=(1.5/d1))*x + .75;
13488		} else if ( x < 2.5/d1 ) {
13489			return n1*(x-=(2.25/d1))*x + .9375;
13490		} else {
13491			return n1*(x-=(2.625/d1))*x + .984375;
13492		}
13493	}
13494
13495	$.extend( $.easing, {
13496		def: 'easeOutQuad',
13497		swing: function (x) {
13498			return $.easing[$.easing.def](x);
13499		},
13500		easeInQuad: function (x) {
13501			return x * x;
13502		},
13503		easeOutQuad: function (x) {
13504			return 1 - ( 1 - x ) * ( 1 - x );
13505		},
13506		easeInOutQuad: function (x) {
13507			return x < 0.5 ?
13508				2 * x * x :
13509				1 - pow( -2 * x + 2, 2 ) / 2;
13510		},
13511		easeInCubic: function (x) {
13512			return x * x * x;
13513		},
13514		easeOutCubic: function (x) {
13515			return 1 - pow( 1 - x, 3 );
13516		},
13517		easeInOutCubic: function (x) {
13518			return x < 0.5 ?
13519				4 * x * x * x :
13520				1 - pow( -2 * x + 2, 3 ) / 2;
13521		},
13522		easeInQuart: function (x) {
13523			return x * x * x * x;
13524		},
13525		easeOutQuart: function (x) {
13526			return 1 - pow( 1 - x, 4 );
13527		},
13528		easeInOutQuart: function (x) {
13529			return x < 0.5 ?
13530				8 * x * x * x * x :
13531				1 - pow( -2 * x + 2, 4 ) / 2;
13532		},
13533		easeInQuint: function (x) {
13534			return x * x * x * x * x;
13535		},
13536		easeOutQuint: function (x) {
13537			return 1 - pow( 1 - x, 5 );
13538		},
13539		easeInOutQuint: function (x) {
13540			return x < 0.5 ?
13541				16 * x * x * x * x * x :
13542				1 - pow( -2 * x + 2, 5 ) / 2;
13543		},
13544		easeInSine: function (x) {
13545			return 1 - cos( x * PI/2 );
13546		},
13547		easeOutSine: function (x) {
13548			return sin( x * PI/2 );
13549		},
13550		easeInOutSine: function (x) {
13551			return -( cos( PI * x ) - 1 ) / 2;
13552		},
13553		easeInExpo: function (x) {
13554			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
13555		},
13556		easeOutExpo: function (x) {
13557			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
13558		},
13559		easeInOutExpo: function (x) {
13560			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13561				pow( 2, 20 * x - 10 ) / 2 :
13562				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
13563		},
13564		easeInCirc: function (x) {
13565			return 1 - sqrt( 1 - pow( x, 2 ) );
13566		},
13567		easeOutCirc: function (x) {
13568			return sqrt( 1 - pow( x - 1, 2 ) );
13569		},
13570		easeInOutCirc: function (x) {
13571			return x < 0.5 ?
13572				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
13573				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
13574		},
13575		easeInElastic: function (x) {
13576			return x === 0 ? 0 : x === 1 ? 1 :
13577				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
13578		},
13579		easeOutElastic: function (x) {
13580			return x === 0 ? 0 : x === 1 ? 1 :
13581				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
13582		},
13583		easeInOutElastic: function (x) {
13584			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13585				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
13586				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
13587		},
13588		easeInBack: function (x) {
13589			return c3 * x * x * x - c1 * x * x;
13590		},
13591		easeOutBack: function (x) {
13592			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
13593		},
13594		easeInOutBack: function (x) {
13595			return x < 0.5 ?
13596				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
13597				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
13598		},
13599		easeInBounce: function (x) {
13600			return 1 - bounceOut( 1 - x );
13601		},
13602		easeOutBounce: bounceOut,
13603		easeInOutBounce: function (x) {
13604			return x < 0.5 ?
13605				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
13606				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
13607		}
13608	});
13609	return $;
13610});
13611
13612/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
13613 * Licensed under the MIT License (LICENSE.txt).
13614 *
13615 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
13616 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
13617 * Thanks to: Seamus Leahy for adding deltaX and deltaY
13618 *
13619 * Version: 3.0.6
13620 *
13621 * Requires: 1.2.2+
13622 */
13623(function($) {
13624    var types = ['DOMMouseScroll', 'mousewheel'];
13625    if ($.event.fixHooks) {
13626        for (var i = types.length; i;) {
13627            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
13628        }
13629    }
13630    $.event.special.mousewheel = {
13631        setup: function() {
13632            if (this.addEventListener) {
13633                for (var i = types.length; i;) {
13634                    this.addEventListener(types[--i], handler, false);
13635                }
13636            } else {
13637                this.onmousewheel = handler;
13638            }
13639        },
13640        teardown: function() {
13641            if (this.removeEventListener) {
13642                for (var i = types.length; i;) {
13643                    this.removeEventListener(types[--i], handler, false);
13644                }
13645            } else {
13646                this.onmousewheel = null;
13647            }
13648        }
13649    };
13650    $.fn.extend({
13651        mousewheel: function(fn) {
13652            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
13653        },
13654        unmousewheel: function(fn) {
13655            return this.unbind("mousewheel", fn);
13656        }
13657    });
13658
13659    function handler(event) {
13660        var orgEvent = event || window.event,
13661            args = [].slice.call(arguments, 1),
13662            delta = 0,
13663            returnValue = true,
13664            deltaX = 0,
13665            deltaY = 0;
13666        event = $.event.fix(orgEvent);
13667        event.type = "mousewheel";
13668        // Old school scrollwheel delta
13669        if (orgEvent.wheelDelta) {
13670            delta = orgEvent.wheelDelta / 120;
13671        }
13672        if (orgEvent.detail) {
13673            delta = -orgEvent.detail / 3;
13674        }
13675        // New school multidimensional scroll (touchpads) deltas
13676        deltaY = delta;
13677        // Gecko
13678        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
13679            deltaY = 0;
13680            deltaX = -1 * delta;
13681        }
13682        // Webkit
13683        if (orgEvent.wheelDeltaY !== undefined) {
13684            deltaY = orgEvent.wheelDeltaY / 120;
13685        }
13686        if (orgEvent.wheelDeltaX !== undefined) {
13687            deltaX = -1 * orgEvent.wheelDeltaX / 120;
13688        }
13689        // Add event and delta to the front of the arguments
13690        args.unshift(event, delta, deltaX, deltaY);
13691        return ($.event.dispatch || $.event.handle).apply(this, args);
13692    }
13693})(jQuery);
13694/**
13695 * jQuery iLightBox - Revolutionary Lightbox Plugin
13696 * http://www.ilightbox.net/
13697 *
13698 * @version: 2.2.4 - October 14, 2017
13699 *
13700 * @author: iProDev (Hemn Chawroka)
13701 *          http://www.iprodev.com/
13702 *
13703 */
13704(function($, window, undefined) {
13705
13706	var extensions = {
13707			flash: ['swf'],
13708			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
13709			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
13710			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
13711		},
13712
13713		// Global DOM elements
13714		$win = $(window),
13715		$doc = $(document),
13716
13717		// Support indicators
13718		browser,
13719		transform,
13720		gpuAcceleration,
13721		fullScreenApi = '',
13722		userAgent = navigator.userAgent || navigator.vendor || window.opera,
13723        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
13724        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
13725        isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4)),
13726
13727		// Events
13728		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
13729		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
13730		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
13731		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
13732
13733		// Math shorthands
13734		abs = Math.abs,
13735		sqrt = Math.sqrt,
13736		round = Math.round,
13737		max = Math.max,
13738		min = Math.min,
13739		floor = Math.floor,
13740		random = Math.random,
13741
13742		pluginspages = {
13743			quicktime: 'http://www.apple.com/quicktime/download',
13744			flash: 'http://www.adobe.com/go/getflash'
13745		},
13746
13747		iLightBox = function(el, options, items, instant) {
13748			var iL = this;
13749
13750			iL.options = options,
13751				iL.selector = options.selector || el,
13752				iL.context = document,
13753				iL.instant = instant;
13754
13755			if (items.length < 1) iL.attachItems();
13756			else iL.items = items;
13757
13758			iL.vars = {
13759				total: iL.items.length,
13760				start: 0,
13761				current: null,
13762				next: null,
13763				prev: null,
13764				BODY: $('body'),
13765				loadRequests: 0,
13766				overlay: $('<div class="ilightbox-overlay"></div>'),
13767				loader: $('<div class="ilightbox-loader"><div></div></div>'),
13768				toolbar: $('<div class="ilightbox-toolbar"></div>'),
13769				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
13770				title: $('<div class="ilightbox-title"></div>'),
13771				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
13772				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
13773				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
13774				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
13775				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
13776				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13777				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13778				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13779				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
13780				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13781				thumbnails: $('<div class="ilightbox-thumbnails" ondragstart="return false;"><div class="ilightbox-thumbnails-container"><a class="ilightbox-thumbnails-dragger"></a><div class="ilightbox-thumbnails-grid"></div></div></div>'),
13782				thumbs: false,
13783				nextLock: false,
13784				prevLock: false,
13785				hashLock: false,
13786				isMobile: false,
13787				mobileMaxWidth: 980,
13788				isInFullScreen: false,
13789				isSwipe: false,
13790				mouseID: 0,
13791				cycleID: 0,
13792				isPaused: 0,
13793				captionHeight: 39,
13794			};
13795
13796			// Hideable elements with mousemove event
13797			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
13798
13799			iL.normalizeItems();
13800
13801			//Check necessary plugins
13802			iL.availPlugins();
13803
13804			//Set startFrom
13805			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
13806
13807			//If randomStart
13808			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
13809			iL.vars.start = iL.options.startFrom;
13810
13811			if (instant) iL.instantCall();
13812			else iL.patchItemsEvents();
13813
13814			if (iL.options.linkId) {
13815				iL.hashChangeHandler();
13816				$win.iLightBoxHashChange(function() {
13817					iL.hashChangeHandler();
13818				});
13819			}
13820
13821			if (supportTouch) {
13822				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
13823					replace = "itap";
13824				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
13825					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
13826					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
13827					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
13828			}
13829
13830			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
13831				$.extend(iL.options.styles, {
13832					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13833					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13834					nextOpacity: 0,
13835					prevOpacity: 0
13836				});
13837			}
13838		};
13839
13840	//iLightBox helpers
13841	iLightBox.prototype = {
13842		showLoader: function() {
13843			var iL = this;
13844			iL.vars.loadRequests += 1;
13845			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
13846				//top: '-30px'
13847				opacity: '1'
13848			}, iL.options.show.speed, 'easeOutCirc');
13849			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
13850				//left: '-30px'
13851				opacity: '1'
13852			}, iL.options.show.speed, 'easeOutCirc');
13853		},
13854
13855		hideLoader: function() {
13856			var iL = this;
13857			iL.vars.loadRequests -= 1;
13858			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
13859			if (iL.options.path.toLowerCase() == "horizontal") {
13860				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13861					//top: '-192px'
13862					opacity: '0'
13863				}, iL.options.show.speed, 'easeInCirc');
13864			} else {
13865				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13866					//left: '-192px'
13867					opacity: '0'
13868				}, iL.options.show.speed, 'easeInCirc');
13869			}
13870		},
13871
13872		createUI: function() {
13873			var iL = this;
13874
13875			iL.ui = {
13876				currentElement: iL.vars.holder,
13877				nextElement: iL.vars.nextPhoto,
13878				prevElement: iL.vars.prevPhoto,
13879				currentItem: iL.vars.current,
13880				nextItem: iL.vars.next,
13881				prevItem: iL.vars.prev,
13882				hide: function() {
13883					iL.closeAction();
13884				},
13885				refresh: function() {
13886					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13887				},
13888				fullscreen: function() {
13889					iL.fullScreenAction();
13890				}
13891			};
13892		},
13893
13894		attachItems: function() {
13895			var iL = this,
13896				itemsObject = new Array(),
13897				items = new Array();
13898
13899			$(iL.selector, iL.context).each(function() {
13900				var t = $(this),
13901					URL = t.attr(iL.options.attr) || null,
13902					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
13903					caption = t.data('caption'),
13904					title = t.data('title'),
13905					type = t.data('type') || getTypeByExtension(URL),
13906					clone = t.data('lbox-clone') || false;
13907
13908				//Uncode addition ##START##
13909				if (type === false) {
13910					return;
13911				}
13912				//Uncode addition ##END##
13913
13914				if (t.data('lbox-clone') != undefined) return;
13915
13916				//Uncode addition ##START##
13917				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
13918					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
13919						URL_i,
13920						URLS_LENGHT = ALBUM_URLS.length;
13921
13922					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
13923						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
13924							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
13925							item_opts = item_opts && eval("({" + item_opts + "})") || {},
13926							items.push({
13927								URL: ALBUM_URLS[URL_i].url,
13928								caption: ALBUM_URLS[URL_i].caption,
13929								title: ALBUM_URLS[URL_i].title,
13930								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
13931								options: item_opts,
13932								clone: clone
13933							});
13934							var newT = t;
13935							newT.attr('href',ALBUM_URLS[URL_i].url);
13936							if (!iL.instant) itemsObject.push(newT);
13937						}
13938					}
13939				} else {
13940				//Uncode addition ##END##
13941					items.push({
13942						URL: URL,
13943						caption: caption,
13944						title: title,
13945						type: type,
13946						options: options,
13947						clone: clone
13948					});
13949				}
13950
13951
13952				if (iL.vars != undefined) iL.vars.total = items.length;
13953
13954				if (!iL.instant) itemsObject.push(t);
13955			});
13956
13957			iL.items = items,
13958				iL.itemsObject = itemsObject;
13959
13960		},
13961
13962		normalizeItems: function() {
13963			var iL = this,
13964				newItems = new Array();
13965
13966			$.each(iL.items, function(key, val) {
13967
13968				if (typeof val == "string") val = {
13969					url: val
13970				};
13971
13972				var URL = val.url || val.URL || null,
13973					options = val.options || {},
13974					caption = val.caption || null,
13975					title = val.title || null,
13976					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
13977					ext = (typeof URL != 'object') ? getExtension(URL) : '';
13978
13979				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
13980				options.videoType = options.videoType || null,
13981				options.skin = options.skin || iL.options.skin,
13982				options.width = options.width || null,
13983				options.height = options.height || null,
13984				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
13985				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
13986				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
13987
13988				if (type == "video") {
13989					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
13990
13991					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
13992					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
13993					options.html5video.preload = options.html5video.preload || "metadata";
13994					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
13995					//UNCODE addition
13996					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
13997				}
13998
13999				if (!options.width || !options.height) {
14000					if (type == "video") options.width = 1280, options.height = 720;
14001					else if (type == "iframe") options.width = '100%', options.height = '90%';
14002					else if (type == "flash") options.width = 1280, options.height = 720;
14003				}
14004
14005				delete val.url;
14006				val.index = key;
14007				val.URL = URL;
14008				val.caption = caption;
14009				val.title = title;
14010				val.type = type;
14011				val.options = options;
14012				val.ext = ext;
14013
14014				newItems.push(val);
14015			});
14016
14017			iL.items = newItems;
14018		},
14019
14020		instantCall: function() {
14021			var iL = this,
14022				key = iL.vars.start;
14023
14024			iL.vars.current = key;
14025			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
14026			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
14027
14028			iL.addContents();
14029			iL.patchEvents();
14030		},
14031
14032		addContents: function() {
14033			var iL = this,
14034				vars = iL.vars,
14035				opts = iL.options,
14036				viewport = getViewport(),
14037				path = opts.path.toLowerCase(),
14038				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
14039					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
14040				}),
14041				needRecognition = recognizingItems.length > 0;
14042
14043			if (opts.mobileOptimizer && !opts.innerToolbar)
14044				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14045
14046			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
14047
14048			if (opts.linkId)
14049				vars.overlay[0].setAttribute('linkid', opts.linkId);
14050
14051			//Add Toolbar Buttons
14052			if (opts.controls.toolbar) {
14053				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
14054				if (opts.controls.fullscreen)
14055					vars.toolbar.append(vars.fullScreenButton);
14056				if (opts.controls.slideshow)
14057					vars.toolbar.append(vars.innerPlayButton);
14058				if (vars.total > 1)
14059					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
14060			}
14061
14062			//Append elements to body
14063			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
14064
14065			if (!opts.innerToolbar)
14066				vars.BODY.append(vars.toolbar);
14067			if (opts.controls.arrows)
14068				vars.BODY.append(vars.nextButton).append(vars.prevButton);
14069
14070			if (opts.controls.thumbnail && vars.total > 1) {
14071				vars.BODY.append(vars.thumbnails);
14072				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
14073				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
14074				vars.thumbs = true;
14075			}
14076
14077			//Configure loader and arrows
14078			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
14079				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
14080			} : {
14081				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
14082			};
14083			vars.loader.addClass(opts.skin).css(loaderCss);
14084			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
14085			if (path == "horizontal")
14086				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
14087
14088			// Configure arrow buttons
14089			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14090
14091			if (!opts.infinite) {
14092				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14093
14094				if (vars.current == 0)
14095					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14096				if (vars.current >= vars.total - 1)
14097					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14098			}
14099
14100			if (opts.show.effect) {
14101				vars.overlay.stop().fadeIn(opts.show.speed);
14102				vars.toolbar.stop().fadeIn(opts.show.speed);
14103			} else {
14104				vars.overlay.show();
14105				vars.toolbar.show();
14106			}
14107
14108			var length = recognizingItems.length;
14109			if (needRecognition) {
14110				iL.showLoader();
14111
14112				$.each(recognizingItems, function(key, val) {
14113					var resultFnc = function(result) {
14114							var key = -1,
14115								filter = iL.items.filter(function(e, i, arr) {
14116									if (e.URL == result.url)
14117										key = i;
14118
14119									return e.URL == result.url;
14120								}),
14121								self = iL.items[key];
14122
14123							if (result)
14124								$.extend(true, self, {
14125									URL: result.source,
14126									type: result.type,
14127									recognized: true,
14128									options: {
14129										html5video: result.html5video,
14130										width: (result.type == "image") ? 0 : (result.width || self.width),
14131										height: (result.type == "image") ? 0 : (result.height || self.height),
14132										thumbnail: self.options.thumbnail || result.thumbnail
14133									}
14134								});
14135
14136							length--;
14137
14138							if (length == 0) {
14139								iL.hideLoader();
14140
14141								vars.dontGenerateThumbs = false;
14142								iL.generateThumbnails();
14143
14144								if (opts.show.effect)
14145									setTimeout(function() {
14146										iL.generateBoxes();
14147									}, opts.show.speed);
14148								else
14149									iL.generateBoxes();
14150							}
14151						};
14152
14153					iL.ogpRecognition(this, resultFnc);
14154				});
14155			}
14156			else {
14157				if (opts.show.effect)
14158					setTimeout(function() {
14159						iL.generateBoxes();
14160					}, opts.show.speed);
14161				else
14162					iL.generateBoxes();
14163			}
14164
14165			iL.createUI();
14166
14167			window.iLightBox = {
14168				close: function() {
14169					iL.closeAction();
14170				},
14171				fullscreen: function() {
14172					iL.fullScreenAction();
14173				},
14174				moveNext: function() {
14175					iL.moveTo('next');
14176				},
14177				movePrev: function() {
14178					iL.moveTo('prev');
14179				},
14180				goTo: function(index) {
14181					iL.goTo(index);
14182				},
14183				refresh: function() {
14184					iL.refresh();
14185				},
14186				reposition: function() {
14187					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
14188				},
14189				setOption: function(options) {
14190					iL.setOption(options);
14191				},
14192				destroy: function() {
14193					iL.closeAction();
14194					iL.dispatchItemsEvents();
14195				}
14196			};
14197
14198			if (opts.linkId) {
14199				vars.hashLock = true;
14200				window.location.hash = opts.linkId + '/' + vars.current;
14201				setTimeout(function() {
14202					vars.hashLock = false;
14203				}, 55);
14204			}
14205
14206			if (!opts.slideshow.startPaused) {
14207				iL.resume();
14208				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
14209			}
14210
14211			//Trigger the onOpen callback
14212			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
14213		},
14214
14215		loadContent: function(obj, opt, speed) {
14216			var iL = this,
14217				holder, item;
14218
14219			iL.createUI();
14220
14221			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
14222
14223			if (opt == 'current') {
14224				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
14225				else iL.vars.lockWheel = false;
14226
14227				if (!obj.options.swipe) iL.vars.lockSwipe = true;
14228				else iL.vars.lockSwipe = false;
14229			}
14230
14231			switch (opt) {
14232				case 'current':
14233					holder = iL.vars.holder, item = iL.vars.current;
14234					break;
14235				case 'next':
14236					holder = iL.vars.nextPhoto, item = iL.vars.next;
14237					break;
14238				case 'prev':
14239					holder = iL.vars.prevPhoto, item = iL.vars.prev;
14240					break;
14241			}
14242
14243			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
14244			$('div.ilightbox-inner-toolbar', holder).remove();
14245
14246			if (obj.title || iL.options.innerToolbar) {
14247				var innerToolbar = iL.vars.innerToolbar.clone();
14248				if (obj.title && iL.options.show.title) {
14249					var title = iL.vars.title.clone();
14250					title.empty().html(obj.title);
14251					innerToolbar.append(title);
14252				}
14253				if (iL.options.innerToolbar) {
14254					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
14255				}
14256				holder.prepend(innerToolbar);
14257			}
14258
14259			//console.warn('loadContent', arguments);
14260
14261			iL.loadSwitcher(obj, holder, item, opt);
14262		},
14263
14264		loadSwitcher: function(obj, holder, item, opt) {
14265			var iL = this,
14266				opts = iL.options,
14267				api = {
14268					element: holder,
14269					position: item
14270				};
14271
14272			switch (obj.type) {
14273				case 'image':
14274					//Trigger the onBeforeLoad callback
14275					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14276					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14277
14278					iL.loadImage(obj.URL, function(img) {
14279						//Trigger the onAfterLoad callback
14280						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14281						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14282
14283						var width = (img) ? img.width : 400,
14284							height = (img) ? img.height : 200;
14285
14286						holder.data({
14287							naturalWidth: width,
14288							naturalHeight: height
14289						});
14290
14291						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
14292
14293						//Trigger the onRender callback
14294						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14295						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14296
14297						iL.configureHolder(obj, opt, holder);
14298					});
14299
14300					break;
14301
14302				case 'video':
14303					holder.data({
14304						naturalWidth: obj.options.width,
14305						naturalHeight: obj.options.height
14306					});
14307
14308					if (opt === 'current') {
14309						iL.addContent(holder, obj);
14310
14311						//Trigger the onRender callback
14312						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14313						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14314					} else {
14315						$('div.ilightbox-container', holder).empty();
14316					}
14317
14318					iL.configureHolder(obj, opt, holder);
14319
14320					break;
14321
14322				case 'iframe':
14323					//iL.showLoader();
14324					holder.data({
14325						naturalWidth: obj.options.width,
14326						naturalHeight: obj.options.height
14327					});
14328
14329					iL.configureHolder(obj, opt, holder);
14330
14331					if (opt === 'current') {
14332						var el = iL.addContent(holder, obj);
14333
14334						//Trigger the onRender callback
14335						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14336						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14337
14338						//Trigger the onBeforeLoad callback
14339						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14340						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14341
14342						el.bind('load', function() {
14343							//Trigger the onAfterLoad callback
14344							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14345							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14346
14347							//iL.hideLoader();
14348							el.unbind('load');
14349						});
14350					} else {
14351						$('div.ilightbox-container', holder).empty();
14352					}
14353
14354					break;
14355
14356				case 'inline':
14357					var el = $(obj.URL),
14358						content = iL.addContent(holder, obj),
14359						images = findImageInElement(holder);
14360
14361					holder.data({
14362						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14363						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14364					});
14365					content.children().eq(0).show();
14366
14367					//Trigger the onRender callback
14368					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14369					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14370
14371					//Trigger the onBeforeLoad callback
14372					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14373					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14374
14375					iL.loadImage(images, function() {
14376						//Trigger the onAfterLoad callback
14377						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14378						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14379
14380						iL.configureHolder(obj, opt, holder);
14381					});
14382
14383					break;
14384
14385				case 'flash':
14386					var el = iL.addContent(holder, obj);
14387
14388					holder.data({
14389						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14390						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14391					});
14392
14393					//Trigger the onRender callback
14394					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14395					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14396
14397					iL.configureHolder(obj, opt, holder);
14398
14399					break;
14400
14401				case 'ajax':
14402					var ajax = obj.options.ajax || {};
14403					//Trigger the onBeforeLoad callback
14404					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14405					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14406
14407					iL.showLoader();
14408					$.ajax({
14409						url: obj.URL || opts.ajaxSetup.url,
14410						data: ajax.data || null,
14411						dataType: ajax.dataType || "html",
14412						type: ajax.type || opts.ajaxSetup.type,
14413						cache: ajax.cache || opts.ajaxSetup.cache,
14414						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
14415						global: ajax.global || opts.ajaxSetup.global,
14416						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
14417						username: ajax.username || opts.ajaxSetup.username,
14418						password: ajax.password || opts.ajaxSetup.password,
14419						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
14420						complete: ajax.complete || opts.ajaxSetup.complete,
14421						success: function(data, textStatus, jqXHR) {
14422							iL.hideLoader();
14423
14424							var el = $(data),
14425								container = $('div.ilightbox-container', holder),
14426								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
14427								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
14428								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
14429									'overflow': 'hidden'
14430								} : {};
14431
14432							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
14433							holder.show().data({
14434								naturalWidth: (elWidth || container.outerWidth()),
14435								naturalHeight: (elHeight || container.outerHeight())
14436							}).hide();
14437
14438							//Trigger the onRender callback
14439							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14440							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14441
14442							var images = findImageInElement(holder);
14443							iL.loadImage(images, function() {
14444								//Trigger the onAfterLoad callback
14445								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14446								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14447
14448								iL.configureHolder(obj, opt, holder);
14449							});
14450
14451							opts.ajaxSetup.success(data, textStatus, jqXHR);
14452							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
14453						},
14454						error: function(jqXHR, textStatus, errorThrown) {
14455							//Trigger the onAfterLoad callback
14456							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14457							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14458
14459							iL.hideLoader();
14460							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
14461							iL.configureHolder(obj, opt, holder);
14462
14463							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
14464							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
14465						}
14466					});
14467
14468					break;
14469
14470				case 'html':
14471					var object = obj.URL,
14472						el
14473					container = $('div.ilightbox-container', holder);
14474
14475					if (object[0].nodeName) el = object.clone();
14476					else {
14477						var dom = $(object);
14478						if (dom.selector) el = $('<div>' + dom + '</div>');
14479						else el = dom;
14480					}
14481
14482					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
14483						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
14484
14485					iL.addContent(holder, obj);
14486
14487					el.appendTo(document.documentElement).hide();
14488
14489					//Trigger the onRender callback
14490					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14491					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14492
14493					var images = findImageInElement(holder);
14494
14495					//Trigger the onBeforeLoad callback
14496					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14497					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14498
14499					iL.loadImage(images, function() {
14500						//Trigger the onAfterLoad callback
14501						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14502						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14503
14504						holder.show().data({
14505							naturalWidth: (elWidth || container.outerWidth()),
14506							naturalHeight: (elHeight || container.outerHeight())
14507						}).hide();
14508						el.remove();
14509
14510						iL.configureHolder(obj, opt, holder);
14511					});
14512
14513					break;
14514			}
14515		},
14516
14517		configureHolder: function(obj, opt, holder) {
14518			var iL = this,
14519				vars = iL.vars,
14520				opts = iL.options;
14521
14522			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
14523
14524			if (opt == "current")
14525				var item = vars.current;
14526			else if (opt == "next")
14527				var opacity = opts.styles.nextOpacity,
14528					item = vars.next;
14529			else
14530				var opacity = opts.styles.prevOpacity,
14531					item = vars.prev;
14532
14533			var api = {
14534				element: holder,
14535				position: item
14536			};
14537
14538			iL.items[item].options.width = iL.items[item].options.width || 0,
14539			iL.items[item].options.height = iL.items[item].options.height || 0;
14540
14541			if (opt == "current") {
14542				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
14543					holder.css(transform, '');
14544					if (obj.caption) {
14545						iL.setCaption(obj, holder);
14546						var caption = $('div.ilightbox-caption', holder),
14547							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
14548						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
14548Speed);
14549					}
14550
14551					var social = obj.options.social;
14552					if (social) {
14553						iL.setSocial(social, obj.URL, holder);
14554						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
14555					}
14556
14557					//Generate thumbnails
14558					iL.generateThumbnails();
14559
14560					//Trigger the onShow callback
14561					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14562					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14563				});
14564				else {
14565					holder.show();
14566
14567					//Generate thumbnails
14568					iL.generateThumbnails();
14569
14570					//Trigger the onShow callback
14571					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14572					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14573				}
14574			} else {
14575				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
14576					if (opt == "next") vars.nextLock = false;
14577					else vars.prevLock = false;
14578
14579					//Generate thumbnails
14580					iL.generateThumbnails();
14581
14582					//Trigger the onShow callback
14583					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14584					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14585				});
14586				else {
14587					holder.css({
14588						opacity: opacity
14589					}).show();
14590					if (opt == "next") vars.nextLock = false;
14591					else vars.prevLock = false;
14592
14593					//Generate thumbnails
14594					iL.generateThumbnails();
14595
14596					//Trigger the onShow callback
14597					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14598					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14599				}
14600			}
14601
14602			setTimeout(function() {
14603				iL.repositionPhoto();
14604			}, 0);
14605		},
14606
14607		generateBoxes: function() {
14608			var iL = this,
14609				vars = iL.vars,
14610				opts = iL.options;
14611
14612			if (opts.infinite && vars.total >= 3) {
14613				if (vars.current == vars.total - 1) vars.next = 0;
14614				if (vars.current == 0) vars.prev = vars.total - 1;
14615			} else opts.infinite = false;
14616
14617			//UNCODE addition
14618			if ( typeof iL.items[vars.current] == 'undefined' )
14619				vars.current = 0;
14620
14621			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
14622
14623			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
14624			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
14625		},
14626
14627		generateThumbnails: function() {
14628			var iL = this,
14629				vars = iL.vars,
14630				opts = iL.options,
14631				timeOut = null;
14632
14633			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
14634				var thumbnails = vars.thumbnails,
14635					container = $('div.ilightbox-thumbnails-container', thumbnails),
14636					grid = $('div.ilightbox-thumbnails-grid', container),
14637					i = 0;
14638
14639				grid.removeAttr('style').empty();
14640
14641				$.each(iL.items, function(key, val) {
14642					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
14643						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
14644						thumb = val.options.thumbnail,
14645						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
14646						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
14647
14648					thumbnail.css({
14649						opacity: 0
14650					}).addClass(isActive);
14651
14652					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
14653						icon.addClass('ilightbox-thumbnail-video');
14654						thumbnail.append(icon);
14655					} else if (val.options.icon) {
14656						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
14657						thumbnail.append(icon);
14658					}
14659
14660					if (thumb) iL.loadImage(thumb, function(img) {
14661						i++;
14662						if (img) thumbnail.data({
14663							naturalWidth: img.width,
14664							naturalHeight: img.height
14665						}).append('<img src="' + thumb + '" border="0" />');
14666						else thumbnail.data({
14667							naturalWidth: opts.thumbnails.maxWidth,
14668							naturalHeight: opts.thumbnails.maxHeight
14669						});
14670
14671						clearTimeout(timeOut);
14672						timeOut = setTimeout(function() {
14673							iL.positionThumbnails(thumbnails, container, grid);
14674						}, 20);
14675						setTimeout(function() {
14676							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
14677						}, i * 20);
14678					});
14679
14680					grid.append(thumbnail);
14681				});
14682				iL.vars.dontGenerateThumbs = true;
14683			}
14684		},
14685
14686		positionThumbnails: function(thumbnails, container, grid) {
14687			var iL = this,
14688				vars = iL.vars,
14689				opts = iL.options,
14690				viewport = getViewport(),
14691				path = opts.path.toLowerCase();
14692
14693			if (!thumbnails) thumbnails = vars.thumbnails;
14694			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
14695			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
14696
14697			var thumbs = $('.ilightbox-thumbnail', grid),
14698				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
14699				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
14700				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
14701				gridHeight = (path == 'horizontal') ? heightAvail : 0,
14702				active = $('.ilightbox-active', grid),
14703				gridCss = {},
14704				css = {};
14705
14706			if (arguments.length < 3) {
14707				thumbs.css({
14708					opacity: opts.thumbnails.normalOpacity
14709				});
14710				active.css({
14711					opacity: opts.thumbnails.activeOpacity
14712				});
14713			}
14714
14715			thumbs.each(function(i) {
14716				var t = $(this),
14717					data = t.data(),
14718					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
14719				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
14720				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
14721
14722				t.css({
14723					width: dims.width,
14724					height: dims.height
14725				});
14726				if (path == 'horizontal') t.css({
14727					'float': 'left'
14728				});
14729
14730				(path == 'horizontal') ? (
14731					gridWidth += t.outerWidth()
14732				) : (
14733					gridHeight += t.outerHeight()
14734				);
14735			});
14736
14737			gridCss = {
14738				width: gridWidth,
14739				height: gridHeight
14740			};
14741
14742			grid.css(gridCss);
14743
14744			gridCss = {};
14745
14746			var gridOffset = grid.offset(),
14747				activeOffset = (active.length) ? active.offset() : {
14748					top: parseInt(heightAvail / 2),
14749					left: parseInt(widthAvail / 2)
14750				};
14751
14752			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
14753				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
14754				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
14755				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
14756
14757			(path == 'horizontal') ? (
14758				gridCss.top = 0,
14759				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
14760			) : (
14761				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
14762				gridCss.left = 0
14763			);
14764
14765			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
14766			else grid.css(gridCss);
14767		},
14768
14769		loadImage: function(image, callback) {
14770			if (!$.isArray(image)) image = [image];
14771
14772			var iL = this,
14773				length = image.length;
14774
14775			if (length > 0) {
14776				iL.showLoader();
14777				$.each(image, function(index, value) {
14778					var img = new Image();
14779					img.onload = function() {
14780						length -= 1;
14781						if (length == 0) {
14782							iL.hideLoader();
14783							callback(img);
14784						}
14785					};
14786					img.onerror = img.onabort = function() {
14787						length -= 1;
14788						if (length == 0) {
14789							iL.hideLoader();
14790							callback(false);
14791						}
14792					};
14793					img.src = image[index];
14794				});
14795			} else callback(false);
14796		},
14797
14798		patchItemsEvents: function() {
14799			var iL = this,
14800				vars = iL.vars,
14801				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
14802				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
14803
14804			if (iL.context && iL.selector) {
14805				var $items = $(iL.selector, iL.context);
14806
14807				$(iL.context).on(clickEvent, iL.selector, function() {
14808					var $this = $(this),
14809						//UNCODE addition
14810						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
14811					if (UNCODE.isMobile) {
14812						var isCarousel = $this.closest('.owl-carousel');
14813						if (isCarousel.length) {
14814							if (isCarousel.hasClass('owl-translating')) return false;
14815						}
14816					}
14817
14818					vars.current = key;
14819					vars.next = iL.items[key + 1] ? key + 1 : null;
14820					vars.prev = iL.items[key - 1] ? key - 1 : null;
14821
14822					//UNCODE addition
14823					if ( vars.BODY.hasClass('fp-slide-scrolling') )
14824						return false;
14825
14826					iL.addContents();
14827					iL.patchEvents();
14828
14829					return false;
14830				}).on(vEvent, iL.selector, function() {
14831					return false;
14832				});
14833			} else
14834				$.each(iL.itemsObject, function(key, val) {
14835					val.on(clickEvent, function() {
14836						vars.current = key;
14837						vars.next = iL.items[key + 1] ? key + 1 : null;
14838						vars.prev = iL.items[key - 1] ? key - 1 : null;
14839
14840						iL.addContents();
14841						iL.patchEvents();
14842
14843						return false;
14844					}).on(vEvent, function() {
14845						return false;
14846					});
14847				});
14848		},
14849
14850		dispatchItemsEvents: function() {
14851			var iL = this,
14852				vars = iL.vars,
14853				opts = iL.options;
14854
14855			if (iL.context && iL.selector)
14856				$(iL.context).off('.iL', iL.selector);
14857			else
14858				$.each(iL.itemsObject, function(key, val) {
14859					val.off('.iL');
14860				});
14861		},
14862
14863		refresh: function() {
14864			var iL = this;
14865
14866			iL.dispatchItemsEvents();
14867			iL.attachItems();
14868			iL.normalizeItems();
14869			iL.patchItemsEvents();
14870		},
14871
14872		patchEvents: function() {
14873			var iL = this,
14874				vars = iL.vars,
14875				opts = iL.options,
14876				path = opts.path.toLowerCase(),
14877				holders = $('.ilightbox-holder'),
14878				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
14879				durationThreshold = 1000,
14880				horizontalDistanceThreshold =
14881				verticalDistanceThreshold = 100,
14882				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
14883
14884			$win.bind('resize.iLightBox', function() {
14885				var viewport = getViewport();
14886
14887				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14888				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14889
14890				iL.repositionPhoto(null);
14891				if (supportTouch) {
14892					clearTimeout(vars.setTime);
14893					vars.setTime = setTimeout(function() {
14894						var scrollTop = getScrollXY().y;
14895						window.scrollTo(0, scrollTop - 30);
14896						window.scrollTo(0, scrollTop + 30);
14897						window.scrollTo(0, scrollTop);
14898					}, 2000);
14899				}
14900				if (vars.thumbs) iL.positionThumbnails();
14901			}).bind('keydown.iLightBox', function(event) {
14902				if (opts.controls.keyboard) {
14903					switch (event.keyCode) {
14904						case 13:
14905							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
14906							break;
14907						case 27:
14908							if (opts.keyboard.esc) iL.closeAction();
14909							break;
14910						case 37:
14911							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
14912							break;
14913						case 38:
14914							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
14915							break;
14916						case 39:
14917							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
14918							break;
14919						case 40:
14920							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
14921							break;
14922					}
14923				}
14924			});
14925
14926			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
14927				iL.doFullscreen();
14928			});
14929
14930			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
14931					return arr.lastIndexOf(e) === i;
14932				}),
14933				holderEvents = "";
14934
14935			$.each(holderEventsArr, function(key, val) {
14936				if (key != 0) holderEvents += ' ';
14937				holderEvents += val;
14938			});
14939
14940			$doc.on(clickEvent, '.ilightbox-overlay', function() {
14941				if (opts.overlay.blur) iL.closeAction();
14942			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
14943				iL.moveTo('next');
14944			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
14945				iL.moveTo('prev');
14946			}).on(clickEvent, '.ilightbox-thumbnail', function() {
14947				var t = $(this),
14948					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
14949					index = thumbs.index(t);
14950
14951				if (index != vars.current) iL.goTo(index);
14952			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14953				var caption = $('div.ilightbox-caption', vars.holder),
14954					social = $('div.ilightbox-social', vars.holder),
14955					fadeSpeed = opts.effects.fadeSpeed;
14956
14957				if (vars.nextLock || vars.prevLock) {
14958					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
14959					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
14960
14961					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
14962					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
14963				} else {
14964					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
14965					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
14966
14967					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
14968					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
14969				}
14970			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
14971				if (e.type == 'mouseenter') vars.lockWheel = true;
14972				else vars.lockWheel = false;
14973			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
14974				var t = $(this);
14975
14976				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
14977				else if (t.hasClass('ilightbox-play')) {
14978					iL.resume();
14979					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
14980				} else if (t.hasClass('ilightbox-pause')) {
14981					iL.pause();
14982					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
14983				} else iL.closeAction();
14984			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
14985				// prevent scrolling
14986				e.preventDefault();
14987			});
14988
14989			function mouseMoveHandler(e) {
14990				if (!vars.isMobile) {
14991					if (!vars.mouseID) {
14992						vars.hideableElements.show();
14993					}
14994
14995					vars.mouseID = clearTimeout(vars.mouseID);
14996
14997					if (buttonsArray.indexOf(e.target) === -1)
14998						vars.mouseID = setTimeout(function() {
14999							vars.hideableElements.hide();
15000							vars.mouseID = clearTimeout(vars.mouseID);
15001						}, 3000);
15002				}
15003			}
15004
15005			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
15006
15007			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15008				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
15009				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
15010			});
15011
15012			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
15013				delay = false;
15014
15015			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
15016				event.preventDefault();
15017				if (delay) return;
15018				delay = true;
15019				if (!vars.lockWheel) {
15020					event.preventDefault();
15021					if (delta < 0) {
15022						iL.moveTo('next');
15023					} else if (delta > 0) {
15024						iL.moveTo('prev');
15025					}
15026				}
15027				setTimeout(function(){
15028					delay = false;
15029				}, 2000);
15030			});
15031
15032			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
15033				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
15034
15035				vars.BODY.addClass('ilightbox-closedhand');
15036
15037				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
15038					scrollTop = $doc.scrollTop(),
15039					scrollLeft = $doc.scrollLeft(),
15040					offsets = [
15041						holders.eq(0).offset(),
15042						holders.eq(1).offset(),
15043						holders.eq(2).offset()
15044					],
15045					offSet = [{
15046						top: offsets[0].top - scrollTop,
15047						left: offsets[0].left - scrollLeft
15048					}, {
15049						top: offsets[1].top - scrollTop,
15050						left: offsets[1].left - scrollLeft
15051					}, {
15052						top: offsets[2].top - scrollTop,
15053						left: offsets[2].left - scrollLeft
15054					}],
15055					start = {
15056						time: (new Date()).getTime(),
15057						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15058					},
15059					stop;
15060
15061				function moveEachHandler(i) {
15062					var t = $(this),
15063						offset = offSet[i],
15064						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
15065
15066					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
15067				}
15068
15069				function moveHandler(event) {
15070
15071					if (!start) return;
15072
15073					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
15074
15075					stop = {
15076						time: (new Date()).getTime(),
15077						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15078					};
15079
15080					holders.each(moveEachHandler);
15081
15082					// prevent scrolling
15083					event.preventDefault();
15084				}
15085
15086				function repositionHolders() {
15087					holders.each(function() {
15088						var t = $(this),
15089							offset = t.data('offset') || {
15090								top: t.offset().top - scrollTop,
15091								left: t.offset().left - scrollLeft
15092							},
15093							top = offset.top,
15094							left = offset.left;
15095
15096						t.css(transform, gpuAcceleration).stop().animate({
15097							top: top,
15098							left: left
15099						}, 500, 'easeOutCirc', function() {
15100							t.css(transform, '');
15101						});
15102					});
15103				}
15104
15105				holders.bind(touchMoveEvent, moveHandler);
15106				$doc.one(touchStopEvent, function(event) {
15107					holders.unbind(touchMoveEvent, moveHandler);
15108
15109					vars.BODY.removeClass('ilightbox-closedhand');
15110
15111					if (start && stop) {
15112						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
15113							if (start.coords[0] > stop.coords[0]) {
15114								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15115								else {
15116									vars.isSwipe = true;
15117									iL.moveTo('next');
15118								}
15119							} else {
15120								if (vars.current == 0 && !opts.infinite) repositionHolders();
15121								else {
15122									vars.isSwipe = true;
15123									iL.moveTo('prev');
15124								}
15125							}
15126						} else if (path == "vertical" && stop.time - start.time < durationThreshold && abs(start.coords[1] - stop.coords[1]) > horizontalDistanceThreshold && abs(start.coords[0] - stop.coords[0]) < verticalDistanceThreshold) {
15127							if (start.coords[1] > stop.coords[1]) {
15128								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15129								else {
15130									vars.isSwipe = true;
15131									iL.moveTo('next');
15132								}
15133							} else {
15134								if (vars.current == 0 && !opts.infinite) repositionHolders();
15135								else {
15136									vars.isSwipe = true;
15137									iL.moveTo('prev');
15138								}
15139							}
15140						} else repositionHolders();
15141					}
15142					start = stop = undefined;
15143				});
15144			});
15145
15146		},
15147
15148		goTo: function(index) {
15149			var iL = this,
15150				vars = iL.vars,
15151				opts = iL.options,
15152				diff = (index - vars.current);
15153
15154			if (opts.infinite) {
15155				if (index == vars.total - 1 && vars.current == 0) diff = -1;
15156				if (vars.current == vars.total - 1 && index == 0) diff = 1;
15157			}
15158
15159			if (diff == 1) iL.moveTo('next');
15160			else if (diff == -1) iL.moveTo('prev');
15161			else {
15162
15163				if (vars.nextLock || vars.prevLock) return false;
15164
15165				//Trigger the onBeforeChange callback
15166				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
15167
15168				if (opts.linkId) {
15169					vars.hashLock = true;
15170					window.location.hash = opts.linkId + '/' + index;
15171				}
15172
15173				if (iL.items[index]) {
15174					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
15175					else iL.vars.lockWheel = false;
15176
15177					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
15178					else vars.lockSwipe = false;
15179				}
15180
15181				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
15182					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
15183				});
15184
15185				vars.current = index;
15186				vars.next = index + 1;
15187				vars.prev = index - 1;
15188
15189				iL.createUI();
15190
15191				setTimeout(function() {
15192					iL.generateBoxes();
15193				}, opts.effects.loadedFadeSpeed + 50);
15194
15195				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
15196				iL.positionThumbnails();
15197
15198				if (opts.linkId) setTimeout(function() {
15199					vars.hashLock = false;
15200				}, 55);
15201
15202				// Configure arrow buttons
15203				if (!opts.infinite) {
15204					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15205
15206					if (vars.current == 0) {
15207						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15208					}
15209					if (vars.current >= vars.total - 1) {
15210						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15211					}
15212				}
15213
15214				// Reset next cycle timeout
15215				iL.resetCycle();
15216
15217				//Trigger the onAfterChange callback
15218				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
15219			}
15220		},
15221
15222		moveTo: function(side) {
15223			var iL = this,
15224				vars = iL.vars,
15225				opts = iL.options,
15226				path = opts.path.toLowerCase(),
15227				viewport = getViewport(),
15228				switchSpeed = opts.effects.switchSpeed;
15229
15230			if (vars.nextLock || vars.prevLock) return false;
15231			else {
15232
15233				var item = (side == "next") ? vars.next : vars.prev;
15234
15235				if (opts.linkId) {
15236					vars.hashLock = true;
15237					window.location.hash = opts.linkId + '/' + item;
15238				}
15239
15240				if (side == "next") {
15241					if (!iL.items[item]) return false;
15242					var firstHolder = vars.nextPhoto,
15243						secondHolder = vars.holder,
15244						lastHolder = vars.prevPhoto,
15245						firstClass = 'ilightbox-prev',
15246						secondClass = 'ilightbox-next';
15247				} else if (side == "prev") {
15248					if (!iL.items[item]) return false;
15249					var firstHolder = vars.prevPhoto,
15250						secondHolder = vars.holder,
15251						lastHolder = vars.nextPhoto,
15252						firstClass = 'ilightbox-next',
15253						secondClass = 'ilightbox-prev';
15254				}
15255
15256				//Trigger the onBeforeChange callback
15257				if (typeof opts.callback.onBeforeChange == 'function')
15258					opts.callback.onBeforeChange.call(iL, iL.ui);
15259
15260				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
15261
15262				var captionFirst = $('div.ilightbox-caption', secondHolder),
15263					socialFirst = $('div.ilightbox-social', secondHolder);
15264
15265				if (captionFirst.length)
15266					captionFirst.stop().fadeOut(switchSpeed, function() {
15267						$(this).remove();
15268					});
15269				if (socialFirst.length)
15270					socialFirst.stop().fadeOut(switchSpeed, function() {
15271						$(this).remove();
15272					});
15273
15274				if (iL.items[item].caption) {
15275					iL.setCaption(iL.items[item], firstHolder);
15276					var caption = $('div.ilightbox-caption', firstHolder),
15277						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
15278					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
15279				}
15280
15281				var social = iL.items[item].options.social;
15282				if (social) {
15283					iL.setSocial(social, iL.items[item].URL, firstHolder);
15284					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
15285				}
15286
15287				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
15288					val.removeClass('ilightbox-next ilightbox-prev');
15289				});
15290
15291				var firstOffset = firstHolder.data('offset'),
15292					winW = (viewport.width - (opts.styles.pageOffsetX)),
15293					winH = (viewport.height - (opts.styles.pageOffsetY)),
15294					width = firstOffset.newDims.width,
15295					height = firstOffset.newDims.height,
15296					thumbsOffset = firstOffset.thumbsOffset,
15297					diff = firstOffset.diff,
15298					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
15299					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15300
15301				var secondOffset = secondHolder.data('offset'),
15302					object = secondOffset.object;
15303
15304				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15305					var objRatio = width / height;
15306					height = height - vars.captionHeight;
15307					width = height * objRatio;
15308					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
15309					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15310				}*/
15311
15312				firstHolder.show().css(transform, gpuAcceleration).animate({
15313					top: top,
15314					left: left,
15315					opacity: 1
15316				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15317					firstHolder.css(transform, '');
15318				});
15319
15320				$('div.ilightbox-container', firstHolder).animate({
15321					width: width,
15322					height: height
15323				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15324
15325				diff = secondOffset.diff;
15326
15327				width = secondOffset.newDims.width,
15328					height = secondOffset.newDims.height;
15329
15330				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15331					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15332					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
15333
15334				if (side == 'prev')
15335					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
15336				else {
15337					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
15338					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
15339				}
15340
15341				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15342					var objRatio = width / height;
15343					height = height - vars.captionHeight;
15344					width = height * objRatio;
15345					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
15346				}*/
15347
15348				$('div.ilightbox-container', secondHolder).animate({
15349					width: width,
15350					height: height
15351				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15352
15353				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
15354					top: top,
15355					left: left,
15356					opacity: opts.styles.prevOpacity,
15357				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15358					secondHolder.css(transform, '');
15359
15360					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
15361					iL.positionThumbnails();
15362
15363					if (iL.items[item]) {
15364						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
15365						else vars.lockWheel = false;
15366
15367						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
15368						else vars.lockSwipe = false;
15369					}
15370
15371					vars.isSwipe = false;
15372
15373					// Remove iframe & video from previous slide
15374					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15375						$('div.ilightbox-container', secondHolder).empty();
15376					}
15377
15378					if (side == "next") {
15379						vars.nextPhoto = lastHolder,
15380							vars.prevPhoto = secondHolder,
15381							vars.holder = firstHolder;
15382
15383						vars.nextPhoto.hide();
15384
15385						vars.next = vars.next + 1,
15386							vars.prev = vars.current,
15387							vars.current = vars.current + 1;
15388
15389						if (opts.infinite) {
15390							if (vars.current > vars.total - 1) vars.current = 0;
15391							if (vars.current == vars.total - 1) vars.next = 0;
15392							if (vars.current == 0) vars.prev = vars.total - 1;
15393						}
15394
15395						iL.createUI();
15396
15397						if (!iL.items[vars.next])
15398							vars.nextLock = false;
15399						else
15400							iL.loadContent(iL.items[vars.next], 'next');
15401					} else {
15402						vars.prevPhoto = lastHolder;
15403						vars.nextPhoto = secondHolder;
15404						vars.holder = firstHolder;
15405
15406						vars.prevPhoto.hide();
15407
15408						vars.next = vars.current;
15409						vars.current = vars.prev;
15410						vars.prev = vars.current - 1;
15411
15412						if (opts.infinite) {
15413							if (vars.current == vars.total - 1) vars.next = 0;
15414							if (vars.current == 0) vars.prev = vars.total - 1;
15415						}
15416
15417						iL.createUI();
15418
15419						if (!iL.items[vars.prev])
15420							vars.prevLock = false;
15421						else
15422							iL.loadContent(iL.items[vars.prev], 'prev');
15423					}
15424
15425					// Add iframe & video content for current slide
15426					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15427						iL.loadContent(iL.items[vars.current], 'current');
15428					}
15429
15430					if (opts.linkId) setTimeout(function() {
15431						vars.hashLock = false;
15432					}, 55);
15433
15434					// Configure arrow buttons
15435					if (!opts.infinite) {
15436						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15437
15438						if (vars.current == 0)
15439							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15440						if (vars.current >= vars.total - 1)
15441							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15442					}
15443
15444					iL.repositionPhoto();
15445
15446					// Reset next cycle timeout
15447					iL.resetCycle();
15448
15449					//Trigger the onAfterChange callback
15450					if (typeof opts.callback.onAfterChange == 'function')
15451						opts.callback.onAfterChange.call(iL, iL.ui);
15452				});
15453
15454				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
15455					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
15456
15457				lastHolder.css(transform, gpuAcceleration).animate({
15458					top: top,
15459					left: left,
15460					opacity: opts.styles.nextOpacity
15461				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15462					lastHolder.css(transform, '');
15463				}).addClass(secondClass);
15464			}
15465		},
15466
15467		setCaption: function(obj, target) {
15468			var iL = this,
15469				caption = $('<div class="ilightbox-caption"></div>');
15470
15471			if (obj.caption) {
15472				caption.html(obj.caption);
15473				$('div.ilightbox-container', target).append(caption);
15474			}
15475		},
15476
15477		normalizeSocial: function(obj, url) {
15478			var iL = this,
15479				vars = iL.vars,
15480				opts = iL.options,
15481				baseURL = window.location.href;
15482
15483			$.each(obj, function(key, value) {
15484				if (!value)
15485					return true;
15486
15487				var item = key.toLowerCase(),
15488					source, text;
15489
15490				switch (item) {
15491					case 'facebook':
15492						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
15493							text = "Share on Facebook";
15494						break;
15495					case 'twitter':
15496						source = "http://twitter.com/home?status={URL}",
15497							text = "Share on Twitter";
15498						break;
15499					case 'digg':
15500						source = "http://digg.com/submit?phase=2&url={URL}",
15501							text = "Share on Digg";
15502						break;
15503					case 'reddit':
15504						source = "http://reddit.com/submit?url={URL}",
15505							text = "Share on reddit";
15506						break;
15507				}
15508
15509				obj[key] = {
15510					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
15511					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
15512					text: value.text || text || "Share on " + key,
15513					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
15514					height: value.height || 360
15515				};
15516
15517			});
15518
15519			return obj;
15520		},
15521
15522		setSocial: function(obj, url, target) {
15523			var iL = this,
15524				socialBar = $('<div class="ilightbox-social"></div>'),
15525				buttons = '<ul>';
15526
15527			obj = iL.normalizeSocial(obj, url);
15528
15529			$.each(obj, function(key, value) {
15530				var item = key.toLowerCase(),
15531					source = value.source.replace(/\{URL\}/g, encodeURIComponent(value.URL).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A').replace(/%20/g, '+'));
15532				buttons += '<li class="' + key + '"><a href="' + source + '" onclick="javascript:window.open(this.href' + ((value.width <= 0 || value.height <= 0) ? '' : ', \'\', \'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=' + value.height + ',width=' + value.width + ',left=40,top=40\'') + ');return false;" title="' + value.text + '" target="_blank"></a></li>';
15533			});
15534
15535			buttons += '</ul>';
15536
15537			socialBar.html(buttons);
15538			$('div.ilightbox-container', target).append(socialBar);
15539		},
15540
15541		fullScreenAction: function() {
15542			var iL = this,
15543				vars = iL.vars;
15544
15545			if (fullScreenApi.supportsFullScreen) {
15546				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
15547				else fullScreenApi.requestFullScreen(document.documentElement);
15548			} else {
15549				iL.doFullscreen();
15550			}
15551		},
15552
15553		doFullscreen: function() {
15554			var iL = this,
15555				vars = iL.vars,
15556				viewport = getViewport(),
15557				opts = iL.options;
15558
15559			if (opts.fullAlone) {
15560				var currentHolder = vars.holder,
15561					current = iL.items[vars.current],
15562					windowWidth = viewport.width,
15563					windowHeight = viewport.height,
15564					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
15565					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15566
15567				if (!vars.isInFullScreen) {
15568					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
15569					vars.overlay.css({
15570						opacity: 1
15571					});
15572
15573					$.each(hideElements, function(i, element) {
15574						element.hide();
15575					});
15576
15577					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
15578
15579					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
15580						naturalWidthOld: currentHolder.data('naturalWidth'),
15581						naturalHeightOld: currentHolder.data('naturalHeight'),
15582						naturalWidth: windowWidth,
15583						naturalHeight: windowHeight
15584					});
15585					else {
15586						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
15587							newWidth = windowWidth,
15588							newHeight = windowHeight,
15589							width = currentHolder.data('naturalWidth'),
15590							height = currentHolder.data('naturalHeight');
15591
15592						if (viewport.toLowerCase() == 'fill') {
15593							newHeight = (newWidth / width) * height;
15594
15595							if (newHeight < windowHeight) {
15596								newWidth = (windowHeight / height) * width,
15597									newHeight = windowHeight;
15598							}
15599						} else if (viewport.toLowerCase() == 'fit') {
15600							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
15601
15602							newWidth = dims.width,
15603								newHeight = dims.height;
15604						} else if (viewport.toLowerCase() == 'stretch') {
15605							newWidth = newWidth,
15606								newHeight = newHeight;
15607						} else {
15608							var scale = (width > newWidth || height > newHeight) ? true : false,
15609								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
15610							newWidth = dims.width,
15611								newHeight = dims.height;
15612						}
15613
15614						currentHolder.data({
15615							naturalWidthOld: currentHolder.data('naturalWidth'),
15616							naturalHeightOld: currentHolder.data('naturalHeight'),
15617							naturalWidth: newWidth,
15618							naturalHeight: newHeight
15619						});
15620					}
15621
15622					$.each(elements, function(key, val) {
15623						val.addClass('ilightbox-fullscreen');
15624					});
15625
15626					//Trigger the onEnterFullScreen callback
15627					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
15628				} else {
15629					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
15630					vars.overlay.css({
15631						opacity: iL.options.overlay.opacity
15632					});
15633
15634					$.each(hideElements, function(i, element) {
15635						element.show();
15636					});
15637
15638					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
15639
15640					currentHolder.data({
15641						naturalWidth: currentHolder.data('naturalWidthOld'),
15642						naturalHeight: currentHolder.data('naturalHeightOld'),
15643						naturalWidthOld: null,
15644						naturalHeightOld: null
15645					});
15646
15647					$.each(elements, function(key, val) {
15648						val.removeClass('ilightbox-fullscreen');
15649					});
15650
15651					//Trigger the onExitFullScreen callback
15652					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
15653				}
15654			} else {
15655				if (!vars.isInFullScreen) vars.isInFullScreen = true;
15656				else vars.isInFullScreen = false;
15657			}
15658			iL.repositionPhoto(true);
15659		},
15660
15661		closeAction: function() {
15662			var iL = this,
15663				vars = iL.vars,
15664				opts = iL.options;
15665
15666			$win.unbind('.iLightBox');
15667			$doc.off('.iLightBox');
15668
15669			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
15670
15671			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
15672
15673			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
15674				vars.overlay.remove();
15675				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15676			});
15677			else {
15678				vars.overlay.remove();
15679				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15680			}
15681
15682			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15683
15684			$.each(fadeOuts, function(i, element) {
15685				element.removeAttr('style').remove();
15686			});
15687
15688			vars.dontGenerateThumbs = vars.isInFullScreen = false;
15689
15690			window.iLightBox = null;
15691
15692			if (opts.linkId) {
15693				vars.hashLock = true;
15694				removeHash();
15695				setTimeout(function() {
15696					vars.hashLock = false;
15697				}, 55);
15698			}
15699
15700			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15701
15702			//Trigger the onHide callback
15703			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
15704		},
15705
15706		repositionPhoto: function() {
15707			var iL = this,
15708				vars = iL.vars,
15709				opts = iL.options,
15710				path = opts.path.toLowerCase(),
15711				viewport = getViewport(),
15712				winWidth = viewport.width,
15713				winHeight = viewport.height;
15714
15715			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
15716
15717			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
15718				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
15719				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
15720				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
15721				offsetW = (path == 'horizontal') ? parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((width / 10) <= 30) ? 30 : (width / 10))) : parseInt(((width / 10) <= 30) ? 30 : (width / 10)) + thumbsOffsetW,
15722				offsetH = (path == 'horizontal') ? parseInt(((height / 10) <= 30) ? 30 : (height / 10)) + thumbsOffsetH : parseInt((iL.items[vars.next] || iL.items[vars.prev]) ? ((opts.styles.nextOffsetX + opts.styles.prevOffsetX)) * 2 : (((height / 10) <= 30) ? 30 : (height / 10)));
15723
15724			var elObject = {
15725				type: 'current',
15726				width: width,
15727				height: height,
15728				item: iL.items[vars.current],
15729				offsetW: offsetW,
15730				offsetH: offsetH,
15731				thumbsOffsetW: thumbsOffsetW,
15732				thumbsOffsetH: thumbsOffsetH,
15733				animate: arguments.length,
15734				holder: vars.holder
15735			};
15736
15737			iL.repositionEl(elObject);
15738
15739			if (iL.items[vars.next]) {
15740				elObject = $.extend(elObject, {
15741					type: 'next',
15742					item: iL.items[vars.next],
15743					offsetX: opts.styles.nextOffsetX,
15744					offsetY: opts.styles.nextOffsetY,
15745					holder: vars.nextPhoto
15746				});
15747
15748				iL.repositionEl(elObject);
15749			}
15750
15751			if (iL.items[vars.prev]) {
15752				elObject = $.extend(elObject, {
15753					type: 'prev',
15754					item: iL.items[vars.prev],
15755					offsetX: opts.styles.nextOffsetX,
15756					offsetY: opts.styles.prevOffsetY,
15757					holder: vars.prevPhoto
15758				});
15759
15760				iL.repositionEl(elObject);
15761			}
15762
15763			var loaderCss = (path == "horizontal") ? {
15764				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
15765			} : {
15766				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
15767			};
15768			vars.loader.css(loaderCss);
15769		},
15770
15771		repositionEl: function(obj) {
15772			var iL = this,
15773				vars = iL.vars,
15774				opts = iL.options,
15775				path = opts.path.toLowerCase(),
15776				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
15777				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
15778				itemParent = obj.item,
15779				item = obj.item.options,
15780				holder = obj.holder,
15781				offsetX = obj.offsetX || 0,
15782				offsetY = obj.offsetY || 0,
15783				//Uncode change ##START##
15784				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
15785				//Uncode change ##END##
15786				thumbsOffsetW = obj.thumbsOffsetW,
15787				thumbsOffsetH = obj.thumbsOffsetH;
15788
15789			if (obj.type == 'current') {
15790				if (typeof item.width == 'number' && item.width) widthAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? widthAvail : ((item.width > widthAvail) ? widthAvail : item.width);
15791				if (typeof item.height == 'number' && item.height) heightAvail = ((vars.isInFullScreen && opts.fullAlone) && (opts.fullStretchTypes.indexOf(itemParent.type) != -1 || item.fullViewPort || opts.fullViewPort)) ? heightAvail : ((item.height > heightAvail) ? heightAvail : item.height);
15792			} else {
15793				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
15794				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
15795			}
15796
15797
15798			//Uncode change ##START##
15799			heightAvail = parseInt(heightAvail - toolbarHeight);
15800			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
15801			//Uncode change ##END##
15802
15803			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
15804				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
15805
15806			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
15807					width: width,
15808					height: height
15809				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
15810				newDims = $.extend({}, dims, {});
15811
15812			if (obj.type == 'prev' || obj.type == 'next')
15813				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
15814				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
15815			else
15816				width = dims.width,
15817				height = dims.height;
15818
15819			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
15820				heightDiff = parseInt((getPixel(holder, 'padding-top') + getPixel(holder, 'padding-bottom') + getPixel(holder, 'border-top-width') + getPixel(holder, 'border-bottom-width') + ($('.ilightbox-inner-toolbar', holder).outerHeight() || 0)) / 2);
15821
15822			switch (obj.type) {
15823				case 'current':
15824					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
15825						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15826					break;
15827
15828				case 'next':
15829					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
15830						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
15831					break;
15832
15833				case 'prev':
15834					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
15835						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15836					break;
15837			}
15838
15839			holder.data('offset', {
15840				top: top,
15841				left: left,
15842				newDims: newDims,
15843				diff: {
15844					W: widthDiff,
15845					H: heightDiff
15846				},
15847				thumbsOffset: {
15848					W: thumbsOffsetW,
15849					H: thumbsOffsetH
15850				},
15851				object: obj
15852			});
15853
15854			var opacityMobile;
15855			if ( isMobile ) {
15856				opacityMobile = {
15857					opacity: 1,
15858					top: top,
15859					left: left
15860				};
15861			} else {
15862				opacityMobile = {
15863					top: top,
15864					left: left
15865				};
15866			}
15867
15868			if (obj.animate > 0 && opts.effects.reposition) {
15869				holder.css(transform, gpuAcceleration).stop().animate(
15870					opacityMobile,
15871					opts.effects.repositionSpeed, 'easeOutCirc', function() {
15872					holder.css(transform, '');
15873				});
15874				$('div.ilightbox-container', holder).stop().animate({
15875					width: width,
15876					height: height
15877				}, opts.effects.repositionSpeed, 'easeOutCirc');
15878				$('div.ilightbox-inner-toolbar', holder).stop().animate({
15879					width: width
15880				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
15881					$(this).css('overflow', 'visible');
15882				});
15883			} else {
15884				holder.css(opacityMobile);
15885				$('div.ilightbox-container', holder).css({
15886					width: width,
15887					height: height
15888				});
15889				$('div.ilightbox-inner-toolbar', holder).css({
15890					width: width
15891				});
15892			}
15893		},
15894
15895
15896		resume: function(priority) {
15897			var iL = this,
15898				vars = iL.vars,
15899				opts = iL.options;
15900
15901			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
15902				return;
15903			}
15904
15905			vars.isPaused = 0;
15906
15907			if (vars.cycleID) {
15908				vars.cycleID = clearTimeout(vars.cycleID);
15909			}
15910
15911			vars.cycleID = setTimeout(function() {
15912				if (vars.current == vars.total - 1) iL.goTo(0);
15913				else iL.moveTo('next');
15914			}, opts.slideshow.pauseTime);
15915		},
15916
15917		pause: function(priority) {
15918			var iL = this,
15919				vars = iL.vars,
15920				opts = iL.options;
15921
15922			if (priority < vars.isPaused) {
15923				return;
15924			}
15925
15926			vars.isPaused = priority || 100;
15927
15928			if (vars.cycleID) {
15929				vars.cycleID = clearTimeout(vars.cycleID);
15930			}
15931		},
15932
15933		resetCycle: function() {
15934			var iL = this,
15935				vars = iL.vars,
15936				opts = iL.options;
15937
15938			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
15939				iL.resume();
15940			}
15941		},
15942
15943		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
15944			var iL = this;
15945
15946			if (!width) factor = height / height_old;
15947			else if (!height) factor = width / width_old;
15948			else factor = min(width / width_old, height / height_old);
15949
15950			if (!thumb) {
15951				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
15952				else if (factor < iL.options.minScale) factor = iL.options.minScale;
15953			}
15954
15955			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
15956				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
15957
15958			return {
15959				width: final_width,
15960				height: final_height,
15961				ratio: factor
15962			};
15963		},
15964
15965		setOption: function(options) {
15966			var iL = this;
15967
15968			iL.options = $.extend(true, iL.options, options || {});
15969			iL.refresh();
15970		},
15971
15972		availPlugins: function() {
15973			var iL = this,
15974				testEl = document.createElement("video");
15975
15976			iL.plugins = {
15977				flash: !isMobile,
15978				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
15979				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
15980				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
15981				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
15982				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
15983			};
15984		},
15985
15986		addContent: function(element, obj) {
15987			var iL = this,
15988				el;
15989
15990			switch (obj.type) {
15991				case 'video':
15992					var HTML5 = false,
15993						videoType = obj.videoType,
15994						html5video = obj.options.html5video;
15995
15996					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
15997						obj.ext = 'mp4',
15998						obj.URL = html5video.h264 || obj.URL;
15999					else if (html5video.webm && iL.plugins.html5WebM)
16000						obj.ext = 'webm',
16001						obj.URL = html5video.webm || obj.URL;
16002					else if (html5video.ogg && iL.plugins.html5Vorbis)
16003						obj.ext = 'ogv',
16004						obj.URL = html5video.ogg || obj.URL;
16005
16006					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
16007					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
16008					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
16009					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
16010
16011					if (HTML5) {
16012						el = $('<video />
16012', {
16013							"width": "100%",
16014							"height": "100%",
16015							"preload": html5video.preload,
16016							"autoplay": html5video.autoplay,
16017							"loop": html5video.loop,
16018							"poster": html5video.poster,
16019							"controls": html5video.controls,
16020							"controlslist": "nodownload"
16021						}).append($('<source />', {
16022							"src": obj.URL,
16023							"type": videoType
16024						}));
16025					} else {
16026						if (!iL.plugins.quicktime) el = $('<span />', {
16027							"class": "ilightbox-alert",
16028							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
16029						});
16030						else {
16031
16032							el = $('<object />', {
16033								"type": "video/quicktime",
16034								"pluginspage": pluginspages.quicktime
16035							}).attr({
16036								"data": obj.URL,
16037								"width": "100%",
16038								"height": "100%"
16039							}).append($('<param />', {
16040								"name": "src",
16041								"value": obj.URL
16042							})).append($('<param />', {
16043								"name": "autoplay",
16044								"value": "false"
16045							})).append($('<param />', {
16046								"name": "loop",
16047								"value": "false"
16048							})).append($('<param />', {
16049								"name": "scale",
16050								"value": "tofit"
16051							}));
16052
16053							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
16054						}
16055					}
16056
16057					break;
16058
16059				case 'flash':
16060					if (!iL.plugins.flash) el = $('<span />', {
16061						"class": "ilightbox-alert",
16062						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
16063					});
16064					else {
16065						var flashvars = "",
16066							i = 0;
16067
16068						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
16069							if (i != 0) flashvars += "&";
16070							flashvars += k + "=" + encodeURIComponent(v);
16071							i++;
16072						});
16073						else flashvars = null;
16074
16075						el = $('<embed />').attr({
16076							"type": "application/x-shockwave-flash",
16077							"src": obj.URL,
16078							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16079							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16080							"quality": "high",
16081							"bgcolor": "#000000",
16082							"play": "true",
16083							"loop": "true",
16084							"menu": "true",
16085							"wmode": "transparent",
16086							"scale": "showall",
16087							"allowScriptAccess": "always",
16088							"allowFullScreen": "true",
16089							"flashvars": flashvars,
16090							"fullscreen": "yes"
16091						});
16092					}
16093
16094					break;
16095
16096				case 'iframe':
16097					el = $('<iframe />').attr({
16098						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16099						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16100						src: obj.URL,
16101						frameborder: 0,
16102						'hspace': 0,
16103						'vspace': 0,
16104						'scrolling': supportTouch ? 'auto' : 'scroll',
16105						'webkitAllowFullScreen': '',
16106						'mozallowfullscreen': '',
16107						'allowFullScreen': ''
16108					});
16109
16110					break;
16111
16112				case 'inline':
16113					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
16114
16115					break;
16116
16117				case 'html':
16118					var object = obj.URL,
16119						el;
16120
16121					if (object[0].nodeName) {
16122						el = $('<div class="ilightbox-wrapper"></div>').html(object);
16123					} else {
16124						var dom = $(obj.URL),
16125							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
16126						el = $('<div class="ilightbox-wrapper"></div>').html(html);
16127					}
16128
16129					break;
16130			}
16131
16132			$('div.ilightbox-container', element).empty().html(el);
16133
16134			// For fixing Chrome about just playing the video for first time
16135			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
16136				var src = el[0].currentSrc + '?' + floor(random() * 30000);
16137				el[0].currentSrc = src;
16138				el[0].src = src;
16139			});
16140
16141			return el;
16142		},
16143
16144		ogpRecognition: function(obj, callback) {
16145			var iL = this,
16146				url = obj.URL;
16147
16148			iL.showLoader();
16149			doAjax(url, function(data) {
16150				iL.hideLoader();
16151				if (data) {
16152					var object = new Object();
16153
16154					object.length = false,
16155					object.url = data.url;
16156
16157					if (data.status == 200) {
16158						var result = data.results,
16159							type = result.type,
16160							source = result.source;
16161
16162						object.source = source.src,
16163						object.width = source.width && parseInt(source.width) || 0,
16164						object.height = source.height && parseInt(source.height) || 0,
16165						object.type = type,
16166						object.thumbnail = source.thumbnail || result.images && result.images[0],
16167						object.html5video = result.html5video || {},
16168						object.length = true;
16169
16170						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
16171						else if (source.type.indexOf("video/") != -1) object.type = "video";
16172						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
16173						else if (source.type.indexOf("image/") != -1) object.type = "image";
16174
16175					} else if (typeof data.response != 'undefined')
16176						throw data.response;
16177
16178					callback.call(this, object.length ? object : false);
16179				}
16180			});
16181		},
16182
16183		hashChangeHandler: function(url) {
16184			var iL = this,
16185				vars = iL.vars,
16186				opts = iL.options,
16187				URL = url || window.location.href,
16188				hash = parseURI(URL).hash,
16189				split = hash.split('/'),
16190				index = split[1];
16191
16192			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
16193
16194			if (index) {
16195				var target = split[1] || 0;
16196				if (iL.items[target]) {
16197					var overlay = $('.ilightbox-overlay');
16198					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
16199						iL.goTo(target);
16200					} else {
16201						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
16202						//iL.goTo(target);
16203					}
16204				} else {
16205					var overlay = $('.ilightbox-overlay');
16206					if (overlay.length) iL.closeAction();
16207				}
16208			} else {
16209				var overlay = $('.ilightbox-overlay');
16210				if (overlay.length) iL.closeAction();
16211			}
16212		}
16213	};
16214
16215	/**
16216	 * Parse style to pixels.
16217	 *
16218	 * @param {Object}   $element   jQuery object with element.
16219	 * @param {Property} property   CSS property to get the pixels from.
16220	 *
16221	 * @return {Int}
16222	 */
16223	function getPixel($element, property) {
16224		return parseInt($element.css(property), 10) || 0;
16225	}
16226
16227	/**
16228	 * Make sure that number is within the limits.
16229	 *
16230	 * @param {Number} number
16231	 * @param {Number} min
16232	 * @param {Number} max
16233	 *
16234	 * @return {Number}
16235	 */
16236	function within(number, min, max) {
16237		return number < min ? min : number > max ? max : number;
16238	}
16239
16240	/**
16241	 * Get viewport/window size (width and height).
16242	 *
16243	 * @return {Object}
16244	 */
16245	function getViewport() {
16246		var e = window,
16247			a = 'inner';
16248		if (!('innerWidth' in window)) {
16249			a = 'client';
16250			e = document.documentElement || document.body;
16251		}
16252		return {
16253			width: e[a + 'Width'],
16254			height: e[a + 'Height']
16255		}
16256	}
16257
16258	/**
16259	 * Remove hash tag from the URL
16260	 *
16261	 * @return {Void}
16262	 */
16263	function removeHash() {
16264		var scroll = getScrollXY();
16265
16266		//UNCODE change
16267		// window.location.hash = "";
16268		// history.pushState("", document.title, window.location.pathname + window.location.search);
16269		history.replaceState({}, document.title, window.location.pathname + window.location.search);
16270
16271		// Restore the scroll offset, should be flicker free
16272		window.scrollTo(scroll.x, scroll.y);
16273	}
16274
16275	/**
16276	 * Do the ajax requests with callback.
16277	 *
16278	 * @param {String}   url
16279	 * @param {Function} callback
16280	 *
16281	 * @return {Void}
16282	 */
16283	function doAjax(url, callback) {
16284		var url = "//ilightbox.net/getSource/jsonp.php?url=" + encodeURIComponent(url).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');
16285		$.ajax({
16286			url: url,
16287			dataType: 'jsonp'
16288		});
16289
16290		iLCallback = function(data) {
16291			callback.call(this, data);
16292		};
16293	}
16294
16295	/**
16296	 * Find image from DOM elements
16297	 *
16298	 * @param {Element} element
16299	 *
16300	 * @return {Void}
16301	 */
16302	function findImageInElement(element) {
16303		var elements = $('*', element),
16304			imagesArr = new Array();
16305
16306		elements.each(function() {
16307			var url = "",
16308				element = this;
16309
16310			if ($(element).css("background-image") != "none") {
16311				url = $(element).css("background-image");
16312			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
16313				url = $(element).attr("src");
16314			}
16315
16316			if (url.indexOf("gradient") == -1) {
16317				url = url.replace(/url\(\"/g, "");
16318				url = url.replace(/url\(/g, "");
16319				url = url.replace(/\"\)/g, "");
16320				url = url.replace(/\)/g, "");
16321
16322				var urls = url.split(",");
16323
16324				for (var i = 0; i < urls.length; i++) {
16325					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
16326						var extra = "";
16327						if (browser.msie && browser.version < 9) {
16328							extra = "?" + floor(random() * 3000);
16329						}
16330						imagesArr.push(urls[i] + extra);
16331					}
16332				}
16333			}
16334		});
16335
16336		return imagesArr;
16337	}
16338
16339	/**
16340	 * Get file extension.
16341	 *
16342	 * @param {String} URL
16343	 *
16344	 * @return {String}
16345	 */
16346	function getExtension(URL) {
16347		if (URL !== null) {
16348			//UNCODE: fix issue to detect media type with query strings
16349			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
16350			ext = ext.split('.').pop().toLowerCase();
16351
16352			return ext;
16353		}
16354	}
16355
16356	/**
16357	 * Get type via extension.
16358	 *
16359	 * @param {String} URL
16360	 *
16361	 * @return {String}
16362	 */
16363	function getTypeByExtension(URL) {
16364		var type,
16365			ext = getExtension(URL);
16366
16367		//Uncode addition ##START##
16368		if (URL == undefined) {
16369			return false;
16370		}
16371		//Uncode addition ##END##
16372
16373		if (extensions.image.indexOf(ext) !== -1) type = 'image';
16374		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
16375		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
16376		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
16377		else type = 'iframe';
16378
16379		return type;
16380	}
16381
16382	/**
16383	 * Return value from percent of a number.
16384	 *
16385	 * @param {Number} percent
16386	 * @param {Number} total
16387	 *
16388	 * @return {Number}
16389	 */
16390	function percentToValue(percent, total) {
16391		return parseInt((total / 100) * percent);
16392	}
16393
16394	/**
16395	 * A JavaScript equivalent of PHP’s parse_url.
16396	 *
16397	 * @param {String} url           The URL to parse.
16398	 *
16399	 * @return {Mixed}
16400	 */
16401	function parseURI(url) {
16402		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
16403		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
16404		return (m ? {
16405			href: m[0] || '',
16406			protocol: m[1] || '',
16407			authority: m[2] || '',
16408			host: m[3] || '',
16409			hostname: m[4] || '',
16410			port: m[5] || '',
16411			pathname: m[6] || '',
16412			search: m[7] || '',
16413			hash: m[8] || ''
16414		} : null);
16415	}
16416
16417	/**
16418	 * Gets the absolute URI.
16419	 *
16420	 * @param {String} href     The relative URL.
16421	 * @param {String} base     The base URL.
16422	 *
16423	 * @return {String}         The absolute URL.
16424	 */
16425	function absolutizeURI(base, href) { // RFC 3986
16426		var iL = this;
16427
16428		function removeDotSegments(input) {
16429			var output = [];
16430			input.replace(/^(\.\.?(\/|$))+/, '')
16431				.replace(/\/(\.(\/|$))+/g, '/')
16432				.replace(/\/\.\.$/, '/../')
16433				.replace(/\/?[^\/]*/g, function(p) {
16434					if (p === '/..') {
16435						output.pop();
16436					} else {
16437						output.push(p);
16438					}
16439				});
16440			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
16441		}
16442
16443		href = parseURI(href || '');
16444		base = parseURI(base || '');
16445
16446		return !href || !base ? null : (href.protocol || base.protocol) +
16447			(href.protocol || href.authority ? href.authority : base.authority) +
16448			removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
16449			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
16450			href.hash;
16451	}
16452
16453	/**
16454	 * A JavaScript equivalent of PHP’s version_compare.
16455	 *
16456	 * @param {String} v1
16457	 * @param {String} v2
16458	 * @param {String} operator
16459	 *
16460	 * @return {Boolean}
16461	 */
16462	function version_compare(v1, v2, operator) {
16463		this.php_js = this.php_js || {};
16464		this.php_js.ENV = this.php_js.ENV || {};
16465		var i = 0,
16466			x = 0,
16467			compare = 0,
16468			vm = {
16469				'dev': -6,
16470				'alpha': -5,
16471				'a': -5,
16472				'beta': -4,
16473				'b': -4,
16474				'RC': -3,
16475				'rc': -3,
16476				'#': -2,
16477				'p': 1,
16478				'pl': 1
16479			},
16480			prepVersion = function(v) {
16481				v = ('' + v).replace(/[_\-+]/g, '.');
16482				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
16483				return (!v.length ? [-8] : v.split('.'));
16484			},
16485			numVersion = function(v) {
16486				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
16487			};
16488		v1 = prepVersion(v1);
16489		v2 = prepVersion(v2);
16490		x = max(v1.length, v2.length);
16491		for (i = 0; i < x; i++) {
16492			if (v1[i] == v2[i]) {
16493				continue;
16494			}
16495			v1[i] = numVersion(v1[i]);
16496			v2[i] = numVersion(v2[i]);
16497			if (v1[i] < v2[i]) {
16498				compare = -1;
16499				break;
16500			} else if (v1[i] > v2[i]) {
16501				compare = 1;
16502				break;
16503			}
16504		}
16505		if (!operator) {
16506			return compare;
16507		}
16508
16509		switch (operator) {
16510			case '>':
16511			case 'gt':
16512				return (compare > 0);
16513			case '>=':
16514			case 'ge':
16515				return (compare >= 0);
16516			case '<=':
16517			case 'le':
16518				return (compare <= 0);
16519			case '==':
16520			case '=':
16521			case 'eq':
16522				return (compare === 0);
16523			case '<>':
16524			case '!=':
16525			case 'ne':
16526				return (compare !== 0);
16527			case '':
16528			case '<':
16529			case 'lt':
16530				return (compare < 0);
16531			default:
16532				return null;
16533		}
16534	}
16535
16536
16537	// Begin the iLightBox plugin
16538	$.fn.iLightBox = function() {
16539
16540		var args = arguments,
16541			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
16542			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
16543
16544		if (!opt) opt = {};
16545
16546		// Default options. Play carefully.
16547		var options = $.extend(true, {
16548			attr: 'href',
16549			path: 'vertical',
16550			skin: 'dark',
16551			linkId: false,
16552			infinite: false,
16553			startFrom: 0,
16554			randomStart: false,
16555			keepAspectRatio: true,
16556			maxScale: 1,
16557			minScale: .2,
16558			innerToolbar: false,
16559			smartRecognition: false,
16560			mobileOptimizer: true,
16561			fullAlone: true,
16562			fullViewPort: null,
16563			fullStretchTypes: 'flash, video',
16564			overlay: {
16565				blur: true,
16566				opacity: .85
16567			},
16568			controls: {
16569				arrows: false,
16570				slideshow: false,
16571				toolbar: true,
16572				fullscreen: true,
16573				thumbnail: true,
16574				keyboard: true,
16575				mousewheel: true,
16576				swipe: true
16577			},
16578			keyboard: {
16579				left: true, // previous
16580				right: true, // next
16581				up: true, // previous
16582				down: true, // next
16583				esc: true, // close
16584				shift_enter: true // fullscreen
16585			},
16586			show: {
16587				effect: true,
16588				speed: 300,
16589				title: true
16590			},
16591			hide: {
16592				effect: true,
16593				speed: 300
16594			},
16595			caption: {
16596				start: true,
16597				show: 'mouseenter',
16598				hide: 'mouseleave'
16599			},
16600			social: {
16601				start: true,
16602				show: 'mouseenter',
16603				hide: 'mouseleave',
16604				buttons: false
16605			},
16606			styles: {
16607				pageOffsetX: 0,
16608				pageOffsetY: 0,
16609				nextOffsetX: 45,
16610				nextOffsetY: 0,
16611				nextOpacity: 1,
16612				nextScale: 1,
16613				prevOffsetX: 45,
16614				prevOffsetY: 0,
16615				prevOpacity: 1,
16616				prevScale: 1
16617			},
16618			thumbnails: {
16619				maxWidth: 120,
16620				maxHeight: 80,
16621				normalOpacity: 1,
16622				activeOpacity: .6
16623			},
16624			effects: {
16625				reposition: true,
16626				repositionSpeed: 200,
16627				switchSpeed: 500,
16628				loadedFadeSpeed: 180,
16629				fadeSpeed: 200
16630			},
16631			slideshow: {
16632				pauseTime: 5000,
16633				pauseOnHover: false,
16634				startPaused: true
16635			},
16636			text: {
16637				close: "Press Esc to close",
16638				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
16639				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
16640				slideShow: "Slideshow",
16641				next: "Next",
16642				previous: "Previous"
16643			},
16644			errors: {
16645				loadImage: "An error occurred when trying to load photo.",
16646				loadContents: "An error occurred when trying to load contents.",
16647				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
16648			},
16649			ajaxSetup: {
16650				url: '',
16651				beforeSend: function(jqXHR, settings) {},
16652				cache: false,
16653				complete: function(jqXHR, textStatus) {},
16654				crossDomain: false,
16655				error: function(jqXHR, textStatus, errorThrown) {},
16656				success: function(data, textStatus, jqXHR) {},
16657				global: true,
16658				ifModified: false,
16659				username: null,
16660				password: null,
16661				type: 'GET'
16662			},
16663			callback: {}
16664		}, opt);
16665
16666		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
16667
16668		items = $.isArray(items) ? items : new Array();
16669
16670		if (typeof args[0] == 'string') items[0] = args[0];
16671
16672		if (version_compare($.fn.jquery, '1.8', '>=')) {
16673			var iLB = new iLightBox($(this), options, items, instant);
16674			return {
16675				close: function() {
16676					iLB.closeAction();
16677				},
16678				fullscreen: function() {
16679					iLB.fullScreenAction();
16680				},
16681				moveNext: function() {
16682					iLB.moveTo('next');
16683				},
16684				movePrev: function() {
16685					iLB.moveTo('prev');
16686				},
16687				goTo: function(index) {
16688					iLB.goTo(index);
16689				},
16690				refresh: function() {
16691					iLB.refresh();
16692				},
16693				reposition: function() {
16694					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
16695				},
16696				setOption: function(options) {
16697					iLB.setOption(options);
16698				},
16699				destroy: function() {
16700					iLB.closeAction();
16701					iLB.dispatchItemsEvents();
16702				}
16703			};
16704		} else {
16705			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
16706		}
16707
16708	};
16709
16710
16711	$.iLightBox = function() {
16712		return $.fn.iLightBox(arguments[0], arguments[1]);
16713	};
16714
16715	function getScrollXY() {
16716		var scrOfX = 0,
16717			scrOfY = 0;
16718		if (typeof(window.pageYOffset) == 'number') {
16719			//Netscape compliant
16720			scrOfY = window.pageYOffset;
16721			scrOfX = window.pageXOffset;
16722		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
16723			//DOM compliant
16724			scrOfY = document.body.scrollTop;
16725			scrOfX = document.body.scrollLeft;
16726		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
16727			//IE6 standards compliant mode
16728			scrOfY = document.documentElement.scrollTop;
16729			scrOfX = document.documentElement.scrollLeft;
16730		}
16731		return {
16732			x: scrOfX,
16733			y: scrOfY
16734		};
16735	}
16736
16737	(function() {
16738		// add new event shortcuts
16739		$.each(("touchstart touchmove touchend " +
16740			"tap taphold " +
16741			"swipe swipeleft swiperight " +
16742			"scrollstart scrollstop").split(" "), function(i, name) {
16743
16744			$.fn[name] = function(fn) {
16745				return fn ? this.bind(name, fn) : this.trigger(name);
16746			};
16747
16748			// jQuery < 1.8
16749			// if ($.attrFn) {
16750			// 	$.attrFn[name] = true;
16751			// }
16752		});
16753
16754		var tapSettings = {
16755			startEvent: 'touchstart.iTap',
16756			endEvent: 'touchend.iTap'
16757		};
16758
16759		// tap Event:
16760		$.event.special.itap = {
16761			setup: function() {
16762
16763				var self = this,
16764					$self = $(this),
16765					start, stop;
16766
16767				$self.bind(tapSettings.startEvent, function(event) {
16768					start = getScrollXY();
16769
16770					$self.one(tapSettings.endEvent, function(event) {
16771						stop = getScrollXY();
16772
16773						var orgEvent = event || window.event;
16774						event = $.event.fix(orgEvent);
16775						event.type = "itap";
16776
16777						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
16778
16779						start = stop = undefined;
16780					});
16781				});
16782			},
16783
16784			teardown: function() {
16785				$(this).unbind(tapSettings.startEvent);
16786			}
16787		};
16788	}());
16789
16790
16791	//Fullscreen API
16792	(function() {
16793		fullScreenApi = {
16794				supportsFullScreen: false,
16795				isFullScreen: function() {
16796					return false;
16797				},
16798				requestFullScreen: function() {},
16799				cancelFullScreen: function() {},
16800				fullScreenEventName: '',
16801				prefix: ''
16802			},
16803			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
16804
16805		// check for native support
16806		if (typeof document.cancelFullScreen != 'undefined') {
16807			fullScreenApi.supportsFullScreen = true;
16808		} else {
16809			// check for fullscreen support by vendor prefix
16810			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
16811				fullScreenApi.prefix = browserPrefixes[i];
16812
16813				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
16814					fullScreenApi.supportsFullScreen = true;
16815
16816					break;
16817				}
16818			}
16819		}
16820
16821		// update methods to do something useful
16822		if (fullScreenApi.supportsFullScreen) {
16823			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
16824
16825			fullScreenApi.isFullScreen = function() {
16826				switch (this.prefix) {
16827					case '':
16828						return document.fullScreen;
16829					case 'webkit':
16830						return document.webkitIsFullScreen;
16831					default:
16832						return document[this.prefix + 'FullScreen'];
16833				}
16834			}
16835			fullScreenApi.requestFullScreen = function(el) {
16836				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
16837			}
16838			fullScreenApi.cancelFullScreen = function(el) {
16839				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
16840			}
16841		}
16842	}());
16843
16844	// Browser detect
16845	(function() {
16846		function uaMatch(ua) {
16847			ua = ua.toLowerCase();
16848
16849			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
16850				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
16851				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
16852				/(msie) ([\w.]+)/.exec(ua) ||
16853				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
16854
16855			return {
16856				browser: match[1] || "",
16857				version: match[2] || "0"
16858			};
16859		}
16860
16861		var matched = uaMatch(navigator.userAgent);
16862		browser = {};
16863
16864		if (matched.browser) {
16865			browser[matched.browser] = true;
16866			browser.version = matched.version;
16867		}
16868
16869		// Chrome is Webkit, but Webkit is also Safari.
16870		if (browser.chrome) {
16871			browser.webkit = true;
16872		} else if (browser.webkit) {
16873			browser.safari = true;
16874		}
16875	}());
16876
16877	// Feature detects
16878	(function() {
16879		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
16880		var el = document.createElement('div');
16881
16882		function testProp(prop) {
16883			for (var p = 0, pl = prefixes.length; p < pl; p++) {
16884				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
16885				if (el.style[prefixedProp] !== undefined) {
16886					return prefixedProp;
16887				}
16888			}
16889		}
16890
16891		// Global support indicators
16892		transform = testProp('transform') || '';
16893		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
16894	}());
16895
16896
16897	/*
16898		PluginDetect v0.7.9
16899		www.pinlady.net/PluginDetect/license/
16900		[ getVersion onWindowLoaded BetterIE ]
16901		[ Flash QuickTime Shockwave ]
16902	*/
16903	var PluginDetect={version:"0.7.9",name:"PluginDetect",handler:function(c,b,a){return function(){c(b,a)}},openTag:"<",isDefined:function(b){return typeof b!="undefined"},isArray:function(b){return(/array/i).test(Object.prototype.toString.call(b))},isFunc:function(b){return typeof b=="function"},isString:function(b){return typeof b=="string"},isNum:function(b){return typeof b=="number"},isStrNum:function(b){return(typeof b=="string"&&(/\d/).test(b))},getNumRegx:/[\d][\d\.\_,-]*/,splitNumRegx:/[\.\_,-]/g,getNum:function(b,c){var d=this,a=d.isStrNum(b)?(d.isDefined(c)?new RegExp(c):d.getNumRegx).exec(b):null;return a?a[0]:null},compareNums:function(h,f,d){var e=this,c,b,a,g=parseInt;if(e.isStrNum(h)&&e.isStrNum(f)){if(e.isDefined(d)&&d.compareNums){return d.compareNums(h,f)}c=h.split(e.splitNumRegx);b=f.split(e.splitNumRegx);for(a=0;a<min(c.length,b.length);a++){if(g(c[a],10)>g(b[a],10)){return 1}if(g(c[a],10)<g(b[a],10)){return -1}}}return 0},formatNum:function(b,c){var d=this,a,e;if(!d.isStrNum(b)){return null}if(!d.isNum(c)){c=4}c--;e=b.replace(/\s/g,"").split(d.splitNumRegx).concat(["0","0","0","0"]);for(a=0;a<4;a++){if(/^(0+)(.+)$/.test(e[a])){e[a]=RegExp.$2}if(a>c||!(/\d/).test(e[a])){e[a]="0"}}return e.slice(0,4).join(",")},$$hasMimeType:function(a){return function(c){if(!a.isIE&&c){var f,e,b,d=a.isArray(c)?c:(a.isString(c)?[c]:[]);for(b=0;b<d.length;b++){if(a.isString(d[b])&&/[^\s]/.test(d[b])){f=navigator.mimeTypes[d[b]];e=f?f.enabledPlugin:0;if(e&&(e.name||e.description)){return f}}}}return null}},findNavPlugin:function(l,e,c){var j=this,h=new RegExp(l,"i"),d=(!j.isDefined(e)||e)?/\d/:0,k=c?new RegExp(c,"i"):0,a=navigator.plugins,g="",f,b,m;for(f=0;f<a.length;f++){m=a[f].description||g;b=a[f].name||g;if((h.test(m)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))||(h.test(b)&&(!d||d.test(RegExp.leftContext+RegExp.rightContext)))){if(!k||!(k.test(m)||k.test(b))){return a[f]}}}return null},getMimeEnabledPlugin:function(k,m,c){var e=this,f,b=new RegExp(m,"i"),h="",g=c?new RegExp(c,"i"):0,a,l,d,j=e.isString(k)?[k]:k;for(d=0;d<j.length;
16903d++){if((f=e.hasMimeType(j[d]))&&(f=f.enabledPlugin)){l=f.description||h;a=f.name||h;if(b.test(l)||b.test(a)){if(!g||!(g.test(l)||g.test(a))){return f}}}}return 0},getPluginFileVersion:function(f,b){var h=this,e,d,g,a,c=-1;if(h.OS>2||!f||!f.version||!(e=h.getNum(f.version))){return b}if(!b){return e}e=h.formatNum(e);b=h.formatNum(b);d=b.split(h.splitNumRegx);g=e.split(h.splitNumRegx);for(a=0;a<d.length;a++){if(c>-1&&a>c&&d[a]!="0"){return b}if(g[a]!=d[a]){if(c==-1){c=a}if(d[a]!="0"){return b}}}return e},AXO:window.ActiveXObject,getAXO:function(a){var f=null,d,b=this,c={};try{f=new b.AXO(a)}catch(d){}return f},convertFuncs:function(f){var a,g,d,b=/^[\$][\$]/,c=this;for(a in f){if(b.test(a)){try{g=a.slice(2);if(g.length>0&&!f[g]){f[g]=f[a](f);delete f[a]}}catch(d){}}}},initObj:function(e,b,d){var a,c;if(e){if(e[b[0]]==1||d){for(a=0;a<b.length;a=a+2){e[b[a]]=b[a+1]}}for(a in e){c=e[a];if(c&&c[b[0]]==1){this.initObj(c,b)}}}},initScript:function(){var d=this,a=navigator,h,i=document,l=a.userAgent||"",j=a.vendor||"",b=a.platform||"",k=a.product||"";d.initObj(d,["$",d]);for(h in d.Plugins){if(d.Plugins[h]){d.initObj(d.Plugins[h],["$",d,"$$",d.Plugins[h]],1)}}d.convertFuncs(d);d.OS=100;if(b){var g=["Win",1,"Mac",2,"Linux",3,"FreeBSD",4,"iPhone",21.1,"iPod",21.2,"iPad",21.3,"Win.*CE",22.1,"Win.*Mobile",22.2,"Pocket\\s*PC",22.3,"",100];for(h=g.length-2;h>=0;h=h-2){if(g[h]&&new RegExp(g[h],"i").test(b)){d.OS=g[h+1];break}}};d.head=i.getElementsByTagName("head")[0]||i.getElementsByTagName("body")[0]||i.body||null;d.isIE=new Function("return/*@cc_on!@*/!1")();d.verIE=d.isIE&&(/MSIE\s*(\d+\.?\d*)/i).test(l)?parseFloat(RegExp.$1,10):null;d.verIEfull=null;d.docModeIE=null;if(d.isIE){var f,n,c=document.createElement("div");try{c.style.behavior="url(#default#clientcaps)";d.verIEfull=(c.getComponentVersion("{89820200-ECBD-11CF-8B85-00AA005B4383}","componentid")).replace(/,/g,".")}catch(f){}n=parseFloat(d.verIEfull||"0",10);d.docModeIE=i.documentMode||((/back/i).test(i.compatMode||"")?5:n)||d.verIE;d.verIE=n||d.docModeIE};d.ActiveXEnabled=false;if(d.isIE){var h,m=["Msxml2.XMLHTTP","Msxml2.DOMDocument","Microsoft.XMLDOM","ShockwaveFlash.ShockwaveFlash","TDCCtl.TDCCtl","Shell.UIHelper","Scripting.Dictionary","wmplayer.ocx"];for(h=0;h<m.length;h++){if(d.getAXO(m[h])){d.ActiveXEnabled=true;break}}};d.isGecko=(/Gecko/i).test(k)&&(/Gecko\s*\/\s*\d/i).test(l);
16903d.verGecko=d.isGecko?d.formatNum((/rv\s*\:\s*([\.\,\d]+)/i).test(l)?RegExp.$1:"0.9"):null;d.isChrome=(/Chrome\s*\/\s*(\d[\d\.]*)/i).test(l);d.verChrome=d.isChrome?d.formatNum(RegExp.$1):null;d.isSafari=((/Apple/i).test(j)||(!j&&!d.isChrome))&&(/Safari\s*\/\s*(\d[\d\.]*)/i).test(l);d.verSafari=d.isSafari&&(/Version\s*\/\s*(\d[\d\.]*)/i).test(l)?d.formatNum(RegExp.$1):null;d.isOpera=(/Opera\s*[\/]?\s*(\d+\.?\d*)/i).test(l);d.verOpera=d.isOpera&&((/Version\s*\/\s*(\d+\.?\d*)/i).test(l)||1)?parseFloat(RegExp.$1,10):null;d.addWinEvent("load",d.handler(d.runWLfuncs,d))},init:function(d){var c=this,b,d,a={status:-3,plugin:0};if(!c.isString(d)){return a}if(d.length==1){c.getVersionDelimiter=d;return a}d=d.toLowerCase().replace(/\s/g,"");b=c.Plugins[d];if(!b||!b.getVersion){return a}a.plugin=b;if(!c.isDefined(b.installed)){b.installed=null;b.version=null;b.version0=null;b.getVersionDone=null;b.pluginName=d}c.garbage=false;if(c.isIE&&!c.ActiveXEnabled&&d!=="java"){a.status=-2;return a}a.status=1;return a},fPush:function(b,a){var c=this;if(c.isArray(a)&&(c.isFunc(b)||(c.isArray(b)&&b.length>0&&c.isFunc(b[0])))){a.push(b)}},callArray:function(b){var c=this,a;if(c.isArray(b)){for(a=0;a<b.length;a++){if(b[a]===null){return}c.call(b[a]);b[a]=null}}},call:function(c){var b=this,a=b.isArray(c)?c.length:-1;if(a>0&&b.isFunc(c[0])){c[0](b,a>1?c[1]:0,a>2?c[2]:0,a>3?c[3]:0)}else{if(b.isFunc(c)){c(b)}}},getVersionDelimiter:",",$$getVersion:function(a){return function(g,d,c){var e=a.init(g),f,b,h={};if(e.status<0){return null};f=e.plugin;if(f.getVersionDone!=1){f.getVersion(null,d,c);if(f.getVersionDone===null){f.getVersionDone=1}}a.cleanup();b=(f.version||f.version0);b=b?b.replace(a.splitNumRegx,a.getVersionDelimiter):b;return b}},cleanup:function(){var a=this;if(a.garbage&&a.isDefined(window.CollectGarbage)){window.CollectGarbage()}},isActiveXObject:function(d,b){var f=this,a=false,g,c='<object width="1" height="1" style="display:none" '+d.getCodeBaseVersion(b)+">"+d.HTML+f.openTag+"/object>";if(!f.head){return a}f.head.insertBefore(document.createElement("object"),f.head.firstChild);f.head.firstChild.outerHTML=c;try{f.head.firstChild.classid=d.classID}catch(g){}try{if(f.head.firstChild.object){a=true}}catch(g){}try{if(a&&f.head.firstChild.readyState<4){f.garbage=true}}catch(g){}f.head.removeChild(f.head.firstChild);return a},codebaseSearch:function(f,b){var c=this;if(!c.ActiveXEnabled||!f){return null}if(f.BIfuncs&&f.BIfuncs.length&&f.BIfuncs[f.BIfuncs.length-1]!==null){c.callArray(f.BIfuncs)}var d,o=f.SEARCH,k={};if(c.isStrNum(b)){if(o.match&&o.min&&c.compareNums(b,o.min)<=0){return true}if(o.match&&o.max&&c.compareNums(b,o.max)>=0){return false}d=c.isActiveXObject(f,b);if(d&&(!o.min||c.compareNums(b,o.min)>0)){o.min=b}if(!d&&(!o.max||c.compareNums(b,o.max)<0)){o.max=b}return d};var e=[0,0,0,0],l=[].concat(o.digits),a=o.min?1:0,j,i,h,g,m,n=function(p,r){var q=[].concat(e);q[p]=r;return c.isActiveXObject(f,q.join(","))};if(o.max){g=o.max.split(c.splitNumRegx);for(j=0;j<g.length;j++){g[j]=parseInt(g[j],10)}if(g[0]<l[0]){l[0]=g[0]}}if(o.min){m=o.min.split(c.splitNumRegx);for(j=0;j<m.length;j++){m[j]=parseInt(m[j],10)}if(m[0]>e[0]){e[0]=m[0]}}if(m&&g){for(j=1;j<m.length;j++){if(m[j-1]!=g[j-1]){break}if(g[j]<l[j]){l[j]=g[j]}if(m[j]>e[j]){e[j]=m[j]}}}if(o.max){for(j=1;j<l.length;j++){if(g[j]>0&&l[j]==0&&l[j-1]<o.digits[j-1]){l[j-1]+=1;break}}};for(j=0;j<l.length;j++){h={};for(i=0;i<20;i++){if(l[j]-e[j]<1){break}d=round((l[j]+e[j])/2);if(h["a"+d]){break}h["a"+d]=1;if(n(j,d)){e[j]=d;a=1}else{l[j]=d}}l[j]=e[j];if(!a&&n(j,e[j])){a=1};if(!a){break}};return a?e.join(","):null},addWinEvent:function(d,c){var e=this,a=window,b;if(e.isFunc(c)){if(a.addEventListener){a.addEventListener(d,c,false)}else{if(a.attachEvent){a.attachEvent("on"+d,c)}else{b=a["on"+d];a["on"+d]=e.winHandler(c,b)}}}},winHandler:function(d,c){return function(){d();if(typeof c=="function"){c()}}},WLfuncs0:[],WLfuncs:[],runWLfuncs:function(a){var b={};a.winLoaded=true;a.callArray(a.WLfuncs0);a.callArray(a.WLfuncs);if(a.onDoneEmptyDiv){a.onDoneEmptyDiv()}},winLoaded:false,$$onWindowLoaded:function(a){return function(b){if(a.winLoaded){a.call(b)}else{a.fPush(b,a.WLfuncs)}}},div:null,divID:"plugindetect",divWidth:50,pluginSize:1,emptyDiv:function(){var d=this,b,h,c,a,f,g;if(d.div&&d.div.childNodes){for(b=d.div.childNodes.length-1;b>=0;b--){c=d.div.childNodes[b];if(c&&c.childNodes){for(h=c.childNodes.length-1;h>=0;h--){g=c.childNodes[h];try{c.removeChild(g)}catch(f){}}}if(c){try{d.div.removeChild(c)}catch(f){}}}}if(!d.div){a=document.getElementById(d.divID);if(a){d.div=a}}if(d.div&&d.div.parentNode){try{d.div.parentNode.removeChild(d.div)}catch(f){}d.div=null}},DONEfuncs:[],onDoneEmptyDiv:function(){var c=this,a,b;if(!c.winLoaded){return}if(c.WLfuncs&&c.WLfuncs.length&&c.WLfuncs[c.WLfuncs.length-1]!==null){return}for(a in c){b=c[a];if(b&&b.funcs){if(b.OTF==3){return}if(b.funcs.length&&b.funcs[b.funcs.length-1]!==null){return}}}for(a=0;a<c.DONEfuncs.length;a++){c.callArray(c.DONEfuncs)}
16903c.emptyDiv()},getWidth:function(c){if(c){var a=c.scrollWidth||c.offsetWidth,b=this;if(b.isNum(a)){return a}}return -1},getTagStatus:function(m,g,a,b){var c=this,f,k=m.span,l=c.getWidth(k),h=a.span,j=c.getWidth(h),d=g.span,i=c.getWidth(d);if(!k||!h||!d||!c.getDOMobj(m)){return -2}if(j<i||l<0||j<0||i<0||i<=c.pluginSize||c.pluginSize<1){return 0}if(l>=i){return -1}try{if(l==c.pluginSize&&(!c.isIE||c.getDOMobj(m).readyState==4)){if(!m.winLoaded&&c.winLoaded){return 1}if(m.winLoaded&&c.isNum(b)){if(!c.isNum(m.count)){m.count=b}if(b-m.count>=10){return 1}}}}catch(f){}return 0},getDOMobj:function(g,a){var f,d=this,c=g?g.span:0,b=c&&c.firstChild?1:0;try{if(b&&a){d.div.focus()}}catch(f){}return b?c.firstChild:null},setStyle:function(b,g){var f=b.style,a,d,c=this;if(f&&g){for(a=0;a<g.length;a=a+2){try{f[g[a]]=g[a+1]}catch(d){}}}},insertDivInBody:function(i,g){var f,c=this,h="pd33993399",b=null,d=g?window.top.document:window.document,a=d.getElementsByTagName("body")[0]||d.body;if(!a){try{d.write('<div id="'+h+'">.'+c.openTag+"/div>");b=d.getElementById(h)}catch(f){}}a=d.getElementsByTagName("body")[0]||d.body;if(a){a.insertBefore(i,a.firstChild);if(b){a.removeChild(b)}}},insertHTML:function(f,b,g,a,k){var l,m=document,j=this,p,o=m.createElement("span"),n,i;var c=["outlineStyle","none","borderStyle","none","padding","0px","margin","0px","visibility","visible"];var h="outline-style:none;border-style:none;padding:0px;margin:0px;visibility:visible;";if(!j.isDefined(a)){a=""}if(j.isString(f)&&(/[^\s]/).test(f)){f=f.toLowerCase().replace(/\s/g,"");p=j.openTag+f+' width="'+j.pluginSize+'" height="'+j.pluginSize+'" ';p+='style="'+h+'display:inline;" ';for(n=0;n<b.length;n=n+2){if(/[^\s]/.test(b[n+1])){p+=b[n]+'="'+b[n+1]+'" '}}p+=">";for(n=0;n<g.length;n=n+2){if(/[^\s]/.test(g[n+1])){p+=j.openTag+'param name="'+g[n]+'" value="'+g[n+1]+'" />'}}p+=a+j.openTag+"/"+f+">"}else{p=a}if(!j.div){i=m.getElementById(j.divID);if(i){j.div=i}else{j.div=m.createElement("div");j.div.id=j.divID}j.setStyle(j.div,c.concat(["width",j.divWidth+"px","height",(j.pluginSize+3)+"px","fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","block"]));if(!i){j.setStyle(j.div,["position","absolute","right","0px","top","0px"]);j.insertDivInBody(j.div)}}if(j.div&&j.div.parentNode){j.setStyle(o,c.concat(["fontSize",(j.pluginSize+3)+"px","lineHeight",(j.pluginSize+3)+"px","verticalAlign","baseline","display","inline"]));try{o.innerHTML=p}catch(l){};try{j.div.appendChild(o)}catch(l){};return{span:o,winLoaded:j.winLoaded,tagName:f,outerHTML:p}}return{span:null,winLoaded:j.winLoaded,tagName:"",outerHTML:p}},Plugins:{quicktime:{mimeType:["video/quicktime","application/x-quicktimeplayer","image/x-macpaint","image/x-quicktime"],progID:"QuickTimeCheckObject.QuickTimeCheck.1",progID0:"QuickTime.QuickTime",classID:"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B",minIEver:7,HTML:'<param name="src" value="" /><param name="controller" value="false" />',getCodeBaseVersion:function(a){return'codebase="#version='+a+'"'},SEARCH:{min:0,max:0,match:0,digits:[16,128,128,0]},getVersion:function(c){var f=this,d=f.$,a=null,e=null,b;if(!d.isIE){if(d.hasMimeType(f.mimeType)){e=d.OS!=3?d.findNavPlugin("QuickTime.*Plug-?in",0):null;if(e&&e.name){a=d.getNum(e.name)}}}else{if(d.isStrNum(c)){b=c.split(d.splitNumRegx);if(b.length>3&&parseInt(b[3],10)>0){b[3]="9999"}c=b.join(",")}if(d.isStrNum(c)&&d.verIE>=f.minIEver&&f.canUseIsMin()>0){f.installed=f.isMin(c);f.getVersionDone=0;return}f.getVersionDone=1;if(!a&&d.verIE>=f.minIEver){a=f.CDBASE2VER(d.codebaseSearch(f))}if(!a){e=d.getAXO(f.progID);if(e&&e.QuickTimeVersion){a=e.QuickTimeVersion.toString(16);a=parseInt(a.charAt(0),16)+"."+parseInt(a.charAt(1),16)+"."+parseInt(a.charAt(2),16)}}}f.installed=a?1:(e?0:-1);f.version=d.formatNum(a,3)},cdbaseUpper:["7,60,0,0","0,0,0,0"],cdbaseLower:["7,50,0,0",null],cdbase2ver:[function(c,b){var a=b.split(c.$.splitNumRegx);return[a[0],a[1].charAt(0),a[1].charAt(1),a[2]].join(",")},null],CDBASE2VER:function(f){var e=this,c=e.$,b,a=e.cdbaseUpper,d=e.cdbaseLower;
16903if(f){f=c.formatNum(f);for(b=0;b<a.length;b++){if(a[b]&&c.compareNums(f,a[b])<0&&d[b]&&c.compareNums(f,d[b])>=0&&e.cdbase2ver[b]){return e.cdbase2ver[b](e,f)}}}return f},canUseIsMin:function(){var f=this,d=f.$,b,c=f.canUseIsMin,a=f.cdbaseUpper,e=f.cdbaseLower;if(!c.value){c.value=-1;for(b=0;b<a.length;b++){if(a[b]&&d.codebaseSearch(f,a[b])){c.value=1;break}if(e[b]&&d.codebaseSearch(f,e[b])){c.value=-1;break}}}f.SEARCH.match=c.value==1?1:0;return c.value},isMin:function(c){var b=this,a=b.$;return a.codebaseSearch(b,c)?0.7:-1}},flash:{mimeType:"application/x-shockwave-flash",progID:"ShockwaveFlash.ShockwaveFlash",classID:"clsid:D27CDB6E-AE6D-11CF-96B8-444553540000",getVersion:function(){var b=function(i){if(!i){return null}var e=/[\d][\d\,\.\s]*[rRdD]{0,1}[\d\,]*/.exec(i);return e?e[0].replace(/[rRdD\.]/g,",").replace(/\s/g,""):null};var j=this,g=j.$,k,h,l=null,c=null,a=null,f,m,d;if(!g.isIE){m=g.hasMimeType(j.mimeType);if(m){f=g.getDOMobj(g.insertHTML("object",["type",j.mimeType],[],"",j));try{l=g.getNum(f.GetVariable("$version"))}catch(k){}}if(!l){d=m?m.enabledPlugin:null;if(d&&d.description){l=b(d.description)}if(l){l=g.getPluginFileVersion(d,l)}}}else{for(h=15;h>2;h--){c=g.getAXO(j.progID+"."+h);if(c){a=h.toString();break}}if(!c){c=g.getAXO(j.progID)}if(a=="6"){try{c.AllowScriptAccess="always"}catch(k){return"6,0,21,0"}}try{l=b(c.GetVariable("$version"))}catch(k){}if(!l&&a){l=a}}j.installed=l?1:-1;j.version=g.formatNum(l);return true}},shockwave:{mimeType:"application/x-director",progID:"SWCtl.SWCtl",classID:"clsid:166B1BCA-3F9C-11CF-8075-444553540000",getVersion:function(){var a=null,b=null,g,f,d=this,c=d.$;if(!c.isIE){f=c.findNavPlugin("Shockwave\\s*for\\s*Director");if(f&&f.description&&c.hasMimeType(d.mimeType)){a=c.getNum(f.description)}if(a){a=c.getPluginFileVersion(f,a)}}else{try{b=c.getAXO(d.progID).ShockwaveVersion("")}catch(g){}if(c.isString(b)&&b.length>0){a=c.getNum(b)}else{if(c.getAXO(d.progID+".8")){a="8"}else{if(c.getAXO(d.progID+".7")){a="7"}else{if(c.getAXO(d.progID+".1")){a="6"}}}}}d.installed=a?1:-1;d.version=c.formatNum(a)}},zz:0}};PluginDetect.initScript();
16904
16905	var gArgCountErr='The "%%" function requires an even number of arguments.\nArguments should be in the form "atttributeName", "attributeValue", ...',gTagAttrs=null,gQTGeneratorVersion=1;function AC_QuickTimeVersion(){return gQTGeneratorVersion}function _QTComplain(a,b){b=b.replace("%%",a);alert(b)}function _QTAddAttribute(a,b,c){var d;d=gTagAttrs[a+b];null==d&&(d=gTagAttrs[b]);return null!=d?(0==b.indexOf(a)&&null==c&&(c=b.substring(a.length)),null==c&&(c=b),c+'="'+d+'" '):""}function _QTAddObjectAttr(a,b){if(0==a.indexOf("emb#"))return"";0==a.indexOf("obj#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("obj#",a,b)}function _QTAddEmbedAttr(a,b){if(0==a.indexOf("obj#"))return"";0==a.indexOf("emb#")&&null==b&&(b=a.substring(4));return _QTAddAttribute("emb#",a,b)}function _QTAddObjectParam(a,b){var c,d="",e=b?" />":">";-1==a.indexOf("emb#")&&(c=gTagAttrs["obj#"+a],null==c&&(c=gTagAttrs[a]),0==a.indexOf("obj#")&&(a=a.substring(4)),null!=c&&(d='  <param name="'+a+'" value="'+c+'"'+e+"\n"));return d}function _QTDeleteTagAttrs(){for(var a=0;a<arguments.length;a++){var b=arguments[a];delete gTagAttrs[b];delete gTagAttrs["emb#"+b];delete gTagAttrs["obj#"+b]}}function _QTGenerate(a,b,c){if(4>c.length||0!=c.length%2)return _QTComplain(a,gArgCountErr),"";gTagAttrs=[];gTagAttrs.src=c[0];gTagAttrs.width=c[1];gTagAttrs.height=c[2];gTagAttrs.classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";gTagAttrs.pluginspage="http://www.apple.com/quicktime/download/";a=c[3];if(null==a||""==a)a="6,0,2,0";gTagAttrs.codebase="http://www.apple.com/qtactivex/qtplugin.cab#version="+a;for(var d,e=4;e<c.length;e+=2)d=c[e].toLowerCase(),a=c[e+1],"name"==d||"id"==d?gTagAttrs.name=a:gTagAttrs[d]=a;c="<object "+_QTAddObjectAttr("classid")+_QTAddObjectAttr("width")+_QTAddObjectAttr("height")+_QTAddObjectAttr("codebase")+_QTAddObjectAttr("name","id")+_QTAddObjectAttr("tabindex")+_QTAddObjectAttr("hspace")+_QTAddObjectAttr("vspace")+_QTAddObjectAttr("border")+_QTAddObjectAttr("align")+_QTAddObjectAttr("class")+_QTAddObjectAttr("title")+_QTAddObjectAttr("accesskey")+_QTAddObjectAttr("noexternaldata")+">\n"+_QTAddObjectParam("src",b);e="  <embed "+_QTAddEmbedAttr("src")+_QTAddEmbedAttr("width")+_QTAddEmbedAttr("height")+_QTAddEmbedAttr("pluginspage")+_QTAddEmbedAttr("name")+_QTAddEmbedAttr("align")+_QTAddEmbedAttr("tabindex");_QTDeleteTagAttrs("src","width","height","pluginspage","classid","codebase","name","tabindex","hspace","vspace","border","align","noexternaldata","class","title","accesskey");for(d in gTagAttrs)a=gTagAttrs[d],null!=a&&(e+=_QTAddEmbedAttr(d),c+=_QTAddObjectParam(d,b));return c+e+"> </embed>\n</object>"}function QT_GenerateOBJECTText(){return _QTGenerate("QT_GenerateOBJECTText",!1,arguments)};
16906
16907
16908	/*
16909		jQuery hashchange event v1.3
16910		https://github.com/cowboy/jquery-hashchange
16911		Copyright (c) 2010 "Cowboy" Ben Alman
16912		Dual licensed under the MIT and GPL licenses.
16913	*/
16914	(function(){function e(a){a=a||location.href;return"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var k=document,b,f=$.event.special,p=k.documentMode,m="oniLightBoxHashChange"in window&&(void 0===p||7<p);$.fn.iLightBoxHashChange=function(a){return a?this.bind("iLightBoxHashChange",a):this.trigger("iLightBoxHashChange")};$.fn.iLightBoxHashChange.delay=50;f.iLightBoxHashChange=$.extend(f.iLightBoxHashChange,{setup:function(){if(m)return!1;$(b.start)},teardown:function(){if(m)return!1;$(b.stop)}});b=function(){function a(){var c=
16915	e(),d=f(l);c!==l?(n(l=c,d),$(window).trigger("iLightBoxHashChange")):d!==l&&(location.href=location.href.replace(/#.*/,"")+d);g=setTimeout(a,$.fn.iLightBoxHashChange.delay)}var h={},g,l=e(),b=function(c){return c},n=b,f=b;h.start=function(){g||a()};h.stop=function(){g&&clearTimeout(g);g=void 0};browser.msie&&!m&&function(){var c,d;h.start=function(){c||(d=(d=$.fn.iLightBoxHashChange.src)&&d+e(),c=$('<iframe tabindex="-1" title="empty"/>').hide().one("load",function(){d||n(e());a()}).attr("src",d||
16916	"javascript:0").insertAfter("body")[0].contentWindow,k.onpropertychange=function(){try{"title"===event.propertyName&&(c.document.title=k.title)}catch(a){}})};h.stop=b;f=function(){return e(c.location.href)};n=function(a,d){var b=c.document,e=$.fn.iLightBoxHashChange.domain;
16916a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
16917
16918	if (!Array.prototype.filter) {
16919		Array.prototype.filter = function(fun /*, thisp */ ) {
16920			"use strict";
16921
16922			if (this == null)
16923				throw new TypeError();
16924
16925			var t = Object(this);
16926			var len = t.length >>> 0;
16927			if (typeof fun != "function")
16928				throw new TypeError();
16929
16930			var res = [];
16931			var thisp = arguments[1];
16932			for (var i = 0; i < len; i++) {
16933				if (i in t) {
16934					var val = t[i]; // in case fun mutates this
16935					if (fun.call(thisp, val, i, t))
16936						res.push(val);
16937				}
16938			}
16939
16940			return res;
16941		};
16942	}
16943
16944	if (!Array.prototype.indexOf) {
16945		Array.prototype.indexOf = function(searchElement, fromIndex) {
16946			var k;
16947
16948			if (this == null) {
16949				throw new TypeError('"this" is null or not defined');
16950			}
16951
16952			var O = Object(this);
16953
16954			var len = O.length >>> 0;
16955
16956			if (len === 0) {
16957				return -1;
16958			}
16959
16960			var n = +fromIndex || 0;
16961
16962			if (abs(n) === Infinity) {
16963				n = 0;
16964			}
16965
16966			if (n >= len) {
16967				return -1;
16968			}
16969
16970			k = max(n >= 0 ? n : len - abs(n), 0);
16971
16972			while (k < len) {
16973				var kValue;
16974				if (k in O && O[k] === searchElement) {
16975					return k;
16976				}
16977				k++;
16978			}
16979			return -1;
16980		};
16981	}
16982
16983	if (!Array.prototype.lastIndexOf) {
16984		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
16985			"use strict";
16986
16987			if (this == null)
16988				throw new TypeError();
16989
16990			var t = Object(this);
16991			var len = t.length >>> 0;
16992			if (len === 0)
16993				return -1;
16994
16995			var n = len;
16996			if (arguments.length > 1) {
16997				n = Number(arguments[1]);
16998				if (n != n)
16999					n = 0;
17000				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
17001					n = (n > 0 || -1) * floor(abs(n));
17002			}
17003
17004			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
17005
17006			for (; k >= 0; k--) {
17007				if (k in t && t[k] === searchElement)
17008					return k;
17009			}
17010			return -1;
17011		};
17012	}
17013})(jQuery, this);
17014
17015/*!
17016 * lightgallery | 2.5.0 | June 13th 2022
17017 * http://www.lightgalleryjs.com/
17018 * Copyright (c) 2020 Sachin Neravath;
17019 * @license GPLv3
17020 */
17021
17022(function (global, factory) {
17023	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
17024	typeof define === 'function' && define.amd ? define(factory) :
17025	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
17026}(this, (function () { 'use strict';
17027
17028	/*! *****************************************************************************
17029	Copyright (c) Microsoft Corporation.
17030
17031	Permission to use, copy, modify, and/or distribute this software for any
17032	purpose with or without fee is hereby granted.
17033
17034	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17035	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17036	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17037	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17038	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17039	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17040	PERFORMANCE OF THIS SOFTWARE.
17041	***************************************************************************** */
17042
17043	var __assign = function() {
17044		__assign = Object.assign || function __assign(t) {
17045			for (var s, i = 1, n = arguments.length; i < n; i++) {
17046				s = arguments[i];
17047				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
17048			}
17049			return t;
17050		};
17051		return __assign.apply(this, arguments);
17052	};
17053
17054	function __spreadArrays() {
17055		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
17056		for (var r = Array(s), k = 0, i = 0; i < il; i++)
17057			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
17058				r[k] = a[j];
17059		return r;
17060	}
17061
17062	/**
17063	 * List of lightGallery events
17064	 * All events should be documented here
17065	 * Below interfaces are used to build the website documentations
17066	 * */
17067	var lGEvents = {
17068		afterAppendSlide: 'lgAfterAppendSlide',
17069		init: 'lgInit',
17070		hasVideo: 'lgHasVideo',
17071		containerResize: 'lgContainerResize',
17072		updateSlides: 'lgUpdateSlides',
17073		afterAppendSubHtml: 'lgAfterAppendSubHtml',
17074		beforeOpen: 'lgBeforeOpen',
17075		afterOpen: 'lgAfterOpen',
17076		slideItemLoad: 'lgSlideItemLoad',
17077		beforeSlide: 'lgBeforeSlide',
17078		afterSlide: 'lgAfterSlide',
17079		posterClick: 'lgPosterClick',
17080		dragStart: 'lgDragStart',
17081		dragMove: 'lgDragMove',
17082		dragEnd: 'lgDragEnd',
17083		beforeNextSlide: 'lgBeforeNextSlide',
17084		beforePrevSlide: 'lgBeforePrevSlide',
17085		beforeClose: 'lgBeforeClose',
17086		afterClose: 'lgAfterClose',
17087		rotateLeft: 'lgRotateLeft',
17088		rotateRight: 'lgRotateRight',
17089		flipHorizontal: 'lgFlipHorizontal',
17090		flipVertical: 'lgFlipVertical',
17091		autoplay: 'lgAutoplay',
17092		autoplayStart: 'lgAutoplayStart',
17093		autoplayStop: 'lgAutoplayStop',
17094	};
17095
17096	var lightGalleryCoreSettings = {
17097		mode: 'lg-slide',
17098		easing: 'ease',
17099		speed: 400,
17100		licenseKey: '0000-0000-000-0000',
17101		height: '100%',
17102		width: '100%',
17103		addClass: '',
17104		startClass: 'lg-start-zoom',
17105		backdropDuration: 300,
17106		container: '',
17107		startAnimationDuration: 400,
17108		zoomFromOrigin: true,
17109		hideBarsDelay: 0,
17110		showBarsAfter: 10000,
17111		slideDelay: 0,
17112		supportLegacyBrowser: true,
17113		allowMediaOverlap: false,
17114		videoMaxSize: '1280-720',
17115		loadYouTubePoster: true,
17116		defaultCaptionHeight: 0,
17117		ariaLabelledby: '',
17118		ariaDescribedby: '',
17119		resetScrollPosition: true,
17120		hideScrollbar: false,
17121		closable: true,
17122		swipeToClose: true,
17123		closeOnTap: true,
17124		showCloseIcon: true,
17125		showMaximizeIcon: false,
17126		loop: true,
17127		escKey: true,
17128		keyPress: true,
17129		trapFocus: true,
17130		controls: true,
17131		slideEndAnimation: true,
17132		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 17133-17680
17133		mousewheel: false,
17134		getCaptionFromTitleOrAlt: true,
17135		appendSubHtmlTo: '.lg-sub-html',
17136		subHtmlSelectorRelative: false,
17137		preload: 2,
17138		numberOfSlideItemsInDom: 10,
17139		selector: '',
17140		selectWithin: '',
17141		nextHtml: '',
17142		prevHtml: '',
17143		index: 0,
17144		iframeWidth: '100%',
17145		iframeHeight: '100%',
17146		iframeMaxWidth: '100%',
17147		iframeMaxHeight: '100%',
17148		download: true,
17149		counter: true,
17150		appendCounterTo: '.lg-toolbar',
17151		swipeThreshold: 50,
17152		enableSwipe: true,
17153		enableDrag: true,
17154		dynamic: false,
17155		dynamicEl: [],
17156		extraProps: [],
17157		exThumbImage: '',
17158		isMobile: undefined,
17159		mobileSettings: {
17160			controls: false,
17161			showCloseIcon: false,
17162			download: false,
17163		},
17164		plugins: [],
17165		strings: {
17166			closeGallery: 'Close gallery',
17167			toggleMaximize: 'Toggle maximize',
17168			previousSlide: 'Previous slide',
17169			nextSlide: 'Next slide',
17170			download: 'Download',
17171			playVideo: 'Play video',
17172		},
17173	};
17174
17175	function initLgPolyfills() {
17176		(function () {
17177			if (typeof window.CustomEvent === 'function')
17178				return false;
17179			function CustomEvent(event, params) {
17180				params = params || {
17181					bubbles: false,
17182					cancelable: false,
17183					detail: null,
17184				};
17185				var evt = document.createEvent('CustomEvent');
17186				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
17187				return evt;
17188			}
17189			window.CustomEvent = CustomEvent;
17190		})();
17191		(function () {
17192			if (!Element.prototype.matches) {
17193				Element.prototype.matches =
17194					Element.prototype.msMatchesSelector ||
17195						Element.prototype.webkitMatchesSelector;
17196			}
17197		})();
17198	}
17199	var lgQuery = /** @class */ (function () {
17200		function lgQuery(selector) {
17201			this.cssVenderPrefixes = [
17202				'TransitionDuration',
17203				'TransitionTimingFunction',
17204				'Transform',
17205				'Transition',
17206			];
17207			this.selector = this._getSelector(selector);
17208			this.firstElement = this._getFirstEl();
17209			return this;
17210		}
17211		lgQuery.generateUUID = function () {
17212			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
17213				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
17214				return v.toString(16);
17215			});
17216		};
17217		lgQuery.prototype._getSelector = function (selector, context) {
17218			if (context === void 0) { context = document; }
17219			if (typeof selector !== 'string') {
17220				return selector;
17221			}
17222			context = context || document;
17223			var fl = selector.substring(0, 1);
17224			if (fl === '#') {
17225				return context.querySelector(selector);
17226			}
17227			else {
17228				return context.querySelectorAll(selector);
17229			}
17230		};
17231		lgQuery.prototype._each = function (func) {
17232			if (!this.selector) {
17233				return this;
17234			}
17235			if (this.selector.length !== undefined) {
17236				[].forEach.call(this.selector, func);
17237			}
17238			else {
17239				func(this.selector, 0);
17240			}
17241			return this;
17242		};
17243		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
17244			// prettier-ignore
17245			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
17246				return group1.toUpperCase();
17247			});
17248			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
17249				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
17250				el.style['webkit' + property] = value;
17251				el.style['moz' + property] = value;
17252				el.style['ms' + property] = value;
17253				el.style['o' + property] = value;
17254			}
17255			else {
17256				el.style[property] = value;
17257			}
17258		};
17259		lgQuery.prototype._getFirstEl = function () {
17260			if (this.selector && this.selector.length !== undefined) {
17261				return this.selector[0];
17262			}
17263			else {
17264				return this.selector;
17265			}
17266		};
17267		lgQuery.prototype.isEventMatched = function (event, eventName) {
17268			var eventNamespace = eventName.split('.');
17269			return event
17270				.split('.')
17271				.filter(function (e) { return e; })
17272				.every(function (e) {
17273				return eventNamespace.indexOf(e) !== -1;
17274			});
17275		};
17276		lgQuery.prototype.attr = function (attr, value) {
17277			if (value === undefined) {
17278				if (!this.firstElement) {
17279					return '';
17280				}
17281				return this.firstElement.getAttribute(attr);
17282			}
17283			this._each(function (el) {
17284				el.setAttribute(attr, value);
17285			});
17286			return this;
17287		};
17288		lgQuery.prototype.find = function (selector) {
17289			return $LG(this._getSelector(selector, this.selector));
17290		};
17291		lgQuery.prototype.first = function () {
17292			if (this.selector && this.selector.length !== undefined) {
17293				return $LG(this.selector[0]);
17294			}
17295			else {
17296				return $LG(this.selector);
17297			}
17298		};
17299		lgQuery.prototype.eq = function (index) {
17300			return $LG(this.selector[index]);
17301		};
17302		lgQuery.prototype.parent = function () {
17303			return $LG(this.selector.parentElement);
17304		};
17305		lgQuery.prototype.get = function () {
17306			return this._getFirstEl();
17307		};
17308		lgQuery.prototype.removeAttr = function (attributes) {
17309			var attrs = attributes.split(' ');
17310			this._each(function (el) {
17311				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
17312			});
17313			return this;
17314		};
17315		lgQuery.prototype.wrap = function (className) {
17316			if (!this.firstElement) {
17317				return this;
17318			}
17319			var wrapper = document.createElement('div');
17320			wrapper.className = className;
17321			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
17322			this.firstElement.parentNode.removeChild(this.firstElement);
17323			wrapper.appendChild(this.firstElement);
17324			return this;
17325		};
17326		lgQuery.prototype.addClass = function (classNames) {
17327			if (classNames === void 0) { classNames = ''; }
17328			this._each(function (el) {
17329				// IE doesn't support multiple arguments
17330				classNames.split(' ').forEach(function (className) {
17331					if (className) {
17332						el.classList.add(className);
17333					}
17334				});
17335			});
17336			return this;
17337		};
17338		lgQuery.prototype.removeClass = function (classNames) {
17339			this._each(function (el) {
17340				// IE doesn't support multiple arguments
17341				classNames.split(' ').forEach(function (className) {
17342					if (className) {
17343						el.classList.remove(className);
17344					}
17345				});
17346			});
17347			return this;
17348		};
17349		lgQuery.prototype.hasClass = function (className) {
17350			if (!this.firstElement) {
17351				return false;
17352			}
17353			return this.firstElement.classList.contains(className);
17354		};
17355		lgQuery.prototype.hasAttribute = function (attribute) {
17356			if (!this.firstElement) {
17357				return false;
17358			}
17359			return this.firstElement.hasAttribute(attribute);
17360		};
17361		lgQuery.prototype.toggleClass = function (className) {
17362			if (!this.firstElement) {
17363				return this;
17364			}
17365			if (this.hasClass(className)) {
17366				this.removeClass(className);
17367			}
17368			else {
17369				this.addClass(className);
17370			}
17371			return this;
17372		};
17373		lgQuery.prototype.css = function (property, value) {
17374			var _this = this;
17375			this._each(function (el) {
17376				_this._setCssVendorPrefix(el, property, value);
17377			});
17378			return this;
17379		};
17380		// Need to pass separate namespaces for separate elements
17381		lgQuery.prototype.on = function (events, listener) {
17382			var _this = this;
17383			if (!this.selector) {
17384				return this;
17385			}
17386			events.split(' ').forEach(function (event) {
17387				if (!Array.isArray(lgQuery.eventListeners[event])) {
17388					lgQuery.eventListeners[event] = [];
17389				}
17390				lgQuery.eventListeners[event].push(listener);
17391				_this.selector.addEventListener(event.split('.')[0], listener);
17392			});
17393			return this;
17394		};
17395		// @todo - test this
17396		lgQuery.prototype.once = function (event, listener) {
17397			var _this = this;
17398			this.on(event, function () {
17399				_this.off(event);
17400				listener(event);
17401			});
17402			return this;
17403		};
17404		lgQuery.prototype.off = function (event) {
17405			var _this = this;
17406			if (!this.selector) {
17407				return this;
17408			}
17409			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
17410				if (_this.isEventMatched(event, eventName)) {
17411					lgQuery.eventListeners[eventName].forEach(function (listener) {
17412						_this.selector.removeEventListener(eventName.split('.')[0], listener);
17413					});
17414					lgQuery.eventListeners[eventName] = [];
17415				}
17416			});
17417			return this;
17418		};
17419		lgQuery.prototype.trigger = function (event, detail) {
17420			if (!this.firstElement) {
17421				return this;
17422			}
17423			var customEvent = new CustomEvent(event.split('.')[0], {
17424				detail: detail || null,
17425			});
17426			this.firstElement.dispatchEvent(customEvent);
17427			return this;
17428		};
17429		// Does not support IE
17430		lgQuery.prototype.load = function (url) {
17431			var _this = this;
17432			fetch(url)
17433				.then(function (res) { return res.text(); })
17434				.then(function (html) {
17435				_this.selector.innerHTML = html;
17436			});
17437			return this;
17438		};
17439		lgQuery.prototype.html = function (html) {
17440			if (html === undefined) {
17441				if (!this.firstElement) {
17442					return '';
17443				}
17444				return this.firstElement.innerHTML;
17445			}
17446			this._each(function (el) {
17447				el.innerHTML = html;
17448			});
17449			return this;
17450		};
17451		lgQuery.prototype.append = function (html) {
17452			this._each(function (el) {
17453				if (typeof html === 'string') {
17454					el.insertAdjacentHTML('beforeend', html);
17455				}
17456				else {
17457					el.appendChild(html);
17458				}
17459			});
17460			return this;
17461		};
17462		lgQuery.prototype.prepend = function (html) {
17463			this._each(function (el) {
17464				el.insertAdjacentHTML('afterbegin', html);
17465			});
17466			return this;
17467		};
17468		lgQuery.prototype.remove = function () {
17469			this._each(function (el) {
17470				el.parentNode.removeChild(el);
17471			});
17472			return this;
17473		};
17474		lgQuery.prototype.empty = function () {
17475			this._each(function (el) {
17476				el.innerHTML = '';
17477			});
17478			return this;
17479		};
17480		lgQuery.prototype.scrollTop = function (scrollTop) {
17481			if (scrollTop !== undefined) {
17482				document.body.scrollTop = scrollTop;
17483				document.documentElement.scrollTop = scrollTop;
17484				return this;
17485			}
17486			else {
17487				return (window.pageYOffset ||
17488					document.documentElement.scrollTop ||
17489					document.body.scrollTop ||
17490					0);
17491			}
17492		};
17493		lgQuery.prototype.scrollLeft = function (scrollLeft) {
17494			if (scrollLeft !== undefined) {
17495				document.body.scrollLeft = scrollLeft;
17496				document.documentElement.scrollLeft = scrollLeft;
17497				return this;
17498			}
17499			else {
17500				return (window.pageXOffset ||
17501					document.documentElement.scrollLeft ||
17502					document.body.scrollLeft ||
17503					0);
17504			}
17505		};
17506		lgQuery.prototype.offset = function () {
17507			if (!this.firstElement) {
17508				return {
17509					left: 0,
17510					top: 0,
17511				};
17512			}
17513			var rect = this.firstElement.getBoundingClientRect();
17514			var bodyMarginLeft = $LG('body').style().marginLeft;
17515			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
17516			return {
17517				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
17518				top: rect.top + this.scrollTop(),
17519			};
17520		};
17521		lgQuery.prototype.style = function () {
17522			if (!this.firstElement) {
17523				return {};
17524			}
17525			return (this.firstElement.currentStyle ||
17526				window.getComputedStyle(this.firstElement));
17527		};
17528		// Width without padding and border even if box-sizing is used.
17529		lgQuery.prototype.width = function () {
17530			var style = this.style();
17531			return (this.firstElement.clientWidth -
17532				parseFloat(style.paddingLeft) -
17533				parseFloat(style.paddingRight));
17534		};
17535		// Height without padding and border even if box-sizing is used.
17536		lgQuery.prototype.height = function () {
17537			var style = this.style();
17538			return (this.firstElement.clientHeight -
17539				parseFloat(style.paddingTop) -
17540				parseFloat(style.paddingBottom));
17541		};
17542		lgQuery.eventListeners = {};
17543		return lgQuery;
17544	}());
17545	function $LG(selector) {
17546		initLgPolyfills();
17547		return new lgQuery(selector);
17548	}
17549
17550	var defaultDynamicOptions = [
17551		'src',
17552		'sources',
17553		'subHtml',
17554		'subHtmlUrl',
17555		'html',
17556		'video',
17557		'poster',
17558		'slideName',
17559		'responsive',
17560		'srcset',
17561		'sizes',
17562		'iframe',
17563		'downloadUrl',
17564		'download',
17565		'width',
17566		'facebookShareUrl',
17567		'tweetText',
17568		'iframeTitle',
17569		'twitterShareUrl',
17570		'pinterestShareUrl',
17571		'pinterestText',
17572		'fbHtml',
17573		'disqusIdentifier',
17574		'disqusUrl',
17575	];
17576	// Convert html data-attribute to camalcase
17577	function convertToData(attr) {
17578		// FInd a way for lgsize
17579		if (attr === 'href') {
17580			return 'src';
17581		}
17582		attr = attr.replace('data-', '');
17583		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
17584		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
17585		return attr;
17586	}
17587	var utils = {
17588		/**
17589		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
17590		 */
17591		//Uncode edit ##START##
17592		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
17593		// getSize: function (el, container, spacing, defaultLgSize) {
17594		//Uncode edit ##END##
17595			if (spacing === void 0) { spacing = 0; }
17596			var LGel = $LG(el);
17597			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
17598			//Uncode edit ##START##
17599			if ( typeof galleryItem.size && galleryItem.size != null ) {
17600				lgSize = galleryItem.size;
17601			}
17602			//Uncode edit ##END##
17603			if (!lgSize) {
17604				return;
17605			}
17606			var isResponsiveSizes = lgSize.split(',');
17607			// if at-least two viewport sizes are available
17608			if (isResponsiveSizes[1]) {
17609				var wWidth = window.innerWidth;
17610				for (var i = 0; i < isResponsiveSizes.length; i++) {
17611					var size_1 = isResponsiveSizes[i];
17612					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
17613					if (responsiveWidth > wWidth) {
17614						lgSize = size_1;
17615						break;
17616					}
17617					// take last item as last option
17618					if (i === isResponsiveSizes.length - 1) {
17619						lgSize = size_1;
17620					}
17621				}
17622			}
17623			var size = lgSize.split('-');
17624			var width = parseInt(size[0], 10);
17625			var height = parseInt(size[1], 10);
17626			var cWidth = container.width();
17627			var cHeight = container.height() - spacing;
17628			var maxWidth = Math.min(cWidth, width);
17629			var maxHeight = Math.min(cHeight, height);
17630			var ratio = Math.min(maxWidth / width, maxHeight / height);
17631			return { width: width * ratio, height: height * ratio };
17632		},
17633		/**
17634		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
17635		 * @param {jQuery Element}
17636		 * @returns {String} Transform CSS string
17637		 */
17638		getTransform: function (el, container, top, bottom, imageSize) {
17639			if (!imageSize) {
17640				return;
17641			}
17642			var LGel = $LG(el).find('img').first();
17643			if (!LGel.get()) {
17644				return;
17645			}
17646			var containerRect = container.get().getBoundingClientRect();
17647			var wWidth = containerRect.width;
17648			// using innerWidth to include mobile safari bottom bar
17649			var wHeight = container.height() - (top + bottom);
17650			var elWidth = LGel.width();
17651			var elHeight = LGel.height();
17652			var elStyle = LGel.style();
17653			var x = (wWidth - elWidth) / 2 -
17654				LGel.offset().left +
17655				(parseFloat(elStyle.paddingLeft) || 0) +
17656				(parseFloat(elStyle.borderLeft) || 0) +
17657				$LG(window).scrollLeft() +
17658				containerRect.left;
17659			var y = (wHeight - elHeight) / 2 -
17660				LGel.offset().top +
17661				(parseFloat(elStyle.paddingTop) || 0) +
17662				(parseFloat(elStyle.borderTop) || 0) +
17663				$LG(window).scrollTop() +
17664				top;
17665			var scX = elWidth / imageSize.width;
17666			var scY = elHeight / imageSize.height;
17667			var transform = 'translate3d(' +
17668				(x *= -1) +
17669				'px, ' +
17670				(y *= -1) +
17671				'px, 0) scale3d(' +
17672				scX +
17673				', ' +
17674				scY +
17675				', 1)';
17676			return transform;
17677		},
17678		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
17679			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
17680			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 17680-17752
17680+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
17681		},
17682		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
17683			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
17684			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17685			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17686			var sourceTag = '';
17687			if (sources) {
17688				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17689				sourceTag = sourceObj.map(function (source) {
17690					var attrs = '';
17691					Object.keys(source).forEach(function (key) {
17692						// Do not remove the first space as it is required to separate the attributes
17693						attrs += " " + key + "=\"" + source[key] + "\"";
17694					});
17695					return "<source " + attrs + "></source>";
17696				});
17697			}
17698			return "" + sourceTag + imgMarkup;
17699		},
17700		// Get src from responsive src
17701		getResponsiveSrc: function (srcItms) {
17702			var rsWidth = [];
17703			var rsSrc = [];
17704			var src = '';
17705			for (var i = 0; i < srcItms.length; i++) {
17706				var _src = srcItms[i].split(' ');
17707				// Manage empty space
17708				if (_src[0] === '') {
17709					_src.splice(0, 1);
17710				}
17711				rsSrc.push(_src[0]);
17712				rsWidth.push(_src[1]);
17713			}
17714			var wWidth = window.innerWidth;
17715			for (var j = 0; j < rsWidth.length; j++) {
17716				if (parseInt(rsWidth[j], 10) > wWidth) {
17717					src = rsSrc[j];
17718					break;
17719				}
17720			}
17721			return src;
17722		},
17723		isImageLoaded: function (img) {
17724			if (!img)
17725				return false;
17726			// During the onload event, IE correctly identifies any images that
17727			// weren’t downloaded as not complete. Others should too. Gecko-based
17728			// browsers act like NS4 in that they report this incorrectly.
17729			if (!img.complete) {
17730				return false;
17731			}
17732			// However, they do have two very useful properties: naturalWidth and
17733			// naturalHeight. These give the true size of the image. If it failed
17734			// to load, either of these should be zero.
17735			if (img.naturalWidth === 0) {
17736				return false;
17737			}
17738			// No other way of checking: assume it’s ok.
17739			return true;
17740		},
17741		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17742			var videoClass = '';
17743			if (_isVideo && _isVideo.youtube) {
17744				videoClass = 'lg-has-youtube';
17745			}
17746			else if (_isVideo && _isVideo.vimeo) {
17747				videoClass = 'lg-has-vimeo';
17748			}
17749			else {
17750				videoClass = 'lg-has-html5';
17751			}
17752			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
vendor: 5,030 bytes, lines 17752-17863
17752\n                <svg\n                    viewBox=\"0 0 20 20\"\n                    preserveAspectRatio=\"xMidYMid\"\n                    focusable=\"false\"\n                    aria-labelledby=\"" + playVideoString + "\"\n                    role=\"img\"\n                    class=\"lg-video-play-icon\"\n                >\n                    <title>" + playVideoString + "</title>\n                    <polygon class=\"lg-video-play-icon-inner\" points=\"1,0 20,10 1,20\"></polygon>\n                </svg>\n                <svg class=\"lg-video-play-icon-bg\" viewBox=\"0 0 50 50\" focusable=\"false\">\n                    <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle></svg>\n                <svg class=\"lg-video-play-icon-circle\" viewBox=\"0 0 50 50\" focusable=\"false\">\n                    <circle cx=\"50%\" cy=\"50%\" r=\"20\"></circle>\n                </svg>\n            </div>\n            " + (dummyImg || '') + "\n            <img class=\"lg-object lg-video-poster\" src=\"" + _poster + "\" />\n        </div>";
17753		},
17754		getFocusableElements: function (container) {
17755			var elements = container.querySelectorAll('a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])');
17756			var visibleElements = [].filter.call(elements, function (element) {
17757				var style = window.getComputedStyle(element);
17758				return style.display !== 'none' && style.visibility !== 'hidden';
17759			});
17760			return visibleElements;
17761		},
17762		/**
17763		 * @desc Create dynamic elements array from gallery items when dynamic option is false
17764		 * It helps to avoid frequent DOM interaction
17765		 * and avoid multiple checks for dynamic elments
17766		 *
17767		 * @returns {Array} dynamicEl
17768		 */
17769		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17770			var dynamicElements = [];
17771			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17772			[].forEach.call(items, function (item) {
17773				var dynamicEl = {};
17774				for (var i = 0; i < item.attributes.length; i++) {
17775					var attr = item.attributes[i];
17776					if (attr.specified) {
17777						var dynamicAttr = convertToData(attr.name);
17778						var label = '';
17779						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17780							label = dynamicAttr;
17781						}
17782						if (label) {
17783							dynamicEl[label] = attr.value;
17784						}
17785					}
17786				}
17787				var currentItem = $LG(item);
17788				var alt = currentItem.find('img').first().attr('alt');
17789				var title = currentItem.attr('title');
17790				//Uncode edit ##START##
17791				// var thumb = exThumbImage
17792				var thumb = exThumbImage && currentItem.attr(exThumbImage)
17793				//Uncode edit ##END##
17794					? currentItem.attr(exThumbImage)
17795					: currentItem.find('img').first().attr('src');
17796				dynamicEl.thumb = thumb;
17797				//Uncode edit ##START##
17798				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17799					// dynamicEl.subHtml = title || alt || '';
17800					dynamicEl.subHtml = title || '';
17801				}
17802				// dynamicEl.alt = alt || title || '';
17803				dynamicEl.alt = title || '';
17804				var inlineType = currentItem.attr('data-type');
17805				dynamicEl.type = inlineType;
17806				//Uncode edit ##END##
17807				dynamicElements.push(dynamicEl);
17808			});
17809			return dynamicElements;
17810		},
17811		isMobile: function () {
17812			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17813		},
17814		/**
17815		 * @desc Check the given src is video
17816		 * @param {String} src
17817		 * @return {Object} video type
17818		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17819		 *
17820		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
17821		 */
17822		isVideo: function (src, isHTML5VIdeo, index) {
17823			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
17824				if (isHTML5VIdeo) {
17825					return {
17826						html5: true,
17827					};
17828				}
17829				else {
17830					console.warn('lightGallery :- data-src is not provided on slide item ' +
17831						(index + 1) +
17832						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17833					return;
17834				}
17835			}
17836			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17837			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17838			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17839			if (youtube) {
17840				return {
17841					youtube: youtube,
17842				};
17843			}
17844			else if (vimeo) {
17845				return {
17846					vimeo: vimeo,
17847				};
17848			}
17849			else if (wistia) {
17850				return {
17851					wistia: wistia,
17852				};
17853			}
17854		},
17855	};
17856
17857	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17858	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17859	// Unique id for each gallery
17860	var lgId = 0;
17861	var LightGallery = /** @class */ (function () {
17862		function LightGallery(element, options) {
17863			this.lgOpened = false;
vendor: 4,563 bytes, lines 17864-17998
17864			this.index = 0;
17865			// lightGallery modules
17866			this.plugins = [];
17867			// false when lightGallery load first slide content;
17868			this.lGalleryOn = false;
17869			// True when a slide animation is in progress
17870			this.lgBusy = false;
17871			this.currentItemsInDom = [];
17872			// Scroll top value before lightGallery is opened
17873			this.prevScrollTop = 0;
17874			this.bodyPaddingRight = 0;
17875			this.isDummyImageRemoved = false;
17876			this.dragOrSwipeEnabled = false;
17877			this.mediaContainerPosition = {
17878				top: 0,
17879				bottom: 0,
17880			};
17881			if (!element) {
17882				return this;
17883			}
17884			lgId++;
17885			this.lgId = lgId;
17886			this.el = element;
17887			this.LGel = $LG(element);
17888			this.generateSettings(options);
17889			this.buildModules();
17890			// When using dynamic mode, ensure dynamicEl is an array
17891			if (this.settings.dynamic &&
17892				this.settings.dynamicEl !== undefined &&
17893				!Array.isArray(this.settings.dynamicEl)) {
17894				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17895			}
17896			this.galleryItems = this.getItems();
17897			this.normalizeSettings();
17898			// Gallery items
17899			this.init();
17900			//Uncode edit ##START##
17901			// this.validateLicense();
17902			//Uncode edit ##END##
17903			return this;
17904		}
17905		LightGallery.prototype.generateSettings = function (options) {
17906			// lightGallery settings
17907			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17908			if (this.settings.isMobile &&
17909				typeof this.settings.isMobile === 'function'
17910				? this.settings.isMobile()
17911				: utils.isMobile()) {
17912				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17913				this.settings = __assign(__assign({}, this.settings), mobileSettings);
17914			}
17915		};
17916		LightGallery.prototype.normalizeSettings = function () {
17917			if (this.settings.slideEndAnimation) {
17918				this.settings.hideControlOnEnd = false;
17919			}
17920			if (!this.settings.closable) {
17921				this.settings.swipeToClose = false;
17922			}
17923			// And reset it on close to get the correct value next time
17924			this.zoomFromOrigin = this.settings.zoomFromOrigin;
17925			// At the moment, Zoom from image doesn't support dynamic options
17926			// @todo add zoomFromOrigin support for dynamic images
17927			if (this.settings.dynamic) {
17928				this.zoomFromOrigin = false;
17929			}
17930			if (!this.settings.container) {
17931				this.settings.container = document.body;
17932			}
17933			// settings.preload should not be grater than $item.length
17934			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17935		};
17936		LightGallery.prototype.init = function () {
17937			var _this = this;
17938			this.addSlideVideoInfo(this.galleryItems);
17939			this.buildStructure();
17940			this.LGel.trigger(lGEvents.init, {
17941				instance: this,
17942			});
17943			if (this.settings.keyPress) {
17944				this.keyPress();
17945			}
17946			setTimeout(function () {
17947				_this.enableDrag();
17948				_this.enableSwipe();
17949				_this.triggerPosterClick();
17950			}, 50);
17951			this.arrow();
17952			if (this.settings.mousewheel) {
17953				this.mousewheel();
17954			}
17955			if (!this.settings.dynamic) {
17956				this.openGalleryOnItemClick();
17957			}
17958		};
17959		LightGallery.prototype.openGalleryOnItemClick = function () {
17960			var _this = this;
17961			var _loop_1 = function (index) {
17962				var element = this_1.items[index];
17963				var $element = $LG(element);
17964				// Using different namespace for click because click event should not unbind if selector is same object('this')
17965				// @todo manage all event listners - should have namespace that represent element
17966				var uuid = lgQuery.generateUUID();
17967				$element
17968					.attr('data-lg-id', uuid)
17969					.on("click.lgcustom-item-" + uuid, function (e) {
17970					e.preventDefault();
17971					var currentItemIndex = _this.settings.index || index;
17972					_this.openGallery(currentItemIndex, element);
17973				});
17974			};
17975			var this_1 = this;
17976			// Using for loop instead of using bubbling as the items can be any html element.
17977			for (var index = 0; index < this.items.length; index++) {
17978				_loop_1(index);
17979			}
17980		};
17981		/**
17982		 * Module constructor
17983		 * Modules are build incrementally.
17984		 * Gallery should be opened only once all the modules are initialized.
17985		 * use moduleBuildTimeout to make sure this
17986		 */
17987		LightGallery.prototype.buildModules = function () {
17988			var _this = this;
17989			this.settings.plugins.forEach(function (plugin) {
17990				_this.plugins.push(new plugin(_this, $LG));
17991			});
17992		};
17993		LightGallery.prototype.validateLicense = function () {
17994			if (!this.settings.licenseKey) {
17995				console.warn('Please provide a valid license key');
17996			}
17997			else if (this.settings.licenseKey === '0000-0000-000-0000') {
17998				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 17998-18412
17998id for production use");
17999			}
18000		};
18001		LightGallery.prototype.getSlideItem = function (index) {
18002			return $LG(this.getSlideItemId(index));
18003		};
18004		LightGallery.prototype.getSlideItemId = function (index) {
18005			return "#lg-item-" + this.lgId + "-" + index;
18006		};
18007		LightGallery.prototype.getIdName = function (id) {
18008			return id + "-" + this.lgId;
18009		};
18010		LightGallery.prototype.getElementById = function (id) {
18011			return $LG("#" + this.getIdName(id));
18012		};
18013		LightGallery.prototype.manageSingleSlideClassName = function () {
18014			if (this.galleryItems.length < 2) {
18015				this.outer.addClass('lg-single-item');
18016			}
18017			else {
18018				this.outer.removeClass('lg-single-item');
18019			}
18020		};
18021		LightGallery.prototype.buildStructure = function () {
18022			var _this = this;
18023			var container = this.$container && this.$container.get();
18024			if (container) {
18025				return;
18026			}
18027			var controls = '';
18028			var subHtmlCont = '';
18029			// Create controls
18030			if (this.settings.controls) {
18031				controls = "<button type=\"button\" id=\"" + this.getIdName('lg-prev') + "\" aria-label=\"" + this.settings.strings['previousSlide'] + "\" class=\"lg-prev lg-icon\"> " + this.settings.prevHtml + " </button>\n                <button type=\"button\" id=\"" + this.getIdName('lg-next') + "\" aria-label=\"" + this.settings.strings['nextSlide'] + "\" class=\"lg-next lg-icon\"> " + this.settings.nextHtml + " </button>";
18032			}
18033			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18034				subHtmlCont =
18035					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
18036			}
18037			var addClasses = '';
18038			if (this.settings.allowMediaOverlap) {
18039				// Do not remove space before last single quote
18040				addClasses += 'lg-media-overlap ';
18041			}
18042			var ariaLabelledby = this.settings.ariaLabelledby
18043				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
18044				: '';
18045			var ariaDescribedby = this.settings.ariaDescribedby
18046				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
18047				: '';
18048			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
18049			var closeIcon = this.settings.closable && this.settings.showCloseIcon
18050				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
18051				: '';
18052			var maximizeIcon = this.settings.showMaximizeIcon
18053				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
18054				: '';
18055			var template = "\n        <div class=\"" + containerClassName + "\" id=\"" + this.getIdName('lg-container') + "\" tabindex=\"-1\" aria-modal=\"true\" " + ariaLabelledby + " " + ariaDescribedby + " role=\"dialog\"\n        >\n            <div id=\"" + this.getIdName('lg-backdrop') + "\" class=\"lg-backdrop\"></div>\n\n            <div id=\"" + this.getIdName('lg-outer') + "\" class=\"lg-outer lg-use-css3 lg-css3 lg-hide-items " + addClasses + " \">\n\n              <div id=\"" + this.getIdName('lg-content') + "\" class=\"lg-content\">\n                <div id=\"" + this.getIdName('lg-inner') + "\" class=\"lg-inner\">\n                </div>\n                " + controls + "\n              </div>\n                <div id=\"" + this.getIdName('lg-toolbar') + "\" class=\"lg-toolbar lg-group\">\n                    " + maximizeIcon + "\n                    " + closeIcon + "\n                    </div>\n                    " + (this.settings.appendSubHtmlTo === '.lg-outer'
18056				? subHtmlCont
18057				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
18058				? subHtmlCont
18059				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
18060			$LG(this.settings.container).append(template);
18061			if (document.body !== this.settings.container) {
18062				$LG(this.settings.container).css('position', 'relative');
18063			}
18064			this.outer = this.getElementById('lg-outer');
18065			this.$lgComponents = this.getElementById('lg-components');
18066			this.$backdrop = this.getElementById('lg-backdrop');
18067			this.$container = this.getElementById('lg-container');
18068			this.$inner = this.getElementById('lg-inner');
18069			this.$content = this.getElementById('lg-content');
18070			this.$toolbar = this.getElementById('lg-toolbar');
18071			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
18072			var outerClassNames = this.settings.mode + " ";
18073			this.manageSingleSlideClassName();
18074			if (this.settings.enableDrag) {
18075				outerClassNames += 'lg-grab ';
18076			}
18077			this.outer.addClass(outerClassNames);
18078			this.$inner.css('transition-timing-function', this.settings.easing);
18079			this.$inner.css('transition-duration', this.settings.speed + 'ms');
18080			if (this.settings.download) {
18081				this.$toolbar.append("<a id=\"" + this.getIdName('lg-download') + "\" target=\"_blank\" rel=\"noopener\" aria-label=\"" + this.settings.strings['download'] + "\" download class=\"lg-download lg-icon\"></a>");
18082			}
18083			this.counter();
18084			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
18085				_this.refreshOnResize();
18086			});
18087			this.hideBars();
18088			this.manageCloseGallery();
18089			this.toggleMaximize();
18090			this.initModules();
18091		};
18092		LightGallery.prototype.refreshOnResize = function () {
18093			if (this.lgOpened) {
18094				var currentGalleryItem = this.galleryItems[this.index];
18095				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
18096				this.mediaContainerPosition = this.getMediaContainerPosition();
18097				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
18098				//Uncode edit ##START##
18099				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18100				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18101				//Uncode edit ##END##
18102				if (__slideVideoInfo) {
18103					this.resizeVideoSlide(this.index, this.currentImageSize);
18104				}
18105				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
18106					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18107					this.outer
18108						.find('.lg-current .lg-dummy-img')
18109						.first()
18110						.attr('style', imgStyle);
18111				}
18112				this.LGel.trigger(lGEvents.containerResize);
18113			}
18114		};
18115		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
18116			var lgVideoStyle = this.getVideoContStyle(imageSize);
18117			var currentSlide = this.getSlideItem(index);
18118			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
18119		};
18120		/**
18121		 * Update slides dynamically.
18122		 * Add, edit or delete slides dynamically when lightGallery is opened.
18123		 * Modify the current gallery items and pass it via updateSlides method
18124		 * @note
18125		 * - Do not mutate existing lightGallery items directly.
18126		 * - Always pass new list of gallery items
18127		 * - You need to take care of thumbnails outside the gallery if any
18128		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
18129		 * @param items Gallery items
18130		 * @param index After the update operation, which slide gallery should navigate to
18131		 * @category lGPublicMethods
18132		 * @example
18133		 * const plugin = lightGallery();
18134		 *
18135		 * // Adding slides dynamically
18136		 * let galleryItems = [
18137		 * // Access existing lightGallery items
18138		 * // galleryItems are automatically generated internally from the gallery HTML markup
18139		 * // or directly from galleryItems when dynamic gallery is used
18140		 *   ...plugin.galleryItems,
18141		 *     ...[
18142		 *       {
18143		 *         src: 'img/img-1.png',
18144		 *           thumb: 'img/thumb1.png',
18145		 *         },
18146		 *     ],
18147		 *   ];
18148		 *   plugin.updateSlides(
18149		 *     galleryItems,
18150		 *     plugin.index,
18151		 *   );
18152		 *
18153		 *
18154		 * // Remove slides dynamically
18155		 * galleryItems = JSON.parse(
18156		 *   JSON.stringify(updateSlideInstance.galleryItems),
18157		 * );
18158		 * galleryItems.shift();
18159		 * updateSlideInstance.updateSlides(galleryItems, 1);
18160		 * @see <a href="/demos/update-slides/">Demo</a>
18161		 */
18162		LightGallery.prototype.updateSlides = function (items, index) {
18163			if (this.index > items.length - 1) {
18164				this.index = items.length - 1;
18165			}
18166			if (items.length === 1) {
18167				this.index = 0;
18168			}
18169			if (!items.length) {
18170				this.closeGallery();
18171				return;
18172			}
18173			var currentSrc = this.galleryItems[index].src;
18174			this.galleryItems = items;
18175			this.updateControls();
18176			this.$inner.empty();
18177			this.currentItemsInDom = [];
18178			var _index = 0;
18179			// Find the current index based on source value of the slide
18180			this.galleryItems.some(function (galleryItem, itemIndex) {
18181				if (galleryItem.src === currentSrc) {
18182					_index = itemIndex;
18183					return true;
18184				}
18185				return false;
18186			});
18187			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
18188			this.loadContent(_index, true);
18189			this.getSlideItem(_index).addClass('lg-current');
18190			this.index = _index;
18191			this.updateCurrentCounter(_index);
18192			this.LGel.trigger(lGEvents.updateSlides);
18193		};
18194		// Get gallery items based on multiple conditions
18195		LightGallery.prototype.getItems = function () {
18196			// Gallery items
18197			this.items = [];
18198			if (!this.settings.dynamic) {
18199				if (this.settings.selector === 'this') {
18200					this.items.push(this.el);
18201				}
18202				else if (this.settings.selector) {
18203					if (typeof this.settings.selector === 'string') {
18204						if (this.settings.selectWithin) {
18205							var selectWithin = $LG(this.settings.selectWithin);
18206							this.items = selectWithin
18207								.find(this.settings.selector)
18208								.get();
18209						}
18210						else {
18211							this.items = this.el.querySelectorAll(this.settings.selector);
18212						}
18213					}
18214					else {
18215						this.items = this.settings.selector;
18216					}
18217				}
18218				else {
18219					this.items = this.el.children;
18220				}
18221				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
18222			}
18223			else {
18224				return this.settings.dynamicEl || [];
18225			}
18226		};
18227		LightGallery.prototype.shouldHideScrollbar = function () {
18228			return (this.settings.hideScrollbar &&
18229				document.body === this.settings.container);
18230		};
18231		LightGallery.prototype.hideScrollbar = function () {
18232			if (!this.shouldHideScrollbar()) {
18233				return;
18234			}
18235			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
18236			var bodyRect = document.documentElement.getBoundingClientRect();
18237			var scrollbarWidth = window.innerWidth - bodyRect.width;
18238			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
18239			$LG(document.body).addClass('lg-overlay-open');
18240		};
18241		LightGallery.prototype.resetScrollBar = function () {
18242			if (!this.shouldHideScrollbar()) {
18243				return;
18244			}
18245			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
18246			$LG(document.body).removeClass('lg-overlay-open');
18247		};
18248		/**
18249		 * Open lightGallery.
18250		 * Open gallery with specific slide by passing index of the slide as parameter.
18251		 * @category lGPublicMethods
18252		 * @param {Number} index  - index of the slide
18253		 * @param {HTMLElement} element - Which image lightGallery should zoom from
18254		 *
18255		 * @example
18256		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
18257		 * const dynamicGallery = lightGallery($dynamicGallery, {
18258		 *     dynamic: true,
18259		 *     dynamicEl: [
18260		 *         {
18261		 *              src: 'img/1.jpg',
18262		 *              thumb: 'img/thumb-1.jpg',
18263		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
18264		 *         },
18265		 *         ...
18266		 *     ],
18267		 * });
18268		 * $dynamicGallery.addEventListener('click', function () {
18269		 *     // Starts with third item.(Optional).
18270		 *     // This is useful if you want use dynamic mode with
18271		 *     // custom thumbnails (thumbnails outside gallery),
18272		 *     dynamicGallery.openGallery(2);
18273		 * });
18274		 *
18275		 */
18276		LightGallery.prototype.openGallery = function (index, element) {
18277			var _this = this;
18278			if (index === void 0) { index = this.settings.index; }
18279			// prevent accidental double execution
18280			if (this.lgOpened)
18281				return;
18282			this.lgOpened = true;
18283			this.outer.removeClass('lg-hide-items');
18284			this.hideScrollbar();
18285			// Add display block, but still has opacity 0
18286			this.$container.addClass('lg-show');
18287			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
18288			this.currentItemsInDom = itemsToBeInsertedToDom;
18289			var items = '';
18290			itemsToBeInsertedToDom.forEach(function (item) {
18291				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18292			});
18293			this.$inner.append(items);
18294			this.addHtml(index);
18295			var transform = '';
18296			this.mediaContainerPosition = this.getMediaContainerPosition();
18297			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
18298			if (!this.settings.allowMediaOverlap) {
18299				this.setMediaContainerPosition(top, bottom);
18300			}
18301			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
18302			if (this.zoomFromOrigin && element) {
18303				//Uncode edit ##START##
18304				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18305				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18306				//Uncode edit ##END##
18307				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
18308			}
18309			if (!this.zoomFromOrigin || !transform) {
18310				this.outer.addClass(this.settings.startClass);
18311				this.getSlideItem(index).removeClass('lg-complete');
18312			}
18313			var timeout = this.settings.zoomFromOrigin
18314				? 100
18315				: this.settings.backdropDuration;
18316			setTimeout(function () {
18317				_this.outer.addClass('lg-components-open');
18318			}, timeout);
18319			this.index = index;
18320			//Uncode edit ##START##
18321			// this.LGel.trigger(lGEvents.beforeOpen);
18322			this.LGel.trigger(lGEvents.beforeOpen, {
18323				galleryItems: this.galleryItems,
18324				items: this.items,
18325				outer: this.outer,
18326			});
18327			//Uncode edit ##END##
18328			// add class lg-current to remove initial transition
18329			this.getSlideItem(index).addClass('lg-current');
18330			this.lGalleryOn = false;
18331			// Store the current scroll top value to scroll back after closing the gallery..
18332			this.prevScrollTop = $LG(window).scrollTop();
18333			setTimeout(function () {
18334				// Need to check both zoomFromOrigin and transform values as we need to set set the
18335				// default opening animation if user missed to add the lg-size attribute
18336				if (_this.zoomFromOrigin && transform) {
18337					var currentSlide_1 = _this.getSlideItem(index);
18338					currentSlide_1.css('transform', transform);
18339					setTimeout(function () {
18340						currentSlide_1
18341							.addClass('lg-start-progress lg-start-end-progress')
18342							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
18343						_this.outer.addClass('lg-zoom-from-image');
18344					});
18345					setTimeout(function () {
18346						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
18347					}, 100);
18348				}
18349				setTimeout(function () {
18350					_this.$backdrop.addClass('in');
18351					_this.$container.addClass('lg-show-in');
18352				}, 10);
18353				setTimeout(function () {
18354					if (_this.settings.trapFocus &&
18355						document.body === _this.settings.container) {
18356						_this.trapFocus();
18357					}
18358				}, _this.settings.backdropDuration + 50);
18359				// lg-visible class resets gallery opacity to 1
18360				if (!_this.zoomFromOrigin || !transform) {
18361					setTimeout(function () {
18362						_this.outer.addClass('lg-visible');
18363					}, _this.settings.backdropDuration);
18364				}
18365				// initiate slide function
18366				_this.slide(index, false, false, false);
18367				_this.LGel.trigger(lGEvents.afterOpen);
18368			});
18369			if (document.body === this.settings.container) {
18370				$LG('html').addClass('lg-on');
18371			}
18372		};
18373		/**
18374		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
18375		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
18376		 * if you have dynamic captions for each media,
18377		 * you can provide an appropriate height for the captions via allowMediaOverlap option
18378		 */
18379		LightGallery.prototype.getMediaContainerPosition = function () {
18380			if (this.settings.allowMediaOverlap) {
18381				return {
18382					top: 0,
18383					bottom: 0,
18384				};
18385			}
18386			var top = this.$toolbar.get().clientHeight || 0;
18387			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
18388			var captionHeight = this.settings.defaultCaptionHeight ||
18389				(subHtml && subHtml.clientHeight) ||
18390				0;
18391			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
18392			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
18393			var bottom = thumbHeight + captionHeight;
18394			//Uncode edit ##START##
18395			bottom = bottom < 55 ? 55 : bottom;
18396			//Uncode edit ##END##
18397			return {
18398				top: top,
18399				bottom: bottom,
18400			};
18401		};
18402		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
18403			if (top === void 0) { top = 0; }
18404			if (bottom === void 0) { bottom = 0; }
18405			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
18406		};
18407		LightGallery.prototype.hideBars = function () {
18408			var _this = this;
18409			// Hide controllers if mouse doesn't move for some period
18410			setTimeout(function () {
18411				_this.outer.removeClass('lg-hide-items');
18412				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 18413-18543
18413					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
18414						_this.outer.removeClass('lg-hide-items');
18415						clearTimeout(_this.hideBarTimeout);
18416						// Timeout will be cleared on each slide movement also
18417						_this.hideBarTimeout = setTimeout(function () {
18418							_this.outer.addClass('lg-hide-items');
18419						}, _this.settings.hideBarsDelay);
18420					});
18421					_this.outer.trigger('mousemove.lg');
18422				}
18423			}, this.settings.showBarsAfter);
18424		};
18425		LightGallery.prototype.initPictureFill = function ($img) {
18426			if (this.settings.supportLegacyBrowser) {
18427				try {
18428					picturefill({
18429						elements: [$img.get()],
18430					});
18431				}
18432				catch (e) {
18433					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
18434				}
18435			}
18436		};
18437		/**
18438		 *  @desc Create image counter
18439		 *  Ex: 1/10
18440		 */
18441		LightGallery.prototype.counter = function () {
18442			if (this.settings.counter) {
18443				var counterHtml = "<div class=\"lg-counter\" role=\"status\" aria-live=\"polite\">\n                <span id=\"" + this.getIdName('lg-counter-current') + "\" class=\"lg-counter-current\">" + (this.index + 1) + " </span> /\n                <span id=\"" + this.getIdName('lg-counter-all') + "\" class=\"lg-counter-all\">" + this.galleryItems.length + " </span></div>";
18444				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
18445			}
18446		};
18447		/**
18448		 *  @desc add sub-html into the slide
18449		 *  @param {Number} index - index of the slide
18450		 */
18451		LightGallery.prototype.addHtml = function (index) {
18452			var subHtml;
18453			var subHtmlUrl;
18454			if (this.galleryItems[index].subHtmlUrl) {
18455				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
18456			}
18457			else {
18458				subHtml = this.galleryItems[index].subHtml;
18459			}
18460			if (!subHtmlUrl) {
18461				if (subHtml) {
18462					// get first letter of sub-html
18463					// if first letter starts with . or # get the html form the jQuery object
18464					var fL = subHtml.substring(0, 1);
18465					if (fL === '.' || fL === '#') {
18466						if (this.settings.subHtmlSelectorRelative &&
18467							!this.settings.dynamic) {
18468							subHtml = $LG(this.items)
18469								.eq(index)
18470								.find(subHtml)
18471								.first()
18472								.html();
18473						}
18474						else {
18475							subHtml = $LG(subHtml).first().html();
18476						}
18477					}
18478				}
18479				else {
18480					subHtml = '';
18481				}
18482			}
18483			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18484				if (subHtmlUrl) {
18485					this.outer.find('.lg-sub-html').load(subHtmlUrl);
18486				}
18487				else {
18488					this.outer.find('.lg-sub-html').html(subHtml);
18489				}
18490			}
18491			else {
18492				var currentSlide = $LG(this.getSlideItemId(index));
18493				if (subHtmlUrl) {
18494					currentSlide.load(subHtmlUrl);
18495				}
18496				else {
18497					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
18498				}
18499			}
18500			// Add lg-empty-html class if title doesn't exist
18501			if (typeof subHtml !== 'undefined' && subHtml !== null) {
18502				if (subHtml === '') {
18503					this.outer
18504						.find(this.settings.appendSubHtmlTo)
18505						.addClass('lg-empty-html');
18506				}
18507				else {
18508					this.outer
18509						.find(this.settings.appendSubHtmlTo)
18510						.removeClass('lg-empty-html');
18511				}
18512			}
18513			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
18514				index: index,
18515			});
18516		};
18517		/**
18518		 *  @desc Preload slides
18519		 *  @param {Number} index - index of the slide
18520		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
18521		 */
18522		LightGallery.prototype.preload = function (index) {
18523			for (var i = 1; i <= this.settings.preload; i++) {
18524				if (i >= this.galleryItems.length - index) {
18525					break;
18526				}
18527				this.loadContent(index + i, false);
18528			}
18529			for (var j = 1; j <= this.settings.preload; j++) {
18530				if (index - j < 0) {
18531					break;
18532				}
18533				this.loadContent(index - j, false);
18534			}
18535		};
18536		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
18537			if (!imageSize)
18538				return '';
18539			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
18540		};
18541		LightGallery.prototype.getVideoContStyle = function (imageSize) {
18542			if (!imageSize)
18543				return '';
18544			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
18545		};
18546		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
18547			var $currentItem;
18548			if (!this.settings.dynamic) {
18549				$currentItem = $LG(this.items).eq(index);
18550			}
18551			if ($currentItem) {
18552				var _dummyImgSrc = void 0;
18553				if (!this.settings.exThumbImage) {
18554					_dummyImgSrc = $currentItem.find('img').first().attr('src');
18555				}
18556				else {
18557					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
18558				}
18559				if (!_dummyImgSrc)
18560					return '';
18561				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18562				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
18563				$currentSlide.addClass('lg-first-slide');
18564				this.outer.addClass('lg-first-slide-loading');
18565				return dummyImgContent;
18566			}
18567			return '';
18568		};
18569		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
18570			var currentGalleryItem = this.galleryItems[index];
18571			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18572			// Use the thumbnail as dummy image which will be resized to actual image size and
18573			// displayed on top of actual image
18574			var imgContent = '';
18575			var altAttr = alt ? 'alt="' + alt + '"' : '';
18576			if (this.isFirstSlideWithZoomAnimation()) {
18577				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
18578			}
18579			else {
18580				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
18581			}
18582			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
18583			$currentSlide.prepend(imgMarkup);
18584		};
18585		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
18586			var mediaObject = $slide.find('.lg-object').first();
18587			if (utils.isImageLoaded(mediaObject.get()) ||
18588				isHTML5VideoWithoutPoster) {
18589				onLoad();
18590			}
18591			else {
18592				mediaObject.on('load.lg error.lg', function () {
18593					onLoad && onLoad();
18594				});
18595				mediaObject.on('error.lg', function () {
18596					onError && onError();
18597				});
18598			}
18599		};
18600		/**
18601		 *
18602		 * @param $el Current slide item
18603		 * @param index
18604		 * @param delay Delay is 0 except first time
18605		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
18606		 * @param isFirstSlide
18607		 */
18608		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
18609			var _this = this;
18610			//Uncode edit ##START##
18611			var $item = _this.galleryItems[index],
18612				type = $item.type;
18613
18614			if ( typeof $item.src !== 'undefined' ) {
18615				var inline_id = $item.src.replace('#', ''),
18616					$inline = document.getElementById(inline_id),
18617					inline_html;
18618
18619				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18620					inline_html = $inline.innerHTML;
18621				} else {
18622					inline_html = '';
18623				}
18624			}
18625			//Uncode edit ##END##
18626			this.onSlideObjectLoad(currentSlide, true, function () {
18627				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
18628			}, function () {
18629				currentSlide.addClass('lg-complete lg-complete_');
18630				//Uncode edit ##START##
18631				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18632				if ( inline_html !== '' ) {
18633					currentSlide.html(inline_html);
18634				} else {
18635					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18636				}
18637				//Uncode edit ##END##
18638			});
18639		};
18640		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
18641			var _this = this;
18642			var currentGalleryItem = this.galleryItems[index];
18643			// Adding delay for video slides without poster for better performance and user experience
18644			// Videos should start playing once once the gallery is completely loaded
18645			var _speed = isFirstSlide &&
vendor: 37,617 bytes, lines 18646-19728
18646				this.getSlideType(currentGalleryItem) === 'video' &&
18647				!currentGalleryItem.poster
18648				? speed
18649				: 0;
18650			setTimeout(function () {
18651				$currentSlide.addClass('lg-complete lg-complete_');
18652				_this.LGel.trigger(lGEvents.slideItemLoad, {
18653					index: index,
18654					delay: delay || 0,
18655					isFirstSlide: isFirstSlide,
18656				});
18657			}, _speed);
18658		};
18659		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
18660			return !!(!this.lGalleryOn &&
18661				this.zoomFromOrigin &&
18662				this.currentImageSize);
18663		};
18664		// Add video slideInfo
18665		LightGallery.prototype.addSlideVideoInfo = function (items) {
18666			var _this = this;
18667			items.forEach(function (element, index) {
18668				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
18669				if (element.__slideVideoInfo &&
18670					_this.settings.loadYouTubePoster &&
18671					!element.poster &&
18672					element.__slideVideoInfo.youtube) {
18673					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
18674				}
18675			});
18676		};
18677		/**
18678		 *  Load slide content into slide.
18679		 *  This is used to load content into slides that is not visible too
18680		 *  @param {Number} index - index of the slide.
18681		 *  @param {Boolean} rec - if true call loadcontent() function again.
18682		 */
18683		LightGallery.prototype.loadContent = function (index, rec) {
18684			var _this = this;
18685			var currentGalleryItem = this.galleryItems[index];
18686			var $currentSlide = $LG(this.getSlideItemId(index));
18687			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18688			var src = currentGalleryItem.src;
18689			var video = currentGalleryItem.video;
18690			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
18691			if (currentGalleryItem.responsive) {
18692				var srcDyItms = currentGalleryItem.responsive.split(',');
18693				src = utils.getResponsiveSrc(srcDyItms) || src;
18694			}
18695			var videoInfo = currentGalleryItem.__slideVideoInfo;
18696			var lgVideoStyle = '';
18697			var iframe = !!currentGalleryItem.iframe;
18698			var isFirstSlide = !this.lGalleryOn;
18699			// delay for adding complete class. it is 0 except first time.
18700			var delay = 0;
18701			if (isFirstSlide) {
18702				if (this.zoomFromOrigin && this.currentImageSize) {
18703					delay = this.settings.startAnimationDuration + 10;
18704				}
18705				else {
18706					delay = this.settings.backdropDuration + 10;
18707				}
18708			}
18709			if (!$currentSlide.hasClass('lg-loaded')) {
18710				if (videoInfo) {
18711					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
18712					//Uncode edit ##START##
18713					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18714					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
18715					//Uncode edit ##END##
18716					lgVideoStyle = this.getVideoContStyle(videoSize);
18717				}
18718				if (iframe) {
18719					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18720					$currentSlide.prepend(markup);
18721				}
18722				else if (poster) {
18723					var dummyImg = '';
18724					var hasStartAnimation = isFirstSlide &&
18725						this.zoomFromOrigin &&
18726						this.currentImageSize;
18727					if (hasStartAnimation) {
18728						dummyImg = this.getDummyImageContent($currentSlide, index, '');
18729					}
18730					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18731					$currentSlide.prepend(markup);
18732				}
18733				//Uncode edit ##START##
18734				// else if (videoInfo) {
18735				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18736					if (! _html5Video) {
18737						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18738					}
18739					//Uncode edit ##END##
18740					$currentSlide.prepend(markup);
18741				}
18742				else {
18743					this.setImgMarkup(src, $currentSlide, index);
18744					if (srcset || sources) {
18745						var $img = $currentSlide.find('.lg-object');
18746						this.initPictureFill($img);
18747					}
18748				}
18749				if (poster || videoInfo) {
18750					this.LGel.trigger(lGEvents.hasVideo, {
18751						index: index,
18752						src: src,
18753						html5Video: _html5Video,
18754						hasPoster: !!poster,
18755					});
18756				}
18757				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18758				if (this.lGalleryOn &&
18759					this.settings.appendSubHtmlTo === '.lg-item') {
18760					this.addHtml(index);
18761				}
18762			}
18763			// For first time add some delay for displaying the start animation.
18764			var _speed = 0;
18765			// Do not change the delay value because it is required for zoom plugin.
18766			// If gallery opened from direct url (hash) speed value should be 0
18767			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18768				_speed = delay;
18769			}
18770			// Only for first slide and zoomFromOrigin is enabled
18771			if (this.isFirstSlideWithZoomAnimation()) {
18772				setTimeout(function () {
18773					$currentSlide
18774						.removeClass('lg-start-end-progress lg-start-progress')
18775						.removeAttr('style');
18776				}, this.settings.startAnimationDuration + 100);
18777				if (!$currentSlide.hasClass('lg-loaded')) {
18778					setTimeout(function () {
18779						if (_this.getSlideType(currentGalleryItem) === 'image') {
18780							var alt = currentGalleryItem.alt;
18781							var altAttr = alt ? 'alt="' + alt + '"' : '';
18782							$currentSlide
18783								.find('.lg-img-wrap')
18784								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
18785							if (srcset || sources) {
18786								var $img = $currentSlide.find('.lg-object');
18787								_this.initPictureFill($img);
18788							}
18789						}
18790						if (_this.getSlideType(currentGalleryItem) === 'image' ||
18791							(_this.getSlideType(currentGalleryItem) === 'video' &&
18792								poster)) {
18793							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18794							// load remaining slides once the slide is completely loaded
18795							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18796								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18797							}, function () {
18798								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18799							});
18800						}
18801					}, this.settings.startAnimationDuration + 100);
18802				}
18803			}
18804			// SLide content has been added to dom
18805			$currentSlide.addClass('lg-loaded');
18806			if (!this.isFirstSlideWithZoomAnimation() ||
18807				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18808				//Uncode edit ##START##
18809				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18810				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.getSlideType(currentGalleryItem) === 'audio'));
18811				//Uncode edit ##END##
18812			}
18813			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18814			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18815				$currentSlide.hasClass('lg-complete_') &&
18816				!this.lGalleryOn) {
18817				setTimeout(function () {
18818					$currentSlide.addClass('lg-complete');
18819				}, this.settings.backdropDuration);
18820			}
18821			// Content loaded
18822			// Need to set lGalleryOn before calling preload function
18823			this.lGalleryOn = true;
18824			if (rec === true) {
18825				if (!$currentSlide.hasClass('lg-complete_')) {
18826					$currentSlide
18827						.find('.lg-object')
18828						.first()
18829						.on('load.lg error.lg', function () {
18830						_this.preload(index);
18831					});
18832				}
18833				else {
18834					this.preload(index);
18835				}
18836			}
18837		};
18838		/**
18839		 * @desc Remove dummy image content and load next slides
18840		 * Called only for the first time if zoomFromOrigin animation is enabled
18841		 * @param index
18842		 * @param $currentSlide
18843		 * @param speed
18844		 */
18845		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18846			var _this = this;
18847			setTimeout(function () {
18848				$currentSlide.find('.lg-dummy-img').remove();
18849				$currentSlide.removeClass('lg-first-slide');
18850				_this.outer.removeClass('lg-first-slide-loading');
18851				_this.isDummyImageRemoved = true;
18852				_this.preload(index);
18853			}, speed + 300);
18854		};
18855		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18856			var _this = this;
18857			if (numberOfItems === void 0) { numberOfItems = 0; }
18858			var itemsToBeInsertedToDom = [];
18859			// Minimum 2 items should be there
18860			var possibleNumberOfItems = Math.max(numberOfItems, 3);
18861			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18862			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18863			if (this.galleryItems.length <= 3) {
18864				this.galleryItems.forEach(function (_element, index) {
18865					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18866				});
18867				return itemsToBeInsertedToDom;
18868			}
18869			if (index < (this.galleryItems.length - 1) / 2) {
18870				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18871					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18872				}
18873				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18874				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18875					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18876				}
18877			}
18878			else {
18879				for (var idx = index; idx <= this.galleryItems.length - 1 &&
18880					idx < index + possibleNumberOfItems / 2; idx++) {
18881					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18882				}
18883				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18884				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18885					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18886				}
18887			}
18888			if (this.settings.loop) {
18889				if (index === this.galleryItems.length - 1) {
18890					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18891				}
18892				else if (index === 0) {
18893					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18894				}
18895			}
18896			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18897				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18898			}
18899			return itemsToBeInsertedToDom;
18900		};
18901		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18902			var _this = this;
18903			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18904			itemsToBeInsertedToDom.forEach(function (item) {
18905				if (_this.currentItemsInDom.indexOf(item) === -1) {
18906					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18907				}
18908			});
18909			this.currentItemsInDom.forEach(function (item) {
18910				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18911					$LG("#" + item).remove();
18912				}
18913			});
18914			return itemsToBeInsertedToDom;
18915		};
18916		/**
18917		 * Get previous index of the slide
18918		 */
18919		LightGallery.prototype.getPreviousSlideIndex = function () {
18920			var prevIndex = 0;
18921			try {
18922				var currentItemId = this.outer
18923					.find('.lg-current')
18924					.first()
18925					.attr('id');
18926				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18927			}
18928			catch (error) {
18929				prevIndex = 0;
18930			}
18931			return prevIndex;
18932		};
18933		LightGallery.prototype.setDownloadValue = function (index) {
18934			if (this.settings.download) {
18935				var currentGalleryItem = this.galleryItems[index];
18936				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18937					currentGalleryItem.downloadUrl === 'false';
18938				if (hideDownloadBtn) {
18939					this.outer.addClass('lg-hide-download');
18940				}
18941				else {
18942					var $download = this.getElementById('lg-download');
18943					this.outer.removeClass('lg-hide-download');
18944					$download.attr('href', currentGalleryItem.downloadUrl ||
18945						currentGalleryItem.src);
18946					if (currentGalleryItem.download) {
18947						//Uncode edit ##START##
18948						var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
18949							download_name = download_url.substring(download_url.lastIndexOf('/')+1);
18950						$download.attr('download', download_name);
18951						// $download.attr('download', currentGalleryItem.download);
18952						//Uncode edit ##END##
18953					}
18954				}
18955			}
18956		};
18957		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
18958			var _this = this;
18959			if (this.lGalleryOn) {
18960				previousSlideItem.addClass('lg-slide-progress');
18961			}
18962			setTimeout(function () {
18963				// remove all transitions
18964				_this.outer.addClass('lg-no-trans');
18965				_this.outer
18966					.find('.lg-item')
18967					.removeClass('lg-prev-slide lg-next-slide');
18968				if (direction === 'prev') {
18969					//prevslide
18970					currentSlideItem.addClass('lg-prev-slide');
18971					previousSlideItem.addClass('lg-next-slide');
18972				}
18973				else {
18974					// next slide
18975					currentSlideItem.addClass('lg-next-slide');
18976					previousSlideItem.addClass('lg-prev-slide');
18977				}
18978				// give 50 ms for browser to add/remove class
18979				setTimeout(function () {
18980					_this.outer.find('.lg-item').removeClass('lg-current');
18981					currentSlideItem.addClass('lg-current');
18982					// reset all transitions
18983					_this.outer.removeClass('lg-no-trans');
18984				}, 50);
18985			}, this.lGalleryOn ? this.settings.slideDelay : 0);
18986		};
18987		/**
18988		 * Goto a specific slide.
18989		 * @param {Number} index - index of the slide
18990		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
18991		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
18992		 * @param {String} direction - Direction of the slide(next/prev)
18993		 * @category lGPublicMethods
18994		 * @example
18995		 *  const plugin = lightGallery();
18996		 *  // to go to 3rd slide
18997		 *  plugin.slide(2);
18998		 *
18999		 */
19000		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
19001			var _this = this;
19002			var prevIndex = this.getPreviousSlideIndex();
19003			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
19004			// Prevent multiple call, Required for hsh plugin
19005			if (this.lGalleryOn && prevIndex === index) {
19006				return;
19007			}
19008			var numberOfGalleryItems = this.galleryItems.length;
19009			if (!this.lgBusy) {
19010				if (this.settings.counter) {
19011					this.updateCurrentCounter(index);
19012				}
19013				var currentSlideItem = this.getSlideItem(index);
19014				var previousSlideItem_1 = this.getSlideItem(prevIndex);
19015				var currentGalleryItem = this.galleryItems[index];
19016				var videoInfo = currentGalleryItem.__slideVideoInfo;
19017				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
19018				this.setDownloadValue(index);
19019				if (videoInfo) {
19020					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
19021					//Uncode edit ##START##
19022					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19023					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
19024					//Uncode edit ##END##
19025					this.resizeVideoSlide(index, videoSize);
19026				}
19027				this.LGel.trigger(lGEvents.beforeSlide, {
19028					prevIndex: prevIndex,
19029					index: index,
19030					fromTouch: !!fromTouch,
19031					fromThumb: !!fromThumb,
19032					//Uncode edit ##START##
19033					currentSlide: currentSlideItem,
19034					previousSlide: previousSlideItem_1,
19035					info: currentGalleryItem,
19036					item: this.items[index]
19037					//Uncode edit ##END##
19038				});
19039				this.lgBusy = true;
19040				clearTimeout(this.hideBarTimeout);
19041				this.arrowDisable(index);
19042				if (!direction) {
19043					if (index < prevIndex) {
19044						direction = 'prev';
19045					}
19046					else if (index > prevIndex) {
19047						direction = 'next';
19048					}
19049				}
19050				if (!fromTouch) {
19051					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
19052				}
19053				else {
19054					this.outer
19055						.find('.lg-item')
19056						.removeClass('lg-prev-slide lg-current lg-next-slide');
19057					var touchPrev = void 0;
19058					var touchNext = void 0;
19059					if (numberOfGalleryItems > 2) {
19060						touchPrev = index - 1;
19061						touchNext = index + 1;
19062						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
19063							// next slide
19064							touchNext = 0;
19065							touchPrev = numberOfGalleryItems - 1;
19066						}
19067						else if (index === numberOfGalleryItems - 1 &&
19068							prevIndex === 0) {
19069							// prev slide
19070							touchNext = 0;
19071							touchPrev = numberOfGalleryItems - 1;
19072						}
19073					}
19074					else {
19075						touchPrev = 0;
19076						touchNext = 1;
19077					}
19078					if (direction === 'prev') {
19079						this.getSlideItem(touchNext).addClass('lg-next-slide');
19080					}
19081					else {
19082						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
19083					}
19084					currentSlideItem.addClass('lg-current');
19085				}
19086				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
19087				if (!this.lGalleryOn) {
19088					this.loadContent(index, true);
19089				}
19090				else {
19091					setTimeout(function () {
19092						_this.loadContent(index, true);
19093						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
19094						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
19095							_this.addHtml(index);
19096						}
19097					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
19098				}
19099				setTimeout(function () {
19100					_this.lgBusy = false;
19101					previousSlideItem_1.removeClass('lg-slide-progress');
19102					_this.LGel.trigger(lGEvents.afterSlide, {
19103						prevIndex: prevIndex,
19104						index: index,
19105						fromTouch: fromTouch,
19106						fromThumb: fromThumb,
19107					});
19108				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
19109			}
19110			this.index = index;
19111		};
19112		LightGallery.prototype.updateCurrentCounter = function (index) {
19113			this.getElementById('lg-counter-current').html(index + 1 + '');
19114		};
19115		LightGallery.prototype.updateCounterTotal = function () {
19116			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
19117		};
19118		LightGallery.prototype.getSlideType = function (item) {
19119			if (item.__slideVideoInfo) {
19120				return 'video';
19121			}
19122			else if (item.iframe) {
19123				return 'iframe';
19124			}
19125			//Uncode edit ##START##
19126			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
19127				return 'audio';
19128			}
19129			//Uncode edit ##END##
19130			else {
19131				return 'image';
19132			}
19133		};
19134		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
19135			var distanceX = endCoords.pageX - startCoords.pageX;
19136			var distanceY = endCoords.pageY - startCoords.pageY;
19137			var allowSwipe = false;
19138			if (this.swipeDirection) {
19139				allowSwipe = true;
19140			}
19141			else {
19142				if (Math.abs(distanceX) > 15) {
19143					this.swipeDirection = 'horizontal';
19144					allowSwipe = true;
19145				}
19146				else if (Math.abs(distanceY) > 15) {
19147					this.swipeDirection = 'vertical';
19148					allowSwipe = true;
19149				}
19150			}
19151			if (!allowSwipe) {
19152				return;
19153			}
19154			var $currentSlide = this.getSlideItem(this.index);
19155			if (this.swipeDirection === 'horizontal') {
19156				e === null || e === void 0 ? void 0 : e.preventDefault();
19157				// reset opacity and transition duration
19158				this.outer.addClass('lg-dragging');
19159				// move current slide
19160				this.setTranslate($currentSlide, distanceX, 0);
19161				// move next and prev slide with current slide
19162				var width = $currentSlide.get().offsetWidth;
19163				var slideWidthAmount = (width * 15) / 100;
19164				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
19165				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
19166				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
19167			}
19168			else if (this.swipeDirection === 'vertical') {
19169				if (this.settings.swipeToClose) {
19170					e === null || e === void 0 ? void 0 : e.preventDefault();
19171					this.$container.addClass('lg-dragging-vertical');
19172					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
19173					this.$backdrop.css('opacity', opacity);
19174					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
19175					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
19176					if (Math.abs(distanceY) > 100) {
19177						this.outer
19178							.addClass('lg-hide-items')
19179							.removeClass('lg-components-open');
19180					}
19181				}
19182			}
19183		};
19184		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
19185			var _this = this;
19186			var distance;
19187			// keep slide animation for any mode while dragg/swipe
19188			if (this.settings.mode !== 'lg-slide') {
19189				this.outer.addClass('lg-slide');
19190			}
19191			// set transition duration
19192			setTimeout(function () {
19193				_this.$container.removeClass('lg-dragging-vertical');
19194				_this.outer
19195					.removeClass('lg-dragging lg-hide-items')
19196					.addClass('lg-components-open');
19197				var triggerClick = true;
19198				if (_this.swipeDirection === 'horizontal') {
19199					distance = endCoords.pageX - startCoords.pageX;
19200					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
19201					if (distance < 0 &&
19202						distanceAbs > _this.settings.swipeThreshold) {
19203						_this.goToNextSlide(true);
19204						triggerClick = false;
19205					}
19206					else if (distance > 0 &&
19207						distanceAbs > _this.settings.swipeThreshold) {
19208						_this.goToPrevSlide(true);
19209						triggerClick = false;
19210					}
19211				}
19212				else if (_this.swipeDirection === 'vertical') {
19213					distance = Math.abs(endCoords.pageY - startCoords.pageY);
19214					if (_this.settings.closable &&
19215						_this.settings.swipeToClose &&
19216						distance > 100) {
19217						_this.closeGallery();
19218						return;
19219					}
19220					else {
19221						_this.$backdrop.css('opacity', 1);
19222					}
19223				}
19224				_this.outer.find('.lg-item').removeAttr('style');
19225				if (triggerClick &&
19226					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
19227					// Trigger click if distance is less than 5 pix
19228					var target = $LG(event.target);
19229					if (_this.isPosterElement(target)) {
19230						_this.LGel.trigger(lGEvents.posterClick);
19231					}
19232				}
19233				_this.swipeDirection = undefined;
19234			});
19235			// remove slide class once drag/swipe is completed if mode is not slide
19236			setTimeout(function () {
19237				if (!_this.outer.hasClass('lg-dragging') &&
19238					_this.settings.mode !== 'lg-slide') {
19239					_this.outer.removeClass('lg-slide');
19240				}
19241			}, this.settings.speed + 100);
19242		};
19243		LightGallery.prototype.enableSwipe = function () {
19244			var _this = this;
19245			var startCoords = {};
19246			var endCoords = {};
19247			var isMoved = false;
19248			var isSwiping = false;
19249			if (this.settings.enableSwipe) {
19250				this.$inner.on('touchstart.lg', function (e) {
19251					_this.dragOrSwipeEnabled = true;
19252					var $item = _this.getSlideItem(_this.index);
19253					if (($LG(e.target).hasClass('lg-item') ||
19254						$item.get().contains(e.target)) &&
19255						!_this.outer.hasClass('lg-zoomed') &&
19256						!_this.lgBusy &&
19257						e.targetTouches.length === 1) {
19258						isSwiping = true;
19259						_this.touchAction = 'swipe';
19260						_this.manageSwipeClass();
19261						startCoords = {
19262							pageX: e.targetTouches[0].pageX,
19263							pageY: e.targetTouches[0].pageY,
19264						};
19265					}
19266				});
19267				this.$inner.on('touchmove.lg', function (e) {
19268					if (isSwiping &&
19269						_this.touchAction === 'swipe' &&
19270						e.targetTouches.length === 1) {
19271						endCoords = {
19272							pageX: e.targetTouches[0].pageX,
19273							pageY: e.targetTouches[0].pageY,
19274						};
19275						_this.touchMove(startCoords, endCoords, e);
19276						isMoved = true;
19277					}
19278				});
19279				this.$inner.on('touchend.lg', function (event) {
19280					if (_this.touchAction === 'swipe') {
19281						if (isMoved) {
19282							isMoved = false;
19283							_this.touchEnd(endCoords, startCoords, event);
19284						}
19285						else if (isSwiping) {
19286							var target = $LG(event.target);
19287							if (_this.isPosterElement(target)) {
19288								_this.LGel.trigger(lGEvents.posterClick);
19289							}
19290						}
19291						_this.touchAction = undefined;
19292						isSwiping = false;
19293					}
19294				});
19295			}
19296		};
19297		LightGallery.prototype.enableDrag = function () {
19298			var _this = this;
19299			var startCoords = {};
19300			var endCoords = {};
19301			var isDraging = false;
19302			var isMoved = false;
19303			if (this.settings.enableDrag) {
19304				this.outer.on('mousedown.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						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
19310							e.preventDefault();
19311							if (!_this.lgBusy) {
19312								_this.manageSwipeClass();
19313								startCoords = {
19314									pageX: e.pageX,
19315									pageY: e.pageY,
19316								};
19317								isDraging = true;
19318								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
19319								_this.outer.get().scrollLeft += 1;
19320								_this.outer.get().scrollLeft -= 1;
19321								// *
19322								_this.outer
19323									.removeClass('lg-grab')
19324									.addClass('lg-grabbing');
19325								_this.LGel.trigger(lGEvents.dragStart);
19326							}
19327						}
19328					}
19329				});
19330				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
19331					if (isDraging && _this.lgOpened) {
19332						isMoved = true;
19333						endCoords = {
19334							pageX: e.pageX,
19335							pageY: e.pageY,
19336						};
19337						_this.touchMove(startCoords, endCoords);
19338						_this.LGel.trigger(lGEvents.dragMove);
19339					}
19340				});
19341				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
19342					if (!_this.lgOpened) {
19343						return;
19344					}
19345					var target = $LG(event.target);
19346					if (isMoved) {
19347						isMoved = false;
19348						_this.touchEnd(endCoords, startCoords, event);
19349						_this.LGel.trigger(lGEvents.dragEnd);
19350					}
19351					else if (_this.isPosterElement(target)) {
19352						_this.LGel.trigger(lGEvents.posterClick);
19353					}
19354					// Prevent execution on click
19355					if (isDraging) {
19356						isDraging = false;
19357						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
19358					}
19359				});
19360			}
19361		};
19362		LightGallery.prototype.triggerPosterClick = function () {
19363			var _this = this;
19364			this.$inner.on('click.lg', function (event) {
19365				if (!_this.dragOrSwipeEnabled &&
19366					_this.isPosterElement($LG(event.target))) {
19367					_this.LGel.trigger(lGEvents.posterClick);
19368				}
19369			});
19370		};
19371		LightGallery.prototype.manageSwipeClass = function () {
19372			var _touchNext = this.index + 1;
19373			var _touchPrev = this.index - 1;
19374			if (this.settings.loop && this.galleryItems.length > 2) {
19375				if (this.index === 0) {
19376					_touchPrev = this.galleryItems.length - 1;
19377				}
19378				else if (this.index === this.galleryItems.length - 1) {
19379					_touchNext = 0;
19380				}
19381			}
19382			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
19383			if (_touchPrev > -1) {
19384				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
19385			}
19386			this.getSlideItem(_touchNext).addClass('lg-next-slide');
19387		};
19388		/**
19389		 * Go to next slide
19390		 * @param {Boolean} fromTouch - true if slide function called via touch event
19391		 * @category lGPublicMethods
19392		 * @example
19393		 *  const plugin = lightGallery();
19394		 *  plugin.goToNextSlide();
19395		 * @see <a href="/demos/methods/">Demo</a>
19396		 */
19397		LightGallery.prototype.goToNextSlide = function (fromTouch) {
19398			var _this = this;
19399			var _loop = this.settings.loop;
19400			if (fromTouch && this.galleryItems.length < 3) {
19401				_loop = false;
19402			}
19403			if (!this.lgBusy) {
19404				if (this.index + 1 < this.galleryItems.length) {
19405					this.index++;
19406					this.LGel.trigger(lGEvents.beforeNextSlide, {
19407						index: this.index,
19408					});
19409					this.slide(this.index, !!fromTouch, false, 'next');
19410				}
19411				else {
19412					if (_loop) {
19413						this.index = 0;
19414						this.LGel.trigger(lGEvents.beforeNextSlide, {
19415							index: this.index,
19416						});
19417						this.slide(this.index, !!fromTouch, false, 'next');
19418					}
19419					else if (this.settings.slideEndAnimation && !fromTouch) {
19420						this.outer.addClass('lg-right-end');
19421						setTimeout(function () {
19422							_this.outer.removeClass('lg-right-end');
19423						}, 400);
19424					}
19425				}
19426			}
19427		};
19428		/**
19429		 * Go to previous slides
19430		 * @param {Boolean} fromTouch - true if slide function called via touch event
19431		 * @category lGPublicMethods
19432		 * @example
19433		 *  const plugin = lightGallery({});
19434		 *  plugin.goToPrevSlide();
19435		 * @see <a href="/demos/methods/">Demo</a>
19436		 *
19437		 */
19438		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
19439			var _this = this;
19440			var _loop = this.settings.loop;
19441			if (fromTouch && this.galleryItems.length < 3) {
19442				_loop = false;
19443			}
19444			if (!this.lgBusy) {
19445				if (this.index > 0) {
19446					this.index--;
19447					this.LGel.trigger(lGEvents.beforePrevSlide, {
19448						index: this.index,
19449						fromTouch: fromTouch,
19450					});
19451					this.slide(this.index, !!fromTouch, false, 'prev');
19452				}
19453				else {
19454					if (_loop) {
19455						this.index = this.galleryItems.length - 1;
19456						this.LGel.trigger(lGEvents.beforePrevSlide, {
19457							index: this.index,
19458							fromTouch: fromTouch,
19459						});
19460						this.slide(this.index, !!fromTouch, false, 'prev');
19461					}
19462					else if (this.settings.slideEndAnimation && !fromTouch) {
19463						this.outer.addClass('lg-left-end');
19464						setTimeout(function () {
19465							_this.outer.removeClass('lg-left-end');
19466						}, 400);
19467					}
19468				}
19469			}
19470		};
19471		LightGallery.prototype.keyPress = function () {
19472			var _this = this;
19473			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19474				if (_this.lgOpened &&
19475					_this.settings.escKey === true &&
19476					e.keyCode === 27) {
19477					e.preventDefault();
19478					if (_this.settings.allowMediaOverlap &&
19479						_this.outer.hasClass('lg-can-toggle') &&
19480						_this.outer.hasClass('lg-components-open')) {
19481						_this.outer.removeClass('lg-components-open');
19482					}
19483					else {
19484						_this.closeGallery();
19485					}
19486				}
19487				if (_this.lgOpened && _this.galleryItems.length > 1) {
19488					if (e.keyCode === 37) {
19489						e.preventDefault();
19490						_this.goToPrevSlide();
19491					}
19492					if (e.keyCode === 39) {
19493						e.preventDefault();
19494						_this.goToNextSlide();
19495					}
19496				}
19497			});
19498		};
19499		LightGallery.prototype.arrow = function () {
19500			var _this = this;
19501			this.getElementById('lg-prev').on('click.lg', function () {
19502				_this.goToPrevSlide();
19503			});
19504			this.getElementById('lg-next').on('click.lg', function () {
19505				_this.goToNextSlide();
19506			});
19507		};
19508		LightGallery.prototype.arrowDisable = function (index) {
19509			// Disable arrows if settings.hideControlOnEnd is true
19510			if (!this.settings.loop && this.settings.hideControlOnEnd) {
19511				var $prev = this.getElementById('lg-prev');
19512				var $next = this.getElementById('lg-next');
19513				if (index + 1 === this.galleryItems.length) {
19514					$next.attr('disabled', 'disabled').addClass('disabled');
19515				}
19516				else {
19517					$next.removeAttr('disabled').removeClass('disabled');
19518				}
19519				if (index === 0) {
19520					$prev.attr('disabled', 'disabled').addClass('disabled');
19521				}
19522				else {
19523					$prev.removeAttr('disabled').removeClass('disabled');
19524				}
19525			}
19526		};
19527		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
19528			if (scaleX === void 0) { scaleX = 1; }
19529			if (scaleY === void 0) { scaleY = 1; }
19530			$el.css('transform', 'translate3d(' +
19531				xValue +
19532				'px, ' +
19533				yValue +
19534				'px, 0px) scale3d(' +
19535				scaleX +
19536				', ' +
19537				scaleY +
19538				', 1)');
19539		};
19540		LightGallery.prototype.mousewheel = function () {
19541			var _this = this;
19542			var lastCall = 0;
19543			this.outer.on('wheel.lg', function (e) {
19544				if (!e.deltaY || _this.galleryItems.length < 2) {
19545					return;
19546				}
19547				e.preventDefault();
19548				var now = new Date().getTime();
19549				if (now - lastCall < 1000) {
19550					return;
19551				}
19552				lastCall = now;
19553				if (e.deltaY > 0) {
19554					_this.goToNextSlide();
19555				}
19556				else if (e.deltaY < 0) {
19557					_this.goToPrevSlide();
19558				}
19559			});
19560		};
19561		LightGallery.prototype.isSlideElement = function (target) {
19562			return (target.hasClass('lg-outer') ||
19563				target.hasClass('lg-item') ||
19564				target.hasClass('lg-img-wrap'));
19565		};
19566		LightGallery.prototype.isPosterElement = function (target) {
19567			var playButton = this.getSlideItem(this.index)
19568				.find('.lg-video-play-button')
19569				.get();
19570			return (target.hasClass('lg-video-poster') ||
19571				target.hasClass('lg-video-play-button') ||
19572				(playButton && playButton.contains(target.get())));
19573		};
19574		/**
19575		 * Maximize minimize inline gallery.
19576		 * @category lGPublicMethods
19577		 */
19578		LightGallery.prototype.toggleMaximize = function () {
19579			var _this = this;
19580			this.getElementById('lg-maximize').on('click.lg', function () {
19581				_this.$container.toggleClass('lg-inline');
19582				_this.refreshOnResize();
19583			});
19584		};
19585		LightGallery.prototype.invalidateItems = function () {
19586			for (var index = 0; index < this.items.length; index++) {
19587				var element = this.items[index];
19588				var $element = $LG(element);
19589				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
19590			}
19591		};
19592		LightGallery.prototype.trapFocus = function () {
19593			var _this = this;
19594			this.$container.get().focus({
19595				preventScroll: true,
19596			});
19597			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19598				if (!_this.lgOpened) {
19599					return;
19600				}
19601				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
19602				if (!isTabPressed) {
19603					return;
19604				}
19605				var focusableEls = utils.getFocusableElements(_this.$container.get());
19606				var firstFocusableEl = focusableEls[0];
19607				var lastFocusableEl = focusableEls[focusableEls.length - 1];
19608				if (e.shiftKey) {
19609					if (document.activeElement === firstFocusableEl) {
19610						lastFocusableEl.focus();
19611						e.preventDefault();
19612					}
19613				}
19614				else {
19615					if (document.activeElement === lastFocusableEl) {
19616						firstFocusableEl.focus();
19617						e.preventDefault();
19618					}
19619				}
19620			});
19621		};
19622		LightGallery.prototype.manageCloseGallery = function () {
19623			var _this = this;
19624			if (!this.settings.closable)
19625				return;
19626			var mousedown = false;
19627			this.getElementById('lg-close').on('click.lg', function () {
19628				_this.closeGallery();
19629			});
19630			if (this.settings.closeOnTap) {
19631				// If you drag the slide and release outside gallery gets close on chrome
19632				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
19633				this.outer.on('mousedown.lg', function (e) {
19634					var target = $LG(e.target);
19635					if (_this.isSlideElement(target)) {
19636						mousedown = true;
19637					}
19638					else {
19639						mousedown = false;
19640					}
19641				});
19642				this.outer.on('mousemove.lg', function () {
19643					mousedown = false;
19644				});
19645				this.outer.on('mouseup.lg', function (e) {
19646					var target = $LG(e.target);
19647					if (_this.isSlideElement(target) && mousedown) {
19648						if (!_this.outer.hasClass('lg-dragging')) {
19649							_this.closeGallery();
19650						}
19651					}
19652				});
19653			}
19654		};
19655		/**
19656		 * Close lightGallery if it is opened.
19657		 *
19658		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
19659		 * @return returns the estimated time to close gallery completely including the close animation duration
19660		 * @category lGPublicMethods
19661		 * @example
19662		 *  const plugin = lightGallery();
19663		 *  plugin.closeGallery();
19664		 *
19665		 */
19666		LightGallery.prototype.closeGallery = function (force) {
19667			var _this = this;
19668			if (!this.lgOpened || (!this.settings.closable && !force)) {
19669				return 0;
19670			}
19671			this.LGel.trigger(lGEvents.beforeClose);
19672			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
19673				$LG(window).scrollTop(this.prevScrollTop);
19674			}
19675			var currentItem = this.items[this.index];
19676			var transform;
19677			if (this.zoomFromOrigin && currentItem) {
19678				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
19679				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
19680				//Uncode edit ##START##
19681				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
19682				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
19683				//Uncode edit ##END##
19684				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
19685			}
19686			if (this.zoomFromOrigin && transform) {
19687				this.outer.addClass('lg-closing lg-zoom-from-image');
19688				this.getSlideItem(this.index)
19689					.addClass('lg-start-end-progress')
19690					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
19691					.css('transform', transform);
19692			}
19693			else {
19694				this.outer.addClass('lg-hide-items');
19695				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
19696				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
19697				this.outer.removeClass('lg-zoom-from-image');
19698			}
19699			// Unbind all events added by lightGallery
19700			// @todo
19701			//this.$el.off('.lg.tm');
19702			this.destroyModules();
19703			this.lGalleryOn = false;
19704			this.isDummyImageRemoved = false;
19705			this.zoomFromOrigin = this.settings.zoomFromOrigin;
19706			clearTimeout(this.hideBarTimeout);
19707			this.hideBarTimeout = false;
19708			$LG('html').removeClass('lg-on');
19709			this.outer.removeClass('lg-visible lg-components-open');
19710			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
19711			this.$backdrop.removeClass('in').css('opacity', 0);
19712			var removeTimeout = this.zoomFromOrigin && transform
19713				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
19714				: this.settings.backdropDuration;
19715			this.$container.removeClass('lg-show-in');
19716			// Once the closign animation is completed and gallery is invisible
19717			setTimeout(function () {
19718				if (_this.zoomFromOrigin && transform) {
19719					_this.outer.removeClass('lg-zoom-from-image');
19720				}
19721				_this.$container.removeClass('lg-show');
19722				// Reset scrollbar
19723				_this.resetScrollBar();
19724				// Need to remove inline opacity as it is used in the stylesheet as well
19725				_this.$backdrop
19726					.removeAttr('style')
19727					.css('transition-duration', _this.settings.backdropDuration + 'ms');
19728				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 19729-19932
19729				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
19730				_this.$inner.empty();
19731				if (_this.lgOpened) {
19732					_this.LGel.trigger(lGEvents.afterClose, {
19733						instance: _this,
19734					});
19735				}
19736				if (_this.$container.get()) {
19737					_this.$container.get().blur();
19738				}
19739				_this.lgOpened = false;
19740			}, removeTimeout + 100);
19741			return removeTimeout + 100;
19742		};
19743		LightGallery.prototype.initModules = function () {
19744			this.plugins.forEach(function (module) {
19745				try {
19746					module.init();
19747				}
19748				catch (err) {
19749					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
19750				}
19751			});
19752		};
19753		LightGallery.prototype.destroyModules = function (destroy) {
19754			this.plugins.forEach(function (module) {
19755				try {
19756					if (destroy) {
19757						module.destroy();
19758					}
19759					else {
19760						module.closeGallery && module.closeGallery();
19761					}
19762				}
19763				catch (err) {
19764					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19765				}
19766			});
19767		};
19768		/**
19769		 * Refresh lightGallery with new set of children.
19770		 *
19771		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19772		 *
19773		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19774		 * @see <a href="/demos/dynamic-mode/">Demo</a>
19775		 * @category lGPublicMethods
19776		 * @example
19777		 *  const plugin = lightGallery();
19778		 *  // Delete or add children, then call
19779		 *  plugin.refresh();
19780		 *
19781		 */
19782		LightGallery.prototype.refresh = function (galleryItems) {
19783			if (!this.settings.dynamic) {
19784				this.invalidateItems();
19785			}
19786			if (galleryItems) {
19787				this.galleryItems = galleryItems;
19788			}
19789			else {
19790				this.galleryItems = this.getItems();
19791			}
19792			this.updateControls();
19793			this.openGalleryOnItemClick();
19794			this.LGel.trigger(lGEvents.updateSlides);
19795		};
19796		LightGallery.prototype.updateControls = function () {
19797			this.addSlideVideoInfo(this.galleryItems);
19798			this.updateCounterTotal();
19799			this.manageSingleSlideClassName();
19800		};
19801		/**
19802		 * Destroy lightGallery.
19803		 * Destroy lightGallery and its plugin instances completely
19804		 *
19805		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19806		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19807		 * You can use refresh method most of the times.
19808		 * @category lGPublicMethods
19809		 * @example
19810		 *  const plugin = lightGallery();
19811		 *  plugin.destroy();
19812		 *
19813		 */
19814		LightGallery.prototype.destroy = function () {
19815			var _this = this;
19816			var closeTimeout = this.closeGallery(true);
19817			setTimeout(function () {
19818				_this.destroyModules(true);
19819				if (!_this.settings.dynamic) {
19820					_this.invalidateItems();
19821				}
19822				$LG(window).off(".lg.global" + _this.lgId);
19823				_this.LGel.off('.lg');
19824				_this.$container.remove();
19825			}, closeTimeout);
19826			return closeTimeout;
19827		};
19828		return LightGallery;
19829	}());
19830
19831	function lightGallery(el, options) {
19832		return new LightGallery(el, options);
19833	}
19834
19835	return lightGallery;
19836
19837})));
19838
19839/*!
19840 * lightgallery | 2.5.0 | June 13th 2022
19841 * http://www.lightgalleryjs.com/
19842 * Copyright (c) 2020 Sachin Neravath;
19843 * @license GPLv3
19844 */
19845
19846(function (global, factory) {
19847	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19848	typeof define === 'function' && define.amd ? define(factory) :
19849	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19850}(this, (function () { 'use strict';
19851
19852	/*! *****************************************************************************
19853	Copyright (c) Microsoft Corporation.
19854
19855	Permission to use, copy, modify, and/or distribute this software for any
19856	purpose with or without fee is hereby granted.
19857
19858	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19859	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19860	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19861	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19862	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19863	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19864	PERFORMANCE OF THIS SOFTWARE.
19865	***************************************************************************** */
19866
19867	var __assign = function() {
19868		__assign = Object.assign || function __assign(t) {
19869			for (var s, i = 1, n = arguments.length; i < n; i++) {
19870				s = arguments[i];
19871				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19872			}
19873			return t;
19874		};
19875		return __assign.apply(this, arguments);
19876	};
19877
19878	var zoomSettings = {
19879		scale: 1,
19880		zoom: true,
19881		actualSize: true,
19882		showZoomInOutIcons: false,
19883		actualSizeIcons: {
19884			zoomIn: 'lg-zoom-in',
19885			zoomOut: 'lg-zoom-out',
19886		},
19887		enableZoomAfter: 300,
19888		zoomPluginStrings: {
19889			zoomIn: 'Zoom in',
19890			zoomOut: 'Zoom out',
19891			viewActualSize: 'View actual size',
19892		},
19893	};
19894
19895	/**
19896	 * List of lightGallery events
19897	 * All events should be documented here
19898	 * Below interfaces are used to build the website documentations
19899	 * */
19900	var lGEvents = {
19901		afterAppendSlide: 'lgAfterAppendSlide',
19902		init: 'lgInit',
19903		hasVideo: 'lgHasVideo',
19904		containerResize: 'lgContainerResize',
19905		updateSlides: 'lgUpdateSlides',
19906		afterAppendSubHtml: 'lgAfterAppendSubHtml',
19907		beforeOpen: 'lgBeforeOpen',
19908		afterOpen: 'lgAfterOpen',
19909		slideItemLoad: 'lgSlideItemLoad',
19910		beforeSlide: 'lgBeforeSlide',
19911		afterSlide: 'lgAfterSlide',
19912		posterClick: 'lgPosterClick',
19913		dragStart: 'lgDragStart',
19914		dragMove: 'lgDragMove',
19915		dragEnd: 'lgDragEnd',
19916		beforeNextSlide: 'lgBeforeNextSlide',
19917		beforePrevSlide: 'lgBeforePrevSlide',
19918		beforeClose: 'lgBeforeClose',
19919		afterClose: 'lgAfterClose',
19920		rotateLeft: 'lgRotateLeft',
19921		rotateRight: 'lgRotateRight',
19922		flipHorizontal: 'lgFlipHorizontal',
19923		flipVertical: 'lgFlipVertical',
19924		autoplay: 'lgAutoplay',
19925		autoplayStart: 'lgAutoplayStart',
19926		autoplayStop: 'lgAutoplayStop',
19927	};
19928
19929	var Zoom = /** @class */ (function () {
19930		function Zoom(instance, $LG) {
19931			// get lightGallery core plugin instance
19932			this.core = instance;
19933			this.$LG = $LG;
19934			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19935			return this;
19936		}
19937		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
19938		Zoom.prototype.buildTemplates = function () {
19939			var zoomIcons = this.settings.showZoomInOutIcons
19940				? "<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>"
19941				: '';
19942			if (this.settings.actualSize) {
19943				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>";
19944			}
19945			this.core.outer.addClass('lg-use-transition-for-zoom');
19946			this.core.$toolbar.first().append(zoomIcons);
19947		};
19948		/**
19949		 * @desc Enable zoom option only once the image is completely loaded
19950		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
19951		 *
19952		 * Zoom styles are defined under lg-zoomable CSS class.
19953		 */
19954		Zoom.prototype.enableZoom = function (event) {
19955			var _this = this;
19956			// delay will be 0 except first time
19957			var _speed = this.settings.enableZoomAfter + event.detail.delay;
19958			// set _speed value 0 if gallery opened from direct url and if it is first slide
19959			if (this.$LG('body').first().hasClass('lg-from-hash') &&
19960				event.detail.delay) {
19961				// will execute only once
19962				_speed = 0;
19963			}
19964			else {
19965				// Remove lg-from-hash to enable starting animation.
19966				this.$LG('body').first().removeClass('lg-from-hash');
19967			}
19968			this.zoomableTimeout = setTimeout(function () {
19969				if (!_this.isImageSlide()) {
19970					return;
19971				}
19972				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
19973				if (event.detail.index === _this.core.index) {
19974					_this.setZoomEssentials();
19975				}
19976			}, _speed + 30);
19977		};
19978		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
19979			// Add zoomable class
19980			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
19981		};
19982		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
19983			var originalRotate = rotateValue;
19984			rotateValue = Math.abs(rotateValue);
19985			var transformValues = this.getCurrentTransform(el);
19986			if (!transformValues) {
19987				return 1;
19988			}
19989			var modifier = 1;
19990			if (axis === 'X') {
19991				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
19992				if (rotateValue === 0 || rotateValue === 180) {
19993					modifier = 1;
19994				}
19995				else if (rotateValue === 90) {
19996					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
19997						(originalRotate === 90 && flipHorizontalValue === -1)) {
19998						modifier = -1;
19999					}
20000					else {
20001						modifier = 1;
20002					}
20003				}
20004				modifier = modifier * flipHorizontalValue;
20005			}
20006			else {
20007				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
20008				if (rotateValue === 0 || rotateValue === 180) {
20009					modifier = 1;
20010				}
20011				else if (rotateValue === 90) {
20012					var sinX = parseFloat(transformValues[1]);
20013					var sinMinusX = parseFloat(transformValues[2]);
20014					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
20015				}
20016				modifier = modifier * flipVerticalValue;
20017			}
20018			return modifier;
20019		};
20020		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
20021			var imageSizes = {
20022				y: 'offsetHeight',
20023				x: 'offsetWidth',
20024			};
20025			if (Math.abs(rotateValue) === 90) {
20026				// Swap axis
20027				if (axis === 'x') {
20028					axis = 'y';
20029				}
20030				else {
20031					axis = 'x';
20032				}
20033			}
20034			return $image[imageSizes[axis]];
20035		};
20036		Zoom.prototype.getDragCords = function (e, rotateValue) {
20037			if (rotateValue === 90) {
20038				return {
20039					x: e.pageY,
20040					y: e.pageX,
20041				};
20042			}
20043			else {
20044				return {
20045					x: e.pageX,
20046					y: e.pageY,
20047				};
20048			}
20049		};
20050		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
20051			var x = e.targetTouches[0].pageX;
20052			var y = e.targetTouches[0].pageY;
20053			if (rotateValue === 90) {
20054				return {
20055					x: y,
20056					y: x,
20057				};
20058			}
20059			else {
20060				return {
20061					x: x,
20062					y: y,
20063				};
20064			}
20065		};
20066		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
20067			scale = scale || this.scale || 1;
20068			var allowY = this.imageYSize * scale > this.containerRect.height;
20069			var allowX = this.imageXSize * scale > this.containerRect.width;
20070			if (rotateValue === 90) {
20071				return {
20072					allowX: allowY,
20073					allowY: allowX,
20074				};
20075			}
20076			else {
20077				return {
20078					allowX: allowX,
20079					allowY: allowY,
20080				};
20081			}
20082		};
20083		/**
20084		 *
20085		 * @param {Element} el
20086		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
20087		 * Get the current transform value
20088		 */
20089		Zoom.prototype.getCurrentTransform = function (el) {
20090			if (!el) {
20091				return;
20092			}
20093			var st = window.getComputedStyle(el, null);
20094			var tm = st.getPropertyValue('-webkit-transform') ||
20095				st.getPropertyValue('-moz-transform') ||
20096				st.getPropertyValue('-ms-transform') ||
20097				st.getPropertyValue('-o-transform') ||
20098				st.getPropertyValue('transform') ||
20099				'none';
20100			if (tm !== 'none') {
20101				return tm.split('(')[1].split(')')[0].split(',');
20102			}
20103			return;
20104		};
20105		Zoom.prototype.getCurrentRotation = function (el) {
20106			if (!el) {
20107				return 0;
20108			}
20109			var values = this.getCurrentTransform(el);
20110			if (values) {
20111				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
20112					(180 / Math.PI));
20113				// If you want rotate in 360
20114				//return (angle < 0 ? angle + 360 : angle);
20115			}
20116			return 0;
20117		};
20118		Zoom.prototype.setZoomEssentials = function () {
20119			var $image = this.core
20120				.getSlideItem(this.core.index)
20121				.find('.lg-image')
20122				.first();
20123			var rotateEl = this.core
20124				.getSlideItem(this.core.index)
20125				.find('.lg-img-rotate')
20126				.first()
20127				.get();
20128			this.rotateValue = this.getCurrentRotation(rotateEl);
20129			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
20130			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
20131			this.containerRect = this.core.outer.get().getBoundingClientRect();
20132			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
20133			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
20134		};
20135		/**
20136		 * @desc Image zoom
20137		 * Translate the wrap and scale the image to get better user experience
20138		 *
20139		 * @param {String} scale - Zoom decrement/increment value
20140		 */
20141		Zoom.prototype.zoomImage = function (scale) {
20142			// Find offset manually to avoid issue after zoom
20143			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
20144				this.containerRect.left;
20145			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20146			var topBottomSpacing = Math.abs(top - bottom) / 2;
20147			var offsetY = (this.containerRect.height -
20148				this.imageYSize -
20149				topBottomSpacing * this.modifierX) /
20150				2 +
20151				this.scrollTop +
20152				this.containerRect.top;
20153			var originalX;
20154			var originalY;
20155			if (scale === 1) {
20156				this.positionChanged = false;
20157			}
20158			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
20159			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
20160			if (this.positionChanged) {
20161				originalX = this.left / (this.scale - 1);
20162				originalY = this.top / (this.scale - 1);
20163				this.pageX = Math.abs(originalX) + offsetX;
20164				this.pageY = Math.abs(originalY) + offsetY;
20165				this.positionChanged = false;
20166			}
20167			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
20168			var _x = offsetX - this.pageX;
20169			var _y = offsetY - this.pageY;
20170			var x = (scale - 1) * _x;
20171			var y = (scale - 1) * _y;
20172			if (allowX) {
20173				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
20174					x = possibleSwipeCords.minX;
20175				}
20176				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
20177					x = possibleSwipeCords.maxX;
20178				}
20179			}
20180			else {
20181				if (scale > 1) {
20182					if (x < possibleSwipeCords.minX) {
20183						x = possibleSwipeCords.minX;
20184					}
20185					else if (x > possibleSwipeCords.maxX) {
20186						x = possibleSwipeCords.maxX;
20187					}
20188				}
20189			}
20190			if (allowY) {
20191				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
20192					y = possibleSwipeCords.minY;
20193				}
20194				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
20195					y = possibleSwipeCords.maxY;
20196				}
20197			}
20198			else {
20199				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
20200				if (scale > 1) {
20201					//If image goes beyond viewport top, use the minim possible translate value
20202					if (y < possibleSwipeCords.minY) {
20203						y = possibleSwipeCords.minY;
20204					}
20205					else if (y > possibleSwipeCords.maxY) {
20206						y = possibleSwipeCords.maxY;
20207					}
20208				}
20209			}
20210			this.setZoomStyles({
20211				x: x,
20212				y: y,
20213				scale: scale,
20214			});
20215		};
20216		/**
20217		 * @desc apply scale3d to image and translate to image wrap
20218		 * @param {style} X,Y and scale
20219		 */
20220		Zoom.prototype.setZoomStyles = function (style) {
20221			var $image = this.core
20222				.getSlideItem(this.core.index)
20223				.find('.lg-image')
20224				.first();
20225			var $dummyImage = this.core.outer
20226				.find('.lg-current .lg-dummy-img')
20227				.first();
20228			var $imageWrap = $image.parent();
20229			this.scale = style.scale;
20230			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20231			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20232			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
20233			$imageWrap.css('transform', transform);
20234			this.left = style.x;
20235			this.top = style.y;
20236		};
20237		/**
20238		 * @param index - Index of the current slide
20239		 * @param event - event will be available only if the function is called on clicking/taping the imags
20240		 */
20241		Zoom.prototype.setActualSize = function (index, event) {
20242			var _this = this;
20243			// Allow zoom only on image
20244			if (!this.isImageSlide() ||
20245				this.core.outer.hasClass('lg-first-slide-loading')) {
20246				return;
20247			}
20248			var scale = this.getCurrentImageActualSizeScale();
20249			if (this.core.outer.hasClass('lg-zoomed')) {
20250				this.scale = 1;
20251			}
20252			else {
20253				this.scale = this.getScale(scale);
20254			}
20255			this.setPageCords(event);
20256			this.beginZoom(this.scale);
20257			this.zoomImage(this.scale);
20258			setTimeout(function () {
20259				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20260			}, 10);
20261		};
20262		Zoom.prototype.getNaturalWidth = function (index) {
20263			var $image = this.core.getSlideItem(index).find('.lg-image').first();
20264			var naturalWidth = this.core.galleryItems[index].width;
20265			return naturalWidth
20266				? parseFloat(naturalWidth)
20267				: $image.get().naturalWidth;
20268		};
20269		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
20270			var _scale;
20271			var scale;
20272			if (naturalWidth > width) {
20273				_scale = naturalWidth / width;
20274				scale = _scale || 2;
20275			}
20276			else {
20277				scale = 1;
20278			}
20279			return scale;
20280		};
20281		Zoom.prototype.getCurrentImageActualSizeScale = function () {
20282			var $image = this.core
20283				.getSlideItem(this.core.index)
20284				.find('.lg-image')
20285				.first();
20286			var width = $image.get().offsetWidth;
20287			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
20288			return this.getActualSizeScale(naturalWidth, width);
20289		};
20290		Zoom.prototype.getPageCords = function (event) {
20291			var cords = {};
20292			if (event) {
20293				cords.x = event.pageX || event.targetTouches[0].pageX;
20294				cords.y = event.pageY || event.targetTouches[0].pageY;
20295			}
20296			else {
20297				var containerRect = this.core.outer.get().getBoundingClientRect();
20298				cords.x = containerRect.width / 2 + containerRect.left;
20299				cords.y =
20300					containerRect.height / 2 + this.scrollTop + containerRect.top;
20301			}
20302			return cords;
20303		};
20304		Zoom.prototype.setPageCords = function (event) {
20305			var pageCords = this.getPageCords(event);
20306			this.pageX = pageCords.x;
20307			this.pageY = pageCords.y;
20308		};
20309		// If true, zoomed - in else zoomed out
20310		Zoom.prototype.beginZoom = function (scale) {
20311			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20312			if (scale > 1) {
20313				this.core.outer.addClass('lg-zoomed');
20314				var $actualSize = this.core.getElementById('lg-actual-size');
20315				$actualSize
20316					.removeClass(this.settings.actualSizeIcons.zoomIn)
20317					.addClass(this.settings.actualSizeIcons.zoomOut);
20318			}
20319			else {
20320				this.resetZoom();
20321			}
20322			return scale > 1;
20323		};
20324		Zoom.prototype.getScale = function (scale) {
20325			var actualSizeScale = this.getCurrentImageActualSizeScale();
20326			if (scale < 1) {
20327				scale = 1;
20328			}
20329			else if (scale > actualSizeScale) {
20330				scale = actualSizeScale;
20331			}
20332			return scale;
20333		};
20334		Zoom.prototype.init = function () {
20335			var _this = this;
20336			if (!this.settings.zoom) {
20337				return;
20338			}
20339			this.buildTemplates();
20340			this.enableZoomOnSlideItemLoad();
20341			var tapped = null;
20342			this.core.outer.on('dblclick.lg', function (event) {
20343				if (!_this.$LG(event.target).hasClass('lg-image')) {
20344					return;
20345				}
20346				_this.setActualSize(_this.core.index, event);
20347			});
20348			this.core.outer.on('touchstart.lg', function (event) {
20349				var $target = _this.$LG(event.target);
20350				if (event.targetTouches.length === 1 &&
20351					$target.hasClass('lg-image')) {
20352					if (!tapped) {
20353						tapped = setTimeout(function () {
20354							tapped = null;
20355						}, 300);
20356					}
20357					else {
20358						clearTimeout(tapped);
20359						tapped = null;
20360						event.preventDefault();
20361						_this.setActualSize(_this.core.index, event);
20362					}
20363				}
20364			});
20365			// Update zoom on resize and orientationchange
20366			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
20367				if (!_this.core.lgOpened || !_this.isImageSlide())
20368					return;
20369				_this.setPageCords();
20370				_this.setZoomEssentials();
20371				_this.zoomImage(_this.scale);
20372			});
20373			// Update zoom on resize and orientationchange
20374			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
20375				if (!_this.core.lgOpened)
20376					return;
20377				_this.scrollTop = _this.$LG(window).scrollTop();
20378			});
20379			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
20380				if (_this.core.outer.find('.lg-current .lg-image').get()) {
20381					_this.scale -= _this.settings.scale;
20382					_this.scale = _this.getScale(_this.scale);
20383					_this.beginZoom(_this.scale);
20384					_this.zoomImage(_this.scale);
20385				}
20386			});
20387			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
20388				_this.zoomIn();
20389			});
20390			this.core.getElementById('lg-actual-size').on('click.lg', function () {
20391				_this.setActualSize(_this.core.index);
20392			});
20393			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
20394				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
20395			});
20396			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
20397				_this.scrollTop = _this.$LG(window).scrollTop();
20398				// Set the initial value center
20399				_this.pageX = _this.core.outer.width() / 2;
20400				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
20401				_this.scale = 1;
20402			});
20403			// Reset zoom on slide change
20404			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
20405				var prevIndex = event.detail.prevIndex;
20406				_this.scale = 1;
20407				_this.positionChanged = false;
20408				_this.resetZoom(prevIndex);
20409				if (_this.isImageSlide()) {
20410					_this.setZoomEssentials();
20411				}
20412			});
20413			// Drag option after zoom
20414			this.zoomDrag();
20415			this.pinchZoom();
20416			this.zoomSwipe();
20417			// Store the zoomable timeout value just to clear it while closing
20418			this.zoomableTimeout = false;
20419			this.positionChanged = false;
20420		};
20421		Zoom.prototype.zoomIn = function (scale) {
20422			// Allow zoom only on image
20423			if (!this.isImageSlide()) {
20424				return;
20425			}
20426			if (scale) {
20427				this.scale = scale;
20428			}
20429			else {
20430				this.scale += this.settings.scale;
20431			}
20432			this.scale = this.getScale(this.scale);
20433			this.beginZoom(this.scale);
20434			this.zoomImage(this.scale);
20435		};
20436		// Reset zoom effect
20437		Zoom.prototype.resetZoom = function (index) {
20438			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
20439			var $actualSize = this.core.getElementById('lg-actual-size');
20440			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
20441			$actualSize
20442				.removeClass(this.settings.actualSizeIcons.zoomOut)
20443				.addClass(this.settings.actualSizeIcons.zoomIn);
20444			$item.find('.lg-img-wrap').first().removeAttr('style');
20445			$item.find('.lg-image').first().removeAttr('style');
20446			this.scale = 1;
20447			this.left = 0;
20448			this.top = 0;
20449			// Reset pagx pagy values to center
20450			this.setPageCords();
20451		};
20452		Zoom.prototype.getTouchDistance = function (e) {
20453			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
20454				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
20455				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
20456					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
20457		};
20458		Zoom.prototype.pinchZoom = function () {
20459			var _this = this;
20460			var startDist = 0;
20461			var pinchStarted = false;
20462			var initScale = 1;
20463			var $item = this.core.getSlideItem(this.core.index);
20464			this.core.$inner.on('touchstart.lg', function (e) {
20465				$item = _this.core.getSlideItem(_this.core.index);
20466				if (!_this.isImageSlide()) {
20467					return;
20468				}
20469				if (e.targetTouches.length === 2 &&
20470					!_this.core.outer.hasClass('lg-first-slide-loading') &&
20471					(_this.$LG(e.target).hasClass('lg-item') ||
20472						$item.get().contains(e.target))) {
20473					initScale = _this.scale || 1;
20474					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20475					_this.core.touchAction = 'pinch';
20476					startDist = _this.getTouchDistance(e);
20477				}
20478			});
20479			this.core.$inner.on('touchmove.lg', function (e) {
20480				if (e.targetTouches.length === 2 &&
20481					_this.core.touchAction === 'pinch' &&
20482					(_this.$LG(e.target).hasClass('lg-item') ||
20483						$item.get().contains(e.target))) {
20484					e.preventDefault();
20485					var endDist = _this.getTouchDistance(e);
20486					var distance = startDist - endDist;
20487					if (!pinchStarted && Math.abs(distance) > 5) {
20488						pinchStarted = true;
20489					}
20490					if (pinchStarted) {
20491						_this.scale = Math.max(1, initScale + -distance * 0.008);
20492						_this.zoomImage(_this.scale);
20493					}
20494				}
20495			});
20496			this.core.$inner.on('touchend.lg', function (e) {
20497				if (_this.core.touchAction === 'pinch' &&
20498					(_this.$LG(e.target).hasClass('lg-item') ||
20499						$item.get().contains(e.target))) {
20500					pinchStarted = false;
20501					startDist = 0;
20502					if (_this.scale <= 1) {
20503						_this.resetZoom();
20504					}
20505					else {
20506						_this.scale = _this.getScale(_this.scale);
20507						_this.zoomImage(_this.scale);
20508						_this.core.outer.addClass('lg-zoomed');
20509					}
20510					_this.core.touchAction = undefined;
20511				}
20512			});
20513		};
20514		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
20515			var distanceXnew = endCoords.x - startCoords.x;
20516			var distanceYnew = endCoords.y - startCoords.y;
20517			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
20518			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
20519			if (speedX > 2) {
20520				speedX += 1;
20521			}
20522			if (speedY > 2) {
20523				speedY += 1;
20524			}
20525			distanceXnew = distanceXnew * speedX;
20526			distanceYnew = distanceYnew * speedY;
20527			var _LGel = this.core
20528				.getSlideItem(this.core.index)
20529				.find('.lg-img-wrap')
20530				.first();
20531			var distance = {};
20532			distance.x = this.left + distanceXnew * this.modifierX;
20533			distance.y = this.top + distanceYnew * this.modifierY;
20534			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
20535			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
20536				if (allowY) {
20537					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20538						distance.y = possibleSwipeCords.minY;
20539					}
20540					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20541						distance.y = possibleSwipeCords.maxY;
20542					}
20543				}
20544				if (allowX) {
20545					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20546						distance.x = possibleSwipeCords.minX;
20547					}
20548					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20549						distance.x = possibleSwipeCords.maxX;
20550					}
20551				}
20552				if (allowY) {
20553					this.top = distance.y;
20554				}
20555				else {
20556					distance.y = this.top;
20557				}
20558				if (allowX) {
20559					this.left = distance.x;
20560				}
20561				else {
20562					distance.x = this.left;
20563				}
20564				this.setZoomSwipeStyles(_LGel, distance);
20565				this.positionChanged = true;
20566			}
20567		};
20568		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
20569			var distance = {};
20570			if (allowY) {
20571				distance.y =
20572					this.top + (endCoords.y - startCoords.y) * this.modifierY;
20573				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20574					var diffMinY = possibleSwipeCords.minY - distance.y;
20575					distance.y = possibleSwipeCords.minY - diffMinY / 6;
20576				}
20577				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20578					var diffMaxY = distance.y - possibleSwipeCords.maxY;
20579					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
20580				}
20581			}
20582			else {
20583				distance.y = this.top;
20584			}
20585			if (allowX) {
20586				distance.x =
20587					this.left + (endCoords.x - startCoords.x) * this.modifierX;
20588				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20589					var diffMinX = possibleSwipeCords.minX - distance.x;
20590					distance.x = possibleSwipeCords.minX - diffMinX / 6;
20591				}
20592				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20593					var difMaxX = distance.x - possibleSwipeCords.maxX;
20594					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
20595				}
20596			}
20597			else {
20598				distance.x = this.left;
20599			}
20600			return distance;
20601		};
20602		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
20603			return x >= minX;
20604		};
20605		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
20606			return x <= maxX;
20607		};
20608		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
20609			return y >= minY;
20610		};
20611		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
20612			return y <= maxY;
20613		};
20614		Zoom.prototype.isImageSlide = function () {
20615			var currentItem = this.core.galleryItems[this.core.index];
20616			return this.core.getSlideType(currentItem) === 'image';
20617		};
20618		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
20619			var dataScale = scale || this.scale || 1;
20620			var elDataScale = Math.abs(dataScale);
20621			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20622			var topBottomSpacing = Math.abs(top - bottom) / 2;
20623			var minY = (this.imageYSize - this.containerRect.height) / 2 +
20624				topBottomSpacing * this.modifierX;
20625			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
20626			var minX = (this.imageXSize - this.containerRect.width) / 2;
20627			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
20628			var possibleSwipeCords = {
20629				minY: minY,
20630				maxY: maxY,
20631				minX: minX,
20632				maxX: maxX,
20633			};
20634			if (Math.abs(rotateValue) === 90) {
20635				possibleSwipeCords = {
20636					minY: minX,
20637					maxY: maxX,
20638					minX: minY,
20639					maxX: maxY,
20640				};
20641			}
20642			return possibleSwipeCords;
20643		};
20644		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
20645			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
20646		};
20647		Zoom.prototype.zoomSwipe = function () {
20648			var _this = this;
20649			var startCoords = {};
20650			var endCoords = {};
20651			var isMoved = false;
20652			// Allow x direction drag
20653			var allowX = false;
20654			// Allow Y direction drag
20655			var allowY = false;
20656			var startTime = new Date();
20657			var endTime = new Date();
20658			var possibleSwipeCords;
20659			var _LGel;
20660			var $item = this.core.getSlideItem(this.core.index);
20661			this.core.$inner.on('touchstart.lg', function (e) {
20662				// Allow zoom only on image
20663				if (!_this.isImageSlide()) {
20664					return;
20665				}
20666				$item = _this.core.getSlideItem(_this.core.index);
20667				if ((_this.$LG(e.target).hasClass('lg-item') ||
20668					$item.get().contains(e.target)) &&
20669					e.targetTouches.length === 1 &&
20670					_this.core.outer.hasClass('lg-zoomed')) {
20671					e.preventDefault();
20672					startTime = new Date();
20673					_this.core.touchAction = 'zoomSwipe';
20674					_LGel = _this.core
20675						.getSlideItem(_this.core.index)
20676						.find('.lg-img-wrap')
20677						.first();
20678					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20679					allowY = dragAllowedAxises.allowY;
20680					allowX = dragAllowedAxises.allowX;
20681					if (allowX || allowY) {
20682						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20683					}
20684					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20685					// reset opacity and transition duration
20686					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
20687				}
20688			});
20689			this.core.$inner.on('touchmove.lg', function (e) {
20690				if (e.targetTouches.length === 1 &&
20691					_this.core.touchAction === 'zoomSwipe' &&
20692					(_this.$LG(e.target).hasClass('lg-item') ||
20693						$item.get().contains(e.target))) {
20694					e.preventDefault();
20695					_this.core.touchAction = 'zoomSwipe';
20696					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20697					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20698					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
20699						Math.abs(endCoords.y - startCoords.y) > 15) {
20700						isMoved = true;
20701						_this.setZoomSwipeStyles(_LGel, distance);
20702					}
20703				}
20704			});
20705			this.core.$inner.on('touchend.lg', function (e) {
20706				if (_this.core.touchAction === 'zoomSwipe' &&
20707					(_this.$LG(e.target).hasClass('lg-item') ||
20708						$item.get().contains(e.target))) {
20709					_this.core.touchAction = undefined;
20710					_this.core.outer.removeClass('lg-zoom-dragging');
20711					if (!isMoved) {
20712						return;
20713					}
20714					isMoved = false;
20715					endTime = new Date();
20716					var touchDuration = endTime.valueOf() - startTime.valueOf();
20717					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20718				}
20719			});
20720		};
20721		Zoom.prototype.zoomDrag = function () {
20722			var _this = this;
20723			var startCoords = {};
20724			var endCoords = {};
20725			var isDragging = false;
20726			var isMoved = false;
20727			// Allow x direction drag
20728			var allowX = false;
20729			// Allow Y direction drag
20730			var allowY = false;
20731			var startTime;
20732			var endTime;
20733			var possibleSwipeCords;
20734			var _LGel;
20735			this.core.outer.on('mousedown.lg.zoom', function (e) {
20736				// Allow zoom only on image
20737				if (!_this.isImageSlide()) {
20738					return;
20739				}
20740				var $item = _this.core.getSlideItem(_this.core.index);
20741				if (_this.$LG(e.target).hasClass('lg-item') ||
20742					$item.get().contains(e.target)) {
20743					startTime = new Date();
20744					_LGel = _this.core
20745						.getSlideItem(_this.core.index)
20746						.find('.lg-img-wrap')
20747						.first();
20748					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20749					allowY = dragAllowedAxises.allowY;
20750					allowX = dragAllowedAxises.allowX;
20751					if (_this.core.outer.hasClass('lg-zoomed')) {
20752						if (_this.$LG(e.target).hasClass('lg-object') &&
20753							(allowX || allowY)) {
20754							e.preventDefault();
20755							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20756							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20757							isDragging = true;
20758							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20759							_this.core.outer.get().scrollLeft += 1;
20760							_this.core.outer.get().scrollLeft -= 1;
20761							_this.core.outer
20762								.removeClass('lg-grab')
20763								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20764							// reset opacity and transition duration
20765						}
20766					}
20767				}
20768			});
20769			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20770				if (isDragging) {
20771					isMoved = true;
20772					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20773					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20774					_this.setZoomSwipeStyles(_LGel, distance);
20775				}
20776			});
20777			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20778				if (isDragging) {
20779					endTime = new Date();
20780					isDragging = false;
20781					_this.core.outer.removeClass('lg-zoom-dragging');
20782					// Fix for chrome mouse move on click
20783					if (isMoved &&
20784						(startCoords.x !== endCoords.x ||
20785							startCoords.y !== endCoords.y)) {
20786						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20787						var touchDuration = endTime.valueOf() - startTime.valueOf();
20788						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20789					}
20790					isMoved = false;
20791				}
20792				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20793			});
20794		};
20795		Zoom.prototype.closeGallery = function () {
20796			this.resetZoom();
20797		};
20798		Zoom.prototype.destroy = function () {
20799			// Unbind all events added by lightGallery zoom plugin
20800			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20801			this.core.LGel.off('.lg.zoom');
20802			this.core.LGel.off('.zoom');
20803			clearTimeout(this.zoomableTimeout);
20804			this.zoomableTimeout = false;
20805		};
20806		return Zoom;
20807	}());
20808
20809	return Zoom;
20810
20811})));
20812/*!
20813 * lightgallery | 2.5.0 | June 13th 2022
20814 * http://www.lightgalleryjs.com/
20815 * Copyright (c) 2020 Sachin Neravath;
20816 * @license GPLv3
20817 */
20818
20819(function (global, factory) {
20820	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20821	typeof define === 'function' && define.amd ? define(factory) :
20822	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20823}(this, (function () { 'use strict';
20824
20825	/*! *****************************************************************************
20826	Copyright (c) Microsoft Corporation.
20827
20828	Permission to use, copy, modify, and/or distribute this software for any
20829	purpose with or without fee is hereby granted.
20830
20831	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20832	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20833	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20834	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20835	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20836	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20837	PERFORMANCE OF THIS SOFTWARE.
20838	***************************************************************************** */
20839
20840	var __assign = function() {
20841		__assign = Object.assign || function __assign(t) {
20842			for (var s, i = 1, n = arguments.length; i < n; i++) {
20843				s = arguments[i];
20844				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20845			}
20846			return t;
20847		};
20848		return __assign.apply(this, arguments);
20849	};
20850
20851	var fullscreenSettings = {
20852		fullScreen: true,
20853		fullscreenPluginStrings: {
20854			toggleFullscreen: 'Toggle Fullscreen',
20855		},
20856	};
20857
20858	var FullScreen = /** @class */ (function () {
20859		function FullScreen(instance, $LG) {
20860			// get lightGallery core plugin instance
20861			this.core = instance;
20862			this.$LG = $LG;
20863			// extend module default settings with lightGallery core settings
20864			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20865			return this;
20866		}
20867		FullScreen.prototype.init = function () {
20868			var fullScreen = '';
20869			if (this.settings.fullScreen) {
20870				// check for fullscreen browser support
20871				if (!document.fullscreenEnabled &&
20872					!document.webkitFullscreenEnabled &&
20873					!document.mozFullScreenEnabled &&
20874					!document.msFullscreenEnabled) {
20875					return;
20876				}
20877				else {
20878					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20879					this.core.$toolbar.append(fullScreen);
20880					this.fullScreen();
20881				}
20882			}
20883		};
20884		FullScreen.prototype.isFullScreen = function () {
20885			return (document.fullscreenElement ||
20886				document.mozFullScreenElement ||
20887				document.webkitFullscreenElement ||
20888				document.msFullscreenElement);
20889		};
20890		FullScreen.prototype.requestFullscreen = function () {
20891			var el = document.documentElement;
20892			if (el.requestFullscreen) {
20893				el.requestFullscreen();
20894			}
20895			else if (el.msRequestFullscreen) {
20896				el.msRequestFullscreen();
20897			}
20898			else if (el.mozRequestFullScreen) {
20899				el.mozRequestFullScreen();
20900			}
20901			else if (el.webkitRequestFullscreen) {
20902				el.webkitRequestFullscreen();
20903			}
20904		};
20905		FullScreen.prototype.exitFullscreen = function () {
20906			if (document.exitFullscreen) {
20907				document.exitFullscreen();
20908			}
20909			else if (document.msExitFullscreen) {
20910				document.msExitFullscreen();
20911			}
20912			else if (document.mozCancelFullScreen) {
20913				document.mozCancelFullScreen();
20914			}
20915			else if (document.webkitExitFullscreen) {
20916				document.webkitExitFullscreen();
20917			}
20918		};
20919		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20920		FullScreen.prototype.fullScreen = function () {
20921			var _this = this;
20922			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 () {
20923				if (!_this.core.lgOpened)
20924					return;
20925				_this.core.outer.toggleClass('lg-fullscreen-on');
20926			});
20927			this.core.outer
20928				.find('.lg-fullscreen')
20929				.first()
20930				.on('click.lg', function () {
20931				if (_this.isFullScreen()) {
20932					_this.exitFullscreen();
20933				}
20934				else {
20935					_this.requestFullscreen();
20936				}
20937			});
20938		};
20939		FullScreen.prototype.closeGallery = function () {
20940			// exit from fullscreen if activated
20941			if (this.isFullScreen()) {
20942				this.exitFullscreen();
20943			}
20944		};
20945		FullScreen.prototype.destroy = function () {
20946			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);
20947		};
20948		return FullScreen;
20949	}());
20950
20951	return FullScreen;
20952
20953})));
20954
20955/*!
20956 * lightgallery | 2.5.0 | June 13th 2022
20957 * http://www.lightgalleryjs.com/
20958 * Copyright (c) 2020 Sachin Neravath;
20959 * @license GPLv3
20960 */
20961
20962(function (global, factory) {
20963	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20964	typeof define === 'function' && define.amd ? define(factory) :
20965	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
20966}(this, (function () { 'use strict';
20967
20968	/*! *****************************************************************************
20969	Copyright (c) Microsoft Corporation.
20970
20971	Permission to use, copy, modify, and/or distribute this software for any
20972	purpose with or without fee is hereby granted.
20973
20974	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20975	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20976	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20977	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20978	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20979	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20980	PERFORMANCE OF THIS SOFTWARE.
20981	***************************************************************************** */
20982
20983	var __assign = function() {
20984		__assign = Object.assign || function __assign(t) {
20985			for (var s, i = 1, n = arguments.length; i < n; i++) {
20986				s = arguments[i];
20987				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20988			}
20989			return t;
20990		};
20991		return __assign.apply(this, arguments);
20992	};
20993
20994	/**
20995	 * List of lightGallery events
20996	 * All events should be documented here
20997	 * Below interfaces are used to build the website documentations
20998	 * */
20999	var lGEvents = {
21000		afterAppendSlide: 'lgAfterAppendSlide',
21001		init: 'lgInit',
21002		hasVideo: 'lgHasVideo',
21003		containerResize: 'lgContainerResize',
21004		updateSlides: 'lgUpdateSlides',
21005		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21006		beforeOpen: 'lgBeforeOpen',
21007		afterOpen: 'lgAfterOpen',
21008		slideItemLoad: 'lgSlideItemLoad',
21009		beforeSlide: 'lgBeforeSlide',
21010		afterSlide: 'lgAfterSlide',
21011		posterClick: 'lgPosterClick',
21012		dragStart: 'lgDragStart',
21013		dragMove: 'lgDragMove',
21014		dragEnd: 'lgDragEnd',
21015		beforeNextSlide: 'lgBeforeNextSlide',
21016		beforePrevSlide: 'lgBeforePrevSlide',
21017		beforeClose: 'lgBeforeClose',
21018		afterClose: 'lgAfterClose',
21019		rotateLeft: 'lgRotateLeft',
21020		rotateRight: 'lgRotateRight',
21021		flipHorizontal: 'lgFlipHorizontal',
21022		flipVertical: 'lgFlipVertical',
21023		autoplay: 'lgAutoplay',
21024		autoplayStart: 'lgAutoplayStart',
21025		autoplayStop: 'lgAutoplayStop',
21026	};
21027
21028	var hashSettings = {
21029		hash: true,
21030		galleryId: '1',
21031		customSlideName: false,
21032	};
21033
21034	var Hash = /** @class */ (function () {
21035		function Hash(instance, $LG) {
21036			// get lightGallery core plugin instance
21037			this.core = instance;
21038			this.$LG = $LG;
21039			// extend module default settings with lightGallery core settings
21040			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
21041			return this;
21042		}
21043		Hash.prototype.init = function () {
21044			var _this = this;
21045			if (!this.settings.hash) {
21046				return;
21047			}
21048			this.oldHash = window.location.hash;
21049			setTimeout(function () {
21050				_this.buildFromHash();
21051			}, 100);
21052			// Change hash value on after each slide transition
21053			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
21054			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
21055			// Listen hash change and change the slide according to slide value
21056			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
21057		};
21058		Hash.prototype.onAfterSlide = function (event) {
21059			var slideName = this.core.galleryItems[event.detail.index].slideName;
21060			slideName = this.settings.customSlideName
21061				? slideName || event.detail.index
21062				: event.detail.index;
21063			if (history.replaceState) {
21064				history.replaceState(null, '', window.location.pathname +
21065					window.location.search +
21066					'#lg=' +
21067					this.settings.galleryId +
21068					'&slide=' +
21069					slideName);
21070			}
21071			else {
21072				window.location.hash =
21073					'lg=' + this.settings.galleryId + '&slide=' + slideName;
21074			}
21075		};
21076		/**
21077		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
21078		 * @param {String} hash
21079		 * @returns {Number} Index of the slide.
21080		 */
21081		Hash.prototype.getIndexFromUrl = function (hash) {
21082			if (hash === void 0) { hash = window.location.hash; }
21083			var slideName = hash.split('&slide=')[1];
21084			var _idx = 0;
21085			if (this.settings.customSlideName) {
21086				for (var index = 0; index < this.core.galleryItems.length; index++) {
21087					var dynamicEl = this.core.galleryItems[index];
21088					if (dynamicEl.slideName === slideName) {
21089						_idx = index;
21090						break;
21091					}
21092				}
21093			}
21094			else {
21095				_idx = parseInt(slideName, 10);
21096			}
21097			return isNaN(_idx) ? 0 : _idx;
21098		};
21099		// Build Gallery if gallery id exist in the URL
21100		Hash.prototype.buildFromHash = function () {
21101			// if dynamic option is enabled execute immediately
21102			var _hash = window.location.hash;
21103			//Uncode edit ##START##
21104			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
21105			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
21106			//Uncode edit ##END##
21107				// This class is used to remove the initial animation if galleryId present in the URL
21108				this.$LG(document.body).addClass('lg-from-hash');
21109				var index = this.getIndexFromUrl(_hash);
21110				this.core.openGallery(index);
21111				return true;
21112			}
21113		};
21114		Hash.prototype.onCloseAfter = function () {
21115			// Reset to old hash value
21116			if (this.oldHash &&
21117				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
21118				if (history.replaceState) {
21119					history.replaceState(null, '', this.oldHash);
21120				}
21121				else {
21122					window.location.hash = this.oldHash;
21123				}
21124			}
21125			else {
21126				if (history.replaceState) {
21127					history.replaceState(null, document.title, window.location.pathname + window.location.search);
21128				}
21129				else {
21130					window.location.hash = '';
21131				}
21132			}
21133		};
21134		Hash.prototype.onHashchange = function () {
21135			if (!this.core.lgOpened)
21136				return;
21137			var _hash = window.location.hash;
21138			var index = this.getIndexFromUrl(_hash);
21139			// it galleryId doesn't exist in the url close the gallery
21140			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
21141				this.core.slide(index, false, false);
21142			}
21143			else if (this.core.lGalleryOn) {
21144				this.core.closeGallery();
21145			}
21146		};
21147		Hash.prototype.closeGallery = function () {
21148			if (this.settings.hash) {
21149				this.$LG(document.body).removeClass('lg-from-hash');
21150			}
21151		};
21152		Hash.prototype.destroy = function () {
21153			this.core.LGel.off('.lg.hash');
21154			this.core.LGel.off('.hash');
21155			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
21156		};
21157		return Hash;
21158	}());
21159
21160	return Hash;
21161
21162})));
21163/*!
21164 * lightgallery | 2.5.0 | June 13th 2022
21165 * http://www.lightgalleryjs.com/
21166 * Copyright (c) 2020 Sachin Neravath;
21167 * @license GPLv3
21168 */
21169
21170(function (global, factory) {
21171	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21172	typeof define === 'function' && define.amd ? define(factory) :
21173	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
21174}(this, (function () { 'use strict';
21175
21176	/*! *****************************************************************************
21177	Copyright (c) Microsoft Corporation.
21178
21179	Permission to use, copy, modify, and/or distribute this software for any
21180	purpose with or without fee is hereby granted.
21181
21182	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21183	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21184	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21185	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21186	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21187	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21188	PERFORMANCE OF THIS SOFTWARE.
21189	***************************************************************************** */
21190
21191	var __assign = function() {
21192		__assign = Object.assign || function __assign(t) {
21193			for (var s, i = 1, n = arguments.length; i < n; i++) {
21194				s = arguments[i];
21195				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21196			}
21197			return t;
21198		};
21199		return __assign.apply(this, arguments);
21200	};
21201
21202	function __spreadArrays() {
21203		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
21204		for (var r = Array(s), k = 0, i = 0; i < il; i++)
21205			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
21206				r[k] = a[j];
21207		return r;
21208	}
21209
21210	var shareSettings = {
21211		share: true,
21212		facebook: true,
21213		facebookDropdownText: 'Facebook',
21214		twitter: true,
21215		twitterDropdownText: 'Twitter',
21216		pinterest: true,
21217		pinterestDropdownText: 'Pinterest',
21218		additionalShareOptions: [],
21219		sharePluginStrings: { share: 'Share' },
21220	};
21221
21222	function getFacebookShareLink(galleryItem) {
21223		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
21224		return (facebookBaseUrl +
21225			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
21226	}
21227
21228	function getTwitterShareLink(galleryItem) {
21229		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
21230		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
21231		var text = galleryItem.tweetText;
21232		return twitterBaseUrl + text + '&url=' + url;
21233	}
21234
21235	function getPinterestShareLink(galleryItem) {
21236		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
21237		var description = galleryItem.pinterestText;
21238		var media = encodeURIComponent(galleryItem.src);
21239		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
21240		return (pinterestBaseUrl +
21241			url +
21242			'&media=' +
21243			media +
21244			'&description=' +
21245			description);
21246	}
21247
21248	/**
21249	 * List of lightGallery events
21250	 * All events should be documented here
21251	 * Below interfaces are used to build the website documentations
21252	 * */
21253	var lGEvents = {
21254		afterAppendSlide: 'lgAfterAppendSlide',
21255		init: 'lgInit',
21256		hasVideo: 'lgHasVideo',
21257		containerResize: 'lgContainerResize',
21258		updateSlides: 'lgUpdateSlides',
21259		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21260		beforeOpen: 'lgBeforeOpen',
21261		afterOpen: 'lgAfterOpen',
21262		slideItemLoad: 'lgSlideItemLoad',
21263		beforeSlide: 'lgBeforeSlide',
21264		afterSlide: 'lgAfterSlide',
21265		posterClick: 'lgPosterClick',
21266		dragStart: 'lgDragStart',
21267		dragMove: 'lgDragMove',
21268		dragEnd: 'lgDragEnd',
21269		beforeNextSlide: 'lgBeforeNextSlide',
21270		beforePrevSlide: 'lgBeforePrevSlide',
21271		beforeClose: 'lgBeforeClose',
21272		afterClose: 'lgAfterClose',
21273		rotateLeft: 'lgRotateLeft',
21274		rotateRight: 'lgRotateRight',
21275		flipHorizontal: 'lgFlipHorizontal',
21276		flipVertical: 'lgFlipVertical',
21277		autoplay: 'lgAutoplay',
21278		autoplayStart: 'lgAutoplayStart',
21279		autoplayStop: 'lgAutoplayStop',
21280	};
21281
21282	var Share = /** @class */ (function () {
21283		function Share(instance) {
21284			this.shareOptions = [];
21285			// get lightGallery core plugin instance
21286			this.core = instance;
21287			// extend module default settings with lightGallery core settings
21288			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
21289			return this;
21290		}
21291		Share.prototype.init = function () {
21292			if (!this.settings.share) {
21293				return;
21294			}
21295			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
21296			this.setLgShareMarkup();
21297			this.core.outer
21298				.find('.lg-share .lg-dropdown')
21299				.append(this.getShareListHtml());
21300			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
21301		};
21302		Share.prototype.getShareListHtml = function () {
21303			var shareHtml = '';
21304			this.shareOptions.forEach(function (shareOption) {
21305				shareHtml += shareOption.dropdownHTML;
21306			});
21307			return shareHtml;
21308		};
21309		Share.prototype.setLgShareMarkup = function () {
21310			var _this = this;
21311			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>");
21312			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
21313			var $shareButton = this.core.outer.find('.lg-share');
21314			$shareButton.first().on('click.lg', function () {
21315				_this.core.outer.toggleClass('lg-dropdown-active');
21316				if (_this.core.outer.hasClass('lg-dropdown-active')) {
21317					_this.core.outer.attr('aria-expanded', true);
21318				}
21319				else {
21320					_this.core.outer.attr('aria-expanded', false);
21321				}
21322			});
21323			this.core.outer
21324				.find('.lg-dropdown-overlay')
21325				.first()
21326				.on('click.lg', function () {
21327				_this.core.outer.removeClass('lg-dropdown-active');
21328				_this.core.outer.attr('aria-expanded', false);
21329			});
21330		};
21331		Share.prototype.onAfterSlide = function (event) {
21332			var _this = this;
21333			var index = event.detail.index;
21334			var currentItem = this.core.galleryItems[index];
21335			setTimeout(function () {
21336				_this.shareOptions.forEach(function (shareOption) {
21337					var selector = shareOption.selector;
21338					_this.core.outer
21339						.find(selector)
21340						.attr('href', shareOption.generateLink(currentItem));
21341				});
21342			}, 100);
21343		};
21344		Share.prototype.getShareListItemHTML = function (type, text) {
21345			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>";
21346		};
21347		Share.prototype.getDefaultShareOptions = function () {
21348			return __spreadArrays((this.settings.facebook
21349				? [
21350					{
21351						type: 'facebook',
21352						generateLink: getFacebookShareLink,
21353						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
21354						selector: '.lg-share-facebook',
21355					},
21356				]
21357				: []), (this.settings.twitter
21358				? [
21359					{
21360						type: 'twitter',
21361						generateLink: getTwitterShareLink,
21362						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
21363						selector: '.lg-share-twitter',
21364					},
21365				]
21366				: []), (this.settings.pinterest
21367				? [
21368					{
21369						type: 'pinterest',
21370						generateLink: getPinterestShareLink,
21371						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
21372						selector: '.lg-share-pinterest',
21373					},
21374				]
21375				: []));
21376		};
21377		Share.prototype.destroy = function () {
21378			this.core.outer.find('.lg-dropdown-overlay').remove();
21379			this.core.outer.find('.lg-share').remove();
21380			this.core.LGel.off('.lg.share');
21381			this.core.LGel.off('.share');
21382		};
21383		return Share;
21384	}());
21385
21386	return Share;
21387
21388})));
21389/*!
21390 * lightgallery | 2.5.0 | June 13th 2022
21391 * http://www.lightgalleryjs.com/
21392 * Copyright (c) 2020 Sachin Neravath;
21393 * @license GPLv3
21394 */
21395
21396(function (global, factory) {
21397	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21398	typeof define === 'function' && define.amd ? define(factory) :
21399	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
21400}(this, (function () { 'use strict';
21401
21402	/*! *****************************************************************************
21403	Copyright (c) Microsoft Corporation.
21404
21405	Permission to use, copy, modify, and/or distribute this software for any
21406	purpose with or without fee is hereby granted.
21407
21408	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21409	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21410	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21411	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21412	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21413	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21414	PERFORMANCE OF THIS SOFTWARE.
21415	***************************************************************************** */
21416
21417	var __assign = function() {
21418		__assign = Object.assign || function __assign(t) {
21419			for (var s, i = 1, n = arguments.length; i < n; i++) {
21420				s = arguments[i];
21421				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21422			}
21423			return t;
21424		};
21425		return __assign.apply(this, arguments);
21426	};
21427
21428	var thumbnailsSettings = {
21429		thumbnail: true,
21430		animateThumb: true,
21431		currentPagerPosition: 'middle',
21432		alignThumbnails: 'middle',
21433		thumbWidth: 100,
21434		thumbHeight: '80px',
21435		thumbMargin: 5,
21436		appendThumbnailsTo: '.lg-components',
21437		toggleThumb: false,
21438		enableThumbDrag: true,
21439		enableThumbSwipe: true,
21440		thumbnailSwipeThreshold: 10,
21441		loadYouTubeThumbnail: true,
21442		youTubeThumbSize: 1,
21443		thumbnailPluginStrings: {
21444			toggleThumbnails: 'Toggle thumbnails',
21445		},
21446	};
21447
21448	/**
21449	 * List of lightGallery events
21450	 * All events should be documented here
21451	 * Below interfaces are used to build the website documentations
21452	 * */
21453	var lGEvents = {
21454		afterAppendSlide: 'lgAfterAppendSlide',
21455		init: 'lgInit',
21456		hasVideo: 'lgHasVideo',
21457		containerResize: 'lgContainerResize',
21458		updateSlides: 'lgUpdateSlides',
21459		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21460		beforeOpen: 'lgBeforeOpen',
21461		afterOpen: 'lgAfterOpen',
21462		slideItemLoad: 'lgSlideItemLoad',
21463		beforeSlide: 'lgBeforeSlide',
21464		afterSlide: 'lgAfterSlide',
21465		posterClick: 'lgPosterClick',
21466		dragStart: 'lgDragStart',
21467		dragMove: 'lgDragMove',
21468		dragEnd: 'lgDragEnd',
21469		beforeNextSlide: 'lgBeforeNextSlide',
21470		beforePrevSlide: 'lgBeforePrevSlide',
21471		beforeClose: 'lgBeforeClose',
21472		afterClose: 'lgAfterClose',
21473		rotateLeft: 'lgRotateLeft',
21474		rotateRight: 'lgRotateRight',
21475		flipHorizontal: 'lgFlipHorizontal',
21476		flipVertical: 'lgFlipVertical',
21477		autoplay: 'lgAutoplay',
21478		autoplayStart: 'lgAutoplayStart',
21479		autoplayStop: 'lgAutoplayStop',
21480	};
21481
21482	var Thumbnail = /** @class */ (function () {
21483		function Thumbnail(instance, $LG) {
21484			this.thumbOuterWidth = 0;
21485			this.thumbTotalWidth = 0;
21486			this.translateX = 0;
21487			this.thumbClickable = false;
21488			// get lightGallery core plugin instance
21489			this.core = instance;
21490			this.$LG = $LG;
21491			return this;
21492		}
21493		Thumbnail.prototype.init = function () {
21494			// extend module default settings with lightGallery core settings
21495			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
21496			this.thumbOuterWidth = 0;
21497			this.thumbTotalWidth =
21498				this.core.galleryItems.length *
21499					(this.settings.thumbWidth + this.settings.thumbMargin);
21500			// Thumbnail animation value
21501			this.translateX = 0;
21502			this.setAnimateThumbStyles();
21503			if (!this.core.settings.allowMediaOverlap) {
21504				this.settings.toggleThumb = false;
21505			}
21506			if (this.settings.thumbnail) {
21507				this.build();
21508				if (this.settings.animateThumb) {
21509					if (this.settings.enableThumbDrag) {
21510						this.enableThumbDrag();
21511					}
21512					if (this.settings.enableThumbSwipe) {
21513						this.enableThumbSwipe();
21514					}
21515					this.thumbClickable = false;
21516				}
21517				else {
21518					this.thumbClickable = true;
21519				}
21520				this.toggleThumbBar();
21521				this.thumbKeyPress();
21522			}
21523		};
21524		Thumbnail.prototype.build = function () {
21525			var _this = this;
21526			this.setThumbMarkup();
21527			this.manageActiveClassOnSlideChange();
21528			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
21529				var $target = _this.$LG(e.target);
21530				if (!$target.hasAttribute('data-lg-item-id')) {
21531					return;
21532				}
21533				setTimeout(function () {
21534					// In IE9 and bellow touch does not support
21535					// Go to slide if browser does not support css transitions
21536					if (_this.thumbClickable && !_this.core.lgBusy) {
21537						var index = parseInt($target.attr('data-lg-item-id'));
21538						_this.core.slide(index, false, true, false);
21539					}
21540				}, 50);
21541			});
21542			//Uncode edit ##START##
21543			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21544			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21545			//Uncode edit ##END##
21546				var index = event.detail.index;
21547				_this.animateThumb(index);
21548			});
21549			//Uncode edit ##START##
21550			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
21551			this.core.LGel.on(lGEvents.beforeOpen, function () {
21552			//Uncode edit ##END##
21553				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21554			});
21555			//Uncode edit ##START##
21556			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
21557			this.core.LGel.on(lGEvents.updateSlides, function () {
21558			//Uncode edit ##END##
21559				_this.rebuildThumbnails();
21560			});
21561			//Uncode edit ##START##
21562			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
21563			this.core.LGel.on(lGEvents.containerResize, function () {
21564			//Uncode edit ##END##
21565				if (!_this.core.lgOpened)
21566					return;
21567				setTimeout(function () {
21568					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21569					_this.animateThumb(_this.core.index);
21570					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21571				}, 50);
21572			});
21573		};
21574		Thumbnail.prototype.setThumbMarkup = function () {
21575			var thumbOuterClassNames = 'lg-thumb-outer ';
21576			if (this.settings.alignThumbnails) {
21577				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
21578			}
21579			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
21580			this.core.outer.addClass('lg-has-thumb');
21581			if (this.settings.appendThumbnailsTo === '.lg-components') {
21582				this.core.$lgComponents.append(html);
21583			}
21584			else {
21585				this.core.outer.append(html);
21586			}
21587			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
21588			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
21589			if (this.settings.animateThumb) {
21590				this.core.outer
21591					.find('.lg-thumb')
21592					.css('transition-duration', this.core.settings.speed + 'ms')
21593					.css('width', this.thumbTotalWidth + 'px')
21594					.css('position', 'relative');
21595			}
21596			this.setThumbItemHtml(this.core.galleryItems);
21597		};
21598		Thumbnail.prototype.enableThumbDrag = function () {
21599			var _this = this;
21600			var thumbDragUtils = {
21601				cords: {
21602					startX: 0,
21603					endX: 0,
21604				},
21605				isMoved: false,
21606				newTranslateX: 0,
21607				startTime: new Date(),
21608				endTime: new Date(),
21609				touchMoveTime: 0,
21610			};
21611			var isDragging = false;
21612			this.$thumbOuter.addClass('lg-grab');
21613			this.core.outer
21614				.find('.lg-thumb')
21615				.first()
21616				.on('mousedown.lg.thumb', function (e) {
21617				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21618					// execute only on .lg-object
21619					e.preventDefault();
21620					thumbDragUtils.cords.startX = e.pageX;
21621					thumbDragUtils.startTime = new Date();
21622					_this.thumbClickable = false;
21623					isDragging = true;
21624					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
21625					_this.core.outer.get().scrollLeft += 1;
21626					_this.core.outer.get().scrollLeft -= 1;
21627					// *
21628					_this.$thumbOuter
21629						.removeClass('lg-grab')
21630						.addClass('lg-grabbing');
21631				}
21632			});
21633			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
21634				if (!_this.core.lgOpened)
21635					return;
21636				if (isDragging) {
21637					thumbDragUtils.cords.endX = e.pageX;
21638					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21639				}
21640			});
21641			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
21642				if (!_this.core.lgOpened)
21643					return;
21644				if (thumbDragUtils.isMoved) {
21645					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21646				}
21647				else {
21648					_this.thumbClickable = true;
21649				}
21650				if (isDragging) {
21651					isDragging = false;
21652					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
21653				}
21654			});
21655		};
21656		Thumbnail.prototype.enableThumbSwipe = function () {
21657			var _this = this;
21658			var thumbDragUtils = {
21659				cords: {
21660					startX: 0,
21661					endX: 0,
21662				},
21663				isMoved: false,
21664				newTranslateX: 0,
21665				startTime: new Date(),
21666				endTime: new Date(),
21667				touchMoveTime: 0,
21668			};
21669			this.$lgThumb.on('touchstart.lg', function (e) {
21670				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21671					e.preventDefault();
21672					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
21673					_this.thumbClickable = false;
21674					thumbDragUtils.startTime = new Date();
21675				}
21676			});
21677			this.$lgThumb.on('touchmove.lg', function (e) {
21678				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21679					e.preventDefault();
21680					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
21681					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21682				}
21683			});
21684			this.$lgThumb.on('touchend.lg', function () {
21685				if (thumbDragUtils.isMoved) {
21686					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21687				}
21688				else {
21689					_this.thumbClickable = true;
21690				}
21691			});
21692		};
21693		// Rebuild thumbnails
21694		Thumbnail.prototype.rebuildThumbnails = function () {
21695			var _this = this;
21696			// Remove transitions
21697			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
21698			setTimeout(function () {
21699				_this.thumbTotalWidth =
21700					_this.core.galleryItems.length *
21701						(_this.settings.thumbWidth + _this.settings.thumbMargin);
21702				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
21703				_this.$lgThumb.empty();
21704				_this.setThumbItemHtml(_this.core.galleryItems);
21705				_this.animateThumb(_this.core.index);
21706			}, 50);
21707			setTimeout(function () {
21708				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
21709			}, 200);
21710		};
21711		// @ts-check
21712		Thumbnail.prototype.setTranslate = function (value) {
21713			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
21714		};
21715		Thumbnail.prototype.getPossibleTransformX = function (left) {
21716			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
21717				left = this.thumbTotalWidth - this.thumbOuterWidth;
21718			}
21719			if (left < 0) {
21720				left = 0;
21721			}
21722			return left;
21723		};
21724		Thumbnail.prototype.animateThumb = function (index) {
21725			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
21726			if (this.settings.animateThumb) {
21727				var position = 0;
21728				switch (this.settings.currentPagerPosition) {
21729					case 'left':
21730						position = 0;
21731						break;
21732					case 'middle':
21733						position =
21734							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
21735						break;
21736					case 'right':
21737						position = this.thumbOuterWidth - this.settings.thumbWidth;
21738				}
21739				this.translateX =
21740					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
21741						1 -
21742						position;
21743				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
21744					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
21745				}
21746				if (this.translateX < 0) {
21747					this.translateX = 0;
21748				}
21749				this.setTranslate(this.translateX);
21750			}
21751		};
21752		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21753			thumbDragUtils.newTranslateX = this.translateX;
21754			thumbDragUtils.isMoved = true;
21755			thumbDragUtils.touchMoveTime = new Date().valueOf();
21756			thumbDragUtils.newTranslateX -=
21757				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21758			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21759			// move current slide
21760			this.setTranslate(thumbDragUtils.newTranslateX);
21761			this.$thumbOuter.addClass('lg-dragging');
21762			return thumbDragUtils;
21763		};
21764		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21765			thumbDragUtils.isMoved = false;
21766			thumbDragUtils.endTime = new Date();
21767			this.$thumbOuter.removeClass('lg-dragging');
21768			var touchDuration = thumbDragUtils.endTime.valueOf() -
21769				thumbDragUtils.startTime.valueOf();
21770			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21771			var speedX = Math.abs(distanceXnew) / touchDuration;
21772			// Some magical numbers
21773			// Can be improved
21774			if (speedX > 0.15 &&
21775				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21776				speedX += 1;
21777				if (speedX > 2) {
21778					speedX += 1;
21779				}
21780				speedX =
21781					speedX +
21782						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21783				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21784				distanceXnew = distanceXnew * speedX;
21785				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21786				this.setTranslate(this.translateX);
21787			}
21788			else {
21789				this.translateX = thumbDragUtils.newTranslateX;
21790			}
21791			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21792				this.settings.thumbnailSwipeThreshold) {
21793				this.thumbClickable = true;
21794			}
21795			return thumbDragUtils;
21796		};
21797		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21798			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21799			var thumbImg;
21800			if (slideVideoInfo.youtube) {
21801				if (this.settings.loadYouTubeThumbnail) {
21802					thumbImg =
21803						'//img.youtube.com/vi/' +
21804							slideVideoInfo.youtube[1] +
21805							'/' +
21806							this.settings.youTubeThumbSize +
21807							'.jpg';
21808				}
21809				else {
21810					thumbImg = thumb;
21811				}
21812			}
21813			else {
21814				thumbImg = thumb;
21815			}
21816			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>";
21817		};
21818		Thumbnail.prototype.getThumbItemHtml = function (items) {
21819			var thumbList = '';
21820			for (var i = 0; i < items.length; i++) {
21821				thumbList += this.getThumbHtml(items[i].thumb, i);
21822			}
21823			return thumbList;
21824		};
21825		Thumbnail.prototype.setThumbItemHtml = function (items) {
21826			var thumbList = this.getThumbItemHtml(items);
21827			this.$lgThumb.html(thumbList);
21828		};
21829		Thumbnail.prototype.setAnimateThumbStyles = function () {
21830			if (this.settings.animateThumb) {
21831				this.core.outer.addClass('lg-animate-thumb');
21832			}
21833		};
21834		// Manage thumbnail active calss
21835		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21836			var _this = this;
21837			// manage active class for thumbnail
21838			//Uncode edit ##START##
21839			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21840			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21841			//Uncode edit ##END##
21842				var $thumb = _this.core.outer.find('.lg-thumb-item');
21843				var index = event.detail.index;
21844				$thumb.removeClass('active');
21845				$thumb.eq(index).addClass('active');
21846			});
21847		};
21848		// Toggle thumbnail bar
21849		Thumbnail.prototype.toggleThumbBar = function () {
21850			var _this = this;
21851			if (this.settings.toggleThumb) {
21852				this.core.outer.addClass('lg-can-toggle');
21853				this.core.$toolbar.append('<button type="button" aria-label="' +
21854					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21855					'" class="lg-toggle-thumb lg-icon"></button>');
21856				this.core.outer
21857					.find('.lg-toggle-thumb')
21858					.first()
21859					.on('click.lg', function () {
21860					_this.core.outer.toggleClass('lg-components-open');
21861				});
21862			}
21863		};
21864		Thumbnail.prototype.thumbKeyPress = function () {
21865			var _this = this;
21866			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21867				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21868					return;
21869				if (e.keyCode === 38) {
21870					e.preventDefault();
21871					_this.core.outer.addClass('lg-components-open');
21872				}
21873				else if (e.keyCode === 40) {
21874					e.preventDefault();
21875					_this.core.outer.removeClass('lg-components-open');
21876				}
21877			});
21878		};
21879		Thumbnail.prototype.destroy = function () {
21880			if (this.settings.thumbnail) {
21881				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21882				this.core.LGel.off('.lg.thumb');
21883				this.core.LGel.off('.thumb');
21884				this.$thumbOuter.remove();
21885				this.core.outer.removeClass('lg-has-thumb');
21886			}
21887		};
21888		return Thumbnail;
21889	}());
21890
21891	return Thumbnail;
21892
21893})));
21894/*!
21895 * lightgallery | 2.5.0 | June 13th 2022
21896 * http://www.lightgalleryjs.com/
21897 * Copyright (c) 2020 Sachin Neravath;
21898 * @license GPLv3
21899 */
21900
21901(function (global, factory) {
21902	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21903	typeof define === 'function' && define.amd ? define(factory) :
21904	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21905}(this, (function () { 'use strict';
21906
21907	/*! *****************************************************************************
21908	Copyright (c) Microsoft Corporation.
21909
21910	Permission to use, copy, modify, and/or distribute this software for any
21911	purpose with or without fee is hereby granted.
21912
21913	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21914	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21915	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21916	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21917	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21918	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21919	PERFORMANCE OF THIS SOFTWARE.
21920	***************************************************************************** */
21921
21922	var __assign = function() {
21923		__assign = Object.assign || function __assign(t) {
21924			for (var s, i = 1, n = arguments.length; i < n; i++) {
21925				s = arguments[i];
21926				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21927			}
21928			return t;
21929		};
21930		return __assign.apply(this, arguments);
21931	};
21932
21933	var videoSettings = {
21934		autoplayFirstVideo: true,
21935		youTubePlayerParams: false,
21936		vimeoPlayerParams: false,
21937		wistiaPlayerParams: false,
21938		gotoNextSlideOnVideoEnd: true,
21939		autoplayVideoOnSlide: false,
21940		videojs: false,
21941		videojsTheme: '',
21942		videojsOptions: {},
21943	};
21944
21945	/**
21946	 * List of lightGallery events
21947	 * All events should be documented here
21948	 * Below interfaces are used to build the website documentations
21949	 * */
21950	var lGEvents = {
21951		afterAppendSlide: 'lgAfterAppendSlide',
21952		init: 'lgInit',
21953		hasVideo: 'lgHasVideo',
21954		containerResize: 'lgContainerResize',
21955		updateSlides: 'lgUpdateSlides',
21956		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21957		beforeOpen: 'lgBeforeOpen',
21958		afterOpen: 'lgAfterOpen',
21959		slideItemLoad: 'lgSlideItemLoad',
21960		beforeSlide: 'lgBeforeSlide',
21961		afterSlide: 'lgAfterSlide',
21962		posterClick: 'lgPosterClick',
21963		dragStart: 'lgDragStart',
21964		dragMove: 'lgDragMove',
21965		dragEnd: 'lgDragEnd',
21966		beforeNextSlide: 'lgBeforeNextSlide',
21967		beforePrevSlide: 'lgBeforePrevSlide',
21968		beforeClose: 'lgBeforeClose',
21969		afterClose: 'lgAfterClose',
21970		rotateLeft: 'lgRotateLeft',
21971		rotateRight: 'lgRotateRight',
21972		flipHorizontal: 'lgFlipHorizontal',
21973		flipVertical: 'lgFlipVertical',
21974		autoplay: 'lgAutoplay',
21975		autoplayStart: 'lgAutoplayStart',
21976		autoplayStop: 'lgAutoplayStop',
21977	};
21978
21979	var param = function (obj) {
21980		return Object.keys(obj)
21981			.map(function (k) {
21982			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
21983		})
21984			.join('&');
21985	};
21986	var getVimeoURLParams = function (defaultParams, videoInfo) {
21987		if (!videoInfo || !videoInfo.vimeo)
21988			return '';
21989		var urlParams = videoInfo.vimeo[2] || '';
21990		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
21991			? '&' + param(defaultParams)
21992			: '';
21993		// Support private video
21994		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
21995		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
21996		var hash = urlWithHashWithParams.split('#')[0];
21997		var isPrivate = videoInfo.vimeo[1] !== hash;
21998		if (isPrivate) {
21999			urlParams = urlParams.replace("/" + hash, '');
22000		}
22001		urlParams =
22002			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
22003		// For vimeo last params gets priority if duplicates found
22004		// Uncode edit ##START##
22005		var vimeoPlayerParams = '?autoplay=0';
22006		if ( videoInfo.autoplay !== '' ) {
22007			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22008			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
22009		} else {
22010			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
22011				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
22012			}
22013		}
22014		if ( videoInfo.muted !== '' ) {
22015			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
22016		} else {
22017			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
22018				vimeoPlayerParams += '&muted=1';
22019			}
22020		}
22021		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22022		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22023		// Uncode edit ##END##
22024		return vimeoPlayerParams;
22025	};
22026
22027	/**
22028	 * Video module for lightGallery
22029	 * Supports HTML5, YouTube, Vimeo, wistia videos
22030	 *
22031	 *
22032	 * @ref Wistia
22033	 * https://wistia.com/support/integrations/wordpress(How to get url)
22034	 * https://wistia.com/support/developers/embed-options#using-embed-options
22035	 * https://wistia.com/support/developers/player-api
22036	 * https://wistia.com/support/developers/construct-an-embed-code
22037	 * http://jsfiddle.net/xvnm7xLm/
22038	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
22039	 * https://wistia.com/support/embed-and-share/sharing-videos
22040	 * https://private-sharing.wistia.com/medias/mwhrulrucj
22041	 *
22042	 * @ref Youtube
22043	 * https://developers.google.com/youtube/player_parameters#enablejsapi
22044	 * https://developers.google.com/youtube/iframe_api_reference
22045	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
22046	 *
22047	 * @ref Vimeo
22048	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
22049	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
22050	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
22051	 */
22052	var Video = /** @class */ (function () {
22053		function Video(instance) {
22054			// get lightGallery core plugin instance
22055			this.core = instance;
22056			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
22057			return this;
22058		}
22059		Video.prototype.init = function () {
22060			var _this = this;
22061			/**
22062			 * Event triggered when video url found without poster
22063			 * Append video HTML
22064			 * Play if autoplayFirstVideo is true
22065			 */
22066			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
22067			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
22068				var $el = _this.core.getSlideItem(_this.core.index);
22069				_this.loadVideoOnPosterClick($el);
22070			});
22071			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
22072			// @desc fired immediately before each slide transition.
22073			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
22074			// @desc fired immediately after each slide transition.
22075			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
22076		};
22077		/**
22078		 * @desc Event triggered when a slide is completely loaded
22079		 *
22080		 * @param {Event} event - lightGalley custom event
22081		 */
22082		Video.prototype.onSlideItemLoad = function (event) {
22083			var _this = this;
22084			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
22085			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
22086			if (this.settings.autoplayFirstVideo &&
22087				isFirstSlide &&
22088				index === this.core.index) {
22089				// Delay is just for the transition effect on video load
22090				setTimeout(function () {
22091					_this.loadAndPlayVideo(index);
22092				}, 200);
22093			}
22094			// Should not call on first slide. should check only if the slide is active
22095			if (!isFirstSlide &&
22096				this.settings.autoplayVideoOnSlide &&
22097				index === this.core.index) {
22098					setTimeout(function () {
22099						_this.loadAndPlayVideo(index);
22100					}, 500);
22101				}
22102		};
22103		/**
22104		 * @desc Event triggered when video url or poster found
22105		 * Append video HTML is poster is not given
22106		 * Play if autoplayFirstVideo is true
22107		 *
22108		 * @param {Event} event - Javascript Event object.
22109		 */
22110		Video.prototype.onHasVideo = function (event) {
22111			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
22112			if (!hasPoster) {
22113				// All functions are called separately if poster exist in loadVideoOnPosterClick function
22114				this.appendVideos(this.core.getSlideItem(index), {
22115					src: src,
22116					addClass: 'lg-object',
22117					index: index,
22118					html5Video: html5Video,
22119					// Uncode edit ##START##
22120					autoplay: event.target.getAttribute('data-lb-autoplay'),
22121					muted: event.target.getAttribute('data-lb-muted'),
22122					// Uncode edit ##END##
22123				});
22124				// Automatically navigate to next slide once video reaches the end.
22125				this.gotoNextSlideOnVideoEnd(src, index);
22126			}
22127		};
22128		/**
22129		 * @desc fired immediately before each slide transition.
22130		 * Pause the previous video
22131		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
22132		 *
22133		 * @param {Event} event - Javascript Event object.
22134		 * @param {number} prevIndex - Previous index of the slide.
22135		 * @param {number} index - Current index of the slide
22136		 */
22137		Video.prototype.onBeforeSlide = function (event) {
22138			if (this.core.lGalleryOn) {
22139				var prevIndex = event.detail.prevIndex;
22140				this.pauseVideo(prevIndex);
22141			}
22142			// Uncode edit ##START##
22143			var _a = event.detail, index = _a.index;
22144			var $slide = this.core.getSlideItem(index);
22145			
22146			var iframe = $slide.selector.querySelector('iframe');
22147			if ( iframe != null ) {
22148
22149				var data_play = iframe.getAttribute('data-autoplay');
22150				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
22151					this.loadAndPlayVideo(index);
22152
22153					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
22154						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
22155					if (videoInfo.vimeo) {
22156						var vimeoPlayer = new Vimeo.Player($videoElement.get());
22157						vimeoPlayer.on('play', function () {
22158							vimeoPlayer.setCurrentTime(0);
22159						});
22160					} else if ( videoInfo.youtube ) {
22161						try {
22162							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
22163						}
22164						catch (e) {
22165							console.warn(e);
22166						}
22167					}
22168				}
22169			}
22170			// Uncode edit ##END##
22171		};
22172		/**
22173		 * @desc fired immediately after each slide transition.
22174		 * Play video if autoplayVideoOnSlide option is enabled.
22175		 *
22176		 * @param {Event} event - Javascript Event object.
22177		 * @param {number} prevIndex - Previous index of the slide.
22178		 * @param {number} index - Current index of the slide
22179		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
22180		 */
22181		Video.prototype.onAfterSlide = function (event) {
22182			var _this = this;
22183			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
22184			// Do not call on first slide
22185			var $slide = this.core.getSlideItem(index);
22186			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
22187				if ($slide.hasClass('lg-complete')) {
22188					setTimeout(function () {
22189						_this.loadAndPlayVideo(index);
22190					}, 100);
22191				}
22192			}
22193		};
22194		Video.prototype.loadAndPlayVideo = function (index) {
22195			var $slide = this.core.getSlideItem(index);
22196			var currentGalleryItem = this.core.galleryItems[index];
22197			if (currentGalleryItem.poster) {
22198				this.loadVideoOnPosterClick($slide, true);
22199			}
22200			else {
22201				//Uncode edit ##START##
22202				// this.playVideo(index);
22203				var iframe = $slide.selector.querySelector('iframe');
22204				if ( iframe != null ) {
22205					var data_play = iframe.getAttribute('data-autoplay');
22206					if ( typeof data_play !== 'undefined' ) {
22207						if ( data_play === '1' && this.core.index == index ) {
22208							this.playVideo(index);
22209						} else {
22210							this.pauseVideo(index);
22211						}
22212					}
22213				}
22214				//Uncode edit ##END##
22215			}
22216		};
22217		/**
22218		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22219		 * @param {number} index - Index of the slide
22220		 */
22221		Video.prototype.playVideo = function (index) {
22222			this.controlVideo(index, 'play');
22223		};
22224		/**
22225		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22226		 * @param {number} index - Index of the slide
22227		 */
22228		Video.prototype.pauseVideo = function (index) {
22229			this.controlVideo(index, 'pause');
22230		};
22231		// Uncode edit ##START##
22232		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
22233		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
22234		// Uncode edit ##END##
22235			var video = '';
22236			var videoInfo = this.core.galleryItems[index]
22237				.__slideVideoInfo || {};
22238			var currentGalleryItem = this.core.galleryItems[index];
22239			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
22240			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
22241			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
22242			if (videoInfo.youtube) {
22243				var videoId = 'lg-youtube' + index;
22244				var slideUrlParams = videoInfo.youtube[2]
22245					? videoInfo.youtube[2] + '&'
22246					: '';
22247				// For youtube first parms gets priority if duplicates found
22248				// Uncode edit ##START##
22249				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
22250				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
22251				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
22252					youTubePlayerParams += '&autoplay=0';
22253				}
22254				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
22255					youTubePlayerParams += '&mute=1';
22256				}
22257				var data_video = '';
22258				if ( autoplay !== '' ) {
22259					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
22260					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22261					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
22262					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22263				}
22264				// if ( muted !== '' ) {
22265				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
22266				// }
22267				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
22268
22269				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
22270				// Uncode edit ##END##
22271				var playerParams = youTubePlayerParams +
22272					(this.settings.youTubePlayerParams
22273						? '&' + param(this.settings.youTubePlayerParams)
22274						: '');
22275				// Uncode edit ##START##
22276				// 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>";
22277				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube.com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
22278				var tag = document.createElement('script');
22279				tag.src = "//www.youtube.com/player_api";
22280				var firstScriptTag = document.getElementsByTagName('script')[0];
22281				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
22282
22283				// Replace the 'ytplayer' element with an <iframe> and
22284				// YouTube player after the API code downloads.
22285				var ytIframeplayer,
22286					setMute = muted === 'yes' ? 0 : 100;
22287				window.onYouTubePlayerAPIReady = function() {
22288					ytIframeplayer = new YT.Player(videoId, {
22289						videoId: videoInfo.youtube[1],
22290						events: {
22291							'onReady': function (event) {
22292								event.target.setVolume(setMute);
22293							}
22294						}
22295					});
22296				}
22297				// Uncode edit ##END##
22298			}
22299			else if (videoInfo.vimeo) {
22300				var videoId = 'lg-vimeo' + index;
22301				// Uncode edit ##START##
22302				videoInfo.autoplay = autoplay;
22303				videoInfo.muted = muted;
22304				// Uncode edit ##END##
22305				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
22306				// Uncode edit ##START##
22307				// 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>";
22308				var data_video = '';
22309				if ( autoplay !== '' ) {
22310					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22311				}
22312				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>";
22313				// Uncode edit ##END##
22314			}
22315			else if (videoInfo.wistia) {
22316				var wistiaId = 'lg-wistia' + index;
22317				var playerParams = param(this.settings.wistiaPlayerParams);
22318				playerParams = playerParams ? '?' + playerParams : '';
22319				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>";
22320			}
22321			else if (videoInfo.html5) {
22322				var html5VideoMarkup = '';
22323				for (var i = 0; i < html5Video.source.length; i++) {
22324					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
22325				}
22326				if (html5Video.tracks) {
22327					var _loop_1 = function (i) {
22328						var trackAttributes = '';
22329						var track = html5Video.tracks[i];
22330						Object.keys(track || {}
22330).forEach(function (key) {
22331							trackAttributes += key + "=\"" + track[key] + "\" ";
22332						});
22333						html5VideoMarkup += "<track " + trackAttributes + ">";
22334					};
22335					for (var i = 0; i < html5Video.tracks.length; i++) {
22336						_loop_1(i);
22337					}
22338				}
22339				var html5VideoAttrs_1 = '';
22340				var videoAttributes_1 = html5Video.attributes || {};
22341				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
22342					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
22343				});
22344				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
22345					? this.settings.videojsTheme + ' '
22346					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
22347			}
22348			return video;
22349		};
22350		/**
22351		 * @desc - Append videos to the slide
22352		 *
22353		 * @param {HTMLElement} el - slide element
22354		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
22355		 */
22356		Video.prototype.appendVideos = function (el, videoParams) {
22357			var _a;
22358			// Uncode edit ##START##
22359			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
22360			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
22361			// Uncode edit ##END##
22362			el.find('.lg-video-cont').append(videoHtml);
22363			var $videoElement = el.find('.lg-video-object').first();
22364			if (videoParams.html5Video) {
22365				$videoElement.on('mousedown.lg.video', function (e) {
22366					e.stopPropagation();
22367				});
22368			}
22369			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
22370				try {
22371					return videojs($videoElement.get(), this.settings.videojsOptions);
22372				}
22373				catch (e) {
22374					console.warn('lightGallery:- Make sure you have included videojs');
22375				}
22376			}
22377		};
22378		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
22379			var _this = this;
22380			var $videoElement = this.core
22381				.getSlideItem(index)
22382				.find('.lg-video-object')
22383				.first();
22384			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22385			if (this.settings.gotoNextSlideOnVideoEnd) {
22386				if (videoInfo.html5) {
22387					$videoElement.on('ended', function () {
22388						_this.core.goToNextSlide();
22389					});
22390				}
22391				else if (videoInfo.vimeo) {
22392					try {
22393						// https://github.com/vimeo/player.js/#ended
22394						new Vimeo.Player($videoElement.get()).on('ended', function () {
22395							_this.core.goToNextSlide();
22396						});
22397					}
22398					catch (e) {
22399						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22400					}
22401				}
22402				else if (videoInfo.wistia) {
22403					try {
22404						window._wq = window._wq || [];
22405						// @todo Event is gettign triggered multiple times
22406						window._wq.push({
22407							id: $videoElement.attr('id'),
22408							onReady: function (video) {
22409								video.bind('end', function () {
22410									_this.core.goToNextSlide();
22411								});
22412							},
22413						});
22414					}
22415					catch (e) {
22416						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22417					}
22418				}
22419			}
22420		};
22421		Video.prototype.controlVideo = function (index, action) {
22422			var $videoElement = this.core
22423				.getSlideItem(index)
22424				.find('.lg-video-object')
22425				.first();
22426			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22427			if (!$videoElement.get())
22428				return;
22429			if (videoInfo.youtube) {
22430				try {
22431					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
22432				}
22433				catch (e) {
22434					console.warn("lightGallery:- " + e);
22435				}
22436			}
22437			else if (videoInfo.vimeo) {
22438				try {
22439					new Vimeo.Player($videoElement.get())[action]();
22440				}
22441				catch (e) {
22442					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22443				}
22444			}
22445			else if (videoInfo.html5) {
22446				if (this.settings.videojs) {
22447					try {
22448						videojs($videoElement.get())[action]();
22449					}
22450					catch (e) {
22451						console.warn('lightGallery:- Make sure you have included videojs');
22452					}
22453				}
22454				else {
22455					$videoElement.get()[action]();
22456				}
22457			}
22458			else if (videoInfo.wistia) {
22459				try {
22460					window._wq = window._wq || [];
22461					// @todo Find a way to destroy wistia player instance
22462					window._wq.push({
22463						id: $videoElement.attr('id'),
22464						onReady: function (video) {
22465							video[action]();
22466						},
22467					});
22468				}
22469				catch (e) {
22470					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22471				}
22472			}
22473		};
22474		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
22475			var _this = this;
22476			// check slide has poster
22477			if (!$el.hasClass('lg-video-loaded')) {
22478				// check already video element present
22479				if (!$el.hasClass('lg-has-video')) {
22480					$el.addClass('lg-has-video');
22481					var _html = void 0;
22482					var _src = this.core.galleryItems[this.core.index].src;
22483					var video = this.core.galleryItems[this.core.index].video;
22484					if (video) {
22485						_html =
22486							typeof video === 'string' ? JSON.parse(video) : video;
22487					}
22488					var videoJsPlayer_1 = this.appendVideos($el, {
22489						src: _src,
22490						addClass: '',
22491						index: this.core.index,
22492						html5Video: _html,
22493					});
22494					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
22495					var $tempImg = $el.find('.lg-object').first().get();
22496					// @todo make sure it is working
22497					$el.find('.lg-video-cont').first().append($tempImg);
22498					$el.addClass('lg-video-loading');
22499					videoJsPlayer_1 &&
22500						videoJsPlayer_1.ready(function () {
22501							videoJsPlayer_1.on('loadedmetadata', function () {
22502								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22503							});
22504						});
22505					$el.find('.lg-video-object')
22506						.first()
22507						.on('load.lg error.lg loadedmetadata.lg', function () {
22508						setTimeout(function () {
22509							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22510						}, 50);
22511					});
22512				}
22513				else {
22514					this.playVideo(this.core.index);
22515				}
22516			}
22517			else if (forcePlay) {
22518				this.playVideo(this.core.index);
22519			}
22520		};
22521		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
22522			$el.addClass('lg-video-loaded');
22523			this.playVideo(index);
22524		};
22525		Video.prototype.destroy = function () {
22526			this.core.LGel.off('.lg.video');
22527			this.core.LGel.off('.video');
22528		};
22529		return Video;
22530	}());
22531
22532	return Video;
22533
22534})));
22535
22536
22537/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
22538!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:{}}
22538),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 22538
22538var 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)}
22538},{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 22538-23745
22538))}(),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});
22539
22540/**
22541 * Owl carousel
22542 * @version 2.0.0-beta.3
22543 * @author Bartosz Wojciechowski
22544 * @license The MIT License (MIT)
22545 * @todo Lazy Load Icon
22546 * @todo prevent animationend bubling
22547 * @todo itemsScaleUp
22548 * @todo Test Zepto
22549 * @todo stagePadding calculate wrong active classes
22550 */
22551;(function($, window, document, undefined) {
22552
22553	/**
22554	 * Creates a carousel.
22555	 * @class The Owl Carousel.
22556	 * @public
22557	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
22558	 * @param {Object} [options] - The options
22559	 */
22560	function Owl(element, options) {
22561
22562		/**
22563		 * Current settings for the carousel.
22564		 * @public
22565		 */
22566		this.settings = null;
22567
22568		/**
22569		 * Current options set by the caller including defaults.
22570		 * @public
22571		 */
22572		this.options = $.extend({}, Owl.Defaults, options);
22573
22574		/**
22575		 * Plugin element.
22576		 * @public
22577		 */
22578		this.$element = $(element);
22579
22580		/**
22581		 * Proxied event handlers.
22582		 * @protected
22583		 */
22584		this._handlers = {};
22585
22586		/**
22587		 * References to the running plugins of this carousel.
22588		 * @protected
22589		 */
22590		this._plugins = {};
22591
22592		/**
22593		 * Currently suppressed events to prevent them from beeing retriggered.
22594		 * @protected
22595		 */
22596		this._supress = {};
22597
22598		/**
22599		 * Absolute current position.
22600		 * @protected
22601		 */
22602		this._current = null;
22603
22604		/**
22605		 * Animation speed in milliseconds.
22606		 * @protected
22607		 */
22608		this._speed = null;
22609
22610		/**
22611		 * Coordinates of all items in pixel.
22612		 * @todo The name of this member is missleading.
22613		 * @protected
22614		 */
22615		this._coordinates = [];
22616
22617		/**
22618		 * Current breakpoint.
22619		 * @todo Real media queries would be nice.
22620		 * @protected
22621		 */
22622		this._breakpoint = null;
22623
22624		/**
22625		 * Current width of the plugin element.
22626		 */
22627		this._width = null;
22628
22629		/**
22630		 * All real items.
22631		 * @protected
22632		 */
22633		this._items = [];
22634
22635		/**
22636		 * All cloned items.
22637		 * @protected
22638		 */
22639		this._clones = [];
22640
22641		/**
22642		 * Merge values of all items.
22643		 * @todo Maybe this could be part of a plugin.
22644		 * @protected
22645		 */
22646		this._mergers = [];
22647
22648		/**
22649		 * Widths of all items.
22650		 */
22651		this._widths = [];
22652
22653		/**
22654		 * Invalidated parts within the update process.
22655		 * @protected
22656		 */
22657		this._invalidated = {};
22658
22659		/**
22660		 * Ordered list of workers for the update process.
22661		 * @protected
22662		 */
22663		this._pipe = [];
22664
22665		/**
22666		 * Current state information for the drag operation.
22667		 * @todo #261
22668		 * @protected
22669		 */
22670		this._drag = {
22671			time: null,
22672			target: null,
22673			pointer: null,
22674			stage: {
22675				start: null,
22676				current: null
22677			},
22678			direction: null
22679		};
22680
22681		/**
22682		 * Current state information and their tags.
22683		 * @type {Object}
22684		 * @protected
22685		 */
22686		this._states = {
22687			current: {},
22688			tags: {
22689				'initializing': [ 'busy' ],
22690				'animating': [ 'busy' ],
22691				'dragging': [ 'interacting' ]
22692			}
22693		};
22694
22695		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
22696			this._handlers[handler] = $.proxy(this[handler], this);
22697		}, this));
22698
22699		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
22700			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
22701				= new plugin(this);
22702		}, this));
22703
22704		$.each(Owl.Workers, $.proxy(function(priority, worker) {
22705			this._pipe.push({
22706				'filter': worker.filter,
22707				'run': $.proxy(worker.run, this)
22708			});
22709		}, this));
22710
22711		this.setup();
22712		this.initialize();
22713	}
22714
22715	/**
22716	 * Default options for the carousel.
22717	 * @public
22718	 */
22719	Owl.Defaults = {
22720		items: 3,
22721		loop: false,
22722		center: false,
22723		rewind: false,
22724
22725		mouseDrag: true,
22726		touchDrag: true,
22727		pullDrag: true,
22728		freeDrag: false,
22729
22730		margin: 0,
22731		stagePadding: 0,
22732
22733		merge: false,
22734		mergeFit: true,
22735		autoWidth: false,
22736
22737		startPosition: 0,
22738		rtl: false,
22739
22740		smartSpeed: 250,
22741		fluidSpeed: false,
22742		dragEndSpeed: false,
22743
22744		responsive: {},
22745		responsiveRefreshRate: 200,
22746		responsiveBaseElement: window,
22747
22748		fallbackEasing: 'swing',
22749
22750		info: false,
22751
22752		nestedItemSelector: false,
22753		itemElement: 'div',
22754		stageElement: 'div',
22755
22756		refreshClass: 'owl-refresh',
22757		loadedClass: 'owl-loaded',
22758		loadingClass: 'owl-loading',
22759		rtlClass: 'owl-rtl',
22760		responsiveClass: 'owl-responsive',
22761		dragClass: 'owl-drag',
22762		itemClass: 'owl-item',
22763		stageClass: 'owl-stage',
22764		stageOuterClass: 'owl-stage-outer',
22765		grabClass: 'owl-grab'
22766	};
22767
22768	/**
22769	 * Enumeration for width.
22770	 * @public
22771	 * @readonly
22772	 * @enum {String}
22773	 */
22774	Owl.Width = {
22775		Default: 'default',
22776		Inner: 'inner',
22777		Outer: 'outer'
22778	};
22779
22780	/**
22781	 * Enumeration for types.
22782	 * @public
22783	 * @readonly
22784	 * @enum {String}
22785	 */
22786	Owl.Type = {
22787		Event: 'event',
22788		State: 'state'
22789	};
22790
22791	/**
22792	 * Contains all registered plugins.
22793	 * @public
22794	 */
22795	Owl.Plugins = {};
22796
22797	/**
22798	 * List of workers involved in the update process.
22799	 */
22800	Owl.Workers = [ {
22801		filter: [ 'width', 'settings' ],
22802		run: function() {
22803			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
22804			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
22805		}
22806	}, {
22807		filter: [ 'width', 'items', 'settings' ],
22808		run: function(cache) {
22809			cache.current = this._items && this._items[this.relative(this._current)];
22810		}
22811	}, {
22812		filter: [ 'items', 'settings' ],
22813		run: function() {
22814			this.$stage.children('.cloned').remove();
22815		}
22816	}, {
22817		filter: [ 'width', 'items', 'settings' ],
22818		run: function(cache) {
22819			var margin = this.settings.margin || '',
22820				grid = !this.settings.autoWidth,
22821				rtl = this.settings.rtl,
22822				css = {
22823					'width': 'auto',
22824					'margin-left': rtl ? margin : '',
22825					'margin-right': rtl ? '' : margin
22826				};
22827
22828			!grid && this.$stage.children().css(css);
22829
22830			cache.css = css;
22831		}
22832	}, {
22833		filter: [ 'width', 'items', 'settings' ],
22834		run: function(cache) {
22835			//UNCODE edit to fix Chrome stage padding issue
22836			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
22837				merge = null,
22838				iterator = this._items.length,
22839				grid = !this.settings.autoWidth,
22840				widths = [];
22841
22842			cache.items = {
22843				merge: false,
22844				width: width
22845			};
22846
22847			while (iterator--) {
22848				merge = this._mergers[iterator];
22849				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
22850
22851				cache.items.merge = merge > 1 || cache.items.merge;
22852
22853				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22854			}
22855
22856			this._widths = widths;
22857		}
22858	}, {
22859		filter: [ 'items', 'settings' ],
22860		run: function() {
22861			var clones = [],
22862				items = this._items,
22863				settings = this.settings,
22864				view = Math.max(settings.items * 2, 4),
22865				size = Math.ceil(items.length / 2) * 2,
22866				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22867				append = '',
22868				prepend = '';
22869
22870			repeat /= 2;
22871
22872			while (repeat--) {
22873				clones.push(this.normalize(clones.length / 2, true));
22874				append = append + items[clones[clones.length - 1]][0].outerHTML;
22875				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22876				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22877			}
22878
22879			this._clones = clones;
22880
22881			// var appendVideo = $(append).find('.uncode-video-container');
22882			// if (appendVideo.length) {
22883			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22884			// }
22885			// var prependVideo = $(prepend).find('.uncode-video-container');
22886			// if (prependVideo.length) {
22887			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22888			// }
22889			$(append).addClass('cloned').appendTo(this.$stage);
22890			$(prepend).addClass('cloned').prependTo(this.$stage);
22891		}
22892	}, {
22893		filter: [ 'width', 'items', 'settings' ],
22894		run: function() {
22895			var rtl = this.settings.rtl ? 1 : -1,
22896				size = this._clones.length + this._items.length,
22897				iterator = -1,
22898				previous = 0,
22899				current = 0,
22900				coordinates = [];
22901
22902			while (++iterator < size) {
22903				previous = coordinates[iterator - 1] || 0;
22904				current = this._widths[this.relative(iterator)] + this.settings.margin;
22905				coordinates.push(previous + current * rtl);
22906			}
22907
22908			this._coordinates = coordinates;
22909		}
22910	}, {
22911		filter: [ 'width', 'items', 'settings' ],
22912		run: function() {
22913			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22914				padding = stagePadding,
22915				coordinates = this._coordinates,
22916				css = {
22917					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22918					'padding-left': padding || '',
22919					'padding-right': padding || ''
22920				};
22921
22922			this.$stage.css(css);
22923		}
22924	}, {
22925		filter: [ 'width', 'items', 'settings' ],
22926		run: function(cache) {
22927			var iterator = this._coordinates.length,
22928				grid = !this.settings.autoWidth,
22929				items = this.$stage.children();
22930
22931			if (grid && cache.items.merge) {
22932				while (iterator--) {
22933					cache.css.width = this._widths[this.relative(iterator)];
22934					items.eq(iterator).css(cache.css);
22935				}
22936			} else if (grid) {
22937				cache.css.width = cache.items.width;
22938				items.css(cache.css);
22939			}
22940		}
22941	}, {
22942		filter: [ 'items' ],
22943		run: function() {
22944			this._coordinates.length < 1 && this.$stage.removeAttr('style');
22945		}
22946	}, {
22947		filter: [ 'width', 'items', 'settings' ],
22948		run: function(cache) {
22949			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
22950			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
22951			this.reset(cache.current);
22952		}
22953	}, {
22954		filter: [ 'position' ],
22955		run: function() {
22956			this.animate(this.coordinates(this._current));
22957		}
22958	}, {
22959		filter: [ 'width', 'position', 'items', 'settings' ],
22960		run: function() {
22961			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22962				rtl = this.settings.rtl ? 1 : -1,
22963				padding = this.settings.stagePadding * 2,
22964				begin = this.coordinates(this.current()) + padding,
22965				end = begin + this.width() * rtl,
22966				inner, outer, matches = [], i, n;
22967
22968			for (i = 0, n = this._coordinates.length; i < n; i++) {
22969				inner = this._coordinates[i - 1] || 0;
22970				outer = Math.abs(this._coordinates[i]) + padding * rtl;
22971
22972				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
22973					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
22974					matches.push(i);
22975				}
22976			}
22977
22978			this.$stage.children('.active').removeClass('active');
22979			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
22980
22981			if (this.settings.center) {
22982				this.$stage.children('.center').removeClass('center');
22983				this.$stage.children().eq(this.current()).addClass('center');
22984			}
22985		}
22986	} ];
22987
22988	/**
22989	 * Initializes the carousel.
22990	 * @protected
22991	 */
22992	Owl.prototype.initialize = function() {
22993		this.enter('initializing');
22994		this.trigger('initialize');
22995
22996		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
22997
22998		if (this.settings.autoWidth && !this.is('pre-loading')) {
22999			var imgs, nestedSelector, width;
23000			imgs = this.$element.find('img');
23001			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
23002			width = this.$element.children(nestedSelector).width();
23003
23004			if (imgs.length && width <= 0) {
23005				this.preloadAutoWidthImages(imgs);
23006			}
23007		}
23008
23009		this.$element.addClass(this.options.loadingClass);
23010
23011		// create stage
23012		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
23013			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
23014
23015		// append stage
23016		this.$element.append(this.$stage.parent());
23017
23018		// append content
23019		this.replace(this.$element.children().not(this.$stage.parent()));
23020
23021		// check visibility
23022		if (this.$element.is(':visible')) {
23023			// update view
23024			this.refresh();
23025		} else {
23026			// invalidate width
23027			this.invalidate('width');
23028		}
23029
23030		this.$element
23031			.removeClass(this.options.loadingClass)
23032			.addClass(this.options.loadedClass);
23033
23034		// register event handlers
23035		this.registerEventHandlers();
23036
23037		this.leave('initializing');
23038		this.trigger('initialized');
23039	};
23040
23041	/**
23042	 * Setups the current settings.
23043	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
23044	 * @todo Support for media queries by using `matchMedia` would be nice.
23045	 * @public
23046	 */
23047	Owl.prototype.setup = function() {
23048		var viewport = this.viewport(),
23049			overwrites = this.options.responsive,
23050			match = -1,
23051			settings = null;
23052
23053		if (!overwrites) {
23054			settings = $.extend({}, this.options);
23055		} else {
23056			$.each(overwrites, function(breakpoint) {
23057				if (breakpoint <= viewport && breakpoint > match) {
23058					match = Number(breakpoint);
23059				}
23060			});
23061
23062			settings = $.extend({}, this.options, overwrites[match]);
23063			delete settings.responsive;
23064
23065			// responsive class
23066			if (settings.responsiveClass) {
23067				this.$element.attr('class',
23068					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
23069				);
23070			}
23071		}
23072
23073		if (this.settings === null || this._breakpoint !== match) {
23074			this.trigger('change', { property: { name: 'settings', value: settings } });
23075			this._breakpoint = match;
23076			this.settings = settings;
23077			this.invalidate('settings');
23078			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
23079		}
23080	};
23081
23082	/**
23083	 * Updates option logic if necessery.
23084	 * @protected
23085	 */
23086	Owl.prototype.optionsLogic = function() {
23087		if (this.settings.autoWidth) {
23088			this.settings.stagePadding = false;
23089			this.settings.merge = false;
23090		}
23091	};
23092
23093	/**
23094	 * Prepares an item before add.
23095	 * @todo Rename event parameter `content` to `item`.
23096	 * @protected
23097	 * @returns {jQuery|HTMLElement} - The item container.
23098	 */
23099	Owl.prototype.prepare = function(item, index) {
23100		var event = this.trigger('prepare', { content: item });
23101		if (!event.data) {
23102			event.data = $('<' + this.settings.itemElement + '/>')
23103				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
23104		}
23105
23106		this.trigger('prepared', { content: event.data });
23107
23108		return event.data;
23109	};
23110
23111	/**
23112	 * Updates the view.
23113	 * @public
23114	 */
23115	Owl.prototype.update = function() {
23116		var i = 0,
23117			n = this._pipe.length,
23118			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
23119			cache = {};
23120
23121		while (i < n) {
23122			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
23123				this._pipe[i].run(cache);
23124			}
23125			i++;
23126		}
23127
23128		this._invalidated = {};
23129
23130		!this.is('valid') && this.enter('valid');
23131	};
23132
23133	/**
23134	 * Gets the width of the view.
23135	 * @public
23136	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
23137	 * @returns {Number} - The width of the view in pixel.
23138	 */
23139	Owl.prototype.width = function(dimension) {
23140		dimension = dimension || Owl.Width.Default;
23141		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
23142		switch (dimension) {
23143			case Owl.Width.Inner:
23144			case Owl.Width.Outer:
23145				return this._width;
23146			default:
23147				return this._width - stagePadding * 2 + this.settings.margin;
23148		}
23149	};
23150
23151	/**
23152	 * Refreshes the carousel primarily for adaptive purposes.
23153	 * @public
23154	 */
23155	Owl.prototype.refresh = function() {
23156		this.enter('refreshing');
23157		this.trigger('refresh');
23158
23159		this.setup();
23160
23161		this.optionsLogic();
23162
23163		this.$element.addClass(this.options.refreshClass);
23164
23165		this.update();
23166
23167		this.$element.removeClass(this.options.refreshClass);
23168
23169		this.leave('refreshing');
23170		this.trigger('refreshed');
23171	};
23172
23173	/**
23174	 * Checks window `resize` event.
23175	 * @protected
23176	 */
23177	Owl.prototype.onThrottledResize = function() {
23178		window.clearTimeout(this.resizeTimer);
23179		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
23180	};
23181
23182	/**
23183	 * Checks window `resize` event.
23184	 * @protected
23185	 */
23186	Owl.prototype.onResize = function() {
23187		if (!this._items.length) {
23188			return false;
23189		}
23190
23191		if (this._width === this.$element.width()) {
23192			return false;
23193		}
23194
23195		if (!this.$element.is(':visible')) {
23196			return false;
23197		}
23198
23199		this.enter('resizing');
23200
23201		if (this.trigger('resize').isDefaultPrevented()) {
23202			this.leave('resizing');
23203			return false;
23204		}
23205
23206		this.invalidate('width');
23207
23208		this.refresh();
23209
23210		this.leave('resizing');
23211		this.trigger('resized');
23212	};
23213
23214	/**
23215	 * Registers event handlers.
23216	 * @todo Check `msPointerEnabled`
23217	 * @todo #261
23218	 * @protected
23219	 */
23220	Owl.prototype.registerEventHandlers = function() {
23221		if ($.support.transition) {
23222			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
23223		}
23224
23225		if (this.settings.responsive !== false) {
23226			this.on(window, 'resize', this._handlers.onThrottledResize);
23227		}
23228
23229		if (this.settings.mouseDrag) {
23230			this.$element.addClass(this.options.dragClass);
23231			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
23232			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
23233		}
23234
23235		if (this.settings.touchDrag){
23236			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
23237			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
23238		}
23239	};
23240
23241	/**
23242	 * Handles `touchstart` and `mousedown` events.
23243	 * @todo Horizontal swipe threshold as option
23244	 * @todo #261
23245	 * @protected
23246	 * @param {Event} event - The event arguments.
23247	 */
23248	Owl.prototype.onDragStart = function(event) {
23249		var stage = null;
23250
23251		if (event.which === 3) {
23252			return;
23253		}
23254
23255		if ($.support.transform) {
23256			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
23257			stage = {
23258				x: stage[stage.length === 16 ? 12 : 4],
23259				y: stage[stage.length === 16 ? 13 : 5]
23260			};
23261		} else {
23262			stage = this.$stage.position();
23263			stage = {
23264				x: this.settings.rtl ?
23265					stage.left + this.$stage.width() - this.width() + this.settings.margin :
23266					stage.left,
23267				y: stage.top
23268			};
23269		}
23270
23271		if (this.is('animating')) {
23272			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
23273			this.invalidate('position');
23274		}
23275
23276		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
23277
23278		this.speed(0);
23279
23280		this._drag.time = new Date().getTime();
23281		this._drag.target = $(event.target);
23282		this._drag.stage.start = stage;
23283		this._drag.stage.current = stage;
23284		this._drag.pointer = this.pointer(event);
23285
23286		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
23287
23288		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
23289			var delta = this.difference(this._drag.pointer, this.pointer(event));
23290
23291			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
23292
23293			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
23294				return;
23295			}
23296
23297			event.preventDefault();
23298
23299			this.enter('dragging');
23300			this.trigger('drag');
23301		}, this));
23302	};
23303
23304	/**
23305	 * Handles the `touchmove` and `mousemove` events.
23306	 * @todo #261
23307	 * @protected
23308	 * @param {Event} event - The event arguments.
23309	 */
23310	Owl.prototype.onDragMove = function(event) {
23311		var minimum = null,
23312			maximum = null,
23313			pull = null,
23314			delta = this.difference(this._drag.pointer, this.pointer(event)),
23315			stage = this.difference(this._drag.stage.start, delta);
23316
23317		if (!this.is('dragging')) {
23318			return;
23319		}
23320
23321		event.preventDefault();
23322
23323		if (this.settings.loop) {
23324			minimum = this.coordinates(this.minimum());
23325			maximum = this.coordinates(this.maximum() + 1) - minimum;
23326			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
23327		} else {
23328			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
23329			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
23330			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
23331			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
23332		}
23333
23334		this._drag.stage.current = stage;
23335
23336		this.animate(stage.x);
23337	};
23338
23339	/**
23340	 * Handles the `touchend` and `mouseup` events.
23341	 * @todo #261
23342	 * @todo Threshold for click event
23343	 * @protected
23344	 * @param {Event} event - The event arguments.
23345	 */
23346	Owl.prototype.onDragEnd = function(event) {
23347		var delta = this.difference(this._drag.pointer, this.pointer(event)),
23348			stage = this._drag.stage.current,
23349			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
23350
23351		$(document).off('.owl.core');
23352
23353		this.$element.removeClass(this.options.grabClass);
23354
23355		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
23356			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
23357			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
23358			this.invalidate('position');
23359			this.update();
23360
23361			this._drag.direction = direction;
23362
23363			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
23364				this._drag.target.one('click.owl.core', function() { return false; });
23365			}
23366		}
23367
23368		if (!this.is('dragging')) {
23369			return;
23370		}
23371
23372		this.leave('dragging');
23373		this.trigger('dragged');
23374	};
23375
23376	/**
23377	 * Gets absolute position of the closest item for a coordinate.
23378	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
23379	 * @protected
23380	 * @param {Number} coordinate - The coordinate in pixel.
23381	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
23382	 * @return {Number} - The absolute position of the closest item.
23383	 */
23384	Owl.prototype.closest = function(coordinate, direction) {
23385		var position = -1,
23386			pull = 30,
23387			width = this.width(),
23388			coordinates = this.coordinates();
23389
23390		if (!this.settings.freeDrag) {
23391			// check closest item
23392			$.each(coordinates, $.proxy(function(index, value) {
23393				if (coordinate > value - pull && coordinate < value + pull) {
23394					position = index;
23395				} else if (this.op(coordinate, '<', value)
23396					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
23397					position = direction === 'left' ? index + 1 : index;
23398				}
23399				return position === -1;
23400			}, this));
23401		}
23402
23403		if (!this.settings.loop) {
23404			// non loop boundries
23405			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
23406				position = coordinate = this.minimum();
23407			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
23408				position = coordinate = this.maximum();
23409			}
23410		}
23411
23412		return position;
23413	};
23414
23415	/**
23416	 * Animates the stage.
23417	 * @todo #270
23418	 * @public
23419	 * @param {Number} coordinate - The coordinate in pixels.
23420	 */
23421	Owl.prototype.animate = function(coordinate) {
23422		var animate = this.speed() > 0;
23423
23424		this.is('animating') && this.onTransitionEnd();
23425
23426		if (animate) {
23427			this.enter('animating');
23428			this.trigger('translate');
23429		}
23430
23431		if ($.support.transform3d && $.support.transition) {
23432			this.$stage.css({
23433				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
23434				transition: (this.speed() / 1000) + 's'
23435			});
23436		} else if (animate) {
23437			this.$stage.animate({
23438				left: coordinate + 'px'
23439			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
23440		} else {
23441			this.$stage.css({
23442				left: coordinate + 'px'
23443			});
23444		}
23445	};
23446
23447	/**
23448	 * Checks whether the carousel is in a specific state or not.
23449	 * @param {String} state - The state to check.
23450	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
23451	 */
23452	Owl.prototype.is = function(state) {
23453		return this._states.current[state] && this._states.current[state] > 0;
23454	};
23455
23456	/**
23457	 * Sets the absolute position of the current item.
23458	 * @public
23459	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
23460	 * @returns {Number} - The absolute position of the current item.
23461	 */
23462	Owl.prototype.current = function(position) {
23463		if (position === undefined) {
23464			return this._current;
23465		}
23466
23467		if (this._items.length === 0) {
23468			return undefined;
23469		}
23470
23471		position = this.normalize(position);
23472
23473		if (this._current !== position) {
23474			var event = this.trigger('change', { property: { name: 'position', value: position } });
23475
23476			if (event.data !== undefined) {
23477				position = this.normalize(event.data);
23478			}
23479
23480			this._current = position;
23481
23482			this.invalidate('position');
23483
23484			this.trigger('changed', { property: { name: 'position', value: this._current } });
23485		}
23486
23487		return this._current;
23488	};
23489
23490	/**
23491	 * Invalidates the given part of the update routine.
23492	 * @param {String} [part] - The part to invalidate.
23493	 * @returns {Array.<String>} - The invalidated parts.
23494	 */
23495	Owl.prototype.invalidate = function(part) {
23496		if ($.type(part) === 'string') {
23497			this._invalidated[part] = true;
23498			this.is('valid') && this.leave('valid');
23499		}
23500		return $.map(this._invalidated, function(v, i) { return i });
23501	};
23502
23503	/**
23504	 * Resets the absolute position of the current item.
23505	 * @public
23506	 * @param {Number} position - The absolute position of the new item.
23507	 */
23508	Owl.prototype.reset = function(position) {
23509		position = this.normalize(position);
23510
23511		if (position === undefined) {
23512			return;
23513		}
23514
23515		this._speed = 0;
23516		this._current = position;
23517
23518		this.suppress([ 'translate', 'translated' ]);
23519
23520		this.animate(this.coordinates(position));
23521
23522		this.release([ 'translate', 'translated' ]);
23523	};
23524
23525	/**
23526	 * Normalizes an absolute or a relative position of an item.
23527	 * @public
23528	 * @param {Number} position - The absolute or relative position to normalize.
23529	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
23530	 * @returns {Number} - The normalized position.
23531	 */
23532	Owl.prototype.normalize = function(position, relative) {
23533		var n = this._items.length,
23534			m = relative ? 0 : this._clones.length;
23535
23536		if (!$.isNumeric(position) || n < 1) {
23537			position = undefined;
23538		} else if (position < 0 || position >= n + m) {
23539			position = ((position - m / 2) % n + n) % n + m / 2;
23540		}
23541
23542		return position;
23543	};
23544
23545	/**
23546	 * Converts an absolute position of an item into a relative one.
23547	 * @public
23548	 * @param {Number} position - The absolute position to convert.
23549	 * @returns {Number} - The converted position.
23550	 */
23551	Owl.prototype.relative = function(position) {
23552		position -= this._clones.length / 2;
23553		return this.normalize(position, true);
23554	};
23555
23556	/**
23557	 * Gets the maximum position for the current item.
23558	 * @public
23559	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23560	 * @returns {Number}
23561	 */
23562	Owl.prototype.maximum = function(relative) {
23563		var settings = this.settings,
23564			maximum = this._coordinates.length,
23565			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
23566			i = -1, j;
23567
23568		if (settings.loop) {
23569			maximum = this._clones.length / 2 + this._items.length - 1;
23570		} else if (settings.autoWidth || settings.merge) {
23571			// binary search
23572			while (maximum - i > 1) {
23573				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
23574					? i = j : maximum = j;
23575			}
23576		} else if (settings.center) {
23577			maximum = this._items.length - 1;
23578		} else {
23579			maximum = this._items.length - settings.items;
23580		}
23581
23582		if (relative) {
23583			maximum -= this._clones.length / 2;
23584		}
23585
23586		return Math.max(maximum, 0);
23587	};
23588
23589	/**
23590	 * Gets the minimum position for the current item.
23591	 * @public
23592	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23593	 * @returns {Number}
23594	 */
23595	Owl.prototype.minimum = function(relative) {
23596		return relative ? 0 : this._clones.length / 2;
23597	};
23598
23599	/**
23600	 * Gets an item at the specified relative position.
23601	 * @public
23602	 * @param {Number} [position] - The relative position of the item.
23603	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23604	 */
23605	Owl.prototype.items = function(position) {
23606		if (position === undefined) {
23607			return this._items.slice();
23608		}
23609
23610		position = this.normalize(position, true);
23611		return this._items[position];
23612	};
23613
23614	/**
23615	 * Gets an item at the specified relative position.
23616	 * @public
23617	 * @param {Number} [position] - The relative position of the item.
23618	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23619	 */
23620	Owl.prototype.mergers = function(position) {
23621		if (position === undefined) {
23622			return this._mergers.slice();
23623		}
23624
23625		position = this.normalize(position, true);
23626		return this._mergers[position];
23627	};
23628
23629	/**
23630	 * Gets the absolute positions of clones for an item.
23631	 * @public
23632	 * @param {Number} [position] - The relative position of the item.
23633	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
23634	 */
23635	Owl.prototype.clones = function(position) {
23636		var odd = this._clones.length / 2,
23637			even = odd + this._items.length,
23638			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
23639
23640		if (position === undefined) {
23641			return $.map(this._clones, function(v, i) { return map(i) });
23642		}
23643
23644		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
23645	};
23646
23647	/**
23648	 * Sets the current animation speed.
23649	 * @public
23650	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
23651	 * @returns {Number} - The current animation speed in milliseconds.
23652	 */
23653	Owl.prototype.speed = function(speed) {
23654		if (speed !== undefined) {
23655			this._speed = speed;
23656		}
23657
23658		return this._speed;
23659	};
23660
23661	/**
23662	 * Gets the coordinate of an item.
23663	 * @todo The name of this method is missleanding.
23664	 * @public
23665	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
23666	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
23667	 */
23668	Owl.prototype.coordinates = function(position) {
23669		var coordinate = null;
23670
23671		if (position === undefined) {
23672			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
23673				return this.coordinates(index);
23674			}, this));
23675		}
23676
23677		if (this.settings.center) {
23678			coordinate = this._coordinates[position];
23679			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
23680		} else {
23681			coordinate = this._coordinates[position - 1] || 0;
23682		}
23683
23684		return coordinate;
23685	};
23686
23687	/**
23688	 * Calculates the speed for a translation.
23689	 * @protected
23690	 * @param {Number} from - The absolute position of the start item.
23691	 * @param {Number} to - The absolute position of the target item.
23692	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
23693	 * @returns {Number} - The time in milliseconds for the translation.
23694	 */
23695	Owl.prototype.duration = function(from, to, factor) {
23696		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
23697	};
23698
23699	/**
23700	 * Slides to the specified item.
23701	 * @public
23702	 * @param {Number} position - The position of the item.
23703	 * @param {Number} [speed] - The time in milliseconds for the transition.
23704	 */
23705	Owl.prototype.to = function(position, speed) {
23706		var current = this.current(),
23707			revert = null,
23708			distance = position - this.relative(current),
23709			direction = (distance > 0) - (distance < 0),
23710			items = this._items.length,
23711			minimum = this.minimum(),
23712			maximum = this.maximum();
23713
23714		if (this.settings.loop) {
23715			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
23716				distance += direction * -1 * items;
23717			}
23718
23719			position = current + distance;
23720			revert = ((position - minimum) % items + items) % items + minimum;
23721
23722			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
23723				current = revert - distance;
23724				position = revert;
23725				this.reset(current);
23726			}
23727		} else if (this.settings.rewind) {
23728			maximum += 1;
23729			position = (position % maximum + maximum) % maximum;
23730		} else {
23731			position = Math.max(minimum, Math.min(maximum, position));
23732		}
23733
23734		this.speed(this.duration(current, position, speed));
23735		this.current(position);
23736
23737		if (this.$element.is(':visible')) {
23738			this.update();
23739		}
23740	};
23741
23742	/**
23743	 * Slides to the next item.
23744	 * @public
23745	 * @param {Number}
vendor: 12,284 bytes, lines 23745-24165
23745 [speed] - The time in milliseconds for the transition.
23746	 */
23747	Owl.prototype.next = function(speed) {
23748		speed = speed || false;
23749		this.to(this.relative(this.current()) + 1, speed);
23750	};
23751
23752	/**
23753	 * Slides to the previous item.
23754	 * @public
23755	 * @param {Number} [speed] - The time in milliseconds for the transition.
23756	 */
23757	Owl.prototype.prev = function(speed) {
23758		speed = speed || false;
23759		this.to(this.relative(this.current()) - 1, speed);
23760	};
23761
23762	/**
23763	 * Handles the end of an animation.
23764	 * @protected
23765	 * @param {Event} event - The event arguments.
23766	 */
23767	Owl.prototype.onTransitionEnd = function(event) {
23768
23769		// if css2 animation then event object is undefined
23770		if (event !== undefined) {
23771			event.stopPropagation();
23772
23773			// Catch only owl-stage transitionEnd event
23774			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
23775				return false;
23776			}
23777		}
23778
23779		this.leave('animating');
23780		this.trigger('translated');
23781	};
23782
23783	/**
23784	 * Gets viewport width.
23785	 * @protected
23786	 * @return {Number} - The width in pixel.
23787	 */
23788	Owl.prototype.viewport = function() {
23789		var width;
23790		if (this.options.responsiveBaseElement !== window) {
23791			width = $(this.options.responsiveBaseElement).width();
23792		} else if (window.innerWidth) {
23793			width = window.innerWidth;
23794		} else if (document.documentElement && document.documentElement.clientWidth) {
23795			width = document.documentElement.clientWidth;
23796		} else {
23797			throw 'Can not detect viewport width.';
23798		}
23799
23800		return width;
23801	};
23802
23803	/**
23804	 * Replaces the current content.
23805	 * @public
23806	 * @param {HTMLElement|jQuery|String} content - The new content.
23807	 */
23808	Owl.prototype.replace = function(content) {
23809		this.$stage.empty();
23810		this._items = [];
23811
23812		if (content) {
23813			content = (content instanceof jQuery) ? content : $(content);
23814		}
23815
23816		if (this.settings.nestedItemSelector) {
23817			content = content.find('.' + this.settings.nestedItemSelector);
23818		}
23819
23820		content.filter(function() {
23821			return this.nodeType === 1;
23822		}).each($.proxy(function(index, item) {
23823			item = this.prepare(item, index);
23824			this.$stage.append(item);
23825			this._items.push(item);
23826			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
23827		}, this));
23828
23829		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
23830
23831		this.invalidate('items');
23832	};
23833
23834	/**
23835	 * Adds an item.
23836	 * @todo Use `item` instead of `content` for the event arguments.
23837	 * @public
23838	 * @param {HTMLElement|jQuery|String} content - The item content to add.
23839	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
23840	 */
23841	Owl.prototype.add = function(content, position) {
23842		var current = this.relative(this._current);
23843
23844		position = position === undefined ? this._items.length : this.normalize(position, true);
23845		content = content instanceof jQuery ? content : $(content);
23846
23847		this.trigger('add', { content: content, position: position });
23848
23849		content = this.prepare(content, this._items[current].index());
23850
23851		if (this._items.length === 0 || position === this._items.length) {
23852			this._items.length === 0 && this.$stage.append(content);
23853			this._items.length !== 0 && this._items[position - 1].after(content);
23854			this._items.push(content);
23855			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23856		} else {
23857			this._items[position].before(content);
23858			this._items.splice(position, 0, content);
23859			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23860		}
23861
23862		this._items[current] && this.reset(this._items[current].index());
23863
23864		this.invalidate('items');
23865
23866		this.trigger('added', { content: content, position: position });
23867	};
23868
23869	/**
23870	 * Removes an item by its position.
23871	 * @todo Use `item` instead of `content` for the event arguments.
23872	 * @public
23873	 * @param {Number} position - The relative position of the item to remove.
23874	 */
23875	Owl.prototype.remove = function(position) {
23876		position = this.normalize(position, true);
23877
23878		if (position === undefined) {
23879			return;
23880		}
23881
23882		this.trigger('remove', { content: this._items[position], position: position });
23883
23884		this._items[position].remove();
23885		this._items.splice(position, 1);
23886		this._mergers.splice(position, 1);
23887
23888		this.invalidate('items');
23889
23890		this.trigger('removed', { content: null, position: position });
23891	};
23892
23893	/**
23894	 * Preloads images with auto width.
23895	 * @todo Replace by a more generic approach
23896	 * @protected
23897	 */
23898	Owl.prototype.preloadAutoWidthImages = function(images) {
23899		images.each($.proxy(function(i, element) {
23900			this.enter('pre-loading');
23901			element = $(element);
23902			$(new Image()).one('load', $.proxy(function(e) {
23903				element.attr('src', e.target.src);
23904				element.css('opacity', 1);
23905				this.leave('pre-loading');
23906				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23907			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23908		}, this));
23909	};
23910
23911	/**
23912	 * Destroys the carousel.
23913	 * @public
23914	 */
23915	Owl.prototype.destroy = function() {
23916
23917		this.$element.off('.owl.core');
23918		this.$stage.off('.owl.core');
23919		$(document).off('.owl.core');
23920
23921		if (this.settings.responsive !== false) {
23922			window.clearTimeout(this.resizeTimer);
23923			this.off(window, 'resize', this._handlers.onThrottledResize);
23924		}
23925
23926		for (var i in this._plugins) {
23927			this._plugins[i].destroy();
23928		}
23929
23930		this.$stage.children('.cloned').remove();
23931
23932		this.$stage.unwrap();
23933		this.$stage.children().contents().unwrap();
23934		this.$stage.children().unwrap();
23935
23936		this.$element
23937			.removeClass(this.options.refreshClass)
23938			.removeClass(this.options.loadingClass)
23939			.removeClass(this.options.loadedClass)
23940			.removeClass(this.options.rtlClass)
23941			.removeClass(this.options.dragClass)
23942			.removeClass(this.options.grabClass)
23943			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
23944			.removeData('owl.carousel');
23945	};
23946
23947	/**
23948	 * Operators to calculate right-to-left and left-to-right.
23949	 * @protected
23950	 * @param {Number} [a] - The left side operand.
23951	 * @param {String} [o] - The operator.
23952	 * @param {Number} [b] - The right side operand.
23953	 */
23954	Owl.prototype.op = function(a, o, b) {
23955		var rtl = this.settings.rtl;
23956		switch (o) {
23957			case '<':
23958				return rtl ? a > b : a < b;
23959			case '>':
23960				return rtl ? a < b : a > b;
23961			case '>=':
23962				return rtl ? a <= b : a >= b;
23963			case '<=':
23964				return rtl ? a >= b : a <= b;
23965			default:
23966				break;
23967		}
23968	};
23969
23970	/**
23971	 * Attaches to an internal event.
23972	 * @protected
23973	 * @param {HTMLElement} element - The event source.
23974	 * @param {String} event - The event name.
23975	 * @param {Function} listener - The event handler to attach.
23976	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
23977	 */
23978	Owl.prototype.on = function(element, event, listener, capture) {
23979		if (element.addEventListener) {
23980			element.addEventListener(event, listener, capture);
23981		} else if (element.attachEvent) {
23982			element.attachEvent('on' + event, listener);
23983		}
23984	};
23985
23986	/**
23987	 * Detaches from an internal event.
23988	 * @protected
23989	 * @param {HTMLElement} element - The event source.
23990	 * @param {String} event - The event name.
23991	 * @param {Function} listener - The attached event handler to detach.
23992	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
23993	 */
23994	Owl.prototype.off = function(element, event, listener, capture) {
23995		if (element.removeEventListener) {
23996			element.removeEventListener(event, listener, capture);
23997		} else if (element.detachEvent) {
23998			element.detachEvent('on' + event, listener);
23999		}
24000	};
24001
24002	/**
24003	 * Triggers a public event.
24004	 * @todo Remove `status`, `relatedTarget` should be used instead.
24005	 * @protected
24006	 * @param {String} name - The event name.
24007	 * @param {*} [data=null] - The event data.
24008	 * @param {String} [namespace=carousel] - The event namespace.
24009	 * @param {String} [state] - The state which is associated with the event.
24010	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
24011	 * @returns {Event} - The event arguments.
24012	 */
24013	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
24014		var status = {
24015			item: { count: this._items.length, index: this.current() }
24016		}, handler = $.camelCase(
24017			$.grep([ 'on', name, namespace ], function(v) { return v })
24018				.join('-').toLowerCase()
24019		), event = $.Event(
24020			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
24021			$.extend({ relatedTarget: this }, status, data)
24022		);
24023
24024		if (!this._supress[name]) {
24025			$.each(this._plugins, function(name, plugin) {
24026				if (plugin.onTrigger) {
24027					plugin.onTrigger(event);
24028				}
24029			});
24030
24031			this.register({ type: Owl.Type.Event, name: name });
24032			this.$element.trigger(event);
24033
24034			if (this.settings && typeof this.settings[handler] === 'function') {
24035				this.settings[handler].call(this, event);
24036			}
24037		}
24038
24039		return event;
24040	};
24041
24042	/**
24043	 * Enters a state.
24044	 * @param name - The state name.
24045	 */
24046	Owl.prototype.enter = function(name) {
24047		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24048			if (this._states.current[name] === undefined) {
24049				this._states.current[name] = 0;
24050			}
24051
24052			this._states.current[name]++;
24053		}, this));
24054	};
24055
24056	/**
24057	 * Leaves a state.
24058	 * @param name - The state name.
24059	 */
24060	Owl.prototype.leave = function(name) {
24061		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24062			this._states.current[name]--;
24063		}, this));
24064	};
24065
24066	/**
24067	 * Registers an event or state.
24068	 * @public
24069	 * @param {Object} object - The event or state to register.
24070	 */
24071	Owl.prototype.register = function(object) {
24072		if (object.type === Owl.Type.Event) {
24073			if (!$.event.special[object.name]) {
24074				$.event.special[object.name] = {};
24075			}
24076
24077			if (!$.event.special[object.name].owl) {
24078				var _default = $.event.special[object.name]._default;
24079				$.event.special[object.name]._default = function(e) {
24080					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
24081						return _default.apply(this, arguments);
24082					}
24083					return e.namespace && e.namespace.indexOf('owl') > -1;
24084				};
24085				$.event.special[object.name].owl = true;
24086			}
24087		} else if (object.type === Owl.Type.State) {
24088			if (!this._states.tags[object.name]) {
24089				this._states.tags[object.name] = object.tags;
24090			} else {
24091				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
24092			}
24093
24094			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
24095				return $.inArray(tag, this._states.tags[object.name]) === i;
24096			}, this));
24097		}
24098	};
24099
24100	/**
24101	 * Suppresses events.
24102	 * @protected
24103	 * @param {Array.<String>} events - The events to suppress.
24104	 */
24105	Owl.prototype.suppress = function(events) {
24106		$.each(events, $.proxy(function(index, event) {
24107			this._supress[event] = true;
24108		}, this));
24109	};
24110
24111	/**
24112	 * Releases suppressed events.
24113	 * @protected
24114	 * @param {Array.<String>} events - The events to release.
24115	 */
24116	Owl.prototype.release = function(events) {
24117		$.each(events, $.proxy(function(index, event) {
24118			delete this._supress[event];
24119		}, this));
24120	};
24121
24122	/**
24123	 * Gets unified pointer coordinates from event.
24124	 * @todo #261
24125	 * @protected
24126	 * @param {Event} - The `mousedown` or `touchstart` event.
24127	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
24128	 */
24129	Owl.prototype.pointer = function(event) {
24130		var result = { x: null, y: null };
24131
24132		event = event.originalEvent || event || window.event;
24133
24134		event = event.touches && event.touches.length ?
24135			event.touches[0] : event.changedTouches && event.changedTouches.length ?
24136				event.changedTouches[0] : event;
24137
24138		if (event.pageX) {
24139			result.x = event.pageX;
24140			result.y = event.pageY;
24141		} else {
24142			result.x = event.clientX;
24143			result.y = event.clientY;
24144		}
24145
24146		return result;
24147	};
24148
24149	/**
24150	 * Gets the difference of two vectors.
24151	 * @todo #261
24152	 * @protected
24153	 * @param {Object} - The first vector.
24154	 * @param {Object} - The second vector.
24155	 * @returns {Object} - The difference.
24156	 */
24157	Owl.prototype.difference = function(first, second) {
24158		return {
24159			x: first.x - second.x,
24160			y: first.y - second.y
24161		};
24162	};
24163
24164	/**
24165	 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 24166-25448
24166	 * @todo Navigation plugin `next` and `prev`
24167	 * @public
24168	 */
24169	$.fn.owlCarousel = function(option) {
24170		var args = Array.prototype.slice.call(arguments, 1);
24171
24172		return this.each(function() {
24173			var $this = $(this),
24174				data = $this.data('owl.carousel');
24175
24176			if (!data) {
24177				data = new Owl(this, typeof option == 'object' && option);
24178				$this.data('owl.carousel', data);
24179
24180				$.each([
24181					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
24182				], function(i, event) {
24183					data.register({ type: Owl.Type.Event, name: event });
24184					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
24185						if (e.namespace && e.relatedTarget !== this) {
24186							this.suppress([ event ]);
24187							data[event].apply(this, [].slice.call(arguments, 1));
24188							this.release([ event ]);
24189						}
24190					}, data));
24191				});
24192			}
24193
24194			if (typeof option == 'string' && option.charAt(0) !== '_') {
24195				data[option].apply(data, args);
24196			}
24197		});
24198	};
24199
24200	/**
24201	 * The constructor for the jQuery Plugin
24202	 * @public
24203	 */
24204	$.fn.owlCarousel.Constructor = Owl;
24205
24206})(window.Zepto || window.jQuery, window, document);
24207
24208/**
24209 * AutoRefresh Plugin
24210 * @version 2.0.0-beta.3
24211 * @author Artus Kolanowski
24212 * @license The MIT License (MIT)
24213 */
24214;(function($, window, document, undefined) {
24215
24216	/**
24217	 * Creates the auto refresh plugin.
24218	 * @class The Auto Refresh Plugin
24219	 * @param {Owl} carousel - The Owl Carousel
24220	 */
24221	var AutoRefresh = function(carousel) {
24222		/**
24223		 * Reference to the core.
24224		 * @protected
24225		 * @type {Owl}
24226		 */
24227		this._core = carousel;
24228
24229		/**
24230		 * Refresh interval.
24231		 * @protected
24232		 * @type {number}
24233		 */
24234		this._interval = null;
24235
24236		/**
24237		 * Whether the element is currently visible or not.
24238		 * @protected
24239		 * @type {Boolean}
24240		 */
24241		this._visible = null;
24242
24243		/**
24244		 * All event handlers.
24245		 * @protected
24246		 * @type {Object}
24247		 */
24248		this._handlers = {
24249			'initialized.owl.carousel': $.proxy(function(e) {
24250				if (e.namespace && this._core.settings.autoRefresh) {
24251					this.watch();
24252				}
24253			}, this)
24254		};
24255
24256		// set default options
24257		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
24258
24259		// register event handlers
24260		this._core.$element.on(this._handlers);
24261	};
24262
24263	/**
24264	 * Default options.
24265	 * @public
24266	 */
24267	AutoRefresh.Defaults = {
24268		autoRefresh: true,
24269		autoRefreshInterval: 500
24270	};
24271
24272	/**
24273	 * Watches the element.
24274	 */
24275	AutoRefresh.prototype.watch = function() {
24276		if (this._interval) {
24277			return;
24278		}
24279
24280		this._visible = this._core.$element.is(':visible');
24281		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
24282	};
24283
24284	/**
24285	 * Refreshes the element.
24286	 */
24287	AutoRefresh.prototype.refresh = function() {
24288		if (this._core.$element.is(':visible') === this._visible) {
24289			return;
24290		}
24291
24292		this._visible = !this._visible;
24293
24294		this._core.$element.toggleClass('owl-hidden', !this._visible);
24295
24296		this._visible && (this._core.invalidate('width') && this._core.refresh());
24297	};
24298
24299	/**
24300	 * Destroys the plugin.
24301	 */
24302	AutoRefresh.prototype.destroy = function() {
24303		var handler, property;
24304
24305		window.clearInterval(this._interval);
24306
24307		for (handler in this._handlers) {
24308			this._core.$element.off(handler, this._handlers[handler]);
24309		}
24310		for (property in Object.getOwnPropertyNames(this)) {
24311			typeof this[property] != 'function' && (this[property] = null);
24312		}
24313	};
24314
24315	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
24316
24317})(window.Zepto || window.jQuery, window, document);
24318
24319/**
24320 * Lazy Plugin
24321 * @version 2.0.0-beta.3
24322 * @author Bartosz Wojciechowski
24323 * @license The MIT License (MIT)
24324 */
24325;(function($, window, document, undefined) {
24326
24327	/**
24328	 * Creates the lazy plugin.
24329	 * @class The Lazy Plugin
24330	 * @param {Owl} carousel - The Owl Carousel
24331	 */
24332	var Lazy = function(carousel) {
24333
24334		/**
24335		 * Reference to the core.
24336		 * @protected
24337		 * @type {Owl}
24338		 */
24339		this._core = carousel;
24340
24341		/**
24342		 * Already loaded items.
24343		 * @protected
24344		 * @type {Array.<jQuery>}
24345		 */
24346		this._loaded = [];
24347
24348		/**
24349		 * Event handlers.
24350		 * @protected
24351		 * @type {Object}
24352		 */
24353		this._handlers = {
24354			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
24355				if (!e.namespace) {
24356					return;
24357				}
24358
24359				if (!this._core.settings || !this._core.settings.lazyLoad) {
24360					return;
24361				}
24362
24363				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
24364					var settings = this._core.settings,
24365						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
24366						i = ((settings.center && n * -1) || 0),
24367						position = ((e.property && e.property.value) || this._core.current()) + i,
24368						clones = this._core.clones().length,
24369						load = $.proxy(function(i, v) { this.load(v) }, this);
24370
24371					while (i++ < n) {
24372						this.load(clones / 2 + this._core.relative(position));
24373						clones && $.each(this._core.clones(this._core.relative(position)), load);
24374						position++;
24375					}
24376				}
24377			}, this)
24378		};
24379
24380		// set the default options
24381		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
24382
24383		// register event handler
24384		this._core.$element.on(this._handlers);
24385	}
24386
24387	/**
24388	 * Default options.
24389	 * @public
24390	 */
24391	Lazy.Defaults = {
24392		lazyLoad: false
24393	}
24394
24395	/**
24396	 * Loads all resources of an item at the specified position.
24397	 * @param {Number} position - The absolute position of the item.
24398	 * @protected
24399	 */
24400	Lazy.prototype.load = function(position) {
24401		var $item = this._core.$stage.children().eq(position),
24402			$elements = $item && $item.find('.owl-lazy');
24403
24404		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
24405			return;
24406		}
24407
24408		$elements.each($.proxy(function(index, element) {
24409			var $element = $(element), image,
24410				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
24411
24412			this._core.trigger('load', { element: $element, url: url }, 'lazy');
24413
24414			if ($element.is('img')) {
24415				$element.one('load.owl.lazy', $.proxy(function() {
24416					$element.css('opacity', 1);
24417					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24418				}, this)).attr('src', url);
24419			} else {
24420				image = new Image();
24421				image.onload = $.proxy(function() {
24422					$element.css({
24423						'background-image': 'url(' + url + ')',
24424						'opacity': '1'
24425					});
24426					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24427				}, this);
24428				image.src = url;
24429			}
24430		}, this));
24431
24432		this._loaded.push($item.get(0));
24433	}
24434
24435	/**
24436	 * Destroys the plugin.
24437	 * @public
24438	 */
24439	Lazy.prototype.destroy = function() {
24440		var handler, property;
24441
24442		for (handler in this.handlers) {
24443			this._core.$element.off(handler, this.handlers[handler]);
24444		}
24445		for (property in Object.getOwnPropertyNames(this)) {
24446			typeof this[property] != 'function' && (this[property] = null);
24447		}
24448	};
24449
24450	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
24451
24452})(window.Zepto || window.jQuery, window, document);
24453
24454/**
24455 * AutoHeight Plugin
24456 * @version 2.0.0-beta.3
24457 * @author Bartosz Wojciechowski
24458 * @license The MIT License (MIT)
24459 */
24460;(function($, window, document, undefined) {
24461
24462	/**
24463	 * Creates the auto height plugin.
24464	 * @class The Auto Height Plugin
24465	 * @param {Owl} carousel - The Owl Carousel
24466	 */
24467	var AutoHeight = function(carousel) {
24468		/**
24469		 * Reference to the core.
24470		 * @protected
24471		 * @type {Owl}
24472		 */
24473		this._core = carousel;
24474
24475		/**
24476		 * All event handlers.
24477		 * @protected
24478		 * @type {Object}
24479		 */
24480		this._handlers = {
24481			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
24482				if (e.namespace && this._core.settings.autoHeight) {
24483					this.update();
24484				}
24485			}, this),
24486			'changed.owl.carousel': $.proxy(function(e) {
24487				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
24488					this.update();
24489				}
24490			}, this),
24491			'loaded.owl.lazy': $.proxy(function(e) {
24492				if (e.namespace && this._core.settings.autoHeight
24493					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
24494					this.update();
24495				}
24496			}, this)
24497		};
24498
24499		// set default options
24500		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
24501
24502		// register event handlers
24503		this._core.$element.on(this._handlers);
24504	};
24505
24506	/**
24507	 * Default options.
24508	 * @public
24509	 */
24510	AutoHeight.Defaults = {
24511		autoHeight: false,
24512		autoHeightClass: 'owl-height'
24513	};
24514
24515	/**
24516	 * Updates the view.
24517	 */
24518	AutoHeight.prototype.update = function() {
24519		var start = this._core._current,
24520			end = start + this._core.settings.items,
24521			visible = this._core.$stage.children().toArray().slice(start, end);
24522			heights = [],
24523			maxheight = 0;
24524
24525		$.each(visible, function(index, item) {
24526			heights.push($(item).height());
24527		});
24528
24529		maxheight = Math.max.apply(null, heights);
24530
24531		this._core.$stage.parent()
24532			.height(maxheight)
24533			.addClass(this._core.settings.autoHeightClass);
24534	};
24535
24536	AutoHeight.prototype.destroy = function() {
24537		var handler, property;
24538
24539		for (handler in this._handlers) {
24540			this._core.$element.off(handler, this._handlers[handler]);
24541		}
24542		for (property in Object.getOwnPropertyNames(this)) {
24543			typeof this[property] != 'function' && (this[property] = null);
24544		}
24545	};
24546
24547	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
24548
24549})(window.Zepto || window.jQuery, window, document);
24550
24551/**
24552 * Video Plugin
24553 * @version 2.0.0-beta.3
24554 * @author Bartosz Wojciechowski
24555 * @license The MIT License (MIT)
24556 */
24557;(function($, window, document, undefined) {
24558
24559	/**
24560	 * Creates the video plugin.
24561	 * @class The Video Plugin
24562	 * @param {Owl} carousel - The Owl Carousel
24563	 */
24564	var Video = function(carousel) {
24565		/**
24566		 * Reference to the core.
24567		 * @protected
24568		 * @type {Owl}
24569		 */
24570		this._core = carousel;
24571
24572		/**
24573		 * Cache all video URLs.
24574		 * @protected
24575		 * @type {Object}
24576		 */
24577		this._videos = {};
24578
24579		/**
24580		 * Current playing item.
24581		 * @protected
24582		 * @type {jQuery}
24583		 */
24584		this._playing = null;
24585
24586		/**
24587		 * All event handlers.
24588		 * @todo The cloned content removale is too late
24589		 * @protected
24590		 * @type {Object}
24591		 */
24592		this._handlers = {
24593			'initialized.owl.carousel': $.proxy(function(e) {
24594				if (e.namespace) {
24595					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
24596				}
24597			}, this),
24598			'resize.owl.carousel': $.proxy(function(e) {
24599				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
24600					e.preventDefault();
24601				}
24602			}, this),
24603			'refreshed.owl.carousel': $.proxy(function(e) {
24604				if (e.namespace && this._core.is('resizing')) {
24605					this._core.$stage.find('.cloned .owl-video-frame').remove();
24606				}
24607			}, this),
24608			'changed.owl.carousel': $.proxy(function(e) {
24609				if (e.namespace && e.property.name === 'position' && this._playing) {
24610					this.stop();
24611				}
24612			}, this),
24613			'prepared.owl.carousel': $.proxy(function(e) {
24614				if (!e.namespace) {
24615					return;
24616				}
24617
24618				var $element = $(e.content).find('.owl-video');
24619
24620				if ($element.length) {
24621					$element.css('display', 'none');
24622					this.fetch($element, $(e.content));
24623				}
24624			}, this)
24625		};
24626
24627		// set default options
24628		this._core.options = $.extend({}, Video.Defaults, this._core.options);
24629
24630		// register event handlers
24631		this._core.$element.on(this._handlers);
24632
24633		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
24634			this.play(e);
24635		}, this));
24636	};
24637
24638	/**
24639	 * Default options.
24640	 * @public
24641	 */
24642	Video.Defaults = {
24643		video: false,
24644		videoHeight: false,
24645		videoWidth: false
24646	};
24647
24648	/**
24649	 * Gets the video ID and the type (YouTube/Vimeo only).
24650	 * @protected
24651	 * @param {jQuery} target - The target containing the video data.
24652	 * @param {jQuery} item - The item containing the video.
24653	 */
24654	Video.prototype.fetch = function(target, item) {
24655		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
24656			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
24657			width = target.attr('data-width') || this._core.settings.videoWidth,
24658			height = target.attr('data-height') || this._core.settings.videoHeight,
24659			url = target.attr('href');
24660
24661		if (url) {
24662			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+)?/);
24663
24664			if (id[3].indexOf('youtu') > -1) {
24665				type = 'youtube';
24666			} else if (id[3].indexOf('vimeo') > -1) {
24667				type = 'vimeo';
24668			} else {
24669				throw new Error('Video URL not supported.');
24670			}
24671			id = id[6];
24672		} else {
24673			throw new Error('Missing video URL.');
24674		}
24675
24676		this._videos[url] = {
24677			type: type,
24678			id: id,
24679			width: width,
24680			height: height
24681		};
24682
24683		item.attr('data-video', url);
24684
24685		this.thumbnail(target, this._videos[url]);
24686	};
24687
24688	/**
24689	 * Creates video thumbnail.
24690	 * @protected
24691	 * @param {jQuery} target - The target containing the video data.
24692	 * @param {Object} info - The video info object.
24693	 * @see `fetch`
24694	 */
24695	Video.prototype.thumbnail = function(target, video) {
24696		var tnLink,
24697			icon,
24698			path,
24699			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
24700			customTn = target.find('img'),
24701			srcType = 'src',
24702			lazyClass = '',
24703			settings = this._core.settings,
24704			create = function(path) {
24705				icon = '<div class="owl-video-play-icon"></div>';
24706
24707				if (settings.lazyLoad) {
24708					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
24709				} else {
24710					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
24711				}
24712				target.after(tnLink);
24713				target.after(icon);
24714			};
24715
24716		// wrap video content into owl-video-wrapper div
24717		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
24718
24719		if (this._core.settings.lazyLoad) {
24720			srcType = 'data-src';
24721			lazyClass = 'owl-lazy';
24722		}
24723
24724		// custom thumbnail
24725		if (customTn.length) {
24726			create(customTn.attr(srcType));
24727			customTn.remove();
24728			return false;
24729		}
24730
24731		if (video.type === 'youtube') {
24732			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
24733			create(path);
24734		} else if (video.type === 'vimeo') {
24735			$.ajax({
24736				type: 'GET',
24737				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
24738				jsonp: 'callback',
24739				dataType: 'jsonp',
24740				success: function(data) {
24741					path = data[0].thumbnail_large;
24742					create(path);
24743				}
24744			});
24745		}
24746	};
24747
24748	/**
24749	 * Stops the current video.
24750	 * @public
24751	 */
24752	Video.prototype.stop = function() {
24753		this._core.trigger('stop', null, 'video');
24754		this._playing.find('.owl-video-frame').remove();
24755		this._playing.removeClass('owl-video-playing');
24756		this._playing = null;
24757		this._core.leave('playing');
24758		this._core.trigger('stopped', null, 'video');
24759	};
24760
24761	/**
24762	 * Starts the current video.
24763	 * @public
24764	 * @param {Event} event - The event arguments.
24765	 */
24766	Video.prototype.play = function(event) {
24767		var target = $(event.target),
24768			item = target.closest('.' + this._core.settings.itemClass),
24769			video = this._videos[item.attr('data-video')],
24770			width = video.width || '100%',
24771			height = video.height || this._core.$stage.height(),
24772			html;
24773
24774		if (this._playing) {
24775			return;
24776		}
24777
24778		this._core.enter('playing');
24779		this._core.trigger('play', null, 'video');
24780
24781		item = this._core.items(this._core.relative(item.index()));
24782
24783		this._core.reset(item.index());
24784
24785		if (video.type === 'youtube') {
24786			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
24787				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
24788		} else if (video.type === 'vimeo') {
24789			html = '<iframe src="//player.vimeo.com/video/' + video.id +
24790				'?autoplay=1" width="' + width + '" height="' + height +
24791				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
24792		}
24793
24794		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
24795
24796		this._playing = item.addClass('owl-video-playing');
24797	};
24798
24799	/**
24800	 * Checks whether an video is currently in full screen mode or not.
24801	 * @todo Bad style because looks like a readonly method but changes members.
24802	 * @protected
24803	 * @returns {Boolean}
24804	 */
24805	Video.prototype.isInFullScreen = function() {
24806		var element = document.fullscreenElement || document.mozFullScreenElement ||
24807				document.webkitFullscreenElement;
24808
24809		return element && $(element).parent().hasClass('owl-video-frame');
24810	};
24811
24812	/**
24813	 * Destroys the plugin.
24814	 */
24815	Video.prototype.destroy = function() {
24816		var handler, property;
24817
24818		this._core.$element.off('click.owl.video');
24819
24820		for (handler in this._handlers) {
24821			this._core.$element.off(handler, this._handlers[handler]);
24822		}
24823		for (property in Object.getOwnPropertyNames(this)) {
24824			typeof this[property] != 'function' && (this[property] = null);
24825		}
24826	};
24827
24828	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
24829
24830})(window.Zepto || window.jQuery, window, document);
24831
24832/**
24833 * Animate Plugin
24834 * @version 2.0.0-beta.3
24835 * @author Bartosz Wojciechowski
24836 * @license The MIT License (MIT)
24837 */
24838;(function($, window, document, undefined) {
24839
24840	/**
24841	 * Creates the animate plugin.
24842	 * @class The Navigation Plugin
24843	 * @param {Owl} scope - The Owl Carousel
24844	 */
24845	var Animate = function(scope) {
24846		this.core = scope;
24847		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
24848		this.swapping = true;
24849		this.previous = undefined;
24850		this.next = undefined;
24851
24852		this.handlers = {
24853			'change.owl.carousel': $.proxy(function(e) {
24854				if (e.namespace && e.property.name == 'position') {
24855					this.previous = this.core.current();
24856					this.next = e.property.value;
24857				}
24858			}, this),
24859			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24860				if (e.namespace) {
24861					this.swapping = e.type == 'translated';
24862				}
24863			}, this),
24864			'translate.owl.carousel': $.proxy(function(e) {
24865				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24866					this.swap();
24867				}
24868			}, this)
24869		};
24870
24871		this.core.$element.on(this.handlers);
24872	};
24873
24874	/**
24875	 * Default options.
24876	 * @public
24877	 */
24878	Animate.Defaults = {
24879		animateOut: false,
24880		animateIn: false
24881	};
24882
24883	/**
24884	 * Toggles the animation classes whenever an translations starts.
24885	 * @protected
24886	 * @returns {Boolean|undefined}
24887	 */
24888	Animate.prototype.swap = function() {
24889
24890		if (this.core.settings.items !== 1) {
24891			return;
24892		}
24893
24894		if (!$.support.animation || !$.support.transition) {
24895			return;
24896		}
24897
24898		this.core.speed(0);
24899
24900		var left,
24901			clear = $.proxy(this.clear, this),
24902			previous = this.core.$stage.children().eq(this.previous),
24903			next = this.core.$stage.children().eq(this.next),
24904			incoming = this.core.settings.animateIn,
24905			outgoing = this.core.settings.animateOut;
24906
24907		if (this.core.current() === this.previous) {
24908			return;
24909		}
24910
24911		if (outgoing) {
24912			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24913			previous.css( { 'left': left + 'px' } )
24914				.addClass('animated owl-animated-out')
24915				.addClass(outgoing)
24916				.on($.support.animation.end, clear);
24917		}
24918
24919		if (incoming) {
24920			next.addClass('animated owl-animated-in')
24921				.addClass(incoming)
24922				.on($.support.animation.end, clear);
24923		}
24924	};
24925
24926	Animate.prototype.clear = function(e) {
24927		if ($(e.target).hasClass('animated')) {
24928			$(e.target).css( { 'left': '' } )
24929				.removeClass('animated owl-animated-out owl-animated-in')
24930				.removeClass(this.core.settings.animateIn)
24931				.removeClass(this.core.settings.animateOut);
24932			this.core.onTransitionEnd();
24933		}
24934	};
24935
24936	/**
24937	 * Destroys the plugin.
24938	 * @public
24939	 */
24940	Animate.prototype.destroy = function() {
24941		var handler, property;
24942
24943		for (handler in this.handlers) {
24944			this.core.$element.off(handler, this.handlers[handler]);
24945		}
24946		for (property in Object.getOwnPropertyNames(this)) {
24947			typeof this[property] != 'function' && (this[property] = null);
24948		}
24949	};
24950
24951	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
24952
24953})(window.Zepto || window.jQuery, window, document);
24954
24955/**
24956 * Autoplay Plugin
24957 * @version 2.0.0-beta.3
24958 * @author Bartosz Wojciechowski
24959 * @author Artus Kolanowski
24960 * @license The MIT License (MIT)
24961 */
24962;(function($, window, document, undefined) {
24963
24964	/**
24965	 * Creates the autoplay plugin.
24966	 * @class The Autoplay Plugin
24967	 * @param {Owl} scope - The Owl Carousel
24968	 */
24969	var Autoplay = function(carousel) {
24970		/**
24971		 * Reference to the core.
24972		 * @protected
24973		 * @type {Owl}
24974		 */
24975		this._core = carousel;
24976
24977		/**
24978		 * The autoplay interval.
24979		 * @type {Number}
24980		 */
24981		this._interval = null;
24982
24983		/**
24984		 * Indicates whenever the autoplay is paused.
24985		 * @type {Boolean}
24986		 */
24987		this._paused = false;
24988
24989		/**
24990		 * All event handlers.
24991		 * @protected
24992		 * @type {Object}
24993		 */
24994		this._handlers = {
24995			'changed.owl.carousel': $.proxy(function(e) {
24996				if (e.namespace && e.property.name === 'settings') {
24997					if (this._core.settings.autoplay) {
24998						this.play();
24999					} else {
25000						this.stop();
25001					}
25002				}
25003			}, this),
25004			'initialized.owl.carousel': $.proxy(function(e) {
25005				if (e.namespace && this._core.settings.autoplay) {
25006					this.play();
25007				}
25008			}, this),
25009			'play.owl.autoplay': $.proxy(function(e, t, s) {
25010				if (e.namespace) {
25011					this.play(t, s);
25012				}
25013			}, this),
25014			'stop.owl.autoplay': $.proxy(function(e) {
25015				if (e.namespace) {
25016					this.stop();
25017				}
25018			}, this),
25019			'mouseover.owl.autoplay': $.proxy(function() {
25020				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25021					this.pause();
25022				}
25023			}, this),
25024			'mouseleave.owl.autoplay': $.proxy(function() {
25025				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25026					this.play();
25027				}
25028			}, this)
25029		};
25030
25031		// register event handlers
25032		this._core.$element.on(this._handlers);
25033
25034		// set default options
25035		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
25036	};
25037
25038	/**
25039	 * Default options.
25040	 * @public
25041	 */
25042	Autoplay.Defaults = {
25043		autoplay: false,
25044		autoplayTimeout: 5000,
25045		autoplayHoverPause: false,
25046		autoplaySpeed: false
25047	};
25048
25049	/**
25050	 * Starts the autoplay.
25051	 * @public
25052	 * @param {Number} [timeout] - The interval before the next animation starts.
25053	 * @param {Number} [speed] - The animation speed for the animations.
25054	 */
25055	Autoplay.prototype.play = function(timeout, speed) {
25056		this._paused = false;
25057
25058		if (this._core.is('rotating')) {
25059			return;
25060		}
25061
25062		this._core.enter('rotating');
25063
25064		this._interval = window.setInterval($.proxy(function() {
25065			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
25066				return;
25067			}
25068			this._core.next(speed || this._core.settings.autoplaySpeed);
25069		}, this), timeout || this._core.settings.autoplayTimeout);
25070	};
25071
25072	/**
25073	 * Stops the autoplay.
25074	 * @public
25075	 */
25076	Autoplay.prototype.stop = function() {
25077		if (!this._core.is('rotating')) {
25078			return;
25079		}
25080
25081		window.clearInterval(this._interval);
25082		this._core.leave('rotating');
25083	};
25084
25085	/**
25086	 * Stops the autoplay.
25087	 * @public
25088	 */
25089	Autoplay.prototype.pause = function() {
25090		if (!this._core.is('rotating')) {
25091			return;
25092		}
25093
25094		this._paused = true;
25095	};
25096
25097	/**
25098	 * Destroys the plugin.
25099	 */
25100	Autoplay.prototype.destroy = function() {
25101		var handler, property;
25102
25103		this.stop();
25104
25105		for (handler in this._handlers) {
25106			this._core.$element.off(handler, this._handlers[handler]);
25107		}
25108		for (property in Object.getOwnPropertyNames(this)) {
25109			typeof this[property] != 'function' && (this[property] = null);
25110		}
25111	};
25112
25113	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
25114
25115})(window.Zepto || window.jQuery, window, document);
25116
25117/**
25118 * Navigation Plugin
25119 * @version 2.0.0-beta.3
25120 * @author Artus Kolanowski
25121 * @license The MIT License (MIT)
25122 */
25123;(function($, window, document, undefined) {
25124	'use strict';
25125
25126	/**
25127	 * Creates the navigation plugin.
25128	 * @class The Navigation Plugin
25129	 * @param {Owl} carousel - The Owl Carousel.
25130	 */
25131	var Navigation = function(carousel) {
25132		/**
25133		 * Reference to the core.
25134		 * @protected
25135		 * @type {Owl}
25136		 */
25137		this._core = carousel;
25138
25139		/**
25140		 * Indicates whether the plugin is initialized or not.
25141		 * @protected
25142		 * @type {Boolean}
25143		 */
25144		this._initialized = false;
25145
25146		/**
25147		 * The current paging indexes.
25148		 * @protected
25149		 * @type {Array}
25150		 */
25151		this._pages = [];
25152
25153		/**
25154		 * All DOM elements of the user interface.
25155		 * @protected
25156		 * @type {Object}
25157		 */
25158		this._controls = {};
25159
25160		/**
25161		 * Markup for an indicator.
25162		 * @protected
25163		 * @type {Array.<String>}
25164		 */
25165		this._templates = [];
25166
25167		/**
25168		 * The carousel element.
25169		 * @type {jQuery}
25170		 */
25171		this.$element = this._core.$element;
25172
25173		/**
25174		 * Overridden methods of the carousel.
25175		 * @protected
25176		 * @type {Object}
25177		 */
25178		this._overrides = {
25179			next: this._core.next,
25180			prev: this._core.prev,
25181			to: this._core.to
25182		};
25183
25184		/**
25185		 * All event handlers.
25186		 * @protected
25187		 * @type {Object}
25188		 */
25189		this._handlers = {
25190			'prepared.owl.carousel': $.proxy(function(e) {
25191				if (e.namespace && this._core.settings.dotsData) {
25192					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
25193						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
25194				}
25195			}, this),
25196			'added.owl.carousel': $.proxy(function(e) {
25197				if (e.namespace && this._core.settings.dotsData) {
25198					this._templates.splice(e.position, 0, this._templates.pop());
25199				}
25200			}, this),
25201			'remove.owl.carousel': $.proxy(function(e) {
25202				if (e.namespace && this._core.settings.dotsData) {
25203					this._templates.splice(e.position, 1);
25204				}
25205			}, this),
25206			'changed.owl.carousel': $.proxy(function(e) {
25207				if (e.namespace && e.property.name == 'position') {
25208					this.draw();
25209				}
25210			}, this),
25211			'initialized.owl.carousel': $.proxy(function(e) {
25212				if (e.namespace && !this._initialized) {
25213					this._core.trigger('initialize', null, 'navigation');
25214					this.initialize();
25215					this.update();
25216					this.draw();
25217					this._initialized = true;
25218					this._core.trigger('initialized', null, 'navigation');
25219				}
25220			}, this),
25221			'refreshed.owl.carousel': $.proxy(function(e) {
25222				if (e.namespace && this._initialized) {
25223					this._core.trigger('refresh', null, 'navigation');
25224					this.update();
25225					this.draw();
25226					this._core.trigger('refreshed', null, 'navigation');
25227				}
25228			}, this)
25229		};
25230
25231		// set default options
25232		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
25233
25234		// register event handlers
25235		this.$element.on(this._handlers);
25236	};
25237
25238	/**
25239	 * Default options.
25240	 * @public
25241	 * @todo Rename `slideBy` to `navBy`
25242	 */
25243	Navigation.Defaults = {
25244		nav: false,
25245		navText: [ 'prev', 'next' ],
25246		navSpeed: false,
25247		navElement: 'div',
25248		navContainer: false,
25249		navContainerClass: 'owl-nav',
25250		navClass: [ 'owl-prev', 'owl-next' ],
25251		slideBy: 1,
25252		dotClass: 'owl-dot',
25253		dotsClass: 'owl-dots',
25254		dots: true,
25255		dotsEach: false,
25256		dotsData: false,
25257		dotsSpeed: false,
25258		dotsContainer: false
25259	};
25260
25261	/**
25262	 * Initializes the layout of the plugin and extends the carousel.
25263	 * @protected
25264	 */
25265	Navigation.prototype.initialize = function() {
25266		var override,
25267			settings = this._core.settings;
25268
25269		// create DOM structure for relative navigation
25270		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
25271			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
25272
25273		this._controls.$previous = $('<' + settings.navElement + '>')
25274			.addClass(settings.navClass[0])
25275			.html(settings.navText[0])
25276			.prependTo(this._controls.$relative)
25277			.on('click', $.proxy(function(e) {
25278				this.prev(settings.navSpeed);
25279			}, this));
25280		this._controls.$next = $('<' + settings.navElement + '>')
25281			.addClass(settings.navClass[1])
25282			.html(settings.navText[1])
25283			.appendTo(this._controls.$relative)
25284			.on('click', $.proxy(function(e) {
25285				this.next(settings.navSpeed);
25286			}, this));
25287
25288		// create DOM structure for absolute navigation
25289		if (!settings.dotsData) {
25290			this._templates = [ $('<div>')
25291				.addClass(settings.dotClass)
25292				.append($('<span>'))
25293				.prop('outerHTML') ];
25294		}
25295
25296		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
25297			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
25298
25299		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
25300			var index = $(e.target).parent().is(this._controls.$absolute)
25301				? $(e.target).index() : $(e.target).parent().index();
25302
25303			e.preventDefault();
25304
25305			this.to(index, settings.dotsSpeed);
25306		}, this));
25307
25308		// override public methods of the carousel
25309		for (override in this._overrides) {
25310			this._core[override] = $.proxy(this[override], this);
25311		}
25312	};
25313
25314	/**
25315	 * Destroys the plugin.
25316	 * @protected
25317	 */
25318	Navigation.prototype.destroy = function() {
25319		var handler, control, property, override;
25320
25321		for (handler in this._handlers) {
25322			this.$element.off(handler, this._handlers[handler]);
25323		}
25324		for (control in this._controls) {
25325			this._controls[control].remove();
25326		}
25327		for (override in this.overides) {
25328			this._core[override] = this._overrides[override];
25329		}
25330		for (property in Object.getOwnPropertyNames(this)) {
25331			typeof this[property] != 'function' && (this[property] = null);
25332		}
25333	};
25334
25335	/**
25336	 * Updates the internal state.
25337	 * @protected
25338	 */
25339	Navigation.prototype.update = function() {
25340		var i, j, k,
25341			lower = this._core.clones().length / 2,
25342			upper = lower + this._core.items().length,
25343			maximum = this._core.maximum(true),
25344			settings = this._core.settings,
25345			size = settings.center || settings.autoWidth || settings.dotsData
25346				? 1 : settings.dotsEach || settings.items;
25347
25348		if (settings.slideBy !== 'page') {
25349			settings.slideBy = Math.min(settings.slideBy, settings.items);
25350		}
25351
25352		if (settings.dots || settings.slideBy == 'page') {
25353			this._pages = [];
25354
25355			for (i = lower, j = 0, k = 0; i < upper; i++) {
25356				if (j >= size || j === 0) {
25357					this._pages.push({
25358						start: Math.min(maximum, i - lower),
25359						end: i - lower + size - 1
25360					});
25361					if (Math.min(maximum, i - lower) === maximum) {
25362						break;
25363					}
25364					j = 0, ++k;
25365				}
25366				j += this._core.mergers(this._core.relative(i));
25367			}
25368		}
25369	};
25370
25371	/**
25372	 * Draws the user interface.
25373	 * @todo The option `dotsData` wont work.
25374	 * @protected
25375	 */
25376	Navigation.prototype.draw = function() {
25377		var difference,
25378			settings = this._core.settings,
25379			disabled = this._core.items().length <= settings.items,
25380			index = this._core.relative(this._core.current()),
25381			loop = settings.loop || settings.rewind;
25382
25383		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
25384
25385		if (settings.nav) {
25386			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
25387			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
25388		}
25389
25390		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
25391
25392		if (settings.dots) {
25393			difference = this._pages.length - this._controls.$absolute.children().length;
25394
25395			if (settings.dotsData && difference !== 0) {
25396				this._controls.$absolute.html(this._templates.join(''));
25397			} else if (difference > 0) {
25398				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
25399			} else if (difference < 0) {
25400				this._controls.$absolute.children().slice(difference).remove();
25401			}
25402
25403			this._controls.$absolute.find('.active').removeClass('active');
25404			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
25405		}
25406	};
25407
25408	/**
25409	 * Extends event data.
25410	 * @protected
25411	 * @param {Event} event - The event object which gets thrown.
25412	 */
25413	Navigation.prototype.onTrigger = function(event) {
25414		var settings = this._core.settings;
25415
25416		event.page = {
25417			index: $.inArray(this.current(), this._pages),
25418			count: this._pages.length,
25419			size: settings && (settings.center || settings.autoWidth || settings.dotsData
25420				? 1 : settings.dotsEach || settings.items)
25421		};
25422	};
25423
25424	/**
25425	 * Gets the current page position of the carousel.
25426	 * @protected
25427	 * @returns {Number}
25428	 */
25429	Navigation.prototype.current = function() {
25430		var current = this._core.relative(this._core.current());
25431		return $.grep(this._pages, $.proxy(function(page, index) {
25432			return page.start <= current && page.end >= current;
25433		}, this)).pop();
25434	};
25435
25436	/**
25437	 * Gets the current succesor/predecessor position.
25438	 * @protected
25439	 * @returns {Number}
25440	 */
25441	Navigation.prototype.getPosition = function(successor) {
25442		var position, length,
25443			settings = this._core.settings;
25444
25445		if (settings.slideBy == 'page') {
25446			position = $.inArray(this.current(), this._pages);
25447			length = this._pages.length;
25448			successor ? ++position : --position;
vendor: 5,678 bytes, lines 25449-25673
25449			position = this._pages[((position % length) + length) % length].start;
25450		} else {
25451			position = this._core.relative(this._core.current());
25452			length = this._core.items().length;
25453			successor ? position += settings.slideBy : position -= settings.slideBy;
25454		}
25455
25456		return position;
25457	};
25458
25459	/**
25460	 * Slides to the next item or page.
25461	 * @public
25462	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25463	 */
25464	Navigation.prototype.next = function(speed) {
25465		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
25466	};
25467
25468	/**
25469	 * Slides to the previous item or page.
25470	 * @public
25471	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25472	 */
25473	Navigation.prototype.prev = function(speed) {
25474		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
25475	};
25476
25477	/**
25478	 * Slides to the specified item or page.
25479	 * @public
25480	 * @param {Number} position - The position of the item or page.
25481	 * @param {Number} [speed] - The time in milliseconds for the transition.
25482	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
25483	 */
25484	Navigation.prototype.to = function(position, speed, standard) {
25485		var length;
25486
25487		if (!standard) {
25488			length = this._pages.length;
25489			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
25490		} else {
25491			$.proxy(this._overrides.to, this._core)(position, speed);
25492		}
25493	};
25494
25495	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
25496
25497})(window.Zepto || window.jQuery, window, document);
25498
25499/**
25500 * Hash Plugin
25501 * @version 2.0.0-beta.3
25502 * @author Artus Kolanowski
25503 * @license The MIT License (MIT)
25504 */
25505;(function($, window, document, undefined) {
25506	'use strict';
25507
25508	/**
25509	 * Creates the hash plugin.
25510	 * @class The Hash Plugin
25511	 * @param {Owl} carousel - The Owl Carousel
25512	 */
25513	var Hash = function(carousel) {
25514		/**
25515		 * Reference to the core.
25516		 * @protected
25517		 * @type {Owl}
25518		 */
25519		this._core = carousel;
25520
25521		/**
25522		 * Hash index for the items.
25523		 * @protected
25524		 * @type {Object}
25525		 */
25526		this._hashes = {};
25527
25528		/**
25529		 * The carousel element.
25530		 * @type {jQuery}
25531		 */
25532		this.$element = this._core.$element;
25533
25534		/**
25535		 * All event handlers.
25536		 * @protected
25537		 * @type {Object}
25538		 */
25539		this._handlers = {
25540			/*'initialized.owl.carousel': $.proxy(function(e) {
25541				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
25542					$(window).trigger('hashchange.owl.navigation');
25543				}
25544			}, this),*/
25545			'prepared.owl.carousel': $.proxy(function(e) {
25546				if (e.namespace) {
25547					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
25548
25549					if (!hash) {
25550						return;
25551					}
25552
25553					this._hashes[hash] = e.content;
25554				}
25555			}, this),
25556			'changed.owl.carousel': $.proxy(function(e) {
25557				if (e.namespace && e.property.name === 'position') {
25558					var current = this._core.items(this._core.relative(this._core.current())),
25559						hash = $.map(this._hashes, function(item, hash) {
25560							return item === current ? hash : null;
25561						}).join();
25562
25563					if (!hash || window.location.hash.slice(1) === hash) {
25564						return;
25565					}
25566
25567					window.location.hash = hash;
25568				}
25569			}, this)
25570		};
25571
25572		// set default options
25573		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
25574
25575		// register the event handlers
25576		this.$element.on(this._handlers);
25577
25578		// register event listener for hash navigation
25579		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
25580			var hash = window.location.hash.substring(1),
25581				items = this._core.$stage.children(),
25582				position = this._hashes[hash] && items.index(this._hashes[hash]);
25583
25584			if (position === undefined || position === this._core.current()) {
25585				return;
25586			}
25587
25588			this._core.to(this._core.relative(position), false, true);
25589		}, this));*/
25590	};
25591
25592	/**
25593	 * Default options.
25594	 * @public
25595	 */
25596	Hash.Defaults = {
25597		URLhashListener: false
25598	};
25599
25600	/**
25601	 * Destroys the plugin.
25602	 * @public
25603	 */
25604	Hash.prototype.destroy = function() {
25605		var handler, property;
25606
25607		$(window).off('hashchange.owl.navigation');
25608
25609		for (handler in this._handlers) {
25610			this._core.$element.off(handler, this._handlers[handler]);
25611		}
25612		for (property in Object.getOwnPropertyNames(this)) {
25613			typeof this[property] != 'function' && (this[property] = null);
25614		}
25615	};
25616
25617	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
25618
25619})(window.Zepto || window.jQuery, window, document);
25620
25621/**
25622 * Support Plugin
25623 *
25624 * @version 2.0.0-beta.3
25625 * @author Vivid Planet Software GmbH
25626 * @author Artus Kolanowski
25627 * @license The MIT License (MIT)
25628 */
25629;(function($, window, document, undefined) {
25630
25631	var style = $('<support>').get(0).style,
25632		prefixes = 'Webkit Moz O ms'.split(' '),
25633		events = {
25634			transition: {
25635				end: {
25636					WebkitTransition: 'webkitTransitionEnd',
25637					MozTransition: 'transitionend',
25638					OTransition: 'oTransitionEnd',
25639					transition: 'transitionend'
25640				}
25641			},
25642			animation: {
25643				end: {
25644					WebkitAnimation: 'webkitAnimationEnd',
25645					MozAnimation: 'animationend',
25646					OAnimation: 'oAnimationEnd',
25647					animation: 'animationend'
25648				}
25649			}
25650		},
25651		tests = {
25652			csstransforms: function() {
25653				return !!test('transform');
25654			},
25655			csstransforms3d: function() {
25656				return !!test('perspective');
25657			},
25658			csstransitions: function() {
25659				return !!test('transition');
25660			},
25661			cssanimations: function() {
25662				return !!test('animation');
25663			}
25664		};
25665
25666	function test(property, prefixed) {
25667		var result = false,
25668			upper = property.charAt(0).toUpperCase() + property.slice(1);
25669
25670		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
25671			if (style[property] !== undefined) {
25672				result = prefixed ? property : true;
25673				return false;
25674			}
25675		});
25676
25677		return result;
25678	}
25679
25680	function prefixed(property) {
25681		return test(property, true);
25682	}
25683
25684	if (tests.csstransitions()) {
25685		/* jshint -W053 */
25686		$.support.transition = new String(prefixed('transition'))
25687		$.support.transition.end = events.transition.end[ $.support.transition ];
25688	}
25689
25690	if (tests.cssanimations()) {
25691		/* jshint -W053 */
25692		$.support.animation = new String(prefixed('animation'))
25693		$.support.animation.end = events.animation.end[ $.support.animation ];
25694	}
25695
25696	if (tests.csstransforms()) {
25697		/* jshint -W053 */
25698		$.support.transform = new String(prefixed('transform'));
25699		$.support.transform3d = tests.csstransforms3d();
25700	}
25701
25702})(window.Zepto || window.jQuery, window, document);
25703
25704(function(window, document, undefined) {
25705
25706	/**
25707	 * Find the absolute position of an element
25708	 */
25709	var absPos = function(element) {
25710		var offsetLeft, offsetTop;
25711		offsetLeft = offsetTop = 0;
25712		if (element.offsetParent) {
25713			do {
25714				offsetLeft += element.offsetLeft;
25715				offsetTop += element.offsetTop;
25716			} while (element = element.offsetParent);
25717		}
25718		return [offsetLeft, offsetTop];
25719	};
25720
25721	/**
25722	 * @constructor Progress Circle class
25723	 * @param params.canvas Canvas on which the circles will be drawn.
25724	 * @param params.minRadius Inner radius of the innermost circle, in px.
25725	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
25726	 * @param params.gapWidth Space between each circle.
25727	 * @param params.centerX X coordinate of the center of circles.
25728	 * @param params.centerY Y coordinate of the center of circles.
25729	 * @param params.infoLineBaseAngle Base angle of the info line.
25730	 * @param params.infoLineAngleInterval Angles between the info lines.
25731	 */
25732	var ProgressCircle = function(params) {
25733		this.canvas = params.canvas;
25734		this.minRadius = params.minRadius || 15;
25735		this.arcWidth = params.arcWidth || 5;
25736		this.gapWidth = params.gapWidth || 3;
25737		this.centerX = params.centerX || this.canvas.width / 2;
25738		this.centerY = params.centerY || this.canvas.height / 2;
25739		this.infoLineLength = params.infoLineLength || 60;
25740		this.horizLineLength = params.horizLineLength || 10;
25741		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
25742		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
25743
25744		this.context = this.canvas.getContext('2d');
25745
25746		this.width = this.canvas.width;
25747		this.height = this.canvas.height;
25748
25749		this.circles = [];
25750		this.runningCount = 0;
25751	};
25752
25753	ProgressCircle.prototype = {
25754		constructor: ProgressCircle,
25755
25756		/**
25757		 * @method Adds an progress monitor entry.
25758		 * @param params.fillColor Color to fill in the circle.
25759		 * @param params.outlineColor Color to outline the circle.
25760		 * @param params.progressListener Callback function to fetch the progress.
25761		 * @param params.infoListener Callback function to fetch the info.
25762		 * @returns this
25763		 */
25764		addEntry: function(params) {
25765			this.circles.push(new Circle({
25766				canvas: this.canvas,
25767				context: this.context,
25768				centerX: this.centerX,
25769				centerY: this.centerY,
25770				innerRadius: this.minRadius + this.circles.length *
25771					(this.gapWidth + this.arcWidth),
25772				arcWidth: this.arcWidth,
25773				infoLineLength: this.infoLineLength,
25774				horizLineLength: this.horizLineLength,
25775
25776				id: this.circles.length,
25777				fillColor: params.fillColor,
25778				outlineColor: params.outlineColor,
25779				progressListener: params.progressListener,
25780				infoListener: params.infoListener,
25781				infoLineAngle: this.infoLineBaseAngle +
25782					this.circles.length * this.infoLineAngleInterval,
25783			}));
25784
25785			return this;
25786		},
25787
25788		/**
25789		 * @method Starts the monitor and updates with the given interval.
25790		 * @param interval Interval between updates, in millisecond.
25791		 * @returns this
25792		 */
25793		start: function(interval) {
25794			var self = this;
25795			this.timer = setInterval(function() {
25796				self._update();
25797			}, interval || 33);
25798
25799			return this;
25800		},
25801
25802		/**
25803		 * @method Stop the animation.
25804		 */
25805		stop: function() {
25806			clearTimeout(this.timer);
25807		},
25808
25809		/**
25810		 * @private
25811		 * @method Call update on each circle and redraw them.
25812		 * @returns this
25813		 */
25814		_update: function() {
25815			this._clear();
25816			this.circles.forEach(function(circle, idx, array) {
25817				circle.update();
25818			});
25819
25820			return this;
25821		},
25822
25823		/**
25824		 * @private
25825		 * @method Clear the canvas.
25826		 * @returns this
25827		 */
25828		_clear: function() {
25829			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
25830
25831			return this;
25832		},
25833
25834	};
25835
25836	/**
25837	 * @private
25838	 * @class Individual progress circle.
25839	 * @param params.canvas Canvas on which the circle will be drawn.
25840	 * @param params.context Context of the canvas.
25841	 * @param params.innerRadius Inner radius of the circle, in px.
25842	 * @param params.arcWidth Width of each arc(circle).
25843	 * @param params.gapWidth Distance between each arc.
25844	 * @param params.centerX X coordinate of the center of circles.
25845	 * @param params.centerY Y coordinate of the center of circles.
25846	 * @param params.fillColor Color to fill in the circle.
25847	 * @param params.outlineColor Color to outline the circle.
25848	 * @param params.progressListener Callback function to fetch the progress.
25849	 * @param params.infoListener Callback function to fetch the info.
25850	 * @param params.infoLineAngle Angle of info line.
25851	 */
25852	var Circle = function(params) {
25853		this.id = params.id;
25854		this.canvas = params.canvas;
25855		this.context = params.context;
25856		this.centerX = params.centerX;
25857		this.centerY = params.centerY;
25858		this.arcWidth = params.arcWidth;
25859		this.innerRadius = params.innerRadius || 0;
25860		this.fillColor = params.fillColor || '#fff';
25861		this.outlineColor = params.outlineColor || this.fillColor;
25862		this.progressListener = params.progressListener;
25863		this.infoLineLength = params.infoLineLength || 250;
25864		this.horizLineLength = params.horizLineLength || 50;
25865		this.infoListener = params.infoListener;
25866		this.infoLineAngle = params.infoLineAngle;
25867
25868		this.outerRadius = this.innerRadius + this.arcWidth;
25869
25870		// If the info listener is not registered, then don't calculate
25871		// the related coordinates
25872		if (!this.infoListener) return;
25873
25874		// calculate the info-line turning points
25875		var angle = this.infoLineAngle,
25876			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25877
25878			sinA = Math.sin(angle),
25879			cosA = Math.cos(angle);
25880
25881		this.infoLineStartX = this.centerX + sinA * arcDistance;
25882		this.infoLineStartY = this.centerY - cosA * arcDistance;
25883
25884		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25885		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25886
25887		this.infoLineEndX = this.infoLineMidX +
25888			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25889		this.infoLineEndY = this.infoLineMidY;
25890
25891		var infoText = document.createElement('div'),
25892			style = infoText.style;
25893
25894		style.color = this.fillColor;
25895		style.position = 'absolute';
25896		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25897		// style.top will be calculated in the `drawInfo` method. Since
25898		// user may want to change the size of the font, so the top offset
25899		// must be updated in each loop.
25900		infoText.className = 'ProgressCircleInfo'; // For css styling
25901		infoText.id = 'progress_circle_info_' + this.id;
25902		document.body.appendChild(infoText);
25903		this.infoText = infoText;
25904	};
25905
25906	Circle.prototype = {
25907		constructor: Circle,
25908
25909		update: function() {
25910			this.progress = this.progressListener();
25911			this._draw();
25912
25913			if (this.infoListener) {
25914				this.info = this.infoListener();
25915				this._drawInfo();
25916			}
25917		},
25918
25919		/**
25920		 * @private
25921		 * @method Draw the circle on the canvas.
25922		 * @returns this
25923		 */
25924		_draw: function() {
25925			var ctx = this.context,
25926
25927				ANGLE_OFFSET = -Math.PI / 2,
25928
25929				startAngle = 0 + ANGLE_OFFSET,
25930				endAngle= startAngle + this.progress * Math.PI * 2,
25931
25932				x = this.centerX,
25933				y = this.centerY,
25934
25935				innerRadius = this.innerRadius - this.arcWidth - 1,
25936				outerRadius = this.outerRadius - this.arcWidth - 1;
25937
25938			if ( innerRadius < 0 )
25939				return;
25940
25941			ctx.fillStyle = this.fillColor;
25942			ctx.strokeStyle = this.outlineColor;
25943
25944			ctx.beginPath();
25945			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
25946			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
25947			ctx.closePath();
25948			ctx.stroke();
25949			ctx.fill();
25950
25951			return this;
25952		},
25953
25954		/**
25955		 * @private
25956		 * @method Draw the info lines and info text.
25957		 * @returns this
25958		 */
25959		_drawInfo: function() {
25960
25961			var pointList, lineHeight;
25962
25963			pointList = [
25964				[this.infoLineStartX, this.infoLineStartY],
25965				[this.infoLineMidX, this.infoLineMidY],
25966				[this.infoLineEndX, this.infoLineEndY],
25967			];
25968			this._drawSegments(pointList, false);
25969
25970			this.infoText.innerHTML = this.info;
25971
25972			lineHeight = this.infoText.offsetHeight;
25973			this.infoText.style.top = this.infoLineEndY +
25974				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
25975
25976			return this;
25977		},
25978
25979		/**
25980		 * @private
25981		 * @method Helper function to draw the segments
25982		 * @param pointList An array of points in the form of [x, y].
25983		 * @param close Whether to connect the first and last point.
25984		 */
25985		_drawSegments: function(pointList, close) {
25986			var ctx = this.context;
25987
25988			ctx.beginPath();
25989			ctx.moveTo(pointList[0][0], pointList[0][1]);
25990			for (var i = 1; i < pointList.length; ++i) {
25991				ctx.lineTo(pointList[i][0], pointList[i][1]);
25992			}
25993
25994			if (close) {
25995				ctx.closePath();
25996			}
25997			ctx.stroke();
25998		},
25999	};
26000
26001	window.ProgressCircle = ProgressCircle;
26002
26003})(window, document);
26004
26005
26006
26007
26008/* =========================================================
26009 * jquery.vc_chart.js v1.0
26010 * =========================================================
26011 * Copyright 2013 Wpbakery
26012 *
26013 * Jquery chart plugin for the Visual Composer.
26014 * ========================================================= */
26015(function($){
26016	/**
26017	 * Pie chart animated.
26018	 * @param element - DOM element
26019	 * @param options - settings object.
26020	 * @constructor
26021	 */
26022	var VcChart = function(element, options) {
26023		this.el = element;
26024		this.$el = $(this.el);
26025		var $this = this;
26026		$this.options = $.extend({
26027			color: 'wpb_button',
26028			units: '',
26029			width: '',
26030			label_selector: '.vc_pie_chart_value',
26031			back_selector: '.vc_pie_chart_back',
26032			responsive: true
26033		}, options);
26034		$this.init();
26035	};
26036	VcChart.prototype = {
26037		constructor: VcChart,
26038		_progress_v: 0,
26039		animated: false,
26040		colors: {
26041			'wpb_button': 'rgba(247, 247, 247, 1)',
26042			'btn-primary': 'rgba(0, 136, 204, 1)',
26043			'btn-info': 'rgba(88, 185, 218, 1)',
26044			'btn-success': 'rgba(106, 177, 101, 1)',
26045			'btn-warning': 'rgba(255, 153, 0, 1)',
26046			'btn-danger': 'rgba(255, 103, 91, 1)',
26047			'btn-inverse': 'rgba(85, 85, 85, 1)'
26048		},
26049		init: function() {
26050			this.setupColor();
26051			this.value = this.$el.data('pie-value')/100;
26052			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
26053			this.$wrapper = $('.vc_pie_wrapper', this.$el);
26054			this.$label = $(this.options.label_selector, this.$el);
26055			this.$back = $(this.options.back_selector, this.$el);
26056			this.$canvas = this.$el.find('canvas');
26057			this.arcWidth = this.$el.data('pie-width') * 2;
26058			this.draw();
26059			this.setWayPoint();
26060			if(this.options.responsive === true) this.setResponsive();
26061			if (UNCODE.isMobile) this._progress_v = this.value;
26062		},
26063		setupColor: function() {
26064			// if(typeof this.colors[this.options.color] !== 'undefined') {
26065			//     this.color = this.colors[this.options.color];
26066			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
26067			//     this.color = this.options.color;
26068			// } else {
26069			//     this.color = 'rgba(247, 247, 247, 0.2)';
26070			// }
26071			if(typeof this.options.color !== 'undefined') {
26072				this.color = this.options.color;
26073			} else this.color = 'rgba(247, 247, 247, 0.2)';
26074
26075		},
26076		setResponsive: function() {
26077			var that = this;
26078			if (!UNCODE.isMobile) {
26079				$(window).resize(function(){
26080					if(that.animated === true) that.circle.stop();
26081					that.draw(true);
26082				});
26083			}
26084		},
26085		draw: function(redraw) {
26086			var w = this.$el.addClass('vc_ready').width() * 2,
26087				border_w = this.arcWidth,
26088				radius;
26089			if(!w) w = this.$el.parents(':visible').first().width()-2;
26090			//w = Math.round(w/100*80);
26091			//if (w < 250) w = 250;
26092			radius = w/2;
26093			this.$wrapper.css({"width" : (w / 2) + "px"});
26094			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
26095			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
26096			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
26097			this.$el.addClass('vc_ready');
26098			this.circle = new ProgressCircle({
26099				canvas: this.$canvas.get(0),
26100				minRadius: radius,
26101				arcWidth: border_w
26102			});
26103			if(redraw === true && this.animated === true) {
26104				this._progress_v = this.value;
26105				this.circle.addEntry({
26106					fillColor: this.color,
26107					progressListener: $.proxy(this.setProgress, this)
26108				}).start();
26109			}
26110		},
26111		setProgress: function() {
26112			if (this._progress_v >= this.value) {
26113				this.circle.stop();
26114				this.animated = true;
26115				this.$label.html(this.label_value + this.options.units);
26116				return this._progress_v;
26117			}
26118			this._progress_v += 0.01;
26119			if (!isNaN(this.label_value)) {
26120				var label_value = this._progress_v/this.value*this.label_value;
26121				var val = Math.round(label_value) + this.options.units;
26122				this.$label.html(val);
26123			} else this.$label.html(this.label_value + this.options.units);
26124			return this._progress_v;
26125		},
26126		animate: function() {
26127			if(this.animated !== true) {
26128				this.circle.addEntry({
26129					fillColor: this.color,
26130					progressListener: $.proxy(this.setProgress, this)
26131				}).start(10);
26132			}
26133		},
26134		setWayPoint: function() {
26135			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
26136				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
26137			} else {
26138				this.animate();
26139			}
26140		}
26141	};
26142	/**
26143	 * jQuery plugin
26144	 * @param option - object with settings
26145	 * @return {*}
26146	 */
26147	$.fn.vcChat = function(option, value) {
26148		return this.each(function () {
26149			var $this = $(this),
26150				data = $this.data('vc_chart'),
26151				options = typeof option === 'object' ? option : {
26152					color: $this.data('pie-color'),
26153					units: $this.data('pie-units')
26154				};
26155			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
26156			if (typeof option == 'string') data[option](value);
26157		});
26158	};
26159	/**
26160	 * Allows users to rewrite function inside theme.
26161	 */
26162	if ( typeof window['vc_pieChart'] !== 'function' ) {
26163		window.vc_pieChart = function() {
26164			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
26165		}
26166	}
26167	$(document).ready(function(){
26168		!window.vc_iframe && vc_pieChart();
26169
26170		/**
26171		* Tab and collapse integration.
26172		*/
26173		$('.nav-tabs a').on('shown.bs.tab', function(e){
26174			var $cont = $(e.target).closest('.tab-container'),
26175				$active = $('.tab-pane.active', $cont);
26176			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
26177		});
26178
26179		$('.panel-collapse').on('shown.bs.collapse', function (e) {
26180			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
26181		})
26182	});
26183
26184})(window.jQuery);
26185
26186/* Progress bar
26187 ---------------------------------------------------------- */
26188function uncode_progress_bar() {
26189	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
26190		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
26191			return;
26192		}
26193		if (!UNCODE.isMobile) {
26194			new Waypoint({
26195				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26196				element: val,
26197				handler: function() {
26198					var element = jQuery(this.element);
26199					element.find('.vc_single_bar').each(function(index) {
26200						var $this = jQuery(this),
26201							bar = $this.find('.vc_bar'),
26202							val = bar.data('percentage-value');
26203						setTimeout(function() {
26204							bar.css({
26205								"width": val + '%'
26206							});
26207						}, index * 200);
26208					});
26209				},
26210				offset: '80%'
26211			});
26212		} else {
26213			var element = jQuery(val);
26214			element.find('.vc_single_bar').each(function(index) {
26215				var $this = jQuery(this),
26216					bar = $this.find('.vc_bar'),
26217					val = bar.data('percentage-value');
26218				setTimeout(function() {
26219					bar.css({
26220						"width": val + '%'
26221					});
26222				}, index * 200);
26223			});
26224		}
26225	});
26226};
26227uncode_progress_bar();
26228
26229/*!
26230 * jquery.counterup.js 1.0
26231 *
26232 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
26233 * Released under the GPL v2 License
26234 *
26235 * Date: Nov 26, 2013
26236 */
26237(function($) {
26238	"use strict";
26239	$.fn.counterUp = function(options) {
26240		// Defaults
26241		var settings = $.extend({
26242			'time': 400,
26243			'delay': 10
26244		}, options);
26245		return this.each(function() {
26246			// Store the object
26247			var $this = $(this);
26248			var $settings = settings;
26249			var counterUpper = function() {
26250				var nums = [];
26251				var divisions = $settings.time / $settings.delay;
26252				var numReal = $this.attr('data-val'),
26253				num = numReal;
26254				var isComma = /[0-9]+,[0-9]+/.test(num);
26255				num = num.replace(/,/g, '');
26256				var isInt = /^[0-9]+$/.test(num);
26257				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
26258				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
26259				// Generate list of incremental numbers to display
26260				for (var i = divisions; i >= 1; i--) {
26261					// Preserve as int if input was int
26262					var newNum = parseInt(num / divisions * i);
26263					// Preserve float if input was float
26264					if (isFloat) {
26265						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
26266					}
26267					// Preserve commas if input had commas
26268					if (isComma) {
26269						while (/(\d+)(\d{3})/.test(newNum.toString())) {
26270							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
26271						}
26272					}
26273					nums.unshift(newNum);
26274				}
26275				nums.push(numReal);
26276				$this.data('counterup-nums', nums);
26277				$this.text('0');
26278				// Updates the number until we're done
26279				var f = function() {
26280					if ($this.data('counterup-nums') != null) {
26281						$this.text($this.data('counterup-nums').shift());
26282						if ($this.data('counterup-nums').length) {
26283							setTimeout($this.data('counterup-func'), $settings.delay);
26284						} else {
26285							delete $this.data('counterup-nums');
26286							$this.data('counterup-nums', null);
26287							$this.data('counterup-func', null);
26288						}
26289					}
26290				};
26291				$this.data('counterup-func', f);
26292				// Start the count up
26293				setTimeout($this.data('counterup-func'), $settings.delay);
26294			};
26295			// Perform counts when the element gets into view
26296			new Waypoint({
26297				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26298				element: this,
26299				handler: function() {
26300					counterUpper();
26301					if (!UNCODE.isUnmodalOpen) {
26302						this.destroy();
26303					}
26304				},
26305				offset: '100%'
26306			});
26307		});
26308	};
26309})(jQuery);
26310
26311/*!
26312 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
26313 * Copyright (c) 2016 Edson Hilios
26314 *
26315 * Permission is hereby granted, free of charge, to any person obtaining a copy of
26316 * this software and associated documentation files (the "Software"), to deal in
26317 * the Software without restriction, including without limitation the rights to
26318 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
26319 * the Software, and to permit persons to whom the Software is furnished to do so,
26320 * subject to the following conditions:
26321 *
26322 * The above copyright notice and this permission notice shall be included in all
26323 * copies or substantial portions of the Software.
26324 *
26325 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26326 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26327 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26328 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26329 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26330 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26331 */
26332(function(factory) {
26333	"use strict";
26334	if (typeof define === "function" && define.amd) {
26335		define([ "jquery" ], factory);
26336	} else {
26337		factory(jQuery);
26338	}
26339})(function($) {
26340	"use strict";
26341	var instances = [], matchers = [], defaultOptions = {
26342		precision: 100,
26343		elapse: false,
26344		defer: false
26345	};
26346	matchers.push(/^[0-9]*$/.source);
26347	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26348	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26349	matchers = new RegExp(matchers.join("|"));
26350	function parseDateString(dateString) {
26351		if (dateString instanceof Date) {
26352			return dateString;
26353		}
26354		if (String(dateString).match(matchers)) {
26355			if (String(dateString).match(/^[0-9]*$/)) {
26356				dateString = Number(dateString);
26357			}
26358			if (String(dateString).match(/\-/)) {
26359				dateString = String(dateString).replace(/\-/g, "/");
26360			}
26361			return new Date(dateString);
26362		} else {
26363			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
26364		}
26365	}
26366	var DIRECTIVE_KEY_MAP = {
26367		Y: "years",
26368		m: "months",
26369		n: "daysToMonth",
26370		d: "daysToWeek",
26371		w: "weeks",
26372		W: "weeksToMonth",
26373		H: "hours",
26374		M: "minutes",
26375		S: "seconds",
26376		D: "totalDays",
26377		I: "totalHours",
26378		N: "totalMinutes",
26379		T: "totalSeconds"
26380	};
26381	function escapedRegExp(str) {
26382		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
26383		return new RegExp(sanitize);
26384	}
26385	function strftime(offsetObject) {
26386		return function(format) {
26387			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
26388			if (directives) {
26389				for (var i = 0, len = directives.length; i < len; ++i) {
26390					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
26391					directive = directive[2];
26392					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
26393						value = DIRECTIVE_KEY_MAP[directive];
26394						value = Number(offsetObject[value]);
26395					}
26396					if (value !== null) {
26397						if (modifier === "!") {
26398							value = pluralize(plural, value);
26399						}
26400						if (modifier === "") {
26401							if (value < 10) {
26402								value = "0" + value.toString();
26403							}
26404						}
26405						format = format.replace(regexp, value.toString());
26406					}
26407				}
26408			}
26409			format = format.replace(/%%/, "%");
26410			return format;
26411		};
26412	}
26413	function pluralize(format, count) {
26414		var plural = "s", singular = "";
26415		if (format) {
26416			format = format.rep
vendor: 8,618 bytes, lines 26416-26560
26416lace(/(:|;|\s)/gi, "").split(/\,/);
26417			if (format.length === 1) {
26418				plural = format[0];
26419			} else {
26420				singular = format[0];
26421				plural = format[1];
26422			}
26423		}
26424		if (Math.abs(count) > 1) {
26425			return plural;
26426		} else {
26427			return singular;
26428		}
26429	}
26430	var Countdown = function(el, finalDate, options) {
26431		this.el = el;
26432		this.$el = $(el);
26433		this.interval = null;
26434		this.offset = {};
26435		this.options = $.extend({}, defaultOptions);
26436		this.instanceNumber = instances.length;
26437		instances.push(this);
26438		this.$el.data("countdown-instance", this.instanceNumber);
26439		if (options) {
26440			if (typeof options === "function") {
26441				this.$el.on("update.countdown", options);
26442				this.$el.on("stoped.countdown", options);
26443				this.$el.on("finish.countdown", options);
26444			} else {
26445				this.options = $.extend({}, defaultOptions, options);
26446			}
26447		}
26448		this.setFinalDate(finalDate);
26449		if (this.options.defer === false) {
26450			this.start();
26451		}
26452	};
26453	$.extend(Countdown.prototype, {
26454		start: function() {
26455			if (this.interval !== null) {
26456				clearInterval(this.interval);
26457			}
26458			var self = this;
26459			this.update();
26460			this.interval = setInterval(function() {
26461				self.update.call(self);
26462			}, this.options.precision);
26463		},
26464		stop: function() {
26465			clearInterval(this.interval);
26466			this.interval = null;
26467			this.dispatchEvent("stoped");
26468		},
26469		toggle: function() {
26470			if (this.interval) {
26471				this.stop();
26472			} else {
26473				this.start();
26474			}
26475		},
26476		pause: function() {
26477			this.stop();
26478		},
26479		resume: function() {
26480			this.start();
26481		},
26482		remove: function() {
26483			this.stop.call(this);
26484			instances[this.instanceNumber] = null;
26485			delete this.$el.data().countdownInstance;
26486		},
26487		setFinalDate: function(value) {
26488			this.finalDate = parseDateString(value);
26489		},
26490		update: function() {
26491			if (this.$el.closest("html").length === 0) {
26492				this.remove();
26493				return;
26494			}
26495			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
26496			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
26497			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
26498			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
26499			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
26500				return;
26501			} else {
26502				this.totalSecsLeft = newTotalSecsLeft;
26503			}
26504			this.elapsed = now >= this.finalDate;
26505			this.offset = {
26506				seconds: this.totalSecsLeft % 60,
26507				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
26508				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
26509				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26510				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26511				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
26512				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
26513				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
26514				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
26515				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
26516				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
26517				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
26518				totalMinutes: Math.floor(this.totalSecsLeft / 60),
26519				totalSeconds: this.totalSecsLeft
26520			};
26521			if (!this.options.elapse && this.totalSecsLeft === 0) {
26522				this.stop();
26523				this.dispatchEvent("finish");
26524			} else {
26525				this.dispatchEvent("update");
26526			}
26527		},
26528		dispatchEvent: function(eventName) {
26529			var event = $.Event(eventName + ".countdown");
26530			event.finalDate = this.finalDate;
26531			event.elapsed = this.elapsed;
26532			event.offset = $.extend({}, this.offset);
26533			event.strftime = strftime(this.offset);
26534			this.$el.trigger(event);
26535		}
26536	});
26537	$.fn.countdown = function() {
26538		var argumentsArray = Array.prototype.slice.call(arguments, 0);
26539		return this.each(function() {
26540			var instanceNumber = $(this).data("countdown-instance");
26541			if (instanceNumber !== undefined) {
26542				var instance = instances[instanceNumber], method = argumentsArray[0];
26543				if (Countdown.prototype.hasOwnProperty(method)) {
26544					instance[method].apply(instance, argumentsArray.slice(1));
26545				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
26546					instance.setFinalDate.call(instance, method);
26547					instance.start();
26548				} else {
26549					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
26550				}
26551			} else {
26552				new Countdown(this, argumentsArray[0], argumentsArray[1]);
26553			}
26554		});
26555	};
26556});
26557
26558!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;
26559function getStyles(config){
26560  // 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;
26560left: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+"}"
26561};
26562  var ShareUtils;
26563
26564if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
26565  Object.defineProperty(HTMLElement.prototype, "classList", {
26566    get: function() {
26567      var ret, self, update;
26568      update = function(fn) {
26569        return function(value) {
26570          var classes, index;
26571          classes = self.className.split(/\s+/);
26572          index = classes.indexOf(value);
26573          fn(classes, index, value);
26574          self.className = classes.join(" ");
26575        };
26576      };
26577      self = this;
26578      ret = {
26579        add: update(function(classes, index, value) {
26580          ~index || classes.push(value);
26581        }),
26582        remove: update(function(classes, index) {
26583          ~index && classes.splice(index, 1);
26584        }),
26585        toggle: update(function(classes, index, value) {
26586          if (~index) {
26587            classes.splice(index, 1);
26588          } else {
26589            classes.push(value);
26590          }
26591        }),
26592        contains: function(value) {
26593          return !!~self.className.split(/\s+/).indexOf(value);
26594        },
26595        item: function(i) {
26596          return self.className.split(/\s+/)[i] || null;
26597        }
26598      };
26599      Object.defineProperty(ret, "length", {
26600        get: function() {
26601          return self.className.split(/\s+/).length;
26602        }
26603      });
26604      return ret;
26605    }
26606  });
26607}
26608
26609String.prototype.to_rfc3986 = function() {
26610  var tmp;
26611  tmp = encodeURIComponent(this);
26612  return tmp.replace(/[!'()*]/g, function(c) {
26613    return "%" + c.charCodeAt(0).toString(16);
26614  });
26615};
26616
26617ShareUtils = (function() {
26618  function ShareUtils() {}
26619
26620  ShareUtils.prototype.extend = function(to, from, overwrite) {
26621    var hasProp, prop;
26622    for (prop in from) {
26623      hasProp = to[prop] !== undefined;
26624      if (hasProp && typeof from[prop] === "object") {
26625        this.extend(to[prop], from[prop], overwrite);
26626      } else {
26627        if (overwrite || !hasProp) {
26628          to[prop] = from[prop];
26629        }
26630      }
26631    }
26632  };
26633
26634  ShareUtils.prototype.hide = function(el) {
26635    return el.style.display = "none";
26636  };
26637
26638  ShareUtils.prototype.show = function(el) {
26639    return el.style.display = "block";
26640  };
26641
26642  ShareUtils.prototype.has_class = function(el, class_name) {
26643    return el.classList.contains(class_name);
26644  };
26645
26646  ShareUtils.prototype.add_class = function(el, class_name) {
26647    return el.classList.add(class_name);
26648  };
26649
26650  ShareUtils.prototype.remove_class = function(el, class_name) {
26651    return el.classList.remove(class_name);
26652  };
26653
26654  ShareUtils.prototype.is_encoded = function(str) {
26655    str = str.to_rfc3986();
26656    return decodeURIComponent(str) !== str;
26657  };
26658
26659  ShareUtils.prototype.encode = function(str) {
26660    if (typeof str === "undefined" || this.is_encoded(str)) {
26661      return str;
26662    } else {
26663      return str.to_rfc3986();
26664    }
26665  };
26666
26667  ShareUtils.prototype.popup = function(url, params) {
26668    var k, popup, qs, v;
26669    if (params == null) {
26670      params = {};
26671    }
26672    popup = {
26673      width: 500,
26674      height: 350
26675    };
26676    popup.top = (screen.height / 2) - (popup.height / 2);
26677    popup.left = (screen.width / 2) - (popup.width / 2);
26678    qs = ((function() {
26679      var _results;
26680      _results = [];
26681      for (k in params) {
26682        v = params[k];
26683        _results.push("" + k + "=" + (this.encode(v)));
26684      }
26685      return _results;
26686    }).call(this)).join('&');
26687    if (qs) {
26688      qs = "?" + qs;
26689    }
26690    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=" 
26690+ popup.width + ",height=" + popup.height);
26691  };
26692
26693  return ShareUtils;
26694
26695})();
26696var Share,
26697  __hasProp = {}.hasOwnProperty,
26698  __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; };
26699
26700Share = (function(_super) {
26701  __extends(Share, _super);
26702
26703  function Share(element, options) {
26704    this.element = element;
26705    this.el = {
26706      head: document.getElementsByTagName('head')[0],
26707      body: document.getElementsByTagName('body')[0]
26708    };
26709    this.config = {
26710      enabled_networks: 0,
26711      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
26712      url: window.location.href.replace("&", "%26"),
26713      caption: null,
26714      title: this.default_title(),
26715      image: this.default_image(),
26716      description: this.default_description(),
26717      ui: {
26718        flyout: 'top center',
26719        button_text: 'Share',
26720        button_font: true,
26721        icon_font: true
26722      },
26723      networks: {
26724        twitter: {
26725          enabled: true,
26726          url: null,
26727          title: null,
26728          description: null
26729        },
26730        facebook: {
26731          enabled: true,
26732          load_sdk: true,
26733          url: null,
26734          app_id: null,
26735          title: null,
26736          caption: null,
26737          description: null,
26738          image: null
26739        },
26740        pinterest: {
26741          enabled: true,
26742          url: null,
26743          image: null,
26744          description: null
26745        },
26746        reddit: {
26747          enabled: true,
26748          url: null,
26749          title: null
26750        },
26751        linkedin: {
26752          enabled: true,
26753          url: null,
26754          title: null,
26755          description: null
26756        },
26757        xing: {
26758          enabled: true,
26759          url: null,
26760          title: null,
26761          image: null,
26762          description: null
26763        },
26764        whatsapp: {
26765          enabled: true,
26766          description: null,
26767          url: null
26768        },
26769        email: {
26770          enabled: true,
26771          title: null,
26772          description: null,
26773          url: null
26774        }
26775      }
26776    };
26777    this.setup(element, options);
26778    return this;
26779  }
26780
26781  Share.prototype.setup = function(element, opts) {
26782    var index, instance, instances, _i, _len;
26783    instances = document.querySelectorAll(element);
26784    this.extend(this.config, opts, true);
26785    this.set_global_configuration();
26786    this.normalize_network_configuration();
26787    if (this.config.ui.icon_font) {
26788      this.inject_icons();
26789    }
26790    if (this.config.ui.button_font) {
26791      this.inject_fonts();
26792    }
26793    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
26794      this.inject_facebook_sdk();
26795    }
26796    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
26797      instance = instances[index];
26798      this.setup_instance(element, index);
26799    }
26800  };
26801
26802  Share.prototype.setup_instance = function(element, index) {
26803    var button, instance, label, network, networks, _i, _len, _results,
26804      _this = this;
26805    instance = document.querySelectorAll(element)[index];
26806    this.hide(instance);
26807    this.add_class(instance, "sharer-" + index);
26808    instance = document.querySelectorAll(element)[index];
26809    this.inject_css(instance);
26810    this.inject_html(instance);
26811    this.show(instance);
26812    label = instance.getElementsByTagName("label")[0];
26813    button = instance.getElementsByClassName("social")[0];
26814    networks = instance.getElementsByTagName('li');
26815    this.add_class(button, "networks-" + this.config.enabled_networks);
26816    label.addEventListener("click", function() {
26817      return _this.event_toggle(button);
26818    });
26819    _this = this;
26820    _results = [];
26821    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
26822      network = networks[index];
26823      _results.push(network.addEventListener("click", function() {
26824        _this.event_network(instance, this);
26825        return _this.event_close(button);
26826      }));
26827    }
26828    return _results;
26829  };
26830
26831  Share.prototype.event_toggle = function(button) {
26832    if (this.has_class(button, "active")) {
26833      return this.event_close(button);
26834    } else {
26835      return this.event_open(button);
26836    }
26837  };
26838
26839  Share.prototype.event_open = function(button) {
26840    if (this.has_class(button, "load")) {
26841      this.remove_class(button, "load");
26842    }
26843    return this.add_class(button, "active");
26844  };
26845
26846  Share.prototype.event_close = function(button) {
26847    return this.remove_class(button, "active");
26848  };
26849
26850  Share.prototype.event_network = function(instance, network) {
26851    var name;
26852    name = network.getAttribute("data-network");
26853    this.hook("before", name, instance);
26854    this["network_" + name]();
26855    return this.hook("after", name, instance);
26856  };
26857
26858  Share.prototype.open = function() {
26859    return this["public"]("open");
26860  };
26861
26862  Share.prototype.close = function() {
26863    return this["public"]("close");
26864  };
26865
26866  Share.prototype.toggle = function() {
26867    return this["public"]("toggle");
26868  };
26869
26870  Share.prototype["public"] = function(action) {
26871    var button, index, instance, _i, _len, _ref, _results;
26872    _ref = document.querySelectorAll(this.element);
26873    _results = [];
26874    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26875      instance = _ref[index];
26876      button = instance.getElementsByClassName("social")[0];
26877      _results.push(this["event_" + action](button));
26878    }
26879    return _results;
26880  };
26881
26882  Share.prototype.network_facebook = function() {
26883    if (this.config.networks.facebook.load_sdk) {
26884      if (!window.FB) {
26885        return console.error("The Facebook JS SDK hasn't loaded yet.");
26886      }
26887      return FB.ui({
26888        method: 'feed',
26889        name: this.config.networks.facebook.title,
26890        link: this.config.networks.facebook.url,
26891        picture: this.config.networks.facebook.image,
26892        caption: this.config.networks.facebook.caption,
26893        description: this.config.networks.facebook.description
26894      });
26895    } else {
26896      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26897        u: this.config.networks.facebook.url
26898      });
26899    }
26900  };
26901
26902  Share.prototype.network_twitter = function() {
26903    return this.popup('https://twitter.com/intent/tweet', {
26904      text: this.config.networks.twitter.title,
26905      url: this.config.networks.twitter.url
26906    });
26907  };
26908
26909  Share.prototype.network_pinterest = function() {
26910    return this.popup('https://www.pinterest.com/pin/create/button', {
26911      url: this.config.networks.pinterest.url,
26912      media: this.config.networks.pinterest.image,
26913      description: this.config.networks.pinterest.description
26914    });
26915  };
26916
26917  Share.prototype.network_linkedin = function() {
26918    return this.popup('https://www.linkedin.com/shareArticle', {
26919      url: this.config.networks.linkedin.url,
26920      title: this.config.networks.linkedin.title,
26921      summary: this.config.networks.linkedin.description
26922    });
26923  }
26924
26925  Share.prototype.network_xing = function() {
26926    return this.popup('https://www.xing.com/spi/shares/new', {
26927      url: this.config.networks.xing.url,
26928      image: this.config.networks.xing.image,
26929      title: this.config.networks.xing.title,
26930      summary: this.config.networks.xing.description
26931    });
26932  }
26933
26934  Share.prototype.network_email = function() {
26935    return this.popup('mailto:', {
26936      subject: this.config.networks.email.title,
26937      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26938    });
26939  };
26940
26941  Share.prototype.inject_icons = function() {
26942  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
26943  };
26944
26945  Share.prototype.inject_fonts = function() {
26946   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
26947  };
26948
26949  Share.prototype.inject_stylesheet = function(url) {
26950    var link;
26951    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
26952      link = document.createElement("link");
26953      link.setAttribute("rel", "stylesheet");
26954      link.setAttribute("href", url);
26955      return this.el.head.appendChild(link);
26956    }
26957  };
26958
26959  Share.prototype.inject_css = function(instance) {
26960    var css, meta, selector, style;
26961    selector = "." + (instance.getAttribute('class').split(" ").join("."));
26962    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
26963      this.config.selector = selector;
26964      css = getStyles(this.config);
26965      style = document.createElement("style");
26966      style.type = "text/css";
26967      if (style.styleSheet) {
26968        style.styleSheet.cssText = css;
26969      } else {
26970        style.appendChild(document.createTextNode(css));
26971      }
26972      this.el.head.appendChild(style);
26973      delete this.config.selector;
26974      meta = document.createElement("meta");
26975      meta.setAttribute("name", "sharer" + selector);
26976      return this.el.head.appendChild(meta);
26977    }
26978  };
26979
26980  Share.prototype.inject_html = function(instance) {
26981    //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>";
26982    return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
26983  };
26984
26985  Share.prototype.inject_facebook_sdk = function() {
26986    var fb_root, script;
26987    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
26988      script = document.createElement("script");
26989      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')";
26990      fb_root = document.createElement("div");
26991      fb_root.id = "fb-root";
26992      this.el.body.appendChild(fb_root);
26993      return this.el.body.appendChild(script);
26994    }
26995  };
26996
26997  Share.prototype.hook = function(type, network, instance) {
26998    var fn, opts;
26999    fn = this.config.networks[network][type];
27000    if (typeof fn === "function") {
27001      opts = fn.call(this.config.networks[network], instance);
27002      if (opts !== void 0) {
27003        opts = this.normalize_filter_config_updates(opts);
27004        this.extend(this.config.networks[network], opts, true);
27005        this.normalize_network_configuration();
27006      }
27007    }
27008  };
27009
27010  Share.prototype.default_title = function() {
27011    var content;
27012    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27013      return encodeURIComponent(content.getAttribute('content'));
27014    } else if (content = document.querySelector('title')) {
27015      return encodeURIComponent(content.innerText);
27016    }
27017  };
27018
27019  Share.prototype.default_image = function() {
27020    var content;
27021    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27022      return content.getAttribute('content');
27023    }
27024  };
27025
27026  Share.prototype.default_description = function() {
27027    var content;
27028    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27029      return encodeURIComponent(content.getAttribute('content'));
27030    } else {
27031      return '';
27032    }
27033  };
27034
27035  Share.prototype.set_global_configuration = function() {
27036    var display, network, option, options, _ref, _results;
27037    _ref = this.config.networks;
27038    _results = [];
27039    for (network in _ref) {
27040      options = _ref[network];
27041      for (option in options) {
27042        if (this.config.networks[network][option] == null) {
27043          this.config.networks[network][option] = this.config[option];
27044        }
27045      }
27046      if (this.config.networks[network].enabled) {
27047        display = 'block';
27048        this.config.enabled_networks += 1;
27049      } else {
27050        display = 'none';
27051      }
27052      _results.push(this.config.networks[network].display = display);
27053    }
27054    return _results;
27055  };
27056
27057  Share.prototype.normalize_network_configuration = function() {
27058    if (!this.config.networks.facebook.app_id) {
27059      this.config.networks.facebook.load_sdk = false;
27060    }
27061    if (!this.is_encoded(this.config.networks.twitter.description)) {
27062      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
27063    }
27064    if (typeof this.config.networks.facebook.app_id === 'number') {
27065      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
27066    }
27067  };
27068
27069  Share.prototype.normalize_filter_config_updates = function(opts) {
27070    if (this.config.networks.facebook.app_id !== opts.app_id) {
27071      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.");
27072      delete opts.app_id;
27073    }
27074    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
27075      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.");
27076      delete opts.app_id;
27077    }
27078    return opts;
27079  };
27080
27081  return Share;
27082
27083})(ShareUtils);
27084 return Share;
27085});
27086
27087// Generated by CoffeeScript 1.9.2
27088
27089// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
27090
27091(function() {
27092  var $, win;
27093
27094  $ = this.jQuery || window.jQuery;
27095
27096  win = $(window);
27097
27098  $.fn.stick_in_parent = function(opts) {
27099    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
27100    if (opts == null) {
27101      opts = {};
27102    }
27103    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;
27104    if (offset_top == null) {
27105      offset_top = 0;
27106    }
27107    if (parent_selector == null) {
27108      parent_selector = void 0;
27109    }
27110    if (inner_scrolling == null) {
27111      inner_scrolling = true;
27112    }
27113    if (sticky_class == null) {
27114      sticky_class = "is_stuck";
27115    }
27116    doc = $(document);
27117    if (enable_bottoming == null) {
27118      enable_bottoming = true;
27119    }
27120    outer_width = function(el) {
27121      var _el, computed, w;
27122      if (window.getComputedStyle) {
27123        _el = el[0];
27124        computed = window.getComputedStyle(el[0]);
27125        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
27126        if (computed.getPropertyValue("box-sizing") !== "border-box") {
27127          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
27128        }
27129        return w;
27130      } else {
27131        return el.outerWidth(true);
27132      }
27133    };
27134    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
27135      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
27136      if (elm.data("sticky_kit")) {
27137        return;
27138      }
27139      elm.data("sticky_kit", true);
27140      last_scroll_height = doc.height();
27141      parent = elm.parent();
27142      if (parent_selector != null) {
27143        parent = parent.closest(parent_selector);
27144      }
27145      if (!parent.length) {
27146        throw "failed to find stick parent";
27147      }
27148      fixed = false;
27149      bottomed = false;
27150      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
27151      if (spacer) {
27152        spacer.css('position', elm.css('position'));
27153      }
27154      recalc = function() {
27155        var border_top, padding_top, restore;
27156        if (detached) {
27157          return;
27158        }
27159        last_scroll_height = doc.height();
27160        border_top = parseInt(parent.css("border-top-width"), 10);
27161        padding_top = parseInt(parent.css("padding-top"), 10);
27162        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
27163        parent_top = parent.offset().top + border_top + padding_top;
27164        parent_height = parent.height();
27165        if (fixed) {
27166          fixed = false;
vendor: 6,068 bytes, lines 27167-27361
27167          bottomed = false;
27168          if (manual_spacer == null) {
27169            elm.insertAfter(spacer);
27170            spacer.detach();
27171          }
27172          elm.css({
27173            position: "",
27174            top: "",
27175            width: "",
27176            bottom: ""
27177          }).removeClass(sticky_class);
27178          restore = true;
27179        }
27180        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
27181        height = elm.outerHeight(true);
27182        el_float = elm.css("float");
27183        if (spacer) {
27184          spacer.css({
27185            width: outer_width(elm),
27186            height: height,
27187            display: elm.css("display"),
27188            "vertical-align": elm.css("vertical-align"),
27189            "float": el_float
27190          });
27191        }
27192        if (restore) {
27193          return tick();
27194        }
27195      };
27196      recalc();
27197      if (height === parent_height) {
27198        return;
27199      }
27200      last_pos = void 0;
27201      offset = offset_top;
27202      recalc_counter = recalc_every;
27203      tick = function() {
27204        var css, delta, recalced, scroll, will_bottom, win_height;
27205        if (detached) {
27206          return;
27207        }
27208        recalced = false;
27209        if (recalc_counter != null) {
27210          recalc_counter -= 1;
27211          if (recalc_counter <= 0) {
27212            recalc_counter = recalc_every;
27213            recalc();
27214            recalced = true;
27215          }
27216        }
27217        if (!recalced && doc.height() !== last_scroll_height) {
27218          recalc();
27219          recalced = true;
27220        }
27221        scroll = win.scrollTop();
27222        if (last_pos != null) {
27223          delta = scroll - last_pos;
27224        }
27225        last_pos = scroll;
27226        if (fixed) {
27227          if (enable_bottoming) {
27228            will_bottom = scroll + height + offset > parent_height + parent_top;
27229            if (bottomed && !will_bottom) {
27230              bottomed = false;
27231              elm.css({
27232                position: "fixed",
27233                bottom: "",
27234                top: offset
27235              }).trigger("sticky_kit:unbottom");
27236            }
27237          }
27238          if (scroll < top) {
27239            fixed = false;
27240            offset = offset_top;
27241            if (manual_spacer == null) {
27242              if (el_float === "left" || el_float === "right") {
27243                elm.insertAfter(spacer);
27244              }
27245              spacer.detach();
27246            }
27247            css = {
27248              position: "",
27249              width: "",
27250              top: ""
27251            };
27252            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
27253          }
27254          if (inner_scrolling) {
27255            win_height = win.height();
27256            if (height + offset_top > win_height) {
27257              if (!bottomed) {
27258                offset -= delta;
27259                offset = Math.max(win_height - height, offset);
27260                offset = Math.min(offset_top, offset);
27261                if (fixed) {
27262                  elm.css({
27263                    top: offset + "px"
27264                  });
27265                }
27266              }
27267            }
27268          }
27269        } else {
27270          if (scroll > top) {
27271            fixed = true;
27272            css = {
27273              position: "fixed",
27274              top: offset
27275            };
27276            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
27277            elm.css(css).addClass(sticky_class);
27278            if (manual_spacer == null) {
27279              elm.after(spacer);
27280              if (el_float === "left" || el_float === "right") {
27281                spacer.append(elm);
27282              }
27283            }
27284            elm.trigger("sticky_kit:stick");
27285          }
27286        }
27287        if (fixed && enable_bottoming) {
27288          if (will_bottom == null) {
27289            will_bottom = scroll + height + offset > parent_height + parent_top;
27290          }
27291          if (!bottomed && will_bottom) {
27292            bottomed = true;
27293            if (parent.css("position") === "static") {
27294              parent.css({
27295                position: "relative"
27296              });
27297            }
27298            return elm.css({
27299              position: "absolute",
27300              bottom: padding_bottom,
27301              top: "auto"
27302            }).trigger("sticky_kit:bottom");
27303          }
27304        }
27305      };
27306      recalc_and_tick = function() {
27307        recalc();
27308        return tick();
27309      };
27310      detach = function() {
27311        detached = true;
27312        win.off("touchmove", tick);
27313        win.off("scroll", tick);
27314        win.off("resize", recalc_and_tick);
27315        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
27316        elm.off("sticky_kit:detach", detach);
27317        elm.removeData("sticky_kit");
27318        elm.css({
27319          position: "",
27320          bottom: "",
27321          top: "",
27322          width: ""
27323        });
27324        parent.position("position", "");
27325        if (fixed) {
27326          if (manual_spacer == null) {
27327            if (el_float === "left" || el_float === "right") {
27328              elm.insertAfter(spacer);
27329            }
27330            spacer.remove();
27331          }
27332          return elm.removeClass(sticky_class);
27333        }
27334      };
27335      win.on("touchmove", tick);
27336      win.on("scroll", tick);
27337      win.on("resize", recalc_and_tick);
27338      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
27339      elm.on("sticky_kit:detach", detach);
27340      return setTimeout(tick, 0);
27341    };
27342    for (i = 0, len = this.length; i < len; i++) {
27343      elm = this[i];
27344      fn($(elm));
27345    }
27346    return this;
27347  };
27348
27349}).call(this);
27350/* ==========================================================================
27351 * bootstrap-tab-history.js
27352 * Author: Michael Narayan <[email protected]>
27353 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
27354 * ==========================================================================
27355 * Licensed under the Apache License, Version 2.0 (the "License"); you may
27356 * not use this file except in compliance with the License. You may obtain a
27357 * copy of the License at
27358 *
27359 * http://www.apache.org/licenses/LICENSE-2.0
27360 *
27361 * Unless required by applicable law or agreed to in writing, softw
27361are
27362 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
27363 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
27364 * License for the specific language governing permissions and limitations
27365 * under the License.
27366 * ========================================================================== */
27367
27368/* ========================================================================== */
27369/* JSHint directives                                                          */
27370/*                                                                            */
27371/* global BootstrapTabHistory: true                                           */
27372/*                                                                            */
27373/* global document                                                            */
27374/* global jQuery                                                              */
27375/* global history                                                             */
27376/* global window                                                              */
27377/* ========================================================================== */
27378
27379/**
27380 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
27381 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
27382 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
27383 *
27384 * See the README for additional information.
27385 *
27386 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
27387 */
27388
27389BootstrapTabHistory = {
27390  options: {
27391    /**
27392     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
27393     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
27394     *
27395     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
27396     *
27397     * @public
27398     * @type {?number}
27399     */
27400    defaultAnchorYOffset: 0,
27401    /**
27402     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
27403     *
27404     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
27405     *
27406     * @public
27407     * @type {string}
27408     */
27409    defaultChanger: 'replace',
27410    /**
27411     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
27412     * `null` is passed as the third parameter to these calls.
27413     *
27414     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
27415     *
27416     * @public
27417     * @type {boolean}
27418     */
27419    defaultUpdateURL: false,
27420    /**
27421     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
27422     * load.
27423     *
27424     * @public
27425     * @type {boolean}
27426     */
27427    showTabsBasedOnAnchor: true
27428  }
27429};
27430
27431(function () {
27432  'use strict';
27433
27434  jQuery(function () {
27435    if(history && history.pushState && history.replaceState) {
27436      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27437
27438      if(bootstrapTabHistory) {
27439        showTabsBasedOnState(bootstrapTabHistory);
27440      } else {
27441        showTabsBasedOnAnchor();
27442      }
27443
27444      backfillHistoryState();
27445
27446      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
27447      jQuery(window).on('popstate', onPopState);
27448    } else {
27449      showTabsBasedOnAnchor();
27450    }
27451  });
27452
27453  /**
27454   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
27455   *
27456   * @type {boolean}
27457   */
27458  var showingTabsBasedOnState = false;
27459
27460  /**
27461   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
27462   * `history.back` handling when `data-tab-history-update-url` is true.
27463   */
27464  function backfillHistoryState() {
27465    var newState = null;
27466
27467    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
27468      var $activeTabElement = jQuery(this);
27469      var selector = getTabSelector($activeTabElement);
27470
27471      if(selector) {
27472        var tabGroup = getTabGroup($activeTabElement);
27473
27474        if(tabGroup) {
27475          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
27476        }
27477      }
27478    });
27479
27480    if(newState) {
27481      history.replaceState(newState, '', null);
27482    }
27483  }
27484
27485  /**
27486   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
27487   * said bootstrapTabHistory attribute.
27488   *
27489   * @param {?object} existingState
27490   * @param {!string} tabGroup
27491   * @param {!string} selector
27492   * @returns {!object}
27493   */
27494  function createNewHistoryState(existingState, tabGroup, selector) {
27495    // Clone history.state and ensure it has a bootstrapTabHistory entry.
27496    var newState = jQuery.extend(true, {}, existingState, {
27497      bootstrapTabHistory: {}
27498    });
27499
27500    newState.bootstrapTabHistory[tabGroup] = selector;
27501
27502    return newState;
27503  }
27504
27505  /**
27506   * @param {jQuery} $tab
27507   * @returns {?string}
27508   */
27509  function getTabGroup($tab) {
27510    return parseTruthyAttributeValue($tab.data('tab-history'));
27511  }
27512
27513  /**
27514   * @param {jQuery} $tab
27515   * @returns {?string}
27516   */
27517  function getTabSelector($tab) {
27518    return $tab.data('target') || $tab.attr('href');
27519  }
27520
27521  /**
27522   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
27523   *
27524   * @param {jQuery.Event} shownEvt
27525   */
27526  function onShownTab(shownEvt) {
27527    if(!showingTabsBasedOnState) {
27528      var $activatedTab = jQuery(shownEvt.target);
27529      if ( $activatedTab.hasClass('panel-collapse') )
27530        $activatedTab = $activatedTab.closest('.panel').find('a');
27531      var selector = getTabSelector($activatedTab);
27532
27533      if(selector) {
27534        var tabGroup = getTabGroup($activatedTab);
27535
27536        if(tabGroup) {
27537          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
27538          var newState = createNewHistoryState(history.state, tabGroup, selector);
27539          var updateURL = (function ($activatedTab) {
27540            if(selector[0] === '#') {
27541              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
27542
27543              if(elementUpdateURLOption === undefined) {
27544                return BootstrapTabHistory.options.defaultUpdateURL;
27545              } else {
27546                return elementUpdateURLOption;
27547              }
27548            } else {
27549              return false;
27550            }
27551          })($activatedTab);
27552
27553          switch(historyChanger) {
27554            case 'push':
27555              history.pushState(newState, '', updateURL ? selector : null);
27556              break;
27557            case 'replace':
27558              history.replaceState(newState, '', updateURL ? selector : null);
27559              break;
27560            default:
27561              throw new Error('Unknown tab-history-changer: ' + historyChanger);
27562          }
27563        }
27564      }
27565    }
27566  }
27567
27568  /**
27569   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
27570   */
27571  function onPopState() {
27572    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27573
27574    if(bootstrapTabHistory) {
27575      showTabsBasedOnState(bootstrapTabHistory);
27576    }
27577  }
27578
27579  /**
27580   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
27581   *
27582   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
27583   *
27584   * @param {*} value
27585   * @returns {*}
27586   */
27587  function parseTruthyAttributeValue(value) {
27588    if(value) {
27589      return value;
27590    } else if(value === '') {
27591      return true;
27592    } else {
27593      return value;
27594    }
27595  }
27596
27597  /**
27598   * Show tabs based upon the anchor component of `window.location`.
27599   */
27600  function showTabsBasedOnAnchor() {
27601    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
27602      var anchor = window.location && window.location.hash;
27603
27604      if(anchor) {
27605        var $tabElement = showTabForSelector(anchor);
27606
27607        if($tabElement && window.addEventListener && window.removeEventListener) {
27608          var anchorYOffset = (function ($tabElement) {
27609            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
27610
27611            if(elementSetting === undefined) {
27612              return BootstrapTabHistory.options.defaultAnchorYOffset;
27613            } else {
27614              return elementSetting;
27615            }
27616          })($tabElement);
27617
27618          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
27619          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
27620          //   `history.state` object should have been used (unless the browser did not support the modern History API).
27621          if(anchorYOffset || anchorYOffset === 0) {
27622            var scrollListener = function resetAnchorScroll () {
27623              window.removeEventListener('scroll', scrollListener);
27624              window.scrollTo(0, anchorYOffset);
27625            };
27626
27627            window.addEventListener('scroll', scrollListener);
27628          }
27629        }
27630      }
27631    }
27632  }
27633
27634  /**
27635   * Show a tab which corresponds to the provided selector.
27636   *
27637   * @param {string} selector - A CSS selector.
27638   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
27639   */
27640  function showTabForSelector(selector) {
27641    var $tabElement = (function (selector) {
27642      var $ret = null;
27643
27644      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
27645        var $potentialTab = jQuery(this);
27646
27647        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
27648          $ret = $potentialTab;
27649          return false;
vendor: 43,483 bytes, lines 27650-28866
27650        } else {
27651         return null;
27652        }
27653      });
27654
27655      return $ret;
27656    })(selector);
27657
27658    if($tabElement) {
27659      if ( !$tabElement.parent().hasClass('active') ) {
27660        $tabElement.trigger('click');
27661      }
27662      //$tabElement.tab('show');
27663    }
27664
27665    return $tabElement;
27666  }
27667
27668  /**
27669   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
27670   *
27671   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
27672   */
27673  function showTabsBasedOnState(bootstrapTabHistory) {
27674    showingTabsBasedOnState = true;
27675
27676    try {
27677      for(var k in bootstrapTabHistory) {
27678        if(bootstrapTabHistory.hasOwnProperty(k)) {
27679          showTabForSelector(bootstrapTabHistory[k]);
27680        }
27681      }
27682    } finally {
27683      showingTabsBasedOnState = false;
27684    }
27685  }
27686})();
27687
27688/*!
27689 * justifiedGallery - v3.8.1
27690 * http://miromannino.github.io/Justified-Gallery/
27691 * Copyright (c) 2020 Miro Mannino
27692 * Licensed under the MIT license.
27693 */
27694(function (factory) {
27695  if (typeof define === 'function' && define.amd) {
27696    // AMD. Register as an anonymous module.
27697    define(['jquery'], factory);
27698  } else if (typeof module === 'object' && module.exports) {
27699    // Node/CommonJS
27700    module.exports = function (root, jQuery) {
27701      if (jQuery === undefined) {
27702        // require('jQuery') returns a factory that requires window to
27703        // build a jQuery instance, we normalize how we use modules
27704        // that require this pattern but the window provided is a noop
27705        // if it's defined (how jquery works)
27706        if (typeof window !== 'undefined') {
27707          jQuery = require('jquery');
27708        }
27709        else {
27710          jQuery = require('jquery')(root);
27711        }
27712      }
27713      factory(jQuery);
27714      return jQuery;
27715    };
27716  } else {
27717    // Browser globals
27718    factory(jQuery);
27719  }
27720}(function ($) {
27721
27722  /**
27723   * Justified Gallery controller constructor
27724   *
27725   * @param $gallery the gallery to build
27726   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
27727   * @constructor
27728   */
27729  var JustifiedGallery = function ($gallery, settings) {
27730
27731    this.settings = settings;
27732    this.checkSettings();
27733
27734    this.imgAnalyzerTimeout = null;
27735    this.entries = null;
27736    this.buildingRow = {
27737      entriesBuff: [],
27738      width: 0,
27739      height: 0,
27740      aspectRatio: 0
27741    };
27742    this.lastFetchedEntry = null;
27743    this.lastAnalyzedIndex = -1;
27744    this.yield = {
27745      every: 2, // do a flush every n flushes (must be greater than 1)
27746      flushed: 0 // flushed rows without a yield
27747    };
27748    this.border = settings.border >= 0 ? settings.border : settings.margins;
27749    this.maxRowHeight = this.retrieveMaxRowHeight();
27750    this.suffixRanges = this.retrieveSuffixRanges();
27751    this.offY = this.border;
27752    this.rows = 0;
27753    this.spinner = {
27754      phase: 0,
27755      timeSlot: 150,
27756      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
27757      intervalId: null
27758    };
27759    this.scrollBarOn = false;
27760    this.checkWidthIntervalId = null;
27761    this.galleryWidth = $gallery.width();
27762    this.$gallery = $gallery;
27763
27764  };
27765
27766  /** @returns {String} the best suffix given the width and the height */
27767  JustifiedGallery.prototype.getSuffix = function (width, height) {
27768    var longestSide, i;
27769    longestSide = (width > height) ? width : height;
27770    for (i = 0; i < this.suffixRanges.length; i++) {
27771      if (longestSide <= this.suffixRanges[i]) {
27772        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27773      }
27774    }
27775    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27776  };
27777
27778  /**
27779   * Remove the suffix from the string
27780   *
27781   * @returns {string} a new string without the suffix
27782   */
27783  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27784    return str.substring(0, str.length - suffix.length);
27785  };
27786
27787  /**
27788   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27789   */
27790  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27791    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27792  };
27793
27794  /**
27795   * Get the used suffix of a particular url
27796   *
27797   * @param str
27798   * @returns {String} return the used suffix
27799   */
27800  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27801    for (var si in this.settings.sizeRangeSuffixes) {
27802      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27803        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27804        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27805      }
27806    }
27807    return '';
27808  };
27809
27810  /**
27811   * Given an image src, with the width and the height, returns the new image src with the
27812   * best suffix to show the best quality thumbnail.
27813   *
27814   * @returns {String} the suffix to use
27815   */
27816  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27817    var newImageSrc;
27818
27819    if (this.settings.thumbnailPath) {
27820      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27821    } else {
27822      var matchRes = imageSrc.match(this.settings.extension);
27823      var ext = (matchRes !== null) ? matchRes[0] : '';
27824      newImageSrc = imageSrc.replace(this.settings.extension, '');
27825      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27826      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27827    }
27828
27829    return newImageSrc;
27830  };
27831
27832  /**
27833   * Shows the images that is in the given entry
27834   *
27835   * @param $entry the entry
27836   * @param callback the callback that is called when the show animation is finished
27837   */
27838  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27839    if (this.settings.cssAnimation) {
27840      $entry.addClass('jg-entry-visible');
27841      if (callback) callback();
27842    } else {
27843      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27844      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27845    }
27846  };
27847
27848  /**
27849   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27850   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27851   *
27852   * @param $image the image to analyze
27853   * @returns {String} the extracted src
27854   */
27855  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27856    var imageSrc = $image.data('safe-src');
27857    var imageSrcLoc = 'data-safe-src';
27858    // Begin Uncode edit
27859    if (typeof imageSrc === 'undefined') {
27860    	var imageCurrentSrc = $image[0].currentSrc;
27861    	if (imageCurrentSrc) {
27862    		imageSrc = imageCurrentSrc;
27863    	} else {
27864    		imageSrc = $image.attr('src');
27865    	}
27866		imageSrcLoc = 'src';
27867    }
27868    // End Uncode edit
27869    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27870    $image.data('jg.src', imageSrc); // this will change overtime
27871    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27872    return imageSrc;
27873  };
27874
27875  /** @returns {jQuery} the image in the given entry */
27876  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27877    var $img = $entry.find(this.settings.imgSelector);
27878    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27879    return $img.length === 0 ? null : $img;
27880  };
27881
27882  /** @returns {jQuery} the caption in the given entry */
27883  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27884    var $caption = $entry.find('> .jg-caption');
27885    return $caption.length === 0 ? null : $caption;
27886  };
27887
27888  /**
27889   * Display the entry
27890   *
27891   * @param {jQuery} $entry the entry to display
27892   * @param {int} x the x position where the entry must be positioned
27893   * @param y the y position where the entry must be positioned
27894   * @param imgWidth the image width
27895   * @param imgHeight the image height
27896   * @param rowHeight the row height of the row that owns the entry
27897   */
27898  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27899    $entry.width(imgWidth);
27900    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27901    $entry.css('top', Math.floor(y));//hacked by Uncode
27902    $entry.css('left', x);
27903
27904    var $image = this.imgFromEntry($entry);
27905    if ($image !== null) {
27906      $image.css('width', imgWidth);
27907      $image.css('height', imgHeight);
27908      $image.css('margin-left', - imgWidth / 2);
27909      $image.css('margin-top', - imgHeight / 2);
27910
27911      // Image reloading for an high quality of thumbnails
27912      var imageSrc = $image.data('jg.src');
27913      if (imageSrc) {
27914        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27915
27916        $image.one('error', function () {
27917           this.resetImgSrc($image); //revert to the original thumbnail
27918        });
27919
27920        var loadNewImage = function () {
27921          // if (imageSrc !== newImageSrc) {
27922            $image.attr('src', imageSrc);
27923          // }
27924        };
27925
27926        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27927          this.onImageEvent(imageSrc, (function() {
27928            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27929            $entry.data('jg.loaded', true);
27930          }).bind(this));
27931        } else {
27932          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27933        }
27934
27935      }
27936
27937    } else {
27938      this.showImg($entry);
27939    }
27940
27941    this.displayEntryCaption($entry);
27942  };
27943
27944  /**
27945   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
27946   * or the 'title' attributes.
27947   *
27948   * @param {jQuery} $entry the entry to process
27949   */
27950  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
27951    var $image = this.imgFromEntry($entry);
27952    if ($image !== null && this.settings.captions) {
27953      var $imgCaption = this.captionFromEntry($entry);
27954
27955      // Create it if it doesn't exists
27956      if ($imgCaption === null) {
27957        var caption = $image.attr('alt');
27958        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
27959        if (this.isValidCaption(caption)) { // Create only we found something
27960          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
27961          $entry.append($imgCaption);
27962          $entry.data('jg.createdCaption', true);
27963        }
27964      }
27965
27966      // Create events (we check again the $imgCaption because it can be still inexistent)
27967      if ($imgCaption !== null) {
27968        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
27969        this.addCaptionEventsHandlers($entry);
27970      }
27971    } else {
27972      this.removeCaptionEventsHandlers($entry);
27973    }
27974  };
27975
27976  /**
27977   * Validates the caption
27978   *
27979   * @param caption The caption that should be validated
27980   * @return {boolean} Validation result
27981   */
27982  JustifiedGallery.prototype.isValidCaption = function (caption) {
27983    return (typeof caption !== 'undefined' && caption.length > 0);
27984  };
27985
27986  /**
27987   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
27988   * It shows the caption using jQuery (or using CSS if it is configured so)
27989   *
27990   * @param {Event} eventObject the event object
27991   */
27992  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
27993    var $caption = this.captionFromEntry($(eventObject.currentTarget));
27994    if (this.settings.cssAnimation) {
27995      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
27996    } else {
27997      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
27998        this.settings.captionSettings.visibleOpacity);
27999    }
28000  };
28001
28002  /**
28003   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28004   * It hides the caption using jQuery (or using CSS if it is configured so)
28005   *
28006   * @param {Event} eventObject the event object
28007   */
28008  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28009    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28010    if (this.settings.cssAnimation) {
28011      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28012    } else {
28013      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28014        this.settings.captionSettings.nonVisibleOpacity);
28015    }
28016  };
28017
28018  /**
28019   * Add the handlers of the entry for the caption
28020   *
28021   * @param $entry the entry to modify
28022   */
28023  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28024    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28025    if (typeof captionMouseEvents === 'undefined') {
28026      captionMouseEvents = {
28027        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28028        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28029      };
28030      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28031      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28032      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28033    }
28034  };
28035
28036  /**
28037   * Remove the handlers of the entry for the caption
28038   *
28039   * @param $entry the entry to modify
28040   */
28041  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28042    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28043    if (typeof captionMouseEvents !== 'undefined') {
28044      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28045      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28046      $entry.removeData('jg.captionMouseEvents');
28047    }
28048  };
28049
28050  /**
28051   * Clear the building row data to be used for a new row
28052   */
28053  JustifiedGallery.prototype.clearBuildingRow = function () {
28054    this.buildingRow.entriesBuff = [];
28055    this.buildingRow.aspectRatio = 0;
28056    this.buildingRow.width = 0;
28057  };
28058
28059  /**
28060   * Justify the building row, preparing it to
28061   *
28062   * @param isLastRow
28063   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28064   * @returns a boolean to know if the row has been justified or not
28065   */
28066  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
28067    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
28068    var minHeight = 0;
28069    var availableWidth = this.galleryWidth - 2 * this.border - (
28070      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28071    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
28072    var defaultRowHeight = this.settings.rowHeight;
28073    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
28074
28075    //Skip the last row if we can't justify it and the lastRow == 'hide'
28076    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
28077      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28078        $entry = this.buildingRow.entriesBuff[i];
28079        if (this.settings.cssAnimation)
28080          $entry.removeClass('jg-entry-visible');
28081        else {
28082          $entry.stop().fadeTo(0, 0.1);
28083          $entry.find('> img, > a > img').fadeTo(0, 0);
28084        }
28085      }
28086      return -1;
28087    }
28088
28089    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
28090    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
28091      justify = false;
28092
28093      if (this.rows > 0) {
28094        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
28095        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
28096      }
28097    }
28098
28099    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28100      $entry = this.buildingRow.entriesBuff[i];
28101      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28102
28103      if (justify) {
28104        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
28105        newImgH = rowHeight;
28106      } else {
28107        newImgW = defaultRowHeight * imgAspectRatio;
28108        newImgH = defaultRowHeight;
28109      }
28110
28111      availableWidth -= Math.round(newImgW);
28112      $entry.data('jg.jwidth', Math.round(newImgW));
28113      $entry.data('jg.jheight', Math.ceil(newImgH));
28114      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
28115    }
28116
28117    this.buildingRow.height = minHeight;
28118    return justify;
28119  };
28120
28121  /**
28122   * Flush a row: justify it, modify the gallery height accordingly to the row height
28123   *
28124   * @param isLastRow
28125   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28126   */
28127  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
28128    var settings = this.settings;
28129    var $entry, buildingRowRes, offX = this.border, i;
28130
28131    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
28132    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
28133      this.clearBuildingRow();
28134      return;
28135    }
28136
28137    if (this.maxRowHeight) {
28138      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
28139    }
28140
28141    //Align last (unjustified) row
28142    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
28143      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
28144
28145      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28146        $entry = this.buildingRow.entriesBuff[i];
28147        availableWidth -= $entry.data('jg.jwidth');
28148      }
28149
28150      if (settings.lastRow === 'center')
28151        offX += Math.round(availableWidth / 2);
28152      else if (settings.lastRow === 'right')
28153        offX += availableWidth;
28154    }
28155
28156    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
28157    for (i = 0; i <= lastEntryIdx; i++) {
28158      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
28159      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
28160      offX += $entry.data('jg.jwidth') + settings.margins;
28161    }
28162
28163    //Gallery Height
28164    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
28165    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
28166
28167    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
28168      //Ready for a new row
28169      this.offY += this.buildingRow.height + settings.margins;
28170      this.rows += 1;
28171      this.clearBuildingRow();
28172      this.settings.triggerEvent.call(this, 'jg.rowflush');
28173    }
28174  };
28175
28176
28177  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
28178  var galleryPrevStaticHeight = 0;
28179
28180  JustifiedGallery.prototype.rememberGalleryHeight = function () {
28181    galleryPrevStaticHeight = this.$gallery.height();
28182    this.$gallery.height(galleryPrevStaticHeight);
28183  };
28184
28185  // grow only
28186  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
28187    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
28188    this.$gallery.height(galleryPrevStaticHeight);
28189  };
28190
28191  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
28192    galleryPrevStaticHeight = height;
28193    this.$gallery.height(height);
28194  };
28195
28196  /**
28197   * Checks the width of the gallery container, to know if a new justification is needed
28198   */
28199  JustifiedGallery.prototype.checkWidth = function () {
28200    this.checkWidthIntervalId = setInterval($.proxy(function () {
28201
28202      // if the gallery is not currently visible, abort.
28203      if (!this.$gallery.is(":visible")) return;
28204
28205      var galleryWidth = parseFloat(this.$gallery.width());
28206      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
28207        this.galleryWidth = galleryWidth;
28208        this.rewind();
28209
28210        this.rememberGalleryHeight();
28211
28212        // Restart to analyze
28213        this.startImgAnalyzer(true);
28214      }
28215    }, this), this.settings.refreshTime);
28216  };
28217
28218  /**
28219   * @returns {boolean} a boolean saying if the spinner is active or not
28220   */
28221  JustifiedGallery.prototype.isSpinnerActive = function () {
28222    return this.spinner.intervalId !== null;
28223  };
28224
28225  /**
28226   * @returns {int} the spinner height
28227   */
28228  JustifiedGallery.prototype.getSpinnerHeight = function () {
28229    return this.spinner.$el.innerHeight();
28230  };
28231
28232  /**
28233   * Stops the spinner animation and modify the gallery height to exclude the spinner
28234   */
28235  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
28236    clearInterval(this.spinner.intervalId);
28237    this.spinner.intervalId = null;
28238    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
28239    this.spinner.$el.detach();
28240  };
28241
28242  /**
28243   * Starts the spinner animation
28244   */
28245  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
28246    var spinnerContext = this.spinner;
28247    var $spinnerPoints = spinnerContext.$el.find('span');
28248    clearInterval(spinnerContext.intervalId);
28249    this.$gallery.append(spinnerContext.$el);
28250    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
28251    spinnerContext.intervalId = setInterval(function () {
28252      if (spinnerContext.phase < $spinnerPoints.length) {
28253        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
28254      } else {
28255        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
28256      }
28257      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
28258    }, spinnerContext.timeSlot);
28259  };
28260
28261  /**
28262   * Rewind the image analysis to start from the first entry.
28263   */
28264  JustifiedGallery.prototype.rewind = function () {
28265    this.lastFetchedEntry = null;
28266    this.lastAnalyzedIndex = -1;
28267    this.offY = this.border;
28268    this.rows = 0;
28269    this.clearBuildingRow();
28270  };
28271
28272  /**
28273   * @returns {String} `settings.selector` rejecting spinner element
28274   */
28275  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
28276    return this.settings.selector + ', div:not(.jg-spinner)';
28277  };
28278
28279  /**
28280   * @returns {Array} all entries matched by `settings.selector`
28281   */
28282  JustifiedGallery.prototype.getAllEntries = function () {
28283    var selector = this.getSelectorWithoutSpinner();
28284    return this.$gallery.children(selector).toArray();
28285  };
28286
28287  /**
28288   * Update the entries searching it from the justified gallery HTML element
28289   *
28290   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
28291   * @returns {boolean} true if some entries has been founded
28292   */
28293  JustifiedGallery.prototype.updateEntries = function (norewind) {
28294    var newEntries;
28295
28296    if (norewind && this.lastFetchedEntry != null) {
28297      var selector = this.getSelectorWithoutSpinner();
28298      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
28299    } else {
28300      this.entries = [];
28301      newEntries = this.getAllEntries();
28302    }
28303
28304    if (newEntries.length > 0) {
28305
28306      // Sort or randomize
28307      if ($.isFunction(this.settings.sort)) {
28308        newEntries = this.sortArray(newEntries);
28309      } else if (this.settings.randomize) {
28310        newEntries = this.shuffleArray(newEntries);
28311      }
28312      this.lastFetchedEntry = newEntries[newEntries.length - 1];
28313
28314      // Filter
28315      if (this.settings.filter) {
28316        newEntries = this.filterArray(newEntries);
28317      } else {
28318        this.resetFilters(newEntries);
28319      }
28320
28321    }
28322
28323    this.entries = this.entries.concat(newEntries);
28324    return true;
28325  };
28326
28327  /**
28328   * Apply the entries order to the DOM, iterating the entries and appending the images
28329   *
28330   * @param entries the entries that has been modified and that must be re-ordered in the DOM
28331   */
28332  JustifiedGallery.prototype.insertToGallery = function (entries) {
28333    var that = this;
28334    $.each(entries, function () {
28335      $(this).appendTo(that.$gallery);
28336    });
28337  };
28338
28339  /**
28340   * Shuffle the array using the Fisher-Yates shuffle algorithm
28341   *
28342   * @param a the array to shuffle
28343   * @return the shuffled array
28344   */
28345  JustifiedGallery.prototype.shuffleArray = function (a) {
28346    var i, j, temp;
28347    for (i = a.length - 1; i > 0; i--) {
28348      j = Math.floor(Math.random() * (i + 1));
28349      temp = a[i];
28350      a[i] = a[j];
28351      a[j] = temp;
28352    }
28353    this.insertToGallery(a);
28354    return a;
28355  };
28356
28357  /**
28358   * Sort the array using settings.comparator as comparator
28359   *
28360   * @param a the array to sort (it is sorted)
28361   * @return the sorted array
28362   */
28363  JustifiedGallery.prototype.sortArray = function (a) {
28364    a.sort(this.settings.sort);
28365    this.insertToGallery(a);
28366    return a;
28367  };
28368
28369  /**
28370   * Reset the filters removing the 'jg-filtered' class from all the entries
28371   *
28372   * @param a the array to reset
28373   */
28374  JustifiedGallery.prototype.resetFilters = function (a) {
28375    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
28376  };
28377
28378  /**
28379   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
28380   *
28381   * @param a the array to filter
28382   * @return the filtered array
28383   */
28384  JustifiedGallery.prototype.filterArray = function (a) {
28385    var settings = this.settings;
28386    if ($.type(settings.filter) === 'string') {
28387      // Filter only keeping the entries passed in the string
28388      return a.filter(function (el) {
28389        var $el = $(el);
28390        if ($el.is(settings.filter)) {
28391          $el.removeClass('jg-filtered');
28392          return true;
28393        } else {
28394          $el.addClass('jg-filtered').removeClass('jg-visible');
28395          return false;
28396        }
28397      });
28398    } else if ($.isFunction(settings.filter)) {
28399      // Filter using the passed function
28400      var filteredArr = a.filter(settings.filter);
28401      for (var i = 0; i < a.length; i++) {
28402        if (filteredArr.indexOf(a[i]) === -1) {
28403          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
28404        } else {
28405          $(a[i]).removeClass('jg-filtered');
28406        }
28407      }
28408      return filteredArr;
28409    }
28410  };
28411
28412  /**
28413   * Revert the image src to the default value.
28414   */
28415  JustifiedGallery.prototype.resetImgSrc = function ($img) {
28416    if ($img.data('jg.originalSrcLoc') === 'src') {
28417      $img.attr('src', $img.data('jg.originalSrc'));
28418    } else {
28419      $img.attr('src', '');
28420    }
28421  };
28422
28423  /**
28424   * Destroy the Justified Gallery instance.
28425   *
28426   * It clears all the css properties added in the style attributes. We doesn't backup the original
28427   * values for those css attributes, because it costs (performance) and because in general one
28428   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
28429   * classes). Creating a backup is also difficult because JG could be called multiple times and
28430   * with different style attributes.
28431   */
28432  JustifiedGallery.prototype.destroy = function () {
28433    clearInterval(this.checkWidthIntervalId);
28434    this.stopImgAnalyzerStarter();
28435
28436    // Get fresh entries list since filtered entries are absent in `this.entries`
28437    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
28438      var $entry = $(entry);
28439
28440      // Reset entry style
28441      $entry.css('width', '');
28442      $entry.css('height', '');
28443      $entry.css('top', '');
28444      $entry.css('left', '');
28445      $entry.data('jg.loaded', undefined);
28446      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
28447
28448      // Reset image style
28449      var $img = this.imgFromEntry($entry);
28450      if ($img) {
28451        $img.css('width', '');
28452        $img.css('height', '');
28453        $img.css('margin-left', '');
28454        $img.css('margin-top', '');
28455        this.resetImgSrc($img);
28456        $img.data('jg.originalSrc', undefined);
28457        $img.data('jg.originalSrcLoc', undefined);
28458        $img.data('jg.src', undefined);
28459      }
28460
28461      // Remove caption
28462      this.removeCaptionEventsHandlers($entry);
28463      var $caption = this.captionFromEntry($entry);
28464      if ($entry.data('jg.createdCaption')) {
28465        // remove also the caption element (if created by jg)
28466        $entry.data('jg.createdCaption', undefined);
28467        if ($caption !== null) $caption.remove();
28468      } else {
28469        if ($caption !== null) $caption.fadeTo(0, 1);
28470      }
28471
28472    }, this));
28473
28474    this.$gallery.css('height', '');
28475    this.$gallery.removeClass('justified-gallery');
28476    this.$gallery.data('jg.controller', undefined);
28477    this.settings.triggerEvent.call(this, 'jg.destroy');
28478  };
28479
28480  /**
28481   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
28482   *
28483   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
28484   */
28485  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
28486    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
28487      var $entry = $(this.entries[i]);
28488      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
28489        var availableWidth = this.galleryWidth - 2 * this.border - (
28490          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28491        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28492
28493        this.buildingRow.entriesBuff.push($entry);
28494        this.buildingRow.aspectRatio += imgAspectRatio;
28495        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
28496        this.lastAnalyzedIndex = i;
28497
28498        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
28499          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28500
28501          if (++this.yield.flushed >= this.yield.every) {
28502            this.startImgAnalyzer(isForResize);
28503            return;
28504          }
28505        }
28506      } else if ($entry.data('jg.loaded') !== 'error') {
28507        return;
28508      }
28509    }
28510
28511    // Last row flush (the row is not full)
28512    if (this.buildingRow.entriesBuff.length > 0) {
28513      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28514    }
28515
28516    if (this.isSpinnerActive()) {
28517      this.stopLoadingSpinnerAnimation();
28518    }
28519
28520    /* Stop, if there is, the timeout to start the analyzeImages.
28521     This is because an image can be set loaded, and the timeout can be set,
28522     but this image can be analyzed yet.
28523     */
28524    this.stopImgAnalyzerStarter();
28525
28526    this.setGalleryFinalHeight(this.galleryHeightToSet);
28527
28528    //On complete callback
28529    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
28530  };
28531
28532  /**
28533   * Stops any ImgAnalyzer starter (that has an assigned timeout)
28534   */
28535  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
28536    this.yield.flushed = 0;
28537    if (this.imgAnalyzerTimeout !== null) {
28538      clearTimeout(this.imgAnalyzerTimeout);
28539      this.imgAnalyzerTimeout = null;
28540    }
28541  };
28542
28543  /**
28544   * Starts the image analyzer. It is not immediately called to let the browser to update the view
28545   *
28546   * @param isForResize specifies if the image analyzer must be called for resizing or not
28547   */
28548  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
28549    var that = this;
28550    this.stopImgAnalyzerStarter();
28551    this.imgAnalyzerTimeout = setTimeout(function () {
28552      that.analyzeImages(isForResize);
28553    }, 0.001); // we can't start it immediately due to a IE different behaviour
28554  };
28555
28556  /**
28557   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
28558   * because some browsers, with a 404 set complete = true.
28559   *
28560   * @param imageSrc the image src to load
28561   * @param onLoad callback that is called when the image has been loaded
28562   * @param onError callback that is called in case of an error
28563   */
28564  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
28565    if (!onLoad && !onError) return;
28566
28567    var memImage = new Image();
28568    var $memImage = $(memImage);
28569    if (onLoad) {
28570      $memImage.one('load', function () {
28571        $memImage.off('load error');
28572        onLoad(memImage);
28573      });
28574    }
28575    if (onError) {
28576      $memImage.one('error', function () {
28577        $memImage.off('load error');
28578        onError(memImage);
28579      });
28580    }
28581    memImage.src = imageSrc;
28582  };
28583
28584  /**
28585   * Init of Justified Gallery controlled
28586   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
28587   */
28588  JustifiedGallery.prototype.init = function () {
28589    var imagesToLoad = false, skippedImages = false, that = this;
28590    $.each(this.entries, function (index, entry) {
28591      var $entry = $(entry);
28592      var $image = that.imgFromEntry($entry);
28593
28594      $entry.addClass('jg-entry');
28595
28596      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
28597
28598        // Link Rel global overwrite
28599        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
28600
28601        // Link Target global overwrite
28602        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
28603
28604        if ($image !== null) {
28605
28606          // Image src
28607          var imageSrc = that.extractImgSrcFromImage($image);
28608
28609          /* If we have the height and the width, we don't wait that the image is loaded,
28610             but we start directly with the justification */
28611          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
28612            var width = parseFloat($image.attr('width'));
28613            var height = parseFloat($image.attr('height'));
28614            if ($image.prop('tagName') === 'svg') {
28615              width = parseFloat($image[0].getBBox().width);
28616              height = parseFloat($image[0].getBBox().height);
28617            }
28618            if (!isNaN(width) && !isNaN(height)) {
28619              $entry.data('jg.width', width);
28620              $entry.data('jg.height', height);
28621              $entry.data('jg.loaded', 'skipped');
28622              skippedImages = true;
28623              that.startImgAnalyzer(false);
28624              return true; // continue
28625            }
28626          }
28627
28628          $entry.data('jg.loaded', false);
28629          imagesToLoad = true;
28630
28631          // Spinner start
28632          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
28633
28634          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
28635            $entry.data('jg.width', loadImg.width);
28636            $entry.data('jg.height', loadImg.height);
28637            $entry.data('jg.loaded', true);
28638            that.startImgAnalyzer(false);
28639          }, function () { // image load error
28640            $entry.data('jg.loaded', 'error');
28641            that.startImgAnalyzer(false);
28642          });
28643
28644        } else {
28645          $entry.data('jg.loaded', true);
28646          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
28647          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
28648        }
28649
28650      }
28651
28652    });
28653
28654    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
28655    this.checkWidth();
28656  };
28657
28658  /**
28659   * Checks that it is a valid number. If a string is passed it is converted to a number
28660   *
28661   * @param settingContainer the object that contains the setting (to allow the conversion)
28662   * @param settingName the setting name
28663   */
28664  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
28665    if ($.type(settingContainer[settingName]) === 'string') {
28666      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
28667    }
28668
28669    if ($.type(settingContainer[settingName]) === 'number') {
28670      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
28671    } else {
28672      throw settingName + ' must be a number';
28673    }
28674  };
28675
28676  /**
28677   * Checks the sizeRangeSuffixes and, if necessary, converts
28678   * its keys from string (e.g. old settings with 'lt100') to int.
28679   */
28680  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
28681    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
28682      throw 'sizeRangeSuffixes must be defined and must be an object';
28683    }
28684
28685    var suffixRanges = [];
28686    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28687      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
28688    }
28689
28690    var newSizeRngSuffixes = { 0: '' };
28691    for (var i = 0; i < suffixRanges.length; i++) {
28692      if ($.type(suffixRanges[i]) === 'string') {
28693        try {
28694          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
28695          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28696        } catch (e) {
28697          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
28698        }
28699      } else {
28700        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28701      }
28702    }
28703
28704    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
28705  };
28706
28707  /**
28708   * check and convert the maxRowHeight setting
28709   * requires rowHeight to be already set
28710   * TODO: should be always called when only rowHeight is changed
28711   * @return number or null
28712   */
28713  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
28714    var newMaxRowHeight = null;
28715    var rowHeight = this.settings.rowHeight;
28716
28717    if ($.type(this.settings.maxRowHeight) === 'string') {
28718      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
28719        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
28720      } else {
28721        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
28722      }
28723    } else if ($.type(this.settings.maxRowHeight) === 'number') {
28724      newMaxRowHeight = this.settings.maxRowHeight;
28725    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
28726      return null;
28727    } else {
28728      throw 'maxRowHeight must be a number or a percentage';
28729    }
28730
28731    // check if the converted value is not a number
28732    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
28733
28734    // check values, maxRowHeight must be >= rowHeight
28735    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
28736
28737    return newMaxRowHeight;
28738  };
28739
28740  /**
28741   * Checks the settings
28742   */
28743  JustifiedGallery.prototype.checkSettings = function () {
28744    this.checkSizeRangesSuffixes();
28745
28746    this.checkOrConvertNumber(this.settings, 'rowHeight');
28747    this.checkOrConvertNumber(this.settings, 'margins');
28748    this.checkOrConvertNumber(this.settings, 'border');
28749    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
28750
28751    var lastRowModes = [
28752      'justify',
28753      'nojustify',
28754      'left',
28755      'center',
28756      'right',
28757      'hide'
28758    ];
28759    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
28760      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
28761    }
28762
28763    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28764    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28765      throw 'justifyThreshold must be in the interval [0,1]';
28766    }
28767    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28768      throw 'cssAnimation must be a boolean';
28769    }
28770
28771    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28772    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28773
28774    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28775    if (this.settings.captionSettings.visibleOpacity < 0 ||
28776      this.settings.captionSettings.visibleOpacity > 1) {
28777      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28778    }
28779
28780    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28781    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28782      this.settings.captionSettings.nonVisibleOpacity > 1) {
28783      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28784    }
28785
28786    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28787    this.checkOrConvertNumber(this.settings, 'refreshTime');
28788    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28789    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28790    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28791
28792    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28793      throw 'sort must be false or a comparison function';
28794    }
28795
28796    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28797      $.type(this.settings.filter) !== 'string') {
28798      throw 'filter must be false, a string or a filter function';
28799    }
28800  };
28801
28802  /**
28803   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28804   * @returns {Array} sorted suffix ranges
28805   */
28806  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28807    var suffixRanges = [];
28808    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28809      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28810    }
28811    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28812    return suffixRanges;
28813  };
28814
28815  /**
28816   * Update the existing settings only changing some of them
28817   *
28818   * @param newSettings the new settings (or a subgroup of them)
28819   */
28820  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28821    // In this case Justified Gallery has been called again changing only some options
28822    this.settings = $.extend({}, this.settings, newSettings);
28823    this.checkSettings();
28824
28825    // As reported in the settings: negative value = same as margins, 0 = disabled
28826    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28827
28828    this.maxRowHeight = this.retrieveMaxRowHeight();
28829    this.suffixRanges = this.retrieveSuffixRanges();
28830  };
28831
28832  JustifiedGallery.prototype.defaults = {
28833    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28834        {
28835          100: '_t',  // used when longest is less than 100px
28836          240: '_m',  // used when longest is between 101px and 240px
28837          320: '_n',  // ...
28838          500: '',
28839          640: '_z',
28840          1024: '_b'  // used as else case because it is the last
28841        }
28842    */
28843    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28844    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28845    current path, width and height */
28846    rowHeight: 120, // required? required to be > 0?
28847    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28848    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28849    // can't exceed 3 * rowHeight)
28850    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28851    margins: 1,
28852    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28853
28854    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28855
28856    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28857                             * (i.e. lastRow setting is not considered) */
28858    waitThumbnailsLoad: true,
28859    captions: true,
28860    cssAnimation: true,
28861    imagesAnimationDuration: 500, // ignored with css animations
28862    captionSettings: { // ignored with css animations
28863      animationDuration: 500,
28864      visibleOpacity: 0.7,
28865      nonVisibleOpacity: 0.0
28866    },
28867    rel: null, // rewrite the rel of each analyzed links
28868    target: null, // rewrite the target of all links
28869    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28870    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28871    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28872    randomize: false,
28873    rtl: false, // right-to-left mode
28874    sort: false, /*
28875      - false: to do not sort
28876      - function: to sort them using the function as comparator (see Array.prototype.sort())
28877    */
28878    filter: false, /*
28879      - false, null or undefined: for a disabled filter
28880      - a string: an entry is kept if entry.is(filter string) returns true
28881                  see jQuery's .is() function for further information
28882      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28883                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28884    */
28885    selector: 'a', // The selector that is used to know what are the entries of the gallery
28886    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28887    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28888      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28889    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28890  };
28891
28892
28893  /**
28894   * Justified Gallery plugin for jQuery
28895   *
28896   * Events
28897   *  - jg.complete : called when all the gallery has been created
28898   *  - jg.resize : called when the gallery has been resized
28899   *  - jg.rowflush : when a new row appears
28900   *
28901   * @param arg the action (or the settings) passed when the plugin is called
28902   * @returns {*} the object itself
28903   */
28904  $.fn.justifiedGallery = function (arg) {
28905    return this.each(function (index, gallery) {
28906
28907      var $gallery = $(gallery);
28908      $gallery.addClass('justified-gallery');
28909
28910      var controller = $gallery.data('jg.controller');
28911      if (typeof controller === 'undefined') {
28912        // Create controller and assign it to the object data
28913        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28914          if (arg === 'destroy') return; // Just a call to an unexisting object
28915          throw 'The argument must be an object';
28916        }
28917        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28918        $gallery.data('jg.controller', controller);
28919      } else if (arg === 'norewind') {
28920        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28921        // ... left to be more readable
28922      } else if (arg === 'destroy') {
28923        controller.destroy();
28924        return;
28925      } else {
28926        // In this case Justified Gallery has been called again changing only some options
28927        controller.updateSettings(arg);
28928        controller.rewind();
28929      }
28930
28931      // Update the entries list
28932      if (!controller.updateEntries(arg === 'norewind')) return;
28933
28934      // Init justified gallery
28935      controller.init();
28936
28937    });
28938  };
28939
28940}));
28941
28942/*!
28943* Customized version of iScroll.js 0.0.1
28944* It fixes bugs affecting its integration with fullpage.js
28945*/
28946/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
28947(function (window, document, Math) {
28948var rAF = window.requestAnimationFrame  ||
28949    window.webkitRequestAnimationFrame  ||
28950    window.mozRequestAnimationFrame     ||
28951    window.oRequestAnimationFrame       ||
28952    window.msRequestAnimationFrame      ||
28953    function (callback) { window.setTimeout(callback, 1000 / 60); };
28954
28955var utils = (function () {
28956    var me = {};
28957
28958    var _elementStyle = document.createElement('div').style;
28959    var _vendor = (function () {
28960        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
28961            transform,
28962            i = 0,
28963            l = vendors.length;
28964
28965        for ( ; i < l; i++ ) {
28966            transform = vendors[i] + 'ransform';
28967            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
28968        }
28969
28970        return false;
vendor: 5,154 bytes, lines 28971-29123
28971    })();
28972
28973    function _prefixStyle (style) {
28974        if ( _vendor === false ) return false;
28975        if ( _vendor === '' ) return style;
28976        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
28977    }
28978
28979    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
28980
28981    me.extend = function (target, obj) {
28982        for ( var i in obj ) {
28983            target[i] = obj[i];
28984        }
28985    };
28986
28987    me.addEvent = function (el, type, fn, capture) {
28988        el.addEventListener(type, fn, !!capture);
28989    };
28990
28991    me.removeEvent = function (el, type, fn, capture) {
28992        el.removeEventListener(type, fn, !!capture);
28993    };
28994
28995    me.prefixPointerEvent = function (pointerEvent) {
28996        return window.MSPointerEvent ?
28997            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
28998            pointerEvent;
28999    };
29000
29001    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29002        var distance = current - start,
29003            speed = Math.abs(distance) / time,
29004            destination,
29005            duration;
29006
29007        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29008
29009        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29010        duration = speed / deceleration;
29011
29012        if ( destination < lowerMargin ) {
29013            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29014            distance = Math.abs(destination - current);
29015            duration = distance / speed;
29016        } else if ( destination > 0 ) {
29017            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29018            distance = Math.abs(current) + destination;
29019            duration = distance / speed;
29020        }
29021
29022        return {
29023            destination: Math.round(destination),
29024            duration: duration
29025        };
29026    };
29027
29028    var _transform = _prefixStyle('transform');
29029
29030    me.extend(me, {
29031        hasTransform: _transform !== false,
29032        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29033        hasTouch: 'ontouchstart' in window,
29034        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29035        hasTransition: _prefixStyle('transition') in _elementStyle
29036    });
29037
29038    /*
29039    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29040    - galaxy S2 is ok
29041    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29042    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29043   - galaxy S3 is badAndroid (stock brower, webview)
29044     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29045   - galaxy S4 is badAndroid (stock brower, webview)
29046     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29047   - galaxy S5 is OK
29048     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29049   - galaxy S6 is OK
29050     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29051  */
29052    me.isBadAndroid = (function() {
29053        var appVersion = window.navigator.appVersion;
29054        // Android browser is not a chrome browser.
29055        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29056            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
29057            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
29058                return parseFloat(safariVersion[1]) < 535.19;
29059            } else {
29060                return true;
29061            }
29062        } else {
29063            return false;
29064        }
29065    })();
29066
29067    me.extend(me.style = {}, {
29068        transform: _transform,
29069        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
29070        transitionDuration: _prefixStyle('transitionDuration'),
29071        transitionDelay: _prefixStyle('transitionDelay'),
29072        transformOrigin: _prefixStyle('transformOrigin')
29073    });
29074
29075    me.hasClass = function (e, c) {
29076        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
29077        return re.test(e.className);
29078    };
29079
29080    me.addClass = function (e, c) {
29081        if ( me.hasClass(e, c) ) {
29082            return;
29083        }
29084
29085        var newclass = e.className.split(' ');
29086        newclass.push(c);
29087        e.className = newclass.join(' ');
29088    };
29089
29090    me.removeClass = function (e, c) {
29091        if ( !me.hasClass(e, c) ) {
29092            return;
29093        }
29094
29095        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
29096        e.className = e.className.replace(re, ' ');
29097    };
29098
29099    me.offset = function (el) {
29100        var left = -el.offsetLeft,
29101            top = -el.offsetTop;
29102
29103        // jshint -W084
29104        while (el = el.offsetParent) {
29105            left -= el.offsetLeft;
29106            top -= el.offsetTop;
29107        }
29108        // jshint +W084
29109
29110        return {
29111            left: left,
29112            top: top
29113        };
29114    };
29115
29116    me.preventDefaultException = function (el, exceptions) {
29117        for ( var i in exceptions ) {
29118            if ( exceptions[i].test(el[i]) ) {
29119                return true;
29120            }
29121        }
29122
29123        return false;
vendor: 5,660 bytes, lines 29124-29289
29124    };
29125
29126    me.extend(me.eventType = {}, {
29127        touchstart: 1,
29128        touchmove: 1,
29129        touchend: 1,
29130
29131        mousedown: 2,
29132        mousemove: 2,
29133        mouseup: 2,
29134
29135        pointerdown: 3,
29136        pointermove: 3,
29137        pointerup: 3,
29138
29139        MSPointerDown: 3,
29140        MSPointerMove: 3,
29141        MSPointerUp: 3
29142    });
29143
29144    me.extend(me.ease = {}, {
29145        quadratic: {
29146            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
29147            fn: function (k) {
29148                return k * ( 2 - k );
29149            }
29150        },
29151        circular: {
29152            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)
29153            fn: function (k) {
29154                return Math.sqrt( 1 - ( --k * k ) );
29155            }
29156        },
29157        back: {
29158            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
29159            fn: function (k) {
29160                var b = 4;
29161                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
29162            }
29163        },
29164        bounce: {
29165            style: '',
29166            fn: function (k) {
29167                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
29168                    return 7.5625 * k * k;
29169                } else if ( k < ( 2 / 2.75 ) ) {
29170                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
29171                } else if ( k < ( 2.5 / 2.75 ) ) {
29172                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
29173                } else {
29174                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
29175                }
29176            }
29177        },
29178        elastic: {
29179            style: '',
29180            fn: function (k) {
29181                var f = 0.22,
29182                    e = 0.4;
29183
29184                if ( k === 0 ) { return 0; }
29185                if ( k == 1 ) { return 1; }
29186
29187                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
29188            }
29189        }
29190    });
29191
29192    me.tap = function (e, eventName) {
29193        var ev = document.createEvent('Event');
29194        ev.initEvent(eventName, true, true);
29195        ev.pageX = e.pageX;
29196        ev.pageY = e.pageY;
29197        e.target.dispatchEvent(ev);
29198    };
29199
29200    me.click = function (e) {
29201        var target = e.target,
29202            ev;
29203
29204        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
29205            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
29206            // initMouseEvent is deprecated.
29207            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
29208            ev.initEvent('click', true, true);
29209            ev.view = e.view || window;
29210            ev.detail = 1;
29211            ev.screenX = target.screenX || 0;
29212            ev.screenY = target.screenY || 0;
29213            ev.clientX = target.clientX || 0;
29214            ev.clientY = target.clientY || 0;
29215            ev.ctrlKey = !!e.ctrlKey;
29216            ev.altKey = !!e.altKey;
29217            ev.shiftKey = !!e.shiftKey;
29218            ev.metaKey = !!e.metaKey;
29219            ev.button = 0;
29220            ev.relatedTarget = null;
29221            ev._constructed = true;
29222            target.dispatchEvent(ev);
29223        }
29224    };
29225
29226    return me;
29227})();
29228function IScroll (el, options) {
29229    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
29230    this.scroller = this.wrapper.children[0];
29231    this.scrollerStyle = this.scroller.style;       // cache style for better performance
29232
29233    this.options = {
29234
29235        resizeScrollbars: true,
29236
29237        mouseWheelSpeed: 20,
29238
29239        snapThreshold: 0.334,
29240
29241// INSERT POINT: OPTIONS
29242        disablePointer : !utils.hasPointer,
29243        disableTouch : utils.hasPointer || !utils.hasTouch,
29244        disableMouse : utils.hasPointer || utils.hasTouch,
29245        startX: 0,
29246        startY: 0,
29247        scrollY: true,
29248        directionLockThreshold: 5,
29249        momentum: true,
29250
29251        bounce: true,
29252        bounceTime: 600,
29253        bounceEasing: '',
29254
29255        preventDefault: true,
29256        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
29257
29258        HWCompositing: true,
29259        useTransition: true,
29260        useTransform: true,
29261        bindToWrapper: typeof window.onmousedown === "undefined"
29262    };
29263
29264    for ( var i in options ) {
29265        this.options[i] = options[i];
29266    }
29267
29268    // Normalize options
29269    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
29270
29271    this.options.useTransition = utils.hasTransition && this.options.useTransition;
29272    this.options.useTransform = utils.hasTransform && this.options.useTransform;
29273
29274    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
29275    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
29276
29277    // If you want eventPassthrough I have to lock one of the axes
29278    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
29279    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
29280
29281    // With eventPassthrough we also need lockDirection mechanism
29282    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
29283    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
29284
29285    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
29286
29287    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
29288
29289    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 29290-29461
29290        this.options.tap = 'tap';
29291    }
29292
29293    // https://github.com/cubiq/iscroll/issues/1029
29294    if (!this.options.useTransition && !this.options.useTransform) {
29295        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
29296            this.scrollerStyle.position = "relative";
29297        }
29298    }
29299
29300    if ( this.options.shrinkScrollbars == 'scale' ) {
29301        this.options.useTransition = false;
29302    }
29303
29304    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
29305
29306// INSERT POINT: NORMALIZATION
29307
29308    // Some defaults
29309    this.x = 0;
29310    this.y = 0;
29311    this.directionX = 0;
29312    this.directionY = 0;
29313    this._events = {};
29314
29315// INSERT POINT: DEFAULTS
29316
29317    this._init();
29318    this.refresh();
29319
29320    this.scrollTo(this.options.startX, this.options.startY);
29321    this.enable();
29322}
29323
29324IScroll.prototype = {
29325    version: '5.2.0',
29326
29327    _init: function () {
29328        this._initEvents();
29329
29330        if ( this.options.scrollbars || this.options.indicators ) {
29331            this._initIndicators();
29332        }
29333
29334        if ( this.options.mouseWheel ) {
29335            this._initWheel();
29336        }
29337
29338        if ( this.options.snap ) {
29339            this._initSnap();
29340        }
29341
29342        if ( this.options.keyBindings ) {
29343            this._initKeys();
29344        }
29345
29346// INSERT POINT: _init
29347
29348    },
29349
29350    destroy: function () {
29351        this._initEvents(true);
29352        clearTimeout(this.resizeTimeout);
29353        this.resizeTimeout = null;
29354        this._execEvent('destroy');
29355    },
29356
29357    _transitionEnd: function (e) {
29358        if ( e.target != this.scroller || !this.isInTransition ) {
29359            return;
29360        }
29361
29362        this._transitionTime();
29363        if ( !this.resetPosition(this.options.bounceTime) ) {
29364            this.isInTransition = false;
29365            this._execEvent('scrollEnd');
29366        }
29367    },
29368
29369    _start: function (e) {
29370        // React to left mouse button only
29371        if ( utils.eventType[e.type] != 1 ) {
29372          // for button property
29373          // http://unixpapa.com/js/mouse.html
29374          var button;
29375        if (!e.which) {
29376          /* IE case */
29377          button = (e.button < 2) ? 0 :
29378                   ((e.button == 4) ? 1 : 2);
29379        } else {
29380          /* All others */
29381          button = e.button;
29382        }
29383            if ( button !== 0 ) {
29384                return;
29385            }
29386        }
29387
29388        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
29389            return;
29390        }
29391
29392        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29393            e.preventDefault();
29394        }
29395
29396        var point = e.touches ? e.touches[0] : e,
29397            pos;
29398
29399        this.initiated  = utils.eventType[e.type];
29400        this.moved      = false;
29401        this.distX      = 0;
29402        this.distY      = 0;
29403        this.directionX = 0;
29404        this.directionY = 0;
29405        this.directionLocked = 0;
29406
29407        this.startTime = utils.getTime();
29408
29409        if ( this.options.useTransition && this.isInTransition ) {
29410            this._transitionTime();
29411            this.isInTransition = false;
29412            pos = this.getComputedPosition();
29413            this._translate(Math.round(pos.x), Math.round(pos.y));
29414            this._execEvent('scrollEnd');
29415        } else if ( !this.options.useTransition && this.isAnimating ) {
29416            this.isAnimating = false;
29417            this._execEvent('scrollEnd');
29418        }
29419
29420        this.startX    = this.x;
29421        this.startY    = this.y;
29422        this.absStartX = this.x;
29423        this.absStartY = this.y;
29424        this.pointX    = point.pageX;
29425        this.pointY    = point.pageY;
29426
29427        this._execEvent('beforeScrollStart');
29428    },
29429
29430    _move: function (e) {
29431        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29432            return;
29433        }
29434
29435        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
29436            e.preventDefault();
29437        }
29438
29439        var point       = e.touches ? e.touches[0] : e,
29440            deltaX      = point.pageX - this.pointX,
29441            deltaY      = point.pageY - this.pointY,
29442            timestamp   = utils.getTime(),
29443            newX, newY,
29444            absDistX, absDistY;
29445
29446        this.pointX     = point.pageX;
29447        this.pointY     = point.pageY;
29448
29449        this.distX      += deltaX;
29450        this.distY      += deltaY;
29451        absDistX        = Math.abs(this.distX);
29452        absDistY        = Math.abs(this.distY);
29453
29454        // We need to move at least 10 pixels for the scrolling to initiate
29455        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
29456            return;
29457        }
29458
29459        // If you are scrolling in one direction lock the other
29460        if ( !this.directionLocked && !this.options.freeScroll ) {
29461            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 29462-29648
29462                this.directionLocked = 'h';     // lock horizontally
29463            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
29464                this.directionLocked = 'v';     // lock vertically
29465            } else {
29466                this.directionLocked = 'n';     // no lock
29467            }
29468        }
29469
29470        if ( this.directionLocked == 'h' ) {
29471            if ( this.options.eventPassthrough == 'vertical' ) {
29472                e.preventDefault();
29473            } else if ( this.options.eventPassthrough == 'horizontal' ) {
29474                this.initiated = false;
29475                return;
29476            }
29477
29478            deltaY = 0;
29479        } else if ( this.directionLocked == 'v' ) {
29480            if ( this.options.eventPassthrough == 'horizontal' ) {
29481                e.preventDefault();
29482            } else if ( this.options.eventPassthrough == 'vertical' ) {
29483                this.initiated = false;
29484                return;
29485            }
29486
29487            deltaX = 0;
29488        }
29489
29490        deltaX = this.hasHorizontalScroll ? deltaX : 0;
29491        deltaY = this.hasVerticalScroll ? deltaY : 0;
29492
29493        newX = this.x + deltaX;
29494        newY = this.y + deltaY;
29495
29496        // Slow down if outside of the boundaries
29497        if ( newX > 0 || newX < this.maxScrollX ) {
29498            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
29499        }
29500        if ( newY > 0 || newY < this.maxScrollY ) {
29501            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
29502        }
29503
29504        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
29505        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
29506
29507        if ( !this.moved ) {
29508            this._execEvent('scrollStart');
29509        }
29510
29511        this.moved = true;
29512
29513        this._translate(newX, newY);
29514
29515/* REPLACE START: _move */
29516
29517        if ( timestamp - this.startTime > 300 ) {
29518            this.startTime = timestamp;
29519            this.startX = this.x;
29520            this.startY = this.y;
29521        }
29522
29523/* REPLACE END: _move */
29524
29525    },
29526
29527    _end: function (e) {
29528        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29529            return;
29530        }
29531
29532        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29533            e.preventDefault();
29534        }
29535
29536        var point = e.changedTouches ? e.changedTouches[0] : e,
29537            momentumX,
29538            momentumY,
29539            duration = utils.getTime() - this.startTime,
29540            newX = Math.round(this.x),
29541            newY = Math.round(this.y),
29542            distanceX = Math.abs(newX - this.startX),
29543            distanceY = Math.abs(newY - this.startY),
29544            time = 0,
29545            easing = '';
29546
29547        this.isInTransition = 0;
29548        this.initiated = 0;
29549        this.endTime = utils.getTime();
29550
29551        // reset if we are outside of the boundaries
29552        if ( this.resetPosition(this.options.bounceTime) ) {
29553            return;
29554        }
29555
29556        this.scrollTo(newX, newY);  // ensures that the last position is rounded
29557
29558        // we scrolled less than 10 pixels
29559        if ( !this.moved ) {
29560            if ( this.options.tap ) {
29561                utils.tap(e, this.options.tap);
29562            }
29563
29564            if ( this.options.click ) {
29565                utils.click(e);
29566            }
29567
29568            this._execEvent('scrollCancel');
29569            return;
29570        }
29571
29572        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
29573            this._execEvent('flick');
29574            return;
29575        }
29576
29577        // start momentum animation if needed
29578        if ( this.options.momentum && duration < 300 ) {
29579            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 };
29580            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 };
29581            newX = momentumX.destination;
29582            newY = momentumY.destination;
29583            time = Math.max(momentumX.duration, momentumY.duration);
29584            this.isInTransition = 1;
29585        }
29586
29587
29588        if ( this.options.snap ) {
29589            var snap = this._nearestSnap(newX, newY);
29590            this.currentPage = snap;
29591            time = this.options.snapSpeed || Math.max(
29592                    Math.max(
29593                        Math.min(Math.abs(newX - snap.x), 1000),
29594                        Math.min(Math.abs(newY - snap.y), 1000)
29595                    ), 300);
29596            newX = snap.x;
29597            newY = snap.y;
29598
29599            this.directionX = 0;
29600            this.directionY = 0;
29601            easing = this.options.bounceEasing;
29602        }
29603
29604// INSERT POINT: _end
29605
29606        if ( newX != this.x || newY != this.y ) {
29607            // change easing function when scroller goes out of the boundaries
29608            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
29609                easing = utils.ease.quadratic;
29610            }
29611
29612            this.scrollTo(newX, newY, time, easing);
29613            return;
29614        }
29615
29616        this._execEvent('scrollEnd');
29617    },
29618
29619    _resize: function () {
29620        var that = this;
29621
29622        clearTimeout(this.resizeTimeout);
29623
29624        this.resizeTimeout = setTimeout(function () {
29625            that.refresh();
29626        }, this.options.resizePolling);
29627    },
29628
29629    resetPosition: function (time) {
29630        var x = this.x,
29631            y = this.y;
29632
29633        time = time || 0;
29634
29635        if ( !this.hasHorizontalScroll || this.x > 0 ) {
29636            x = 0;
29637        } else if ( this.x < this.maxScrollX ) {
29638            x = this.maxScrollX;
29639        }
29640
29641        if ( !this.hasVerticalScroll || this.y > 0 ) {
29642            y = 0;
29643        } else if ( this.y < this.maxScrollY ) {
29644            y = this.maxScrollY;
29645        }
29646
29647        if ( x == this.x && y == this.y ) {
29648            return false;
vendor: 5,509 bytes, lines 29649-29853
29649        }
29650
29651        this.scrollTo(x, y, time, this.options.bounceEasing);
29652
29653        return true;
29654    },
29655
29656    disable: function () {
29657        this.enabled = false;
29658    },
29659
29660    enable: function () {
29661        this.enabled = true;
29662    },
29663
29664    refresh: function () {
29665        var rf = this.wrapper.offsetHeight;     // Force reflow
29666
29667        this.wrapperWidth   = this.wrapper.clientWidth;
29668        this.wrapperHeight  = this.wrapper.clientHeight;
29669
29670/* REPLACE START: refresh */
29671
29672        this.scrollerWidth  = this.scroller.offsetWidth;
29673        this.scrollerHeight = this.scroller.offsetHeight;
29674
29675        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
29676        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
29677
29678/* REPLACE END: refresh */
29679
29680        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
29681        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
29682
29683        if ( !this.hasHorizontalScroll ) {
29684            this.maxScrollX = 0;
29685            this.scrollerWidth = this.wrapperWidth;
29686        }
29687
29688        if ( !this.hasVerticalScroll ) {
29689            this.maxScrollY = 0;
29690            this.scrollerHeight = this.wrapperHeight;
29691        }
29692
29693        this.endTime = 0;
29694        this.directionX = 0;
29695        this.directionY = 0;
29696
29697        this.wrapperOffset = utils.offset(this.wrapper);
29698
29699        this._execEvent('refresh');
29700
29701        this.resetPosition();
29702
29703// INSERT POINT: _refresh
29704
29705    },
29706
29707
29708    on: function (type, fn) {
29709        if ( !this._events[type] ) {
29710            this._events[type] = [];
29711        }
29712
29713        this._events[type].push(fn);
29714    },
29715
29716    off: function (type, fn) {
29717        if ( !this._events[type] ) {
29718            return;
29719        }
29720
29721        var index = this._events[type].indexOf(fn);
29722
29723        if ( index > -1 ) {
29724            this._events[type].splice(index, 1);
29725        }
29726    },
29727
29728    _execEvent: function (type) {
29729        if ( !this._events[type] ) {
29730            return;
29731        }
29732
29733        var i = 0,
29734            l = this._events[type].length;
29735
29736        if ( !l ) {
29737            return;
29738        }
29739
29740        for ( ; i < l; i++ ) {
29741            this._events[type][i].apply(this, [].slice.call(arguments, 1));
29742        }
29743    },
29744
29745    scrollBy: function (x, y, time, easing) {
29746        x = this.x + x;
29747        y = this.y + y;
29748        time = time || 0;
29749
29750        this.scrollTo(x, y, time, easing);
29751    },
29752
29753    scrollTo: function (x, y, time, easing) {
29754        easing = easing || utils.ease.circular;
29755
29756        this.isInTransition = this.options.useTransition && time > 0;
29757        var transitionType = this.options.useTransition && easing.style;
29758        if ( !time || transitionType ) {
29759                if(transitionType) {
29760                    this._transitionTimingFunction(easing.style);
29761                    this._transitionTime(time);
29762                }
29763            this._translate(x, y);
29764        } else {
29765            this._animate(x, y, time, easing.fn);
29766        }
29767    },
29768
29769    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29770        el = el.nodeType ? el : this.scroller.querySelector(el);
29771
29772        if ( !el ) {
29773            return;
29774        }
29775
29776        var pos = utils.offset(el);
29777
29778        pos.left -= this.wrapperOffset.left;
29779        pos.top  -= this.wrapperOffset.top;
29780
29781        // if offsetX/Y are true we center the element to the screen
29782        if ( offsetX === true ) {
29783            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29784        }
29785        if ( offsetY === true ) {
29786            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29787        }
29788
29789        pos.left -= offsetX || 0;
29790        pos.top  -= offsetY || 0;
29791
29792        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29793        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29794
29795        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29796
29797        this.scrollTo(pos.left, pos.top, time, easing);
29798    },
29799
29800    _transitionTime: function (time) {
29801        if (!this.options.useTransition) {
29802            return;
29803        }
29804        time = time || 0;
29805        var durationProp = utils.style.transitionDuration;
29806        if(!durationProp) {
29807            return;
29808        }
29809
29810        this.scrollerStyle[durationProp] = time + 'ms';
29811
29812        if ( !time && utils.isBadAndroid ) {
29813            this.scrollerStyle[durationProp] = '0.0001ms';
29814            // remove 0.0001ms
29815            var self = this;
29816            rAF(function() {
29817                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29818                    self.scrollerStyle[durationProp] = '0s';
29819                }
29820            });
29821        }
29822
29823
29824        if ( this.indicators ) {
29825            for ( var i = this.indicators.length; i--; ) {
29826                this.indicators[i].transitionTime(time);
29827            }
29828        }
29829
29830
29831// INSERT POINT: _transitionTime
29832
29833    },
29834
29835    _transitionTimingFunction: function (easing) {
29836        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29837
29838
29839        if ( this.indicators ) {
29840            for ( var i = this.indicators.length; i--; ) {
29841                this.indicators[i].transitionTimingFunction(easing);
29842            }
29843        }
29844
29845
29846// INSERT POINT: _transitionTimingFunction
29847
29848    },
29849
29850    _translate: function (x, y) {
29851        //Uncode addition
29852        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29853            return false;
vendor: 9,939 bytes, lines 29854-30165
29854
29855        if ( this.options.useTransform ) {
29856
29857/* REPLACE START: _translate */
29858
29859            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29860
29861/* REPLACE END: _translate */
29862
29863        } else {
29864            x = Math.round(x);
29865            y = Math.round(y);
29866            this.scrollerStyle.left = x + 'px';
29867            this.scrollerStyle.top = y + 'px';
29868        }
29869
29870        this.x = x;
29871        this.y = y;
29872
29873
29874        if ( this.indicators ) {
29875            for ( var i = this.indicators.length; i--; ) {
29876                this.indicators[i].updatePosition();
29877            }
29878        }
29879
29880        //Uncode addition
29881        var uncodevent = new CustomEvent('fp-slide-scroll');
29882        window.dispatchEvent(uncodevent);
29883
29884// INSERT POINT: _translate
29885
29886    },
29887
29888    _initEvents: function (remove) {
29889        var eventType = remove ? utils.removeEvent : utils.addEvent,
29890            target = this.options.bindToWrapper ? this.wrapper : window;
29891
29892        eventType(window, 'orientationchange', this);
29893        eventType(window, 'resize', this);
29894
29895        if ( this.options.click ) {
29896            eventType(this.wrapper, 'click', this, true);
29897        }
29898
29899        if ( !this.options.disableMouse ) {
29900            eventType(this.wrapper, 'mousedown', this);
29901            eventType(target, 'mousemove', this);
29902            eventType(target, 'mousecancel', this);
29903            eventType(target, 'mouseup', this);
29904        }
29905
29906        if ( utils.hasPointer && !this.options.disablePointer ) {
29907            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29908            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29909            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29910            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29911        }
29912
29913        if ( utils.hasTouch && !this.options.disableTouch ) {
29914            eventType(this.wrapper, 'touchstart', this);
29915            eventType(target, 'touchmove', this);
29916            eventType(target, 'touchcancel', this);
29917            eventType(target, 'touchend', this);
29918        }
29919
29920        eventType(this.scroller, 'transitionend', this);
29921        eventType(this.scroller, 'webkitTransitionEnd', this);
29922        eventType(this.scroller, 'oTransitionEnd', this);
29923        eventType(this.scroller, 'MSTransitionEnd', this);
29924    },
29925
29926    getComputedPosition: function () {
29927        var matrix = window.getComputedStyle(this.scroller, null),
29928            x, y;
29929
29930        if ( this.options.useTransform ) {
29931            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29932            x = +(matrix[12] || matrix[4]);
29933            y = +(matrix[13] || matrix[5]);
29934        } else {
29935            x = +matrix.left.replace(/[^-\d.]/g, '');
29936            y = +matrix.top.replace(/[^-\d.]/g, '');
29937        }
29938
29939        return { x: x, y: y };
29940    },
29941    _initIndicators: function () {
29942        var interactive = this.options.interactiveScrollbars,
29943            customStyle = typeof this.options.scrollbars != 'string',
29944            indicators = [],
29945            indicator;
29946
29947        var that = this;
29948
29949        this.indicators = [];
29950
29951        if ( this.options.scrollbars ) {
29952            // Vertical scrollbar
29953            if ( this.options.scrollY ) {
29954                indicator = {
29955                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
29956                    interactive: interactive,
29957                    defaultScrollbars: true,
29958                    customStyle: customStyle,
29959                    resize: this.options.resizeScrollbars,
29960                    shrink: this.options.shrinkScrollbars,
29961                    fade: this.options.fadeScrollbars,
29962                    listenX: false
29963                };
29964
29965                this.wrapper.appendChild(indicator.el);
29966                indicators.push(indicator);
29967            }
29968
29969            // Horizontal scrollbar
29970            if ( this.options.scrollX ) {
29971                indicator = {
29972                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
29973                    interactive: interactive,
29974                    defaultScrollbars: true,
29975                    customStyle: customStyle,
29976                    resize: this.options.resizeScrollbars,
29977                    shrink: this.options.shrinkScrollbars,
29978                    fade: this.options.fadeScrollbars,
29979                    listenY: false
29980                };
29981
29982                this.wrapper.appendChild(indicator.el);
29983                indicators.push(indicator);
29984            }
29985        }
29986
29987        if ( this.options.indicators ) {
29988            // TODO: check concat compatibility
29989            indicators = indicators.concat(this.options.indicators);
29990        }
29991
29992        for ( var i = indicators.length; i--; ) {
29993            this.indicators.push( new Indicator(this, indicators[i]) );
29994        }
29995
29996        // TODO: check if we can use array.map (wide compatibility and performance issues)
29997        function _indicatorsMap (fn) {
29998            if (that.indicators) {
29999                for ( var i = that.indicators.length; i--; ) {
30000                    fn.call(that.indicators[i]);
30001                }
30002            }
30003        }
30004
30005        if ( this.options.fadeScrollbars ) {
30006            this.on('scrollEnd', function () {
30007                _indicatorsMap(function () {
30008                    this.fade();
30009                });
30010            });
30011
30012            this.on('scrollCancel', function () {
30013                _indicatorsMap(function () {
30014                    this.fade();
30015                });
30016            });
30017
30018            this.on('scrollStart', function () {
30019                _indicatorsMap(function () {
30020                    this.fade(1);
30021                });
30022            });
30023
30024            this.on('beforeScrollStart', function () {
30025                _indicatorsMap(function () {
30026                    this.fade(1, true);
30027                });
30028            });
30029        }
30030
30031
30032        this.on('refresh', function () {
30033            _indicatorsMap(function () {
30034                this.refresh();
30035            });
30036        });
30037
30038        this.on('destroy', function () {
30039            _indicatorsMap(function () {
30040                this.destroy();
30041            });
30042
30043            delete this.indicators;
30044        });
30045    },
30046
30047    _initWheel: function () {
30048        utils.addEvent(this.wrapper, 'wheel', this);
30049        utils.addEvent(this.wrapper, 'mousewheel', this);
30050        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30051
30052        this.on('destroy', function () {
30053            clearTimeout(this.wheelTimeout);
30054            this.wheelTimeout = null;
30055            utils.removeEvent(this.wrapper, 'wheel', this);
30056            utils.removeEvent(this.wrapper, 'mousewheel', this);
30057            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
30058        });
30059    },
30060
30061    _wheel: function (e) {
30062        if ( !this.enabled ) {
30063            return;
30064        }
30065
30066        var wheelDeltaX, wheelDeltaY,
30067            newX, newY,
30068            that = this;
30069
30070        if ( this.wheelTimeout === undefined ) {
30071            that._execEvent('scrollStart');
30072        }
30073
30074        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
30075        clearTimeout(this.wheelTimeout);
30076        this.wheelTimeout = setTimeout(function () {
30077            if(!that.options.snap) {
30078                that._execEvent('scrollEnd');
30079            }
30080            that.wheelTimeout = undefined;
30081        }, 400);
30082
30083        if ( 'deltaX' in e ) {
30084            if (e.deltaMode === 1) {
30085                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
30086                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
30087            } else {
30088                wheelDeltaX = -e.deltaX;
30089                wheelDeltaY = -e.deltaY;
30090            }
30091        } else if ( 'wheelDeltaX' in e ) {
30092            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
30093            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
30094        } else if ( 'wheelDelta' in e ) {
30095            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
30096        } else if ( 'detail' in e ) {
30097            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
30098        } else {
30099            return;
30100        }
30101
30102        wheelDeltaX *= this.options.invertWheelDirection;
30103        wheelDeltaY *= this.options.invertWheelDirection;
30104
30105        if ( !this.hasVerticalScroll ) {
30106            wheelDeltaX = wheelDeltaY;
30107            wheelDeltaY = 0;
30108        }
30109
30110        if ( this.options.snap ) {
30111            newX = this.currentPage.pageX;
30112            newY = this.currentPage.pageY;
30113
30114            if ( wheelDeltaX > 0 ) {
30115                newX--;
30116            } else if ( wheelDeltaX < 0 ) {
30117                newX++;
30118            }
30119
30120            if ( wheelDeltaY > 0 ) {
30121                newY--;
30122            } else if ( wheelDeltaY < 0 ) {
30123                newY++;
30124            }
30125
30126            this.goToPage(newX, newY);
30127
30128            return;
30129        }
30130
30131        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
30132        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
30133
30134        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
30135        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
30136
30137        if ( newX > 0 ) {
30138            newX = 0;
30139        } else if ( newX < this.maxScrollX ) {
30140            newX = this.maxScrollX;
30141        }
30142
30143        if ( newY > 0 ) {
30144            newY = 0;
30145        } else if ( newY < this.maxScrollY ) {
30146            newY = this.maxScrollY;
30147        }
30148
30149        this.scrollTo(newX, newY, 0);
30150
30151// INSERT POINT: _wheel
30152    },
30153
30154    _initSnap: function () {
30155        this.currentPage = {};
30156
30157        if ( typeof this.options.snap == 'string' ) {
30158            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
30159        }
30160
30161        this.on('refresh', function () {
30162            var i = 0, l,
30163                m = 0, n,
30164                cx, cy,
30165                x = 0, y,
vendor: 7,339 bytes, lines 30166-30419
30166                stepX = this.options.snapStepX || this.wrapperWidth,
30167                stepY = this.options.snapStepY || this.wrapperHeight,
30168                el;
30169
30170            this.pages = [];
30171
30172            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
30173                return;
30174            }
30175
30176            if ( this.options.snap === true ) {
30177                cx = Math.round( stepX / 2 );
30178                cy = Math.round( stepY / 2 );
30179
30180                while ( x > -this.scrollerWidth ) {
30181                    this.pages[i] = [];
30182                    l = 0;
30183                    y = 0;
30184
30185                    while ( y > -this.scrollerHeight ) {
30186                        this.pages[i][l] = {
30187                            x: Math.max(x, this.maxScrollX),
30188                            y: Math.max(y, this.maxScrollY),
30189                            width: stepX,
30190                            height: stepY,
30191                            cx: x - cx,
30192                            cy: y - cy
30193                        };
30194
30195                        y -= stepY;
30196                        l++;
30197                    }
30198
30199                    x -= stepX;
30200                    i++;
30201                }
30202            } else {
30203                el = this.options.snap;
30204                l = el.length;
30205                n = -1;
30206
30207                for ( ; i < l; i++ ) {
30208                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
30209                        m = 0;
30210                        n++;
30211                    }
30212
30213                    if ( !this.pages[m] ) {
30214                        this.pages[m] = [];
30215                    }
30216
30217                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
30218                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
30219                    cx = x - Math.round(el[i].offsetWidth / 2);
30220                    cy = y - Math.round(el[i].offsetHeight / 2);
30221
30222                    this.pages[m][n] = {
30223                        x: x,
30224                        y: y,
30225                        width: el[i].offsetWidth,
30226                        height: el[i].offsetHeight,
30227                        cx: cx,
30228                        cy: cy
30229                    };
30230
30231                    if ( x > this.maxScrollX ) {
30232                        m++;
30233                    }
30234                }
30235            }
30236
30237            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
30238
30239            // Update snap threshold if needed
30240            if ( this.options.snapThreshold % 1 === 0 ) {
30241                this.snapThresholdX = this.options.snapThreshold;
30242                this.snapThresholdY = this.options.snapThreshold;
30243            } else {
30244                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
30245                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
30246            }
30247        });
30248
30249        this.on('flick', function () {
30250            var time = this.options.snapSpeed || Math.max(
30251                    Math.max(
30252                        Math.min(Math.abs(this.x - this.startX), 1000),
30253                        Math.min(Math.abs(this.y - this.startY), 1000)
30254                    ), 300);
30255
30256            this.goToPage(
30257                this.currentPage.pageX + this.directionX,
30258                this.currentPage.pageY + this.directionY,
30259                time
30260            );
30261        });
30262    },
30263
30264    _nearestSnap: function (x, y) {
30265        if ( !this.pages.length ) {
30266            return { x: 0, y: 0, pageX: 0, pageY: 0 };
30267        }
30268
30269        var i = 0,
30270            l = this.pages.length,
30271            m = 0;
30272
30273        // Check if we exceeded the snap threshold
30274        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
30275            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
30276            return this.currentPage;
30277        }
30278
30279        if ( x > 0 ) {
30280            x = 0;
30281        } else if ( x < this.maxScrollX ) {
30282            x = this.maxScrollX;
30283        }
30284
30285        if ( y > 0 ) {
30286            y = 0;
30287        } else if ( y < this.maxScrollY ) {
30288            y = this.maxScrollY;
30289        }
30290
30291        for ( ; i < l; i++ ) {
30292            if ( x >= this.pages[i][0].cx ) {
30293                x = this.pages[i][0].x;
30294                break;
30295            }
30296        }
30297
30298        l = this.pages[i].length;
30299
30300        for ( ; m < l; m++ ) {
30301            if ( y >= this.pages[0][m].cy ) {
30302                y = this.pages[0][m].y;
30303                break;
30304            }
30305        }
30306
30307        if ( i == this.currentPage.pageX ) {
30308            i += this.directionX;
30309
30310            if ( i < 0 ) {
30311                i = 0;
30312            } else if ( i >= this.pages.length ) {
30313                i = this.pages.length - 1;
30314            }
30315
30316            x = this.pages[i][0].x;
30317        }
30318
30319        if ( m == this.currentPage.pageY ) {
30320            m += this.directionY;
30321
30322            if ( m < 0 ) {
30323                m = 0;
30324            } else if ( m >= this.pages[0].length ) {
30325                m = this.pages[0].length - 1;
30326            }
30327
30328            y = this.pages[0][m].y;
30329        }
30330
30331        return {
30332            x: x,
30333            y: y,
30334            pageX: i,
30335            pageY: m
30336        };
30337    },
30338
30339    goToPage: function (x, y, time, easing) {
30340        easing = easing || this.options.bounceEasing;
30341
30342        if ( x >= this.pages.length ) {
30343            x = this.pages.length - 1;
30344        } else if ( x < 0 ) {
30345            x = 0;
30346        }
30347
30348        if ( y >= this.pages[x].length ) {
30349            y = this.pages[x].length - 1;
30350        } else if ( y < 0 ) {
30351            y = 0;
30352        }
30353
30354        var posX = this.pages[x][y].x,
30355            posY = this.pages[x][y].y;
30356
30357        time = time === undefined ? this.options.snapSpeed || Math.max(
30358            Math.max(
30359                Math.min(Math.abs(posX - this.x), 1000),
30360                Math.min(Math.abs(posY - this.y), 1000)
30361            ), 300) : time;
30362
30363        this.currentPage = {
30364            x: posX,
30365            y: posY,
30366            pageX: x,
30367            pageY: y
30368        };
30369
30370        this.scrollTo(posX, posY, time, easing);
30371    },
30372
30373    next: function (time, easing) {
30374        var x = this.currentPage.pageX,
30375            y = this.currentPage.pageY;
30376
30377        x++;
30378
30379        if ( x >= this.pages.length && this.hasVerticalScroll ) {
30380            x = 0;
30381            y++;
30382        }
30383
30384        this.goToPage(x, y, time, easing);
30385    },
30386
30387    prev: function (time, easing) {
30388        var x = this.currentPage.pageX,
30389            y = this.currentPage.pageY;
30390
30391        x--;
30392
30393        if ( x < 0 && this.hasVerticalScroll ) {
30394            x = 0;
30395            y--;
30396        }
30397
30398        this.goToPage(x, y, time, easing);
30399    },
30400
30401    _initKeys: function (e) {
30402        // default key bindings
30403        var keys = {
30404            pageUp: 33,
30405            pageDown: 34,
30406            end: 35,
30407            home: 36,
30408            left: 37,
30409            up: 38,
30410            right: 39,
30411            down: 40
30412        };
30413        var i;
30414
30415        // if you give me characters I give you keycode
30416        if ( typeof this.options.keyBindings == 'object' ) {
30417            for ( i in this.options.keyBindings ) {
30418                if ( typeof this.options.keyBindings[i] == 'string' ) {
30419                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 30419-30772
30419deAt(0);
30420                }
30421            }
30422        } else {
30423            this.options.keyBindings = {};
30424        }
30425
30426        for ( i in keys ) {
30427            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
30428        }
30429
30430        utils.addEvent(window, 'keydown', this);
30431
30432        this.on('destroy', function () {
30433            utils.removeEvent(window, 'keydown', this);
30434        });
30435    },
30436
30437    _key: function (e) {
30438        if ( !this.enabled ) {
30439            return;
30440        }
30441
30442        var snap = this.options.snap,   // we are using this alot, better to cache it
30443            newX = snap ? this.currentPage.pageX : this.x,
30444            newY = snap ? this.currentPage.pageY : this.y,
30445            now = utils.getTime(),
30446            prevTime = this.keyTime || 0,
30447            acceleration = 0.250,
30448            pos;
30449
30450        if ( this.options.useTransition && this.isInTransition ) {
30451            pos = this.getComputedPosition();
30452
30453            this._translate(Math.round(pos.x), Math.round(pos.y));
30454            this.isInTransition = false;
30455        }
30456
30457        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
30458
30459        switch ( e.keyCode ) {
30460            case this.options.keyBindings.pageUp:
30461                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30462                    newX += snap ? 1 : this.wrapperWidth;
30463                } else {
30464                    newY += snap ? 1 : this.wrapperHeight;
30465                }
30466                break;
30467            case this.options.keyBindings.pageDown:
30468                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30469                    newX -= snap ? 1 : this.wrapperWidth;
30470                } else {
30471                    newY -= snap ? 1 : this.wrapperHeight;
30472                }
30473                break;
30474            case this.options.keyBindings.end:
30475                newX = snap ? this.pages.length-1 : this.maxScrollX;
30476                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
30477                break;
30478            case this.options.keyBindings.home:
30479                newX = 0;
30480                newY = 0;
30481                break;
30482            case this.options.keyBindings.left:
30483                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
30484                break;
30485            case this.options.keyBindings.up:
30486                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
30487                break;
30488            case this.options.keyBindings.right:
30489                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
30490                break;
30491            case this.options.keyBindings.down:
30492                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
30493                break;
30494            default:
30495                return;
30496        }
30497
30498        if ( snap ) {
30499            this.goToPage(newX, newY);
30500            return;
30501        }
30502
30503        if ( newX > 0 ) {
30504            newX = 0;
30505            this.keyAcceleration = 0;
30506        } else if ( newX < this.maxScrollX ) {
30507            newX = this.maxScrollX;
30508            this.keyAcceleration = 0;
30509        }
30510
30511        if ( newY > 0 ) {
30512            newY = 0;
30513            this.keyAcceleration = 0;
30514        } else if ( newY < this.maxScrollY ) {
30515            newY = this.maxScrollY;
30516            this.keyAcceleration = 0;
30517        }
30518
30519        this.scrollTo(newX, newY, 0);
30520
30521        this.keyTime = now;
30522    },
30523
30524    _animate: function (destX, destY, duration, easingFn) {
30525        var that = this,
30526            startX = this.x,
30527            startY = this.y,
30528            startTime = utils.getTime(),
30529            destTime = startTime + duration;
30530
30531        function step () {
30532            var now = utils.getTime(),
30533                newX, newY,
30534                easing;
30535
30536            if ( now >= destTime ) {
30537                that.isAnimating = false;
30538                that._translate(destX, destY);
30539
30540                if ( !that.resetPosition(that.options.bounceTime) ) {
30541                    that._execEvent('scrollEnd');
30542                }
30543
30544                return;
30545            }
30546
30547            now = ( now - startTime ) / duration;
30548            easing = easingFn(now);
30549            newX = ( destX - startX ) * easing + startX;
30550            newY = ( destY - startY ) * easing + startY;
30551            that._translate(newX, newY);
30552
30553            if ( that.isAnimating ) {
30554                rAF(step);
30555            }
30556        }
30557
30558        this.isAnimating = true;
30559        step();
30560    },
30561    handleEvent: function (e) {
30562        switch ( e.type ) {
30563            case 'touchstart':
30564            case 'pointerdown':
30565            case 'MSPointerDown':
30566            case 'mousedown':
30567                this._start(e);
30568                break;
30569            case 'touchmove':
30570            case 'pointermove':
30571            case 'MSPointerMove':
30572            case 'mousemove':
30573                this._move(e);
30574                break;
30575            case 'touchend':
30576            case 'pointerup':
30577            case 'MSPointerUp':
30578            case 'mouseup':
30579            case 'touchcancel':
30580            case 'pointercancel':
30581            case 'MSPointerCancel':
30582            case 'mousecancel':
30583                this._end(e);
30584                break;
30585            case 'orientationchange':
30586            case 'resize':
30587                this._resize();
30588                break;
30589            case 'transitionend':
30590            case 'webkitTransitionEnd':
30591            case 'oTransitionEnd':
30592            case 'MSTransitionEnd':
30593                this._transitionEnd(e);
30594                break;
30595            case 'wheel':
30596            case 'DOMMouseScroll':
30597            case 'mousewheel':
30598                this._wheel(e);
30599                break;
30600            case 'keydown':
30601                this._key(e);
30602                break;
30603            case 'click':
30604                if ( this.enabled && !e._constructed ) {
30605                    e.preventDefault();
30606                    e.stopPropagation();
30607                }
30608                break;
30609        }
30610    }
30611};
30612function createDefaultScrollbar (direction, interactive, type) {
30613    var scrollbar = document.createElement('div'),
30614        indicator = document.createElement('div');
30615
30616    if ( type === true ) {
30617        scrollbar.style.cssText = 'position:absolute;z-index:9999';
30618        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';
30619    }
30620
30621    indicator.className = 'iScrollIndicator';
30622
30623    if ( direction == 'h' ) {
30624        if ( type === true ) {
30625            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
30626            indicator.style.height = '100%';
30627        }
30628        scrollbar.className = 'iScrollHorizontalScrollbar';
30629    } else {
30630        if ( type === true ) {
30631            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
30632            indicator.style.width = '100%';
30633        }
30634        scrollbar.className = 'iScrollVerticalScrollbar';
30635    }
30636
30637    scrollbar.style.cssText += ';overflow:hidden';
30638
30639    if ( !interactive ) {
30640        scrollbar.style.pointerEvents = 'none';
30641    }
30642
30643    scrollbar.appendChild(indicator);
30644
30645    return scrollbar;
30646}
30647
30648function Indicator (scroller, options) {
30649    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
30650    this.wrapperStyle = this.wrapper.style;
30651    this.indicator = this.wrapper.children[0];
30652    this.indicatorStyle = this.indicator.style;
30653    this.scroller = scroller;
30654
30655    this.options = {
30656        listenX: true,
30657        listenY: true,
30658        interactive: false,
30659        resize: true,
30660        defaultScrollbars: false,
30661        shrink: false,
30662        fade: false,
30663        speedRatioX: 0,
30664        speedRatioY: 0
30665    };
30666
30667    for ( var i in options ) {
30668        this.options[i] = options[i];
30669    }
30670
30671    this.sizeRatioX = 1;
30672    this.sizeRatioY = 1;
30673    this.maxPosX = 0;
30674    this.maxPosY = 0;
30675
30676    if ( this.options.interactive ) {
30677        if ( !this.options.disableTouch ) {
30678            utils.addEvent(this.indicator, 'touchstart', this);
30679            utils.addEvent(window, 'touchend', this);
30680        }
30681        if ( !this.options.disablePointer ) {
30682            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30683            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
30684        }
30685        if ( !this.options.disableMouse ) {
30686            utils.addEvent(this.indicator, 'mousedown', this);
30687            utils.addEvent(window, 'mouseup', this);
30688        }
30689    }
30690
30691    if ( this.options.fade ) {
30692        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
30693        var durationProp = utils.style.transitionDuration;
30694        if(!durationProp) {
30695            return;
30696        }
30697        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
30698        // remove 0.0001ms
30699        var self = this;
30700        if(utils.isBadAndroid) {
30701            rAF(function() {
30702                if(self.wrapperStyle[durationProp] === '0.0001ms') {
30703                    self.wrapperStyle[durationProp] = '0s';
30704                }
30705            });
30706        }
30707        this.wrapperStyle.opacity = '0';
30708    }
30709}
30710
30711Indicator.prototype = {
30712    handleEvent: function (e) {
30713        switch ( e.type ) {
30714            case 'touchstart':
30715            case 'pointerdown':
30716            case 'MSPointerDown':
30717            case 'mousedown':
30718                this._start(e);
30719                break;
30720            case 'touchmove':
30721            case 'pointermove':
30722            case 'MSPointerMove':
30723            case 'mousemove':
30724                this._move(e);
30725                break;
30726            case 'touchend':
30727            case 'pointerup':
30728            case 'MSPointerUp':
30729            case 'mouseup':
30730            case 'touchcancel':
30731            case 'pointercancel':
30732            case 'MSPointerCancel':
30733            case 'mousecancel':
30734                this._end(e);
30735                break;
30736        }
30737    },
30738
30739    destroy: function () {
30740        if ( this.options.fadeScrollbars ) {
30741            clearTimeout(this.fadeTimeout);
30742            this.fadeTimeout = null;
30743        }
30744        if ( this.options.interactive ) {
30745            utils.removeEvent(this.indicator, 'touchstart', this);
30746            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30747            utils.removeEvent(this.indicator, 'mousedown', this);
30748
30749            utils.removeEvent(window, 'touchmove', this);
30750            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30751            utils.removeEvent(window, 'mousemove', this);
30752
30753            utils.removeEvent(window, 'touchend', this);
30754            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
30755            utils.removeEvent(window, 'mouseup', this);
30756        }
30757
30758        if ( this.options.defaultScrollbars ) {
30759            this.wrapper.parentNode.removeChild(this.wrapper);
30760        }
30761    },
30762
30763    _start: function (e) {
30764        var point = e.touches ? e.touches[0] : e;
30765
30766        e.preventDefault();
30767        e.stopPropagation();
30768
30769        this.transitionTime();
30770
30771        this.initiated = true;
30772        this.moved = false;
vendor: 9,615 bytes, lines 30773-31031
30773        this.lastPointX = point.pageX;
30774        this.lastPointY = point.pageY;
30775
30776        this.startTime  = utils.getTime();
30777
30778        if ( !this.options.disableTouch ) {
30779            utils.addEvent(window, 'touchmove', this);
30780        }
30781        if ( !this.options.disablePointer ) {
30782            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30783        }
30784        if ( !this.options.disableMouse ) {
30785            utils.addEvent(window, 'mousemove', this);
30786        }
30787
30788        this.scroller._execEvent('beforeScrollStart');
30789    },
30790
30791    _move: function (e) {
30792        var point = e.touches ? e.touches[0] : e,
30793            deltaX, deltaY,
30794            newX, newY,
30795            timestamp = utils.getTime();
30796
30797        if ( !this.moved ) {
30798            this.scroller._execEvent('scrollStart');
30799        }
30800
30801        this.moved = true;
30802
30803        deltaX = point.pageX - this.lastPointX;
30804        this.lastPointX = point.pageX;
30805
30806        deltaY = point.pageY - this.lastPointY;
30807        this.lastPointY = point.pageY;
30808
30809        newX = this.x + deltaX;
30810        newY = this.y + deltaY;
30811
30812        this._pos(newX, newY);
30813
30814// INSERT POINT: indicator._move
30815
30816        e.preventDefault();
30817        e.stopPropagation();
30818    },
30819
30820    _end: function (e) {
30821        if ( !this.initiated ) {
30822            return;
30823        }
30824
30825        this.initiated = false;
30826
30827        e.preventDefault();
30828        e.stopPropagation();
30829
30830        utils.removeEvent(window, 'touchmove', this);
30831        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30832        utils.removeEvent(window, 'mousemove', this);
30833
30834        if ( this.scroller.options.snap ) {
30835            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30836
30837            var time = this.options.snapSpeed || Math.max(
30838                    Math.max(
30839                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30840                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30841                    ), 300);
30842
30843            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30844                this.scroller.directionX = 0;
30845                this.scroller.directionY = 0;
30846                this.scroller.currentPage = snap;
30847                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30848            }
30849        }
30850
30851        if ( this.moved ) {
30852            this.scroller._execEvent('scrollEnd');
30853        }
30854    },
30855
30856    transitionTime: function (time) {
30857        time = time || 0;
30858        var durationProp = utils.style.transitionDuration;
30859        if(!durationProp) {
30860            return;
30861        }
30862
30863        this.indicatorStyle[durationProp] = time + 'ms';
30864
30865        if ( !time && utils.isBadAndroid ) {
30866            this.indicatorStyle[durationProp] = '0.0001ms';
30867            // remove 0.0001ms
30868            var self = this;
30869            rAF(function() {
30870                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30871                    self.indicatorStyle[durationProp] = '0s';
30872                }
30873            });
30874        }
30875    },
30876
30877    transitionTimingFunction: function (easing) {
30878        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30879    },
30880
30881    refresh: function () {
30882        this.transitionTime();
30883
30884        if ( this.options.listenX && !this.options.listenY ) {
30885            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30886        } else if ( this.options.listenY && !this.options.listenX ) {
30887            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30888        } else {
30889            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30890        }
30891
30892        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30893            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30894            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30895
30896            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30897                if ( this.options.listenX ) {
30898                    this.wrapper.style.right = '8px';
30899                } else {
30900                    this.wrapper.style.bottom = '8px';
30901                }
30902            }
30903        } else {
30904            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30905            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30906
30907            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30908                if ( this.options.listenX ) {
30909                    this.wrapper.style.right = '2px';
30910                } else {
30911                    this.wrapper.style.bottom = '2px';
30912                }
30913            }
30914        }
30915
30916        var r = this.wrapper.offsetHeight;  // force refresh
30917
30918        if ( this.options.listenX ) {
30919            this.wrapperWidth = this.wrapper.clientWidth;
30920            if ( this.options.resize ) {
30921                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30922                this.indicatorStyle.width = this.indicatorWidth + 'px';
30923            } else {
30924                this.indicatorWidth = this.indicator.clientWidth;
30925            }
30926
30927            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30928
30929            if ( this.options.shrink == 'clip' ) {
30930                this.minBoundaryX = -this.indicatorWidth + 8;
30931                this.maxBoundaryX = this.wrapperWidth - 8;
30932            } else {
30933                this.minBoundaryX = 0;
30934                this.maxBoundaryX = this.maxPosX;
30935            }
30936
30937            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30938        }
30939
30940        if ( this.options.listenY ) {
30941            this.wrapperHeight = this.wrapper.clientHeight;
30942            if ( this.options.resize ) {
30943                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
30944                this.indicatorStyle.height = this.indicatorHeight + 'px';
30945            } else {
30946                this.indicatorHeight = this.indicator.clientHeight;
30947            }
30948
30949            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30950
30951            if ( this.options.shrink == 'clip' ) {
30952                this.minBoundaryY = -this.indicatorHeight + 8;
30953                this.maxBoundaryY = this.wrapperHeight - 8;
30954            } else {
30955                this.minBoundaryY = 0;
30956                this.maxBoundaryY = this.maxPosY;
30957            }
30958
30959            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30960            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
30961        }
30962
30963        this.updatePosition();
30964    },
30965
30966    updatePosition: function () {
30967        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
30968            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
30969
30970        if ( !this.options.ignoreBoundaries ) {
30971            if ( x < this.minBoundaryX ) {
30972                if ( this.options.shrink == 'scale' ) {
30973                    this.width = Math.max(this.indicatorWidth + x, 8);
30974                    this.indicatorStyle.width = this.width + 'px';
30975                }
30976                x = this.minBoundaryX;
30977            } else if ( x > this.maxBoundaryX ) {
30978                if ( this.options.shrink == 'scale' ) {
30979                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
30980                    this.indicatorStyle.width = this.width + 'px';
30981                    x = this.maxPosX + this.indicatorWidth - this.width;
30982                } else {
30983                    x = this.maxBoundaryX;
30984                }
30985            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
30986                this.width = this.indicatorWidth;
30987                this.indicatorStyle.width = this.width + 'px';
30988            }
30989
30990            if ( y < this.minBoundaryY ) {
30991                if ( this.options.shrink == 'scale' ) {
30992                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
30993                    this.indicatorStyle.height = this.height + 'px';
30994                }
30995                y = this.minBoundaryY;
30996            } else if ( y > this.maxBoundaryY ) {
30997                if ( this.options.shrink == 'scale' ) {
30998                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
30999                    this.indicatorStyle.height = this.height + 'px';
31000                    y = this.maxPosY + this.indicatorHeight - this.height;
31001                } else {
31002                    y = this.maxBoundaryY;
31003                }
31004            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31005                this.height = this.indicatorHeight;
31006                this.indicatorStyle.height = this.height + 'px';
31007            }
31008        }
31009
31010        this.x = x;
31011        this.y = y;
31012
31013        if ( this.scroller.options.useTransform ) {
31014            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31015        } else {
31016            this.indicatorStyle.left = x + 'px';
31017            this.indicatorStyle.top = y + 'px';
31018        }
31019    },
31020
31021    _pos: function (x, y) {
31022        if ( x < 0 ) {
31023            x = 0;
31024        } else if ( x > this.maxPosX ) {
31025            x = this.maxPosX;
31026        }
31027
31028        if ( y < 0 ) {
31029            y = 0;
31030        } else if ( y > this.maxPosY ) {
31031            y = this.maxPosY;
31032        }
31033
31034        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31035        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31036
31037        this.scroller.scrollTo(x, y);
31038    },
31039
31040    fade: function (val, hold) {
31041        if ( hold && !this.visible ) {
31042            return;
31043        }
31044
31045        clearTimeout(this.fadeTimeout);
31046        this.fadeTimeout = null;
31047
31048        var time = val ? 250 : 500,
31049            delay = val ? 0 : 300;
31050
31051        val = val ? '1' : '0';
31052
31053        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31054
31055        this.fadeTimeout = setTimeout((function (val) {
31056            this.wrapperStyle.opacity = val;
31057            this.visible = +val;
31058        }).bind(this, val), delay);
31059    }
31060};
31061
31062IScroll.utils = utils;
31063
31064if ( typeof module != 'undefined' && module.exports ) {
31065    module.exports = IScroll;
31066} else if ( typeof define == 'function' && define.amd ) {
31067        define( function () { return IScroll; } );
31068} else {
31069    window.IScroll = IScroll;
31070}
31071
31072})(window, document, Math);
31073/*!
31074 * fullPage 2.9.4
31075 * https://github.com/alvarotrigo/fullPage.js
31076 * @license MIT licensed
31077 *
31078 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
31079 */
31080(function(global, factory) {
31081    'use strict';
31082    if (typeof define === 'function' && define.amd) {
31083        define(['jquery'], function($) {
31084          return factory($, global, global.document, global.Math);
31085        });
31086    } else if (typeof exports === "object" && exports) {
31087        module.exports = factory(require('jquery'), global, global.document, global.Math);
31088    } else {
31089        factory(jQuery, global, global.document, global.Math);
31090    }
31091})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
31092    'use strict';
31093
31094    // keeping central set of classnames and selectors
31095    var WRAPPER =               'fullpage-wrapper';
31096    var WRAPPER_SEL =           '.' + WRAPPER;
31097
31098    // slimscroll
31099    var SCROLLABLE =            'fp-scrollable';
31100    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
31101
31102    // util
31103    var RESPONSIVE =            'fp-responsive';
31104    var NO_TRANSITION =         'fp-notransition';
31105    var DESTROYED =             'fp-destroyed';
31106    var ENABLED =               'fp-enabled';
31107    var VIEWING_PREFIX =        'fp-viewing';
31108    var ACTIVE =                'active';
31109    var ACTIVE_SEL =            '.' + ACTIVE;
31110    var COMPLETELY =            'fp-completely';
31111    var COMPLETELY_SEL =        '.' + COMPLETELY;
31112
31113    // section
31114    var SECTION_DEFAULT_SEL =   '.section';
31115    var SECTION =               'fp-section';
31116    var SECTION_SEL =           '.' + SECTION;
31117    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
31118    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
31119    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
31120    var TABLE_CELL =            'fp-tableCell';
31121    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
31122    var AUTO_HEIGHT =           'fp-auto-height';
31123    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
31124    var NORMAL_SCROLL =         'fp-normal-scroll';
31125    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
31126
31127    // section nav
31128    var SECTION_NAV =           'fp-nav';
31129    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
31130    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
31131    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
31132    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
31133
31134    // slide
31135    var SLIDE_DEFAULT_SEL =     '.slide';
31136    var SLIDE =                 'fp-slide';
31137    var SLIDE_SEL =             '.' + SLIDE;
31138    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
31139    var SLIDES_WRAPPER =        'fp-slides';
31140    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
31141    var SLIDES_CONTAINER =      'fp-slidesContainer';
31142    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
31143    var TABLE =                 'fp-table';
31144
31145    // slide nav
31146    var SLIDES_NAV =            'fp-slidesNav';
31147    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
31148    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
31149    var SLIDES_ARROW =          'fp-controlArrow';
31150    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
31151    var SLIDES_PREV =           'fp-prev';
31152    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
31153    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
31154    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
31155    var SLIDES_NEXT =           'fp-next';
31156    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
31157    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
31158    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
31159
31160    var $window = $(window);
31161    var $document = $(document);
31162
31163    // Default options for iScroll.js used when using scrollOverflow
31164    var iscrollOptions = {
31165        scrollbars: true,
31166        mouseWheel: true,
31167        hideScrollbars: false,
31168        fadeScrollbars: false,
31169        disableMouse: true,
31170        interactiveScrollbars: true,
31171        bounce: false,
31172    };
31173
31174    $.fn.fullpage = function(options) {
31175        //only once my friend!
31176        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
31177
31178        // common jQuery objects
31179        var $htmlBody = $('html, body');
31180        var $body = $('body');
31181
31182        var FP = $.fn.fullpage;
31183
31184        // Creating some defaults, extending them with any options that were provided
31185        options = $.extend({
31186            //navigation
31187            menu: false,
31188            anchors:[],
31189            lockAnchors: false,
31190            navigation: false,
31191            navigationPosition: 'right',
31192            navigationTooltips: [],
31193            showActiveTooltip: false,
31194            slidesNavigation: false,
31195            slidesNavPosition: 'bottom',
31196            scrollBar: false,
31197            hybrid: false,
31198
31199            //scrolling
31200            css3: true,
31201            scrollingSpeed: 700,
31202            autoScrolling: true,
31203            fitToSection: true,
31204            fitToSectionDelay: 1000,
31205            easing: 'easeInOutCubic',
31206            easingcss3: 'ease',
31207            loopBottom: false,
31208            loopTop: false,
31209            loopHorizontal: true,
31210            continuousVertical: false,
31211            continuousHorizontal: false,
31212            scrollHorizontally: false,
31213            interlockedSlides: false,
31214            dragAndMove: false,
31215            offsetSections: false,
31216            resetSliders: false,
31217            fadingEffect: false,
31218            normalScrollElements: null,
31219            scrollOverflow: false,
31220            scrollOverflowReset: false,
31221            scrollOverflowHandler: iscrollHandler,
31222            scrollOverflowOptions: null,
31223            touchSensitivity: 5,
31224            normalScrollElementTouchThreshold: 5,
31225            bigSectionsDestination: null,
31226
31227            //Accessibility
31228            keyboardScrolling: true,
31229            animateAnchor: true,
31230            recordHistory: true,
31231
31232            //design
31233            controlArrows: true,
31234            controlArrowColor: '#fff',
31235            verticalCentered: true,
31236            sectionsColor : [],
31237            paddingTop: 0,
31238            paddingBottom: 0,
31239            fixedElements: null,
31240            responsive: 0, //backwards compabitility with responsiveWiddth
31241            responsiveWidth: 0,
31242            responsiveHeight: 0,
31243            responsiveSlides: false,
31244            parallax: false,
31245            parallaxOptions: {
31246                type: 'reveal',
31247                percentage: 62,
31248                property: 'translate'
31249            },
31250
31251            //Custom selectors
31252            sectionSelector: SECTION_DEFAULT_SEL,
31253            slideSelector: SLIDE_DEFAULT_SEL,
31254
31255            //events
31256            afterLoad: null,
31257            onLeave: null,
31258            afterRender: null,
31259            afterResize: null,
31260            afterReBuild: null,
31261            afterSlideLoad: null,
31262            onSlideLeave: null,
31263            afterResponsive: null,
31264
31265            lazyLoading: true
31266        }, options);
31267
31268        //flag to avoid very fast sliding for landscape sliders
31269        var slideMoving = false;
31270
31271        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
31272        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
31273        var container = $(this);
31274        var windowsHeight = $window.height();
31275        var isResizing = false;
31276        var isWindowFocused = true;
31277        var lastScrolledDestiny;
31278        var lastScrolledSlide;
31279        var canScroll = true;
31280        var scrollings = [];
31281        var controlPressed;
31282        var startingSection;
31283        var isScrollAllowed = {};
31284        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
31285        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
31286        var MSPointer = getMSPointer();
31287        var events = {
31288            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
31289            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
31290        };
31291
31292        //cheks for passive event support
31293        //added by Uncode from new fullPage updates
31294        var g_supportsPassive = false;
31295        try {
31296          var opts = Object.defineProperty({}, 'passive', {
31297            get: function() {
31298              g_supportsPassive = true;
31299            }
31300          });
31301          window.addEventListener("testPassive", null, opts);
31302          window.removeEventListener("testPassive", null, opts);
31303        } catch (e) {}
31304
31305        //timeouts
31306        var resizeId;
31307        var afterSectionLoadsId;
31308        var afterSlideLoadsId;
31309        var scrollId;
31310        var scrollId2;
31311        var keydownId;
31312        var originals = $.extend(true, {}, options); //deep copy
31313
31314        //Uncode addition
31315        var $masthead = $('#masthead');
31316        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
31317        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
31318        var bodyBorder = UNCODE.bodyBorder;
31319        var adminBarHeight = UNCODE.adminBarHeight;
31320
31321        displayWarnings();
31322
31323        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
31324        iscrollOptions.click = isTouch; // see #2035
31325
31326        //extending iScroll options with the user custom ones
31327        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
31328
31329        //easeInOutCubic animation included in the plugin
31330        $.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;}});
31331
31332        /**
31333        * Sets the autoScroll option.
31334        * It changes the scroll bar visibility and the history of the site as a result.
31335        */
31336        function setAutoScrolling(value, type){
31337            //removing the transformation
31338            if(!value){
31339                silentScroll(0);
31340            }
31341
31342            setVariableState('autoScrolling', value, type);
31343
31344            var element = $(SECTION_ACTIVE_SEL);
31345
31346            if(options.autoScrolling && !options.scrollBar){
31347                $htmlBody.css({
31348                    'overflow' : 'hidden !important',
31349                    'height' : '100%'
31350                });
31351
31352                //Uncode addition
31353                //setRecordHistory(originals.recordHistory, 'internal');
31354
31355                //for IE touch devices
31356                container.css({
31357                    '-ms-touch-action': 'none',
31358                    'touch-action': 'none'
31359                });
31360
31361                if(element.length){
31362                    //moving the container up
31363                    silentScroll(element.position().top);
31364                }
31365
31366            }else{
31367                $htmlBody.css({
31368                    'overflow' : 'visible !important',
31369                    'height' : 'initial'
31370                });
31371
31372                //Uncode addition
31373                //setRecordHistory(false, 'internal');
31374
31375                //for IE touch devices
31376                container.css({
31377                    '-ms-touch-action': '',
31378                    'touch-action': ''
31379                });
31380
31381                //scrolling the page to the section with no animation
31382                if (element.length) {
31383                    $htmlBody.scrollTop(element.position().top);
31384                }
31385            }
31386        }
31387
31388        /**
31389        * Defines wheter to record the history for each hash change in the URL.
31390        */
31391        function setRecordHistory(value, type){
31392            setVariableState('recordHistory', value, type);
31393        }
31394
31395        /**
31396        * Defines the scrolling speed
31397        */
31398        function setScrollingSpeed(value, type){
31399            setVariableState('scrollingSpeed', value, type);
31400        }
31401
31402        /**
31403        * Sets fitToSection
31404        */
31405        function setFitToSection(value, type){
31406            setVariableState('fitToSection', value, type);
31407        }
31408
31409        /**
31410        * Sets lockAnchors
31411        */
31412        function setLockAnchors(value){
31413            options.lockAnchors = value;
31414        }
31415
31416        /**
31417        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
31418        */
31419        function setMouseWheelScrolling(value){
31420            if(value){
31421                addMouseWheelHandler();
31422                addMiddleWheelHandler();
31423            }else{
31424                removeMouseWheelHandler();
31425                removeMiddleWheelHandler();
31426            }
31427        }
31428
31429        /**
31430        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
31431        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
31432        *
31433        * @param directions string containing the direction or directions separated by comma.
31434        */
31435        function setAllowScrolling(value, directions){
31436            if(typeof directions !== 'undefined'){
31437                directions = directions.replace(/ /g,'').split(',');
31438
31439                $.each(directions, function (index, direction){
31440                    setIsScrollAllowed(value, direction, 'm');
31441                });
31442            }
31443            else if(value){
31444                setMouseWheelScrolling(true);
31445                addTouchHandler();
31446            }else{
31447                setMouseWheelScrolling(false);
31448                removeTouchHandler();
31449            }
31450        }
31451
31452        /**
31453        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
31454        */
31455        function setKeyboardScrolling(value, directions){
31456            if(typeof directions !== 'undefined'){
31457                directions = directions.replace(/ /g,'').split(',');
31458
31459                $.each(directions, function (index, direction){
31460                    setIsScrollAllowed(value, direction, 'k');
31461                });
31462            }else{
31463                options.keyboardScrolling = value;
31464            }
31465        }
31466
31467        /**
31468        * Moves the page up one section.
31469        */
31470        function moveSectionUp(){
31471            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
31472
31473            //looping to the bottom if there's no more sections above
31474            if (!prev.length && (options.loopTop || options.continuousVertical)) {
31475                prev = $(SECTION_SEL).last();
31476            }
31477
31478            if (prev.length) {
31479                scrollPage(prev, null, true);
31480            }
31481        }
31482
31483        /**
31484        * Moves the page down one section.
31485        */
31486        function moveSectionDown(){
31487            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
31488
31489            //looping to the top if there's no more sections below
31490            if(!next.length &&
31491                (options.loopBottom || options.continuousVertical)){
31492                next = $(SECTION_SEL).first();
31493            }
31494
31495            if(next.length){
31496                scrollPage(next, null, false);
31497            }
31498        }
31499
31500        /**
31501        * Moves the page to the given section and slide with no animation.
31502        * Anchors or index positions can be used as params.
31503        */
31504        function silentMoveTo(sectionAnchor, slideAnchor){
31505            setScrollingSpeed (0, 'internal');
31506            moveTo(sectionAnchor, slideAnchor);
31507            setScrollingSpeed (originals.scrollingSpeed, 'internal');
31508        }
31509
31510        /**
31511        * Moves the page to the given section and slide.
31512        * Anchors or index positions can be used as params.
31513        */
31514        function moveTo(sectionAnchor, slideAnchor){
31515            var destiny = getSectionByAnchor(sectionAnchor);
31516
31517            if (typeof slideAnchor !== 'undefined'){
31518                scrollPageAndSlide(sectionAnchor, slideAnchor);
31519            }else if(destiny.length > 0){
31520                scrollPage(destiny);
31521            }
31522        }
31523
31524        /**
31525        * Slides right the slider of the active section.
31526        * Optional `section` param.
31527        */
31528        function moveSlideRight(section){
31529            moveSlide('right', section);
31530        }
31531
31532        /**
31533        * Slides left the slider of the active section.
31534        * Optional `section` param.
31535        */
31536        function moveSlideLeft(section){
31537            moveSlide('left', section);
31538        }
31539
31540        /**
31541         * When resizing is finished, we adjust the slides sizes and positions
31542         */
31543        function reBuild(resizing){
31544            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
31545
31546            isResizing = true;
31547
31548            windowsHeight = $window.height();  //updating global var
31549
31550            $(SECTION_SEL).each(function(){
31551                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
31552                var slides = $(this).find(SLIDE_SEL);
31553
31554                //adjusting the height of the table-cell for IE and Firefox
31555                if(options.verticalCentered){
31556                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
31557                }
31558
31559                $(this).css('height', windowsHeight + 'px');
31560
31561                //resizing the scrolling divs
31562                if(options.scrollOverflow){
31563                    if(slides.length){
31564                        slides.each(function(){
31565                            createScrollBar($(this));
31566                        });
31567                    }else{
31568                        createScrollBar($(this));
31569                    }
31570                }
31571
31572                //adjusting the position fo the FULL WIDTH slides...
31573                if (slides.length > 1) {
31574                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
31575                }
31576            });
31577
31578            var activeSection = $(SECTION_ACTIVE_SEL);
31579            var sectionIndex = activeSection.index(SECTION_SEL);
31580
31581            //isn't it the first section?
31582            if(sectionIndex){
31583                //adjusting the position for the current section
31584                silentMoveTo(sectionIndex + 1);
31585            }
31586
31587            isResizing = false;
31588            // Uncode change
31589            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
31590            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
31591            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
31592        }
31593
31594        /**
31595        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
31596        * are smaller than the set limit values.
31597        */
31598        function setResponsive(active){
31599            var isResponsive = $body.hasClass(RESPONSIVE);
31600
31601            if(active){
31602                if(!isResponsive){
31603                    setAutoScrolling(false, 'internal');
31604                    setFitToSection(false, 'internal');
31605                    $(SECTION_NAV_SEL).hide();
31606                    $body.addClass(RESPONSIVE);
31607                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31608                }
31609            }
31610            else if(isResponsive){
31611                setAutoScrolling(originals.autoScrolling, 'internal');
31612                setFitToSection(originals.autoScrolling, 'internal');
31613                $(SECTION_NAV_SEL).show();
31614                $body.removeClass(RESPONSIVE);
31615                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31616            }
31617        }
31618
31619        if($(this).length){
31620            //public functions
31621            FP.setAutoScrolling = setAutoScrolling;
31622            FP.setRecordHistory = setRecordHistory;
31623            FP.setScrollingSpeed = setScrollingSpeed;
31624            FP.setFitToSection = setFitToSection;
31625            FP.setLockAnchors = setLockAnchors;
31626            FP.setMouseWheelScrolling = setMouseWheelScrolling;
31627            FP.setAllowScrolling = setAllowScrolling;
31628            FP.setKeyboardScrolling = setKeyboardScrolling;
31629            FP.moveSectionUp = moveSectionUp;
31630            FP.moveSectionDown = moveSectionDown;
31631            FP.silentMoveTo = silentMoveTo;
31632            FP.moveTo = moveTo;
31633            FP.moveSlideRight = moveSlideRight;
31634            FP.moveSlideLeft = moveSlideLeft;
31635            FP.fitToSection = fitToSection;
31636            FP.reBuild = reBuild;
31637            FP.setResponsive = setResponsive;
31638            FP.destroy = destroy;
31639
31640            init();
31641
31642            bindEvents();
31643        }
31644
31645        function init(){
31646            //if css3 is not supported, it will use jQuery animations
31647            if(options.css3){
31648                options.css3 = support3d();
31649            }
31650
31651            options.scrollBar = options.scrollBar || options.hybrid;
31652
31653            setOptionsFromDOM();
31654            prepareDom();
31655            setAllowScrolling(true);
31656            setAutoScrolling(options.autoScrolling, 'internal');
31657            responsive();
31658
31659            //setting the class for the body element
31660            setBodyClass();
31661
31662            //Uncode addition
31663            // if(document.readyState === 'complete'){
31664            //     scrollToAnchor();
31665            // }
31666            // $window.on('load', scrollToAnchor);
31667        }
31668
31669        function bindEvents(){
31670            $window
31671                //when scrolling...
31672                //.on('scroll', scrollHandler)
31673
31674                //detecting any change on the URL to scroll to the given anchor link
31675                //(a way to detect back history button as we play with the hashes on the URL)
31676                .on('hashchange', hashChangeHandler)
31677
31678                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
31679                .blur(blurHandler)
31680
31681                //when resizing the site, we adjust the heights of the sections, slimScroll...
31682                .resize(resizeHandler);
31683
31684            $document
31685                //Sliding with arrow keys, both, vertical and horizontal
31686                .keydown(keydownHandler)
31687
31688                //to prevent scrolling while zooming
31689                .keyup(keyUpHandler)
31690
31691                //Scrolls to the section when clicking the navigation bullet
31692                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
31693
31694                //Scrolls the slider to the given slide destination for the given section
31695                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
31696
31697                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
31698
31699            //Scrolling horizontally when clicking on the slider controls.
31700            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
31701
31702            /**
31703            * Applying normalScroll elements.
31704            * Ignoring the scrolls over the specified selectors.
31705            */
31706            if(options.normalScrollElements){
31707                $document.on('mouseenter', options.normalScrollElements, function () {
31708                    setMouseWheelScrolling(false);
31709                });
31710
31711                $document.on('mouseleave', options.normalScrollElements, function(){
31712                    setMouseWheelScrolling(true);
31713                });
31714            }
31715        }
31716
31717        /**
31718        * Setting options from DOM elements if they are not provided.
31719        */
31720        function setOptionsFromDOM(){
31721            var sections = container.find(options.sectionSelector);
31722
31723            //no anchors option? Checking for them in the DOM attributes
31724            if(!options.anchors.length){
31725                options.anchors = sections.filter('[data-anchor]').map(function(){
31726                    return $(this).data('anchor').toString();
31727                }).get();
31728            }
31729
31730            //no tooltips option? Checking for them in the DOM attributes
31731            if(!options.navigationTooltips.length){
31732                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
31733                    return $(this).data('tooltip').toString();
31734                }).get();
31735            }
31736        }
31737
31738        /**
31739        * Works over the DOM structure to set it up for the current fullpage options.
31740        */
31741        function prepareDom(){
31742            container.css({
31743                'height': '100%',
31744                'position': 'relative'
31745            });
31746
31747            //adding a class to recognize the container internally in the code
31748            container.addClass(WRAPPER);
31749            $('html').addClass(ENABLED);
31750
31751            windowsHeight = $window.height();
31752
31753            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
31754
31755            addInternalSelectors();
31756
31757             //styling the sections / slides / menu
31758            $(SECTION_SEL).each(function(index){
31759                var section = $(this);
31760                var slides = section.find(SLIDE_SEL);
31761                var numSlides = slides.length;
31762
31763                styleSection(section, index);
31764                styleMenu(section, index);
31765
31766                // if there's any slide
31767                if (numSlides > 0) {
31768                    styleSlides(section, slides, numSlides);
31769                }else{
31770                    if(options.verticalCentered){
31771                        addTableClass(section);
31772                    }
31773                }
31774            });
31775
31776            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31777            if(options.fixedElements && options.css3){
31778                $(options.fixedElements).appendTo($body);
31779            }
31780
31781            //vertical centered of the navigation + active bullet
31782            if(options.navigation){
31783                addVerticalNavigation();
31784            }
31785
31786            enableYoutubeAPI();
31787
31788            if(options.scrollOverflow){
31789                if(document.readyState === 'complete'){
31790                    createScrollBarHandler();
31791                }
31792                //after DOM and images are loaded
31793                $window.on('load', createScrollBarHandler);
31794            }else{
31795                afterRenderActions();
31796            }
31797        }
31798
31799        /**
31800        * Styles the horizontal slides for a section.
31801        */
31802        function styleSlides(section, slides, numSlides){
31803            var sliderWidth = numSlides * 100;
31804            var slideWidth = 100 / numSlides;
31805
31806            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31807            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31808
31809            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31810
31811            if(numSlides > 1){
31812                if(options.controlArrows){
31813                    createSlideArrows(section);
31814                }
31815
31816                if(options.slidesNavigation){
31817                    addSlidesNavigation(section, numSlides);
31818                }
31819            }
31820
31821            slides.each(function(index) {
31822                $(this).css('width', slideWidth + '%');
31823
31824                if(options.verticalCentered){
31825                    addTableClass($(this));
31826                }
31827            });
31828
31829            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31830
31831            //if the slide won't be an starting point, the default will be the first one
31832            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31832ide by default.
31833            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31834                silentLandscapeScroll(startingSlide, 'internal');
31835            }else{
31836                slides.eq(0).addClass(ACTIVE);
31837            }
31838        }
31839
31840        /**
31841        * Styling vertical sections
31842        */
31843        function styleSection(section, index){
31844            //if no active section is defined, the 1st one will be the default one
31845            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31846                section.addClass(ACTIVE);
31847            }
31848            startingSection = $(SECTION_ACTIVE_SEL);
31849
31850            section.css('height', windowsHeight + 'px');
31851
31852            if(options.paddingTop){
31853                section.css('padding-top', options.paddingTop);
31854            }
31855
31856            if(options.paddingBottom){
31857                section.css('padding-bottom', options.paddingBottom);
31858            }
31859
31860            if (typeof options.sectionsColor[index] !==  'undefined') {
31861                section.css('background-color', options.sectionsColor[index]);
31862            }
31863
31864            if (typeof options.anchors[index] !== 'undefined') {
31865                section.attr('data-anchor', options.anchors[index]);
31866            }
31867        }
31868
31869        /**
31870        * Sets the data-anchor attributes to the menu elements and activates the current one.
31871        */
31872        function styleMenu(section, index){
31873            if (typeof options.anchors[index] !== 'undefined') {
31874                //activating the menu / nav element on load
31875                if(section.hasClass(ACTIVE)){
31876                    activateMenuAndNav(options.anchors[index], index);
31877                }
31878            }
31879
31880            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31881            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31882                $(options.menu).appendTo($body);
31883            }
31884        }
31885
31886        /**
31887        * Adds internal classes to be able to provide customizable selectors
31888        * keeping the link with the style sheet.
31889        */
31890        function addInternalSelectors(){
31891            container.find(options.sectionSelector).addClass(SECTION);
31892            container.find(options.slideSelector).addClass(SLIDE);
31893        }
31894
31895        /**
31896        * Creates the control arrows for the given section
31897        */
31898        function createSlideArrows(section){
31899            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31900
31901            if(options.controlArrowColor!='#fff'){
31902                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31903                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31904            }
31905
31906            if(!options.loopHorizontal){
31907                section.find(SLIDES_ARROW_PREV_SEL).hide();
31908            }
31909        }
31910
31911        /**
31912        * Creates a vertical navigation bar.
31913        */
31914        function addVerticalNavigation(){
31915            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31916            var nav = $(SECTION_NAV_SEL);
31917
31918            nav.addClass(function() {
31919                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31920            });
31921
31922            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31923                var link = '';
31924                if (options.anchors.length) {
31925                    link = options.anchors[i];
31926                }
31927
31928                var li = '<li><a href="#' + link + '"><span></span></a>';
31929
31930                // Only add tooltip if needed (defined by user)
31931                var tooltip = options.navigationTooltips[i];
31932
31933                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31934                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31935                }
31936
31937                li += '</li>';
31938
31939                nav.find('ul').append(li);
31940            }
31941
31942            //centering it vertically
31943            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
31944
31945            //activating the current active section
31946            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
31947        }
31948
31949        /**
31950        * Creates the slim scroll scrollbar for the sections and slides inside them.
31951        */
31952        function createScrollBarHandler(){
31953            $(SECTION_SEL).each(function(){
31954                var slides = $(this).find(SLIDE_SEL);
31955
31956                if(slides.length){
31957                    slides.each(function(){
31958                        createScrollBar($(this));
31959                    });
31960                }else{
31961                    createScrollBar($(this));
31962                }
31963
31964            });
31965            afterRenderActions();
31966        }
31967
31968        /*
31969        * Enables the Youtube videos API so we can control their flow if necessary.
31970        */
31971        function enableYoutubeAPI(){
31972            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
31973                addURLParam($(this), 'enablejsapi=1');
31974            });
31975        }
31976
31977        /**
31978        * Adds a new parameter and its value to the `src` of a given element
31979        */
31980        function addURLParam(element, newParam){
31981            var originalSrc = element.attr('src');
31982            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
31983        }
31984
31985        /*
31986        * Returns the prefix sign to use for a new parameter in an existen URL.
31987        *
31988        * @return {String}  ? | &
31989        */
31990        function getUrlParamSign(url){
31991            return ( !/\?/.test( url ) ) ? '?' : '&';
31992        }
31993
31994        /**
31995        * Actions and callbacks to fire afterRender
31996        */
31997        function afterRenderActions(){
31998            var section = $(SECTION_ACTIVE_SEL);
31999
32000            section.addClass(COMPLETELY);
32001
32002            if(options.scrollOverflowHandler.afterRender){
32003                options.scrollOverflowHandler.afterRender(section);
32004            }
32005            lazyLoad(section);
32006            playMedia(section);
32007            options.scrollOverflowHandler.afterLoad();
32008
32009            if(isDestinyTheStartingSection()){
32010                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32011            }
32012
32013            // Uncode change
32014            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32015            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32016        }
32017
32018        /**
32019        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32020        */
32021        function isDestinyTheStartingSection(){
32022            var anchors =  window.location.hash.replace('#', '').split('/');
32023            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32024
32025            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32026        }
32027
32028
32029        var isScrolling = false;
32030        var lastScroll = 0;
32031
32032        //when scrolling...
32033        function scrollHandler(){
32034            var currentSection;
32035
32036            if(!options.autoScrolling || options.scrollBar){
32037                var currentScroll = $window.scrollTop();
32038                var scrollDirection = getScrollDirection(currentScroll);
32039                var visibleSectionIndex = 0;
32040                var screen_mid = currentScroll + ($window.height() / 2.0);
32041                var isAtBottom = $body.height() - $window.height() === currentScroll;
32042                var sections =  document.querySelectorAll(SECTION_SEL);
32043
32044                //when using `auto-height` for a small last section it won't be centered in the viewport
32045                if(isAtBottom){
32046                    visibleSectionIndex = sections.length - 1;
32047                }
32048                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32049                else if(!currentScroll){
32050                    visibleSectionIndex = 0;
32051                }
32052
32053                //taking the section which is showing more content in the viewport
32054                else{
32055                    for (var i = 0; i < sections.length; ++i) {
32056                        var section = sections[i];
32057
32058                        // Pick the the last section which passes the middle line of the screen.
32059                        if (section.offsetTop <= screen_mid)
32060                        {
32061                            visibleSectionIndex = i;
32062                        }
32063                    }
32064                }
32065
32066                if(isCompletelyInViewPort(scrollDirection)){
32067                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
32068                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32069                    }
32070                }
32071
32072                //geting the last one, the current one on the screen
32073                currentSection = $(sections).eq(visibleSectionIndex);
32074
32075                //setting the visible section as active when manually scrolling
32076                //executing only once the first time we reach the section
32077                if(!currentSection.hasClass(ACTIVE)){
32078                    isScrolling = true;
32079                    var leavingSection = $(SECTION_ACTIVE_SEL);
32080                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
32081                    var yMovement = getYmovement(currentSection);
32082                    var anchorLink  = currentSection.data('anchor');
32083                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
32084                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
32085                    var slideIndex;
32086                    var slideAnchorLink;
32087
32088                    if(activeSlide.length){
32089                        slideAnchorLink = activeSlide.data('anchor');
32090                        slideIndex = activeSlide.index();
32091                    }
32092
32093                    if(canScroll){
32094                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32095
32096                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
32097                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
32098
32099                        stopMedia(leavingSection);
32100                        lazyLoad(currentSection);
32101                        playMedia(currentSection);
32102
32103                        activateMenuAndNav(anchorLink, sectionIndex - 1);
32104
32105                        if(options.anchors.length){
32106                            //needed to enter in hashChange event when using the menu with anchor links
32107                            lastScrolledDestiny = anchorLink;
32108                        }
32109                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
32110                    }
32111
32112                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
32113                    clearTimeout(scrollId);
32114                    scrollId = setTimeout(function(){
32115                        isScrolling = false;
32116                    }, 100);
32117                }
32118
32119                if(options.fitToSection){
32120                    //for the auto adjust of the viewport to fit a whole section
32121                    clearTimeout(scrollId2);
32122
32123                    scrollId2 = setTimeout(function(){
32124                        //checking it again in case it changed during the delay
32125                        if(options.fitToSection){
32126                            fitToSection();
32127                        }
32128                    }, options.fitToSectionDelay);
32129                }
32130            }
32131        }
32132
32133        /**
32134        * Fits the site to the nearest active section
32135        */
32136        function fitToSection(){
32137            //checking fitToSection again in case it was set to false before the timeout delay
32138            if(canScroll){
32139                //allows to scroll to an active section and
32140                //if the section is already active, we prevent firing callbacks
32141                isResizing = true;
32142
32143                scrollPage($(SECTION_ACTIVE_SEL));
32144                isResizing = false;
32145            }
32146        }
32147
32148        /**
32149        * Determines whether the active section has seen in its whole or not.
32150        */
32151        function isCompletelyInViewPort(movement){
32152            var top = $(SECTION_ACTIVE_SEL).position().top;
32153            var bottom = top + $window.height();
32154
32155            if(movement == 'up'){
32156                return bottom >= ($window.scrollTop() + $window.height());
32157            }
32158            return top <= $window.scrollTop();
32159        }
32160
32161        /**
32162        * Gets the directon of the the scrolling fired by the scroll event.
32163        */
32164        function getScrollDirection(currentScroll){
32165            var direction = currentScroll > lastScroll ? 'down' : 'up';
32166
32167            lastScroll = currentScroll;
32168
32169            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
32170            previousDestTop = currentScroll;
32171
32172            return direction;
32173        }
32174
32175        /**
32176        * Determines the way of scrolling up or down:
32177        * by 'automatically' scrolling a section or by using the default and normal scrolling.
32178        */
32179        function scrolling(type, scrollable){
32180            if (!isScrollAllowed.m[type]){
32181                return;
32182            }
32183            var check = (type === 'down') ? 'bottom' : 'top';
32184            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
32185
32186            if(scrollable.length > 0 ){
32187                //is the scrollbar at the start/end of the scroll?
32188                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
32189                    scrollSection();
32190                }else{
32191                    return true;
32192                }
32193            }else{
32194                // moved up/down
32195                scrollSection();
32196            }
32197        }
32198
32199        /*
32200        * Preventing bouncing in iOS #2285
32201        */
32202        function preventBouncing(event){
32203            var e = event.originalEvent;
32204            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
32205                //preventing the easing on iOS devices
32206                event.preventDefault();
32207            }
32208        }
32209
32210        var touchStartY = 0;
32211        var touchStartX = 0;
32212        var touchEndY = 0;
32213        var touchEndX = 0;
32214
32215        /* Detecting touch events
32216
32217        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
32218        * This way, the touchstart and the touch moves shows an small difference between them which is the
32219        * used one to determine the direction.
32220        */
32221        function touchMoveHandler(event){
32222            var e = event.originalEvent;
32223            var activeSection = $(e.target).closest(SECTION_SEL);
32224
32225            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
32226            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
32227
32228                if(options.autoScrolling){
32229                    //preventing the easing on iOS devices
32230                    event.preventDefault();
32231                }
32232
32233                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32234                var touchEvents = getEventsPage(e);
32235
32236                touchEndY = touchEvents.y;
32237                touchEndX = touchEvents.x;
32238
32239                //if movement in the X axys is greater than in the Y and the currect section has slides...
32240                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
32241
32242                    //is the movement greater than the minimum resistance to scroll?
32243                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
32244                        if (touchStartX > touchEndX) {
32245                            if(isScrollAllowed.m.right){
32246                                moveSlideRight(activeSection); //next
32247                            }
32248                        } else {
32249                            if(isScrollAllowed.m.left){
32250                                moveSlideLeft(activeSection); //prev
32251                            }
32252                        }
32253                    }
32254                }
32255
32256                //vertical scrolling (only when autoScrolling is enabled)
32257                else if(options.autoScrolling && canScroll){
32258
32259                    //is the movement greater than the minimum resistance to scroll?
32260                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
32261                        if (touchStartY > touchEndY) {
32262                            scrolling('down', scrollable);
32263                        } else if (touchEndY > touchStartY) {
32264                            scrolling('up', scrollable);
32265                        }
32266                    }
32267                }
32268            }
32269        }
32270
32271        /**
32272         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
32273         * Currently works well for iOS - Android might need some testing
32274         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
32275         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
32276         * @return {boolean} true if there is a match to options.normalScrollElements
32277         */
32278        function checkParentForNormalScrollElement (el, hop) {
32279            hop = hop || 0;
32280            var parent = $(el).parent();
32281
32282            if (hop < options.normalScrollElementTouchThreshold &&
32283                parent.is(options.normalScrollElements) ) {
32284                return true;
32285            } else if (hop == options.normalScrollElementTouchThreshold) {
32286                return false;
32287            } else {
32288                return checkParentForNormalScrollElement(parent, ++hop);
32289            }
32290        }
32291
32292        /**
32293        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
32294        * this way we make sure that is really a touch event what IE is detecting.
32295        */
32296        function isReallyTouch(e){
32297            //if is not IE   ||  IE is detecting `touch` or `pen`
32298            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
32299        }
32300
32301        /**
32302        * Handler for the touch start event.
32303        */
32304        function touchStartHandler(event){
32305            var e = event.originalEvent;
32306
32307            //stopping the auto scroll to adjust to a section
32308            if(options.fitToSection){
32309                $htmlBody.stop();
32310            }
32311
32312            if(isReallyTouch(e)){
32313                var touchEvents = getEventsPage(e);
32314                touchStartY = touchEvents.y;
32315                touchStartX = touchEvents.x;
32316            }
32317        }
32318
32319        /**
32320        * Gets the average of the last `number` elements of the given array.
32321        */
32322        function getAverage(elements, number){
32323            var sum = 0;
32324
32325            //taking `number` elements from the end to make the average, if there are not enought, 1
32326            var lastElements = elements.slice(Math.max(elements.length - number, 1));
32327
32328            for(var i = 0; i < lastElements.length; i++){
32329                sum = sum + lastElements[i];
32330            }
32331
32332            return Math.ceil(sum/number);
32333        }
32334
32335        /**
32336         * Detecting mousewheel scrolling
32337         *
32338         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
32339         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
32340         */
32341        var prevTime = new Date().getTime();
32342
32343        function MouseWheelHandler(e) {
32344            var curTime = new Date().getTime();
32345            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
32346
32347            //autoscrolling and not zooming?
32348            if(options.autoScrolling && !controlPressed && !isNormalScroll){
32349                // cross-browser wheel delta
32350                e = e || window.event;
32351                var value = e.wheelDelta || -e.deltaY || -e.detail;
32352                var delta = Math.max(-1, Math.min(1, value));
32353
32354                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
32355                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
32356
32357                //Limiting the array to 150 (lets not waste memory!)
32358                if(scrollings.length > 149){
32359                    scrollings.shift();
32360                }
32361
32362                //keeping record of the previous scrollings
32363                scrollings.push(Math.abs(value));
32364
32365                //preventing to scroll the site on mouse wheel when scrollbar is present
32366                if(options.scrollBar){
32367                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
32368                }
32369
32370                var activeSection = $(SECTION_ACTIVE_SEL);
32371                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32372
32373                //time difference between the last scroll and the current one
32374                var timeDiff = curTime-prevTime;
32375                prevTime = curTime;
32376
32377                //haven't they scrolled in a while?
32378                //(enough to be consider a different scrolling action to scroll another section)
32379                if(timeDiff > 200){
32380                    //emptying the array, we dont care about old scrollings for our averages
32381                    scrollings = [];
32382                }
32383
32384                if(canScroll){
32385                    var averageEnd = getAverage(scrollings, 10);
32386                    var averageMiddle = getAverage(scrollings, 70);
32387                    var isAccelerating = averageEnd >= averageMiddle;
32388
32389                    //to avoid double swipes...
32390                    if(isAccelerating && isScrollingVertically){
32391                        //scrolling down?
32392                        if (delta < 0) {
32393                            scrolling('down', scrollable);
32394
32395                        //scrolling up?
32396                        }else {
32397                            scrolling('up', scrollable);
32398                        }
32399                    }
32400                }
32401
32402                return false;
32403            }
32404
32405            if(options.fitToSection){
32406                //stopping the auto scroll to adjust to a section
32407                $htmlBody.stop();
32408            }
32409        }
32410
32411        /**
32412        * Slides a slider to the given direction.
32413        * Optional `section` param.
32414        */
32415        function moveSlide(direction, section){
32416            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
32417            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
32418            var numSlides = slides.find(SLIDE_SEL).length;
32419
32420            // more than one slide needed and nothing should be sliding
32421            if (!slides.length || slideMoving || numSlides < 2) {
32422                return;
32423            }
32424
32425            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
32426            var destiny = null;
32427
32428            if(direction === 'left'){
32429                destiny = currentSlide.prev(SLIDE_SEL);
32430            }else{
32431                destiny = currentSlide.next(SLIDE_SEL);
32432            }
32433
32434            //isn't there a next slide in the secuence?
32435            if(!destiny.length){
32436                //respect loopHorizontal settin
32437                if (!options.loopHorizontal) return;
32438
32439                if(direction === 'left'){
32440                    destiny = currentSlide.siblings(':last');
32441                }else{
32442                    destiny = currentSlide.siblings(':first');
32443                }
32444            }
32445
32446            slideMoving = true;
32447
32448            landscapeScroll(slides, destiny, direction);
32449        }
32450
32451        /**
32452        * Maintains the active slides in the viewport
32453        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
32454        */
32455        function keepSlidesPosition(){
32456            $(SLIDE_ACTIVE_SEL).each(function(){
32457                silentLandscapeScroll($(this), 'internal');
32458            });
32459        }
32460
32461        var previousDestTop = 0;
32462        /**
32463        * Returns the destination Y position based on the scrolling direction and
32464        * the height of the section.
32465        */
32466        function getDestinationPosition(element){
32467            var elemPosition = element.position();
32468
32469            //top of the desination will be at the top of the viewport
32470            var position = elemPosition.top;
32471            var isScrollingDown =  elemPosition.top > previousDestTop;
32472            var sectionBottom = position - windowsHeight + element.outerHeight();
32473            var bigSectionsDestination = options.bigSectionsDestination;
32474
32475            //Uncode addition
32476            var containerH = container.outerHeight();
32477            var containerPosition = container.offset();
32478
32479            //########### Commented by Uncode - START ###########
32480            //is the destination element bigger than the viewport?
32481            // if(element.outerHeight() > windowsHeight){
32482            //     //scrolling up?
32483            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
32484            //         position = sectionBottom;
32485            //     }
32486            // }
32487
32488            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
32489            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
32490            //     //The bottom of the destination will be at the bottom of the viewport
32491            //     position = sectionBottom;
32492            // }
32493            //########### Commented by Uncode - END ###########
32494
32495            //Uncode addition
32496            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
32497                position += 18;
32498            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
32499                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
32500            }
32501
32502            /*
32503            Keeping record of the last scrolled position to determine the scrolling direction.
32504            No conventional methods can be used as the scroll bar might not be present
32505            AND the section might not be active if it is auto-height and didnt reach the middle
32506            of the viewport.
32507            */
32508            previousDestTop = position;
32509            return position;
32510        }
32511
32512        /**
32513        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
32514        */
32515        function scrollPage(element, callback, isMovementUp){
32516            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
32517
32518            var dtop = getDestinationPosition(element);
32519            var slideAnchorLink;
32520            var slideIndex;
32521
32522            //local variables
32523            var v = {
32524                element: element,
32525                callback: callback,
32526                isMovementUp: isMovementUp,
32527                dtop: dtop,
32528                yMovement: getYmovement(element),
32529                anchorLink: element.data('anchor'),
32530                sectionIndex: element.index(SECTION_SEL),
32531                activeSlide: element.find(SLIDE_ACTIVE_SEL),
32532                activeSection: $(SECTION_ACTIVE_SEL),
32533                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
32534
32535                //caching the value of isResizing at the momment the function is called
32536                //because it will be checked later inside a setTimeout and the value might change
32537                localIsResizing: isResizing
32538            };
32539
32540            //quiting when destination scroll is the same as the current one
32541            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
32542
32543            if(v.activeSlide.length){
32544                slideAnchorLink = v.activeSlide.data('anchor');
32545                slideIndex = v.activeSlide.index();
32546            }
32547
32548            // If continuousVertical && we need to wrap around
32549            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
32550                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
32551                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
32552
32553                v = createInfiniteSections(v);
32554            }
32555
32556            //callback (onLeave) if the site is not just resizing and readjusting the slides
32557            if($.isFunction(options.onLeave) && !v.localIsResizing){
32558                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
32559                    return;
32560                }
32561            }
32562
32563            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
32564            if(!v.localIsResizing){
32565                stopMedia(v.activeSection);
32566            }
32567
32568            options.scrollOverflowHandler.beforeLeave();
32569            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32570            lazyLoad(element);
32571            options.scrollOverflowHandler.onLeave();
32572
32573
32574            //preventing from activating the MouseWheelHandler event
32575            //more than once if the page is scrolling
32576            canScroll = false;
32577
32578            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
32579
32580            performMovement(v);
32581
32582            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
32583            lastScrolledDestiny = v.anchorLink;
32584
32585            //avoid firing it twice (as it does also on scroll)
32586            activateMenuAndNav(v.anchorLink, v.sectionIndex);
32587        }
32588
32589        /**
32590        * Performs the vertical movement (by CSS3 or by jQuery)
32591        */
32592        function performMovement(v){
32593            // using CSS3 translate functionality
32594            if (options.css3 && options.autoScrolling && !options.scrollBar) {
32595
32596                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32597                // that's why we round it to 0.
32598                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
32599                transformContainer(translate3d, true);
32600
32601                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
32602                //scrollingSpeed to change in case of using silentMoveTo();
32603                if(options.scrollingSpeed){
32604                    clearTimeout(afterSectionLoadsId);
32605                    afterSectionLoadsId = setTimeout(function () {
32606                        afterSectionLoads(v);
32607                    }, options.scrollingSpeed);
32608                }else{
32609                    afterSectionLoads(v);
32610                }
32611            }
32612
32613            // using jQuery animate
32614            else{
32615                var scrollSettings = getScrollSettings(v);
32616
32617                $(scrollSettings.element).animate(
32618                    scrollSettings.options,
32619                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
32620                    if(options.scrollBar){
32621
32622                        /* Hack!
32623                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
32624                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
32625
32626                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
32627                        */
32628                        setTimeout(function(){
32629                            afterSectionLoads(v);
32630                        },30);
32631                    }else{
32632                        afterSectionLoads(v);
32633                    }
32634                });
32635            }
32636        }
32637
32638        /**
32639        * Gets the scrolling settings depending on the plugin autoScrolling option
32640        */
32641        function getScrollSettings(v){
32642            var scroll = {};
32643
32644            if(options.autoScrolling && !options.scrollBar){
32645                scroll.options = { 'top': -v.dtop};
32646                scroll.element = WRAPPER_SEL;
32647            }else{
32648                scroll.options = { 'scrollTop': v.dtop};
32649                scroll.element = 'html, body';
32650            }
32651
32652            return scroll;
32653        }
32654
32655        /**
32656        * Adds sections before or after the current one to create the infinite effect.
32657        */
32658        function createInfiniteSections(v){
32659            // Scrolling down
32660            if (!v.isMovementUp) {
32661                // Move all previous sections to after the active section
32662                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
32663            }
32664            else { // Scrolling up
32665                // Move all next sections to before the active section
32666                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
32667            }
32668
32669            // Maintain the displayed position (now that we changed the element order)
32670            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32671
32672            // Maintain the active slides visible in the viewport
32673            keepSlidesPosition();
32674
32675            // save for later the elements that still need to be reordered
32676            v.wrapAroundElements = v.activeSection;
32677
32678            // Recalculate animation variables
32679            v.dtop = v.element.position().top;
32680            v.yMovement = getYmovement(v.element);
32681
32682            return v;
32683        }
32684
32685        /**
32686        * Fix section order after continuousVertical changes have been animated
32687        */
32688        function continuousVerticalFixSectionOrder (v) {
32689            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
32690            // finish moving the elements around so the direct navigation will function more simply
32691            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
32692                return;
32693            }
32694
32695            if (v.isMovementUp) {
32696                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
32697            }
32698            else {
32699                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
32700            }
32701
32702            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32703
32704            // Maintain the active slides visible in the viewport
32705            keepSlidesPosition();
32706        }
32707
32708
32709        /**
32710        * Actions to do once the section is loaded.
32711        */
32712        function afterSectionLoads (v){
32713            continuousVerticalFixSectionOrder(v);
32714
32715            //callback (afterLoad) if the site is not just resizing and readjusting the slides
32716            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
32717            options.scrollOverflowHandler.afterLoad();
32718
32719            if(!v.localIsResizing){
32720                playMedia(v.element);
32721            }
32722
32723            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32724
32725            canScroll = true;
32726
32727            $.isFunction(v.callback) && v.callback.call(this);
32728        }
32729
32730        /**
32731        * Sets the value for the given attribute from the `data-` attribute with the same suffix
32732        * ie: data-srcset ==> srcset  |  data-src ==> src
32733        */
32734        function setSrc(element, attribute){
32735            element
32736                .attr(attribute, element.data(attribute))
32737                .removeAttr('data-' + attribute);
32738        }
32739
32740        /**
32741        * Lazy loads image, video and audio elements.
32742        */
32743        function lazyLoad(destiny){
32744            if (!options.lazyLoading){
32745                return;
32746            }
32747
32748            var panel = getSlideOrSection(destiny);
32749            var element;
32750
32751            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
32752                element = $(this);
32753
32754                $.each(['src', 'srcset'], function(index, type){
32755                    var attribute = element.attr('data-' + type);
32756                    if(typeof attribute !== 'undefined' && attribute){
32757                        setSrc(element, type);
32758                    }
32759                });
32760
32761                if(element.is('source')){
32762                    element.closest('video').get(0).load();
32763                }
32764            });
32765        }
32766
32767        /**
32768        * Plays video and audio elements.
32769        */
32770        function playMedia(destiny){
32771            var panel = getSlideOrSection(destiny);
32772
32773            //playing HTML5 media elements
32774            panel.find('video, audio').each(function(){
32775                var element = $(this).get(0);
32776
32777                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32778                    element.play();
32779                }
32780            });
32781
32782            //youtube videos
32783            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32784                var element = $(this).get(0);
32785
32786                if ( element.hasAttribute('data-autoplay') ){
32787                    playYoutube(element);
32788                }
32789
32790                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32791                element.onload = function() {
32792                    if ( element.hasAttribute('data-autoplay') ){
32793                        playYoutube(element);
32794                    }
32795                };
32796            });
32797        }
32798
32799        /**
32800        * Plays a youtube video
32801        */
32802        function playYoutube(element){
32803            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32804        }
32805
32806        /**
32807        * Stops video and audio elements.
32808        */
32809        function stopMedia(destiny){
32810            var panel = getSlideOrSection(destiny);
32811
32812            //stopping HTML5 media elements
32813            panel.find('video, audio').each(function(){
32814                var element = $(this).get(0);
32815
32816                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32817                    element.pause();
32818                }
32819            });
32820
32821            //youtube videos
32822            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32823                var element = $(this).get(0);
32824
32825                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32826                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32827                }
32828            });
32829        }
32830
32831        /**
32832        * Gets the active slide (or section) for the given section
32833        */
32834        function getSlideOrSection(destiny){
32835            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32836            if( slide.length ) {
32837                destiny = $(slide);
32838            }
32839
32840            return destiny;
32841        }
32842
32843        /**
32844        * Scrolls to the anchor in the URL when loading the site
32845        */
32846        function scrollToAnchor(){
32847            //getting the anchor link in the URL and deleting the `#`
32848            var value =  window.location.hash.replace('#', '').split('/');
32849            var sectionAnchor = decodeURIComponent(value[0]);
32850            var slideAnchor = decodeURIComponent(value[1]);
32851
32852            if(sectionAnchor){  //if theres any #
32853                if(options.animateAnchor){
32854                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32855                }else{
32856                    silentMoveTo(sectionAnchor, slideAnchor);
32857                }
32858            }
32859        }
32860
32861        /**
32862        * Detecting any change on the URL to scroll to the given anchor link
32863        * (a way to detect back history button as we play with the hashes on the URL)
32864        */
32865        function hashChangeHandler(){
32866            if(!isScrolling && !options.lockAnchors){
32867                var value =  window.location.hash.replace('#', '').split('/');
32868                var sectionAnchor = decodeURIComponent(value[0]);
32869                var slideAnchor = decodeURIComponent(value[1]);
32870
32871                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32872                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32873                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32874
32875
32876                if(sectionAnchor.length){
32877                    /*in order to call scrollpage() only once for each destination at a time
32878                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32879                    event is fired on every scroll too.*/
32880                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32881                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32882                    }
32883                }
32884            }
32885        }
32886
32887        //Sliding with arrow keys, both, vertical and horizontal
32888        function keydownHandler(e) {
32889
32890            clearTimeout(keydownId);
32891
32892            var activeElement = $(':focus');
32893
32894            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32895                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32896                options.keyboardScrolling && options.autoScrolling){
32897                var keyCode = e.which;
32898
32899                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32900                var keyControls = [40, 38, 32, 33, 34];
32901                if($.inArray(keyCode, keyControls) > -1){
32902                    e.preventDefault();
32903                }
32904
32905                controlPressed = e.ctrlKey;
32906
32907                keydownId = setTimeout(function(){
32908                    onkeydown(e);
32909                },150);
32910            }
32911        }
32912
32913        function tooltipTextHandler(){
32914            $(this).prev().trigger('click');
32915        }
32916
32917        //to prevent scrolling while zooming
32918        function keyUpHandler(e){
32919            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32920                controlPressed = e.ctrlKey;
32921            }
32922        }
32923
32924        //binding the mousemove when the mouse's middle button is released
32925        function mouseDownHandler(e){
32926            //middle button
32927            if (e.which == 2){
32928                oldPageY = e.pageY;
32929                container.on('mousemove', mouseMoveHandler);
32930            }
32931        }
32932
32933        //unbinding the mousemove when the mouse's middle button is released
32934        function mouseUpHandler(e){
32935            //middle button
32936            if (e.which == 2){
32937                container.off('mousemove');
32938            }
32939        }
32940
32941        //Scrolling horizontally when clicking on the slider controls.
32942        function slideArrowHandler(){
32943            var section = $(this).closest(SECTION_SEL);
32944
32945            if ($(this).hasClass(SLIDES_PREV)) {
32946                if(isScrollAllowed.m.left){
32947                    moveSlideLeft(section);
32948                }
32949            } else {
32950                if(isScrollAllowed.m.right){
32951                    moveSlideRight(section);
32952                }
32953            }
32954        }
32955
32956        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32957        function blurHandler(){
32958            isWindowFocused = false;
32959            controlPressed = false;
32960        }
32961
32962        //Scrolls to the section when clicking the navigation bullet
32963        function sectionBulletHandler(e){
32964            e.preventDefault();
32965            var index = $(this).parent().index();
32966            scrollPage($(SECTION_SEL).eq(index));
32967        }
32968
32969        //Scrolls the slider to the given slide destination for the given section
32970        function slideBulletHandler(e){
32971            e.preventDefault();
32972            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
32973            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
32974
32975            landscapeScroll(slides, destiny);
32976        }
32977
32978        /**
32979        * Keydown event
32980        */
32981        function onkeydown(e){
32982            var shiftPressed = e.shiftKey;
32983
32984            //do nothing if we can not scroll or we are not using horizotnal key arrows.
32985            if(!canScroll && [37,39].indexOf(e.which) < 0){
32986                return;
32987            }
32988
32989            switch (e.which) {
32990                //up
32991                case 38:
32992                case 33:
32993                    if(isScrollAllowed.k.up){
32994                        moveSectionUp();
32995                    }
32996                    break;
32997
32998                //down
32999                case 32: //spacebar
33000                    if(shiftPressed && isScrollAllowed.k.up){
33001                        moveSectionUp();
33002                        break;
33003                    }
33004                /* falls through */
33005                case 40:
33006                case 34:
33007                    if(isScrollAllowed.k.down){
33008                        moveSectionDown();
33009                    }
33010                    break;
33011
33012                //Home
33013                case 36:
33014                    if(isScrollAllowed.k.up){
33015                        moveTo(1);
33016                    }
33017                    break;
33018
33019                //End
33020                case 35:
33021                     if(isScrollAllowed.k.down){
33022                        moveTo( $(SECTION_SEL).length );
33023                    }
33024                    break;
33025
33026                //left
33027                case 37:
33028                    if(isScrollAllowed.k.left){
33029                        moveSlideLeft();
33030                    }
33031                    break;
33032
33033                //right
33034                case 39:
33035                    if(isScrollAllowed.k.right){
33036                        moveSlideRight();
33037                    }
33038                    break;
33039
33040                default:
33041                    return; // exit this handler for other keys
33042            }
33043        }
33044
33045        /**
33046        * Detecting the direction of the mouse movement.
33047        * Used only for the middle button of the mouse.
33048        */
33049        var oldPageY = 0;
33050        function mouseMoveHandler(e){
33051            if(canScroll){
33052                // moving up
33053                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33054                    moveSectionUp();
33055                }
33056
33057                // moving down
33058                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
33059                    moveSectionDown();
33060                }
33061            }
33062            oldPageY = e.pageY;
33063        }
33064
33065        /**
33066        * Scrolls horizontal sliders.
33067        */
33068        function landscapeScroll(slides, destiny, direction){
33069            var section = slides.closest(SECTION_SEL);
33070            var v = {
33071                slides: slides,
33072                destiny: destiny,
33073                direction: direction,
33074                destinyPos: destiny.position(),
33075                slideIndex: destiny.index(),
33076                section: section,
33077                sectionIndex: section.index(SECTION_SEL),
33078                anchorLink: section.data('anchor'),
33079                slidesNav: section.find(SLIDES_NAV_SEL),
33080                slideAnchor:  getAnchor(destiny),
33081                prevSlide: section.find(SLIDE_ACTIVE_SEL),
33082                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
33083
33084                //caching the value of isResizing at the momment the function is called
33085                //because it will be checked later inside a setTimeout and the value might change
33086                localIsResizing: isResizing
33087            };
33088            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
33089            v.direction = v.direction ? v.direction : v.xMovement;
33090
33091            //important!! Only do it when not resizing
33092            if(!v.localIsResizing){
33093                //preventing from scrolling to the next/prev section when using scrollHorizontally
33094                canScroll = false;
33095            }
33096
33097            if(options.onSlideLeave){
33098
33099                //if the site is not just resizing and readjusting the slides
33100                if(!v.localIsResizing && v.xMovement!=='none'){
33101                    if($.isFunction( options.onSlideLeave )){
33102                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
33103                            slideMoving = false;
33104                            return;
33105                        }
33106                    }
33107                }
33108            }
33109
33110            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33111
33112            if(!v.localIsResizing){
33113                stopMedia(v.prevSlide);
33114                lazyLoad(destiny);
33115            }
33116
33117            if(!options.loopHorizontal && options.controlArrows){
33118                //hidding it for the fist slide, showing for the rest
33119                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
33120
33121                //hidding it for the last slide, showing for the rest
33122                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
33123            }
33124
33125            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
33126            if(section.hasClass(ACTIVE) && !v.localIsResizing){
33127                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
33128            }
33129
33130            performHorizontalMove(slides, v, true);
33131        }
33132
33133
33134        function afterSlideLoads(v){
33135            activeSlidesNavigation(v.slidesNav, v.slideIndex);
33136
33137            //if the site is not just resizing and readjusting the slides
33138            if(!v.localIsResizing){
33139                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
33140
33141                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
33142                //and to prevent double scroll right after a windows resize
33143                canScroll = true;
33144
33145                playMedia(v.destiny);
33146            }
33147
33148            //letting them slide again
33149            slideMoving = false;
33150        }
33151
33152        /**
33153        * Performs the horizontal movement. (CSS3 or jQuery)
33154        *
33155        * @param fireCallback {Bool} - determines whether or not to fire the callback
33156        */
33157        function performHorizontalMove(slides, v, fireCallback){
33158            var destinyPos = v.destinyPos;
33159
33160            if(options.css3){
33161                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
33162
33163                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
33164
33165                afterSlideLoadsId = setTimeout(function(){
33166                    fireCallback && afterSlideLoads(v);
33167                }, options.scrollingSpeed, options.easing);
33168            }else{
33169                slides.animate({
33170                    scrollLeft : Math.round(destinyPos.left)
33171                }, options.scrollingSpeed, options.easing, function() {
33172
33173                    fireCallback && afterSlideLoads(v);
33174                });
33175            }
33176        }
33177
33178        /**
33179        * Sets the state for the horizontal bullet navigations.
33180        */
33181        function activeSlidesNavigation(slidesNav, slideIndex){
33182            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
33183            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
33184        }
33185
33186        var previousHeight = windowsHeight;
33187
33188        //when resizing the site, we adjust the heights of the sections, slimScroll...
33189        function resizeHandler(){
33190            //checking if it needs to get responsive
33191            responsive();
33192
33193            // rebuild immediately on touch devices
33194            if (isTouchDevice) {
33195                var activeElement = $(document.activeElement);
33196
33197                //if the keyboard is NOT visible
33198                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
33199                    var currentHeight = $window.height();
33200
33201                    //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)
33202                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
33203                        reBuild(true);
33204                        previousHeight = currentHeight;
33205                    }
33206                }
33207            }else{
33208                //in order to call the functions only when the resize is finished
33209                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
33210                clearTimeout(resizeId);
33211
33212                resizeId = setTimeout(function(){
33213                    reBuild(true);
33214                }, 350);
33215            }
33216        }
33217
33218        /**
33219        * Checks if the site needs to get responsive and disables autoScrolling if so.
33220        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
33221        */
33222        function responsive(){
33223            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
33224            var heightLimit = options.responsiveHeight;
33225
33226            //only calculating what we need. Remember its called on the resize event.
33227            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
33228            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
33229
33230            if(widthLimit && heightLimit){
33231                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
33232            }
33233            else if(widthLimit){
33234                setResponsive(isBreakingPointWidth);
33235            }
33236            else if(heightLimit){
33237                setResponsive(isBreakingPointHeight);
33238            }
33239        }
33240
33241        /**
33242        * Adds transition animations for the given element
33243        */
33244        function addAnimation(container, element){
33245            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
33246
33247            container.removeClass(NO_TRANSITION);
33248            return container.css({
33249                '-webkit-transition': transition,
33250                'transition': transition
33251            });
33252        }
33253
33254        /**
33255        * Remove transition animations for the given element
33256        */
33257        function removeAnimation(element){
33258            return element.addClass(NO_TRANSITION);
33259        }
33260
33261        /**
33262        * Activating the vertical navigation bullets according to the given slide name.
33263        */
33264        function activateNavDots(name, sectionIndex){
33265            if(options.navigation){
33266                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
33267                if(name){
33268                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
33269                }else{
33270                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
33271                }
33272            }
33273        }
33274
33275        /**
33276        * Activating the website main menu elements according to the given slide name.
33277        */
33278        function activateMenuElement(name){
33279            if(options.menu){
33280                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
33281                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
33282            }
33283        }
33284
33285        /**
33286        * Sets to active the current menu and vertical nav items.
33287        */
33288        function activateMenuAndNav(anchor, index){
33289            activateMenuElement(anchor);
33290            activateNavDots(anchor, index);
33291        }
33292
33293        /**
33294        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
33295        * from the current section.
33296        */
33297        function getYmovement(destiny){
33298            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
33299            var toIndex = destiny.index(SECTION_SEL);
33300            if( fromIndex == toIndex){
33301                return 'none';
33302            }
33303            if(fromIndex > toIndex){
33304                return 'up';
33305            }
33306            return 'down';
33307        }
33308
33309        /**
33310        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
33311        * from the current slide.
33312        */
33313        function getXmovement(fromIndex, toIndex){
33314            if( fromIndex == toIndex){
33315                return 'none';
33316            }
33317            if(fromIndex > toIndex){
33318                return 'left';
33319            }
33320            return 'right';
33321        }
33322
33323        /**
33324        * Checks if the element needs scrollbar and if the user wants to apply it.
33325        * If so it creates it.
33326        *
33327        * @param {Object} element   jQuery object of the section or slide
33328        */
33329        function createScrollBar(element){
33330            //User doesn't want scrollbar here? Sayonara baby!
33331            if(element.hasClass('fp-noscroll')) return;
33332
33333            //needed to make `scrollHeight` work under Opera 12
33334            element.css('overflow', 'hidden');
33335
33336            var scrollOverflowHandler = options.scrollOverflowHandler;
33337            var wrap = scrollOverflowHandler.wrapContent();
33338            //in case element is a slide
33339            var section = element.closest(SECTION_SEL);
33340            var scrollable = scrollOverflowHandler.scrollable(element);
33341            var contentHeight;
33342
33343            //if there was scroll, the contentHeight will be the one in the scrollable section
33344            if(scrollable.length){
33345                contentHeight = scrollOverflowHandler.scrollHeight(element);
33346            }else{
33347                contentHeight = element.get(0).scrollHeight;
33348                if(options.verticalCentered){
33349                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
33350                }
33351            }
33352
33353            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
33354
33355            //needs scroll?
33356            if ( contentHeight > scrollHeight) {
33357                //did we already have an scrollbar ? Updating it
33358                if(scrollable.length){
33359                    scrollOverflowHandler.update(element, scrollHeight);
33360                }
33361                //creating the scrolling
33362                else{
33363                    if(options.verticalCentered){
33364                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
33365                    }else{
33366                        element.wrapInner(wrap);
33367                    }
33368                    scrollOverflowHandler.create(element, scrollHeight);
33369                }
33370            }
33371            //removing the scrolling when it is not necessary anymore
33372            else{
33373                scrollOverflowHandler.remove(element);
33374            }
33375
33376            //undo
33377            element.css('overflow', '');
33378        }
33379
33380        function addTableClass(element){
33381            //In case we are styling for the 2nd time as in with reponsiveSlides
33382            if(!element.hasClass(TABLE)){
33383                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
33384            }
33385        }
33386
33387        function getTableHeight(element){
33388            var sectionHeight = windowsHeight;
33389
33390            if(options.paddingTop || options.paddingBottom){
33391                var section = element;
33392                if(!section.hasClass(SECTION)){
33393                    section = element.closest(SECTION_SEL);
33394                }
33395
33396                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
33397                sectionHeight = (windowsHeight - paddings);
33398            }
33399
33400            return sectionHeight;
33401        }
33402
33403        /**
33404        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
33405        */
33406        function transformContainer(translate3d, animated){
33407            if(animated){
33408                addAnimation(container);
33409            }else{
33410                removeAnimation(container);
33411            }
33412
33413            container.css(getTransforms(translate3d));
33414
33415            //syncronously removing the class after the animation has been applied.
33416            setTimeout(function(){
33417                container.removeClass(NO_TRANSITION);
33418            },10);
33419        }
33420
33421        /**
33422        * Gets a section by its anchor / index
33423        */
33424        function getSectionByAnchor(sectionAnchor){
33425            if(!sectionAnchor) return [];
33426
33427            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
33428            if(!section.length){
33429                section = $(SECTION_SEL).eq( sectionAnchor -1);
33430            }
33431
33432            return section;
33433        }
33434
33435        /**
33436        * Gets a slide inside a given section by its anchor / index
33437        */
33438        function getSlideByAnchor(slideAnchor, section){
33439            var slides = section.find(SLIDES_WRAPPER_SEL);
33440            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
33441
33442            if(!slide.length){
33443                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
33444            }
33445
33446            return slide;
33447        }
33448
33449        /**
33450        * Scrolls to the given section and slide anchors
33451        */
33452        function scrollPageAndSlide(destiny, slide){
33453            var section = getSectionByAnchor(destiny);
33454
33455            //do nothing if there's no section with the given anchor name
33456            if(!section.length) return;
33457
33458            //default slide
33459            if (typeof slide === 'undefined') {
33460                slide = 0;
33461            }
33462
33463            //we need to scroll to the section and then to the slide
33464            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
33465                scrollPage(section, function(){
33466                    scrollSlider(section, slide);
33467                });
33468            }
33469            //if we were already in the section
33470            else{
33471                scrollSlider(section, slide);
33472            }
33473        }
33474
33475        /**
33476        * Scrolls the slider to the given slide destination for the given section
33477        */
33478        function scrollSlider(section, slideAnchor){
33479            if(typeof slideAnchor !== 'undefined'){
33480                var slides = section.find(SLIDES_WRAPPER_SEL);
33481                var destiny =  getSlideByAnchor(slideAnchor, section);
33482
33483                if(destiny.length){
33484                    landscapeScroll(slides, destiny);
33485                }
33486            }
33487        }
33488
33489        /**
33490        * Creates a landscape navigation bar with dots for horizontal sliders.
33491        */
33492        function addSlidesNavigation(section, numSlides){
33493            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
33494            var nav = section.find(SLIDES_NAV_SEL);
33495
33496            //top or bottom
33497            nav.addClass(options.slidesNavPosition);
33498
33499            for(var i=0; i< numSlides; i++){
33500                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
33501            }
33502
33503            //centering it
33504            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
33505
33506            nav.find('li').first().find('a').addClass(ACTIVE);
33507        }
33508
33509
33510        /**
33511        * Sets the state of the website depending on the active section/slide.
33512        * It changes the URL hash when needed and updates the body class.
33513        */
33514        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
33515            var sectionHash = '';
33516
33517            if(options.anchors.length && !options.lockAnchors){
33518
33519                //isn't it the first slide?
33520                if(slideIndex){
33521                    if(typeof anchorLink !== 'undefined'){
33522                        sectionHash = anchorLink;
33523                    }
33524
33525                    //slide without anchor link? We take the index instead.
33526                    if(typeof slideAnchor === 'undefined'){
33527                        slideAnchor = slideIndex;
33528                    }
33529
33530                    lastScrolledSlide = slideAnchor;
33531                    setUrlHash(sectionHash + '/' + slideAnchor);
33532
33533                //first slide won't have slide anchor, just the section one
33534                }else if(typeof slideIndex !== 'undefined'){
33535                    lastScrolledSlide = slideAnchor;
33536                    setUrlHash(anchorLink);
33537                }
33538
33539                //section without slides
33540                else{
33541                    setUrlHash(anchorLink);
33542                }
33543            }
33544
33545            setBodyClass();
33546        }
33547
33548        /**
33549        * Sets the URL hash.
33550        */
33551        function setUrlHash(url){
33552            //Uncode addition
33553            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
33554                return false;
33555
33556            if(options.recordHistory){
33557                location.hash = url;
33558            }else{
33559                //Uncode addition
33560                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
33561                // if(isTouchDevice || isTouch){
33562                //     window.history.replaceState(undefined, undefined, '#' + url);
33563                // }else{
33564                //     var baseUrl = window.location.href.split('#')[0];
33565                //     window.location.replace( baseUrl + '#' + url );
33566                // }
33567                return false;
33568            }
33569        }
33570
33571        /**
33572        * Gets the anchor for the given slide / section. Its index will be used if there's none.
33573        */
33574        function getAnchor(element){
33575            var anchor = element.data('anchor');
33576            var index = element.index();
33577
33578            //Slide without anchor link? We take the index instead.
33579            if(typeof anchor === 'undefined'){
33580                anchor = index;
33581            }
33582
33583            return anchor;
33584        }
33585
33586        /**
33587        * Sets a class for the body of the page depending on the active section / slide
33588        */
33589        function setBodyClass(){
33590            var section = $(SECTION_ACTIVE_SEL);
33591            var slide = section.find(SLIDE_ACTIVE_SEL);
33592
33593            var sectionAnchor = getAnchor(section);
33594            var slideAnchor = getAnchor(slide);
33595
33596            var text = String(sectionAnchor);
33597
33598            if(slide.length){
33599                text = text + '-' + slideAnchor;
33600            }
33601
33602            //changing slash for dash to make it a valid CSS style
33603            text = text.replace('/', '-').replace('#','');
33604
33605            //removing previous anchor classes
33606            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
33607            $body[0].className = $body[0].className.replace(classRe, '');
33608
33609            //adding the current anchor
33610            $body.addClass(VIEWING_PREFIX + '-' + text);
33611        }
33612
33613        /**
33614        * Checks for translate3d support
33615        * @return boolean
33616        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
33617        */
33618        function support3d() {
33619            var el = document.createElement('p'),
33620                has3d,
33621                transforms = {
33622                    'webkitTransform':'-webkit-transform',
33623                    'OTransform':'-o-transform',
33624                    'msTransform':'-ms-transform',
33625                    'MozTransform':'-moz-transform',
33626                    'transform':'transform'
33627                };
33628
33629            // Add it to the body to get the computed style.
33630            document.body.insertBefore(el, null);
33631
33632            for (var t in transforms) {
33633                if (el.style[t] !== undefined) {
33634                    el.style[t] = 'translate3d(1px,1px,1px)';
33635                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
33636                }
33637            }
33638
33639            document.body.removeChild(el);
33640
33641            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
33642        }
33643
33644        /**
33645        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
33646        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
33647        */
33648        function removeMouseWheelHandler(){
33649            if (document.addEventListener) {
33650                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
33651                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
33652                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
33653            } else {
33654                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
33655            }
33656        }
33657
33658        /**
33659        * Adds the auto scrolling action for the mouse wheel and trackpad.
33660        * After this function is called, the mousewheel and trackpad movements will scroll through sections
33661        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
33662        */
33663        function addMouseWheelHandler(){
33664            var prefix = '';
33665            var _addEventListener;
33666
33667            if (window.addEventListener){
33668                _addEventListener = "addEventListener";
33669            }else{
33670                _addEventListener = "attachEvent";
33671                prefix = 'on';
33672            }
33673
33674             // detect available wheel event
33675            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
33676                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
33677                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
33678            var passiveEvent = g_supportsPassive ? {passive: false }
33678: false;
33679
33680
33681            if(support == 'DOMMouseScroll'){
33682                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
33683            }
33684
33685            //handle MozMousePixelScroll in older Firefox
33686            else{
33687                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
33688            }
33689        }
33690
33691        /**
33692        * Binding the mousemove when the mouse's middle button is pressed
33693        */
33694        function addMiddleWheelHandler(){
33695            container
33696                .on('mousedown', mouseDownHandler)
33697                .on('mouseup', mouseUpHandler);
33698        }
33699
33700        /**
33701        * Unbinding the mousemove when the mouse's middle button is released
33702        */
33703        function removeMiddleWheelHandler(){
33704            container
33705                .off('mousedown', mouseDownHandler)
33706                .off('mouseup', mouseUpHandler);
33707        }
33708
33709        /**
33710        * Adds the possibility to auto scroll through sections on touch devices.
33711        */
33712        function addTouchHandler(){
33713            if(isTouchDevice || isTouch){
33714                if(options.autoScrolling){
33715                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
33716                }
33717
33718                $(WRAPPER_SEL)
33719                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
33720                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
33721            }
33722        }
33723
33724        /**
33725        * Removes the auto scrolling for touch devices.
33726        */
33727        function removeTouchHandler(){
33728            if(isTouchDevice || isTouch){
33729                $(WRAPPER_SEL)
33730                    .off(events.touchstart)
33731                    .off(events.touchmove);
33732            }
33733        }
33734
33735        /*
33736        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
33737        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
33738        */
33739        function getMSPointer(){
33740            var pointer;
33741
33742            //IE >= 11 & rest of browsers
33743            if(window.PointerEvent){
33744                pointer = { down: 'pointerdown', move: 'pointermove'};
33745            }
33746
33747            //IE < 11
33748            else{
33749                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
33750            }
33751
33752            return pointer;
33753        }
33754
33755        /**
33756        * Gets the pageX and pageY properties depending on the browser.
33757        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
33758        */
33759        function getEventsPage(e){
33760            var events = [];
33761
33762            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
33763            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33764
33765            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33766            if(isTouch && isReallyTouch(e) && options.scrollBar){
33767                events.y = e.touches[0].pageY;
33768                events.x = e.touches[0].pageX;
33769            }
33770
33771            return events;
33772        }
33773
33774        /**
33775        * Slides silently (with no animation) the active slider to the given slide.
33776        * @param noCallback {bool} true or defined -> no callbacks
33777        */
33778        function silentLandscapeScroll(activeSlide, noCallbacks){
33779            setScrollingSpeed (0, 'internal');
33780
33781            if(typeof noCallbacks !== 'undefined'){
33782                //preventing firing callbacks afterSlideLoad etc.
33783                isResizing = true;
33784            }
33785
33786            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33787
33788            if(typeof noCallbacks !== 'undefined'){
33789                isResizing = false;
33790            }
33791
33792            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33793        }
33794
33795        /**
33796        * Scrolls silently (with no animation) the page to the given Y position.
33797        */
33798        function silentScroll(top){
33799            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33800            // that's why we round it to 0.
33801            var roundedTop = Math.round(top);
33802
33803            if (options.css3 && options.autoScrolling && !options.scrollBar){
33804                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33805                transformContainer(translate3d, false);
33806            }
33807            else if(options.autoScrolling && !options.scrollBar){
33808                container.css('top', -roundedTop);
33809            }
33810            else{
33811                $htmlBody.scrollTop(roundedTop);
33812            }
33813        }
33814
33815        /**
33816        * Returns the cross-browser transform string.
33817        */
33818        function getTransforms(translate3d){
33819            return {
33820                '-webkit-transform': translate3d,
33821                '-moz-transform': translate3d,
33822                '-ms-transform':translate3d,
33823                'transform': translate3d
33824            };
33825        }
33826
33827        /**
33828        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33829        * @type  m (mouse) or k (keyboard)
33830        */
33831        function setIsScrollAllowed(value, direction, type){
33832            switch (direction){
33833                case 'up': isScrollAllowed[type].up = value; break;
33834                case 'down': isScrollAllowed[type].down = value; break;
33835                case 'left': isScrollAllowed[type].left = value; break;
33836                case 'right': isScrollAllowed[type].right = value; break;
33837                case 'all':
33838                    if(type == 'm'){
33839                        setAllowScrolling(value);
33840                    }else{
33841                        setKeyboardScrolling(value);
33842                    }
33843            }
33844        }
33845
33846        /*
33847        * Destroys fullpage.js plugin events and optinally its html markup and styles
33848        */
33849        function destroy(all){
33850            setAutoScrolling(false, 'internal');
33851            setAllowScrolling(false);
33852            setKeyboardScrolling(false);
33853            container.addClass(DESTROYED);
33854
33855            clearTimeout(afterSlideLoadsId);
33856            clearTimeout(afterSectionLoadsId);
33857            clearTimeout(resizeId);
33858            clearTimeout(scrollId);
33859            clearTimeout(scrollId2);
33860
33861            $window
33862                .off('scroll', scrollHandler)
33863                .off('hashchange', hashChangeHandler)
33864                .off('resize', resizeHandler);
33865
33866            $document
33867                .off('click touchstart', SECTION_NAV_SEL + ' a')
33868                .off('mouseenter', SECTION_NAV_SEL + ' li')
33869                .off('mouseleave', SECTION_NAV_SEL + ' li')
33870                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33871                .off('mouseover', options.normalScrollElements)
33872                .off('mouseout', options.normalScrollElements);
33873
33874            $(SECTION_SEL)
33875                .off('click touchstart', SLIDES_ARROW_SEL);
33876
33877            clearTimeout(afterSlideLoadsId);
33878            clearTimeout(afterSectionLoadsId);
33879
33880            //lets make a mess!
33881            if(all){
33882                destroyStructure();
33883            }
33884        }
33885
33886        /*
33887        * Removes inline styles added by fullpage.js
33888        */
33889        function destroyStructure(){
33890            //reseting the `top` or `translate` properties to 0
33891            silentScroll(0);
33892
33893            //loading all the lazy load content
33894            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33895                setSrc($(this), 'src');
33896            });
33897
33898            container.find('img[data-srcset]').each(function(){
33899                setSrc($(this), 'srcset');
33900            });
33901
33902            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33903
33904            //removing inline styles
33905            $(SECTION_SEL).css( {
33906                'height': '',
33907                'background-color' : '',
33908                'padding': ''
33909            });
33910
33911            $(SLIDE_SEL).css( {
33912                'width': ''
33913            });
33914
33915            container.css({
33916                'height': '',
33917                'position': '',
33918                '-ms-touch-action': '',
33919                'touch-action': ''
33920            });
33921
33922            $htmlBody.css({
33923                'overflow': '',
33924                'height': ''
33925            });
33926
33927            // remove .fp-enabled class
33928            $('html').removeClass(ENABLED);
33929
33930            // remove .fp-responsive class
33931            $body.removeClass(RESPONSIVE);
33932
33933            // remove all of the .fp-viewing- classes
33934            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33935                if (className.indexOf(VIEWING_PREFIX) === 0) {
33936                    $body.removeClass(className);
33937                }
33938            });
33939
33940            //removing added classes
33941            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
33942                options.scrollOverflowHandler.remove($(this));
33943                $(this).removeClass(TABLE + ' ' + ACTIVE);
33944            });
33945
33946            removeAnimation(container);
33947
33948            //Unwrapping content
33949            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
33950                //unwrap not being use in case there's no child element inside and its just text
33951                $(this).replaceWith(this.childNodes);
33952            });
33953
33954            //removing the applied transition from the fullpage wrapper
33955            container.css({
33956                '-webkit-transition': 'none',
33957                'transition': 'none'
33958            });
33959
33960            //scrolling the page to the top with no animation
33961            $htmlBody.scrollTop(0);
33962
33963            //removing selectors
33964            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
33965            $.each(usedSelectors, function(index, value){
33966                $('.' + value).removeClass(value);
33967            });
33968        }
33969
33970        /*
33971        * Sets the state for a variable with multiple states (original, and temporal)
33972        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
33973        * This function is used to keep track of both states, the original and the temporal one.
33974        * If type is not 'internal', then we assume the user is globally changing the variable.
33975        */
33976        function setVariableState(variable, value, type){
33977            options[variable] = value;
33978            if(type !== 'internal'){
33979                originals[variable] = value;
33980            }
33981        }
33982
33983        /**
33984        * Displays warnings
33985        */
33986        function displayWarnings(){
33987            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
33988            //UNCODE.addition
33989            // if($('html').hasClass(ENABLED)){
33990            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
33991            //     return;
33992            // }
33993
33994            // Disable mutually exclusive settings
33995            //UNCODE.addition
33996            // if (options.continuousVertical &&
33997            //     (options.loopTop || options.loopBottom)) {
33998            //     options.continuousVertical = false;
33999            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34000            // }
34001
34002            // if(options.scrollBar && options.scrollOverflow){
34003            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34004            // }
34005
34006            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34007            //     options.continuousVertical = false;
34008            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34009            // }
34010
34011            //using extensions? Wrong file!
34012            $.each(extensions, function(index, extension){
34013                //is the option set to true?
34014                if(options[extension]){
34015                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34016                }
34017            });
34018
34019            //anchors can not have the same value as any element ID or NAME
34020            $.each(options.anchors, function(index, name){
34021
34022                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34023                var nameAttr = $document.find('[name]').filter(function() {
34024                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34025                });
34026
34027                var idAttr = $document.find('[id]').filter(function() {
34028                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34029                });
34030
34031                if(idAttr.length || nameAttr.length ){
34032                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34033                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34034                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34035                }
34036            });
34037        }
34038
34039        /**
34040        * Shows a message in the console of the given type.
34041        */
34042        function showError(type, text){
34043            console && console[type] && console[type]('fullPage: ' + text);
34044        }
34045
34046    }; //end of $.fn.fullpage
34047
34048    if(typeof IScroll !== 'undefined'){
34049        /*
34050        * Turns iScroll `mousewheel` option off dynamically
34051        * https://github.com/cubiq/iscroll/issues/1036
34052        */
34053        IScroll.prototype.wheelOn = function () {
34054            this.wrapper.addEventListener('wheel', this);
34055            this.wrapper.addEventListener('mousewheel', this);
34056            this.wrapper.addEventListener('DOMMouseScroll', this);
34057        };
34058
34059        /*
34060        * Turns iScroll `mousewheel` option on dynamically
34061        * https://github.com/cubiq/iscroll/issues/1036
34062        */
34063        IScroll.prototype.wheelOff = function () {
34064            this.wrapper.removeEventListener('wheel', this);
34065            this.wrapper.removeEventListener('mousewheel', this);
34066            this.wrapper.removeEventListener('DOMMouseScroll', this);
34067        };
34068    }
34069
34070    /**
34071     * An object to handle overflow scrolling.
34072     * This uses jquery.slimScroll to accomplish overflow scrolling.
34073     * It is possible to pass in an alternate scrollOverflowHandler
34074     * to the fullpage.js option that implements the same functions
34075     * as this handler.
34076     *
34077     * @type {Object}
34078     */
34079    var iscrollHandler = {
34080        refreshId: null,
34081        iScrollInstances: [],
34082
34083        // Enables or disables the mouse wheel for the active section or all slides in it
34084        toggleWheel: function(value){
34085            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
34086            scrollable.each(function(){
34087                var iScrollInstance = $(this).data('iscrollInstance');
34088                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
34089                    if(value){
34090                        iScrollInstance.wheelOn();
34091                    }
34092                    else{
34093                        iScrollInstance.wheelOff();
34094                    }
34095                }
34096            });
34097        },
34098
34099        /**
34100        * Turns off iScroll for the destination section.
34101        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
34102        * scroll the destination section/slide before the sections animations ends.
34103        */
34104        onLeave: function(){
34105            iscrollHandler.toggleWheel(false);
34106        },
34107
34108        // Turns off iScroll for the leaving section
34109        beforeLeave: function(){
34110            iscrollHandler.onLeave()
34111        },
34112
34113        // Turns on iScroll on section load
34114        afterLoad: function(){
34115            iscrollHandler.toggleWheel(true);
34116        },
34117
34118        /**
34119         * Called when overflow scrolling is needed for a section.
34120         *
34121         * @param  {Object} element      jQuery object containing current section
34122         * @param  {Number} scrollHeight Current window height in pixels
34123         */
34124        create: function(element, scrollHeight) {
34125            var scrollable = element.find(SCROLLABLE_SEL);
34126
34127            scrollable.height(scrollHeight);
34128            scrollable.each(function() {
34129                var $this = $(this);
34130                var iScrollInstance = $this.data('iscrollInstance');
34131                if (iScrollInstance) {
34132                    $.each(iscrollHandler.iScrollInstances, function(){
34133                        $(this).destroy();
34134                    });
34135                }
34136
34137                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
34138                iscrollHandler.iScrollInstances.push(iScrollInstance);
34139
34140                //off by default until the section gets active
34141                iScrollInstance.wheelOff();
34142
34143                $this.data('iscrollInstance', iScrollInstance);
34144            });
34145        },
34146
34147        /**
34148         * Return a boolean depending on whether the scrollable element is a
34149         * the end or at the start of the scrolling depending on the given type.
34150         *
34151         * @param  {String}  type       Either 'top' or 'bottom'
34152         * @param  {Object}  scrollable jQuery object for the scrollable element
34153         * @return {Boolean}
34154         */
34155        isScrolled: function(type, scrollable) {
34156            var scroller = scrollable.data('iscrollInstance');
34157
34158            //no scroller?
34159            if (!scroller) {
34160                return true;
34161            }
34162
34163            //Uncode addition
34164            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
34165            //End Uncode addition
34166
34167            if (type === 'top') {
34168                return scroller.y >= 0 && !scrollable.scrollTop();
34169            } else if (type === 'bottom') {
34170                //Uncode change
34171                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34172                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34173                //End Uncode change
34174            }
34175        },
34176
34177        /**
34178         * Returns the scrollable element for the given section.
34179         * If there are landscape slides, will only return a scrollable element
34180         * if it is in the active slide.
34181         *
34182         * @param  {Object}  activeSection jQuery object containing current section
34183         * @return {Boolean}
34184         */
34185        scrollable: function(activeSection){
34186            // if there are landscape slides, we check if the scrolling bar is in the current one or not
34187            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
34188                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
34189            }
34190            return activeSection.find(SCROLLABLE_SEL);
34191        },
34192
34193        /**
34194         * Returns the scroll height of the wrapped content.
34195         * If this is larger than the window height minus section padding,
34196         * overflow scrolling is needed.
34197         *
34198         * @param  {Object} element jQuery object containing current section
34199         * @return {Number}
34200         */
34201        scrollHeight: function(element) {
34202            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
34203        },
34204
34205        /**
34206         * Called when overflow scrolling is no longer needed for a section.
34207         *
34208         * @param  {Object}
34208 element      jQuery object containing current section
34209         */
34210        remove: function(element) {
34211            var scrollable = element.find(SCROLLABLE_SEL);
34212            if (scrollable.length) {
34213                var iScrollInstance = scrollable.data('iscrollInstance');
34214                iScrollInstance.destroy();
34215
34216                scrollable.data('iscrollInstance', null);
34217            }
34218            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
34219        },
34220
34221        /**
34222         * Called when overflow scrolling has already been setup but the
34223         * window height has potentially changed.
34224         *
34225         * @param  {Object} element      jQuery object containing current section
34226         * @param  {Number} scrollHeight Current window height in pixels
34227         */
34228        update: function(element, scrollHeight) {
34229            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
34230            //short period of time.
34231            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
34232            clearTimeout(iscrollHandler.refreshId);
34233            iscrollHandler.refreshId = setTimeout(function(){
34234                $.each(iscrollHandler.iScrollInstances, function(){
34235                    $(this).get(0).refresh();
34236                });
34237            }, 150);
34238
34239            //updating the wrappers height
34240            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
34241        },
34242
34243        /**
34244         * Called to get any additional elements needed to wrap the section
34245         * content in order to facilitate overflow scrolling.
34246         *
34247         * @return {String|Object} Can be a string containing HTML,
34248         *                         a DOM element, or jQuery object.
34249         */
34250        wrapContent: function() {
34251            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
34252        }
34253    };
34254});
34255
34256(function (global, factory) {
34257	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
34258	typeof define === 'function' && define.amd ? define(['exports'], factory) :
34259	(global = global || self, factory(global.window = global.window || {}));
34260}(this, (function (exports) { 'use strict';
34261
34262	/*!
34263	 * ScrollTrigger 3.8.0
34264	 * https://greensock.com
34265	 *
34266	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
34267	 * Subject to the terms at https://greensock.com/standard-license or for
34268	 * Club GreenSock members, the agreement issued with that membership.
34269	 * @author: Jack Doyle, [email protected]
34270	*/
34271	var gsap,
34272	    _coreInitted,
34273	    _win,
34274	    _doc,
34275	    _docEl,
34276	    _body,
34277	    _root,
34278	    _resizeDelay,
34279	    _raf,
34280	    _request,
34281	    _toArray,
34282	    _clamp,
34283	    _time2,
34284	    _syncInterval,
34285	    _refreshing,
34286	    _pointerIsDown,
34287	    _transformProp,
34288	    _i,
34289	    _prevWidth,
34290	    _prevHeight,
34291	    _autoRefresh,
34292	    _sort,
34293	    _suppressOverwrites,
34294	    _ignoreResize,
34295	    _limitCallbacks,
34296	    _startup = 1,
34297	    _proxies = [],
34298	    _scrollers = [],
34299	    _getTime = Date.now,
34300	    _time1 = _getTime(),
34301	    _lastScrollTime = 0,
34302	    _enabled = 1,
34303	    _passThrough = function _passThrough(v) {
34304	  return v;
34305	},
34306	    _getTarget = function _getTarget(t) {
34307	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
34308	},
34309	    _round = function _round(value) {
34310	  return Math.round(value * 100000) / 100000 || 0;
34311	},
34312	    _windowExists = function _windowExists() {
34313	  return typeof window !== "undefined";
34314	},
34315	    _getGSAP = function _getGSAP() {
34316	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
34317	},
34318	    _isViewport = function _isViewport(e) {
34319	  return !!~_root.indexOf(e);
34320	},
34321	    _getProxyProp = function _getProxyProp(element, property) {
34322	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
34323	},
34324	    _getScrollFunc = function _getScrollFunc(element, _ref) {
34325	  var s = _ref.s,
34326	      sc = _ref.sc;
34327
34328	  var i = _scrollers.indexOf(element),
34329	      offset = sc === _vertical.sc ? 1 : 2;
34330
34331	  !~i && (i = _scrollers.push(element) - 1);
34332	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
34333	    return arguments.length ? element[s] = value : element[s];
34334	  }));
34335	},
34336	    _getBoundsFunc = function _getBoundsFunc(element) {
34337	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
34338	    _winOffsets.width = _win.innerWidth;
34339	    _winOffsets.height = _win.innerHeight;
34340	    return _winOffsets;
34341	  } : function () {
34342	    return _getBounds(element);
34343	  });
34344	},
34345	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
34346	  var d = _ref2.d,
34347	      d2 = _ref2.d2,
34348	      a = _ref2.a;
34349	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
34350	    return a()[d];
34351	  } : function () {
34352	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
34353	  };
34354	},
34355	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
34356	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
34357	    return _winOffsets;
34358	  };
34359	},
34360	    _maxScroll = function _maxScroll(element, _ref3) {
34361	  var s = _ref3.s,
34362	      d2 = _ref3.d2,
34363	      d = _ref3.d,
34364	      a = _ref3.a;
34365	  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];
34366	},
34367	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
34368	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 34369-34573
34369	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
34370	  }
34371	},
34372	    _isString = function _isString(value) {
34373	  return typeof value === "string";
34374	},
34375	    _isFunction = function _isFunction(value) {
34376	  return typeof value === "function";
34377	},
34378	    _isNumber = function _isNumber(value) {
34379	  return typeof value === "number";
34380	},
34381	    _isObject = function _isObject(value) {
34382	  return typeof value === "object";
34383	},
34384	    _callIfFunc = function _callIfFunc(value) {
34385	  return _isFunction(value) && value();
34386	},
34387	    _combineFunc = function _combineFunc(f1, f2) {
34388	  return function () {
34389	    var result1 = _callIfFunc(f1),
34390	        result2 = _callIfFunc(f2);
34391
34392	    return function () {
34393	      _callIfFunc(result1);
34394
34395	      _callIfFunc(result2);
34396	    };
34397	  };
34398	},
34399	    _endAnimation = function _endAnimation(animation, reversed, pause) {
34400	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
34401	},
34402	    _callback = function _callback(self, func) {
34403	  var result = func(self);
34404	  result && result.totalTime && (self.callbackAnimation = result);
34405	},
34406	    _abs = Math.abs,
34407	    _scrollLeft = "scrollLeft",
34408	    _scrollTop = "scrollTop",
34409	    _left = "left",
34410	    _top = "top",
34411	    _right = "right",
34412	    _bottom = "bottom",
34413	    _width = "width",
34414	    _height = "height",
34415	    _Right = "Right",
34416	    _Left = "Left",
34417	    _Top = "Top",
34418	    _Bottom = "Bottom",
34419	    _padding = "padding",
34420	    _margin = "margin",
34421	    _Width = "Width",
34422	    _Height = "Height",
34423	    _px = "px",
34424	    _horizontal = {
34425	  s: _scrollLeft,
34426	  p: _left,
34427	  p2: _Left,
34428	  os: _right,
34429	  os2: _Right,
34430	  d: _width,
34431	  d2: _Width,
34432	  a: "x",
34433	  sc: function sc(value) {
34434	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
34435	  }
34436	},
34437	    _vertical = {
34438	  s: _scrollTop,
34439	  p: _top,
34440	  p2: _Top,
34441	  os: _bottom,
34442	  os2: _Bottom,
34443	  d: _height,
34444	  d2: _Height,
34445	  a: "y",
34446	  op: _horizontal,
34447	  sc: function sc(value) {
34448	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
34449	  }
34450	},
34451	    _getComputedStyle = function _getComputedStyle(element) {
34452	  return _win.getComputedStyle(element);
34453	},
34454	    _makePositionable = function _makePositionable(element) {
34455	  var position = _getComputedStyle(element).position;
34456
34457	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
34458	},
34459	    _setDefaults = function _setDefaults(obj, defaults) {
34460	  for (var p in defaults) {
34461	    p in obj || (obj[p] = defaults[p]);
34462	  }
34463
34464	  return obj;
34465	},
34466	    _getBounds = function _getBounds(element, withoutTransforms) {
34467	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
34468	    x: 0,
34469	    y: 0,
34470	    xPercent: 0,
34471	    yPercent: 0,
34472	    rotation: 0,
34473	    rotationX: 0,
34474	    rotationY: 0,
34475	    scale: 1,
34476	    skewX: 0,
34477	    skewY: 0
34478	  }).progress(1),
34479	      bounds = element.getBoundingClientRect();
34480	  tween && tween.progress(0).kill();
34481	  return bounds;
34482	},
34483	    _getSize = function _getSize(element, _ref4) {
34484	  var d2 = _ref4.d2;
34485	  return element["offset" + d2] || element["client" + d2] || 0;
34486	},
34487	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
34488	  var a = [],
34489	      labels = timeline.labels,
34490	      duration = timeline.duration(),
34491	      p;
34492
34493	  for (p in labels) {
34494	    a.push(labels[p] / duration);
34495	  }
34496
34497	  return a;
34498	},
34499	    _getClosestLabel = function _getClosestLabel(animation) {
34500	  return function (value) {
34501	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
34502	  };
34503	},
34504	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
34505	  var snap = gsap.utils.snap(snapIncrementOrArray),
34506	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
34507	    return a - b;
34508	  });
34509	  return a ? function (value, direction) {
34510	    var i;
34511
34512	    if (!direction) {
34513	      return snap(value);
34514	    }
34515
34516	    if (direction > 0) {
34517	      value -= 1e-4;
34518
34519	      for (i = 0; i < a.length; i++) {
34520	        if (a[i] >= value) {
34521	          return a[i];
34522	        }
34523	      }
34524
34525	      return a[i - 1];
34526	    } else {
34527	      i = a.length;
34528	      value += 1e-4;
34529
34530	      while (i--) {
34531	        if (a[i] <= value) {
34532	          return a[i];
34533	        }
34534	      }
34535	    }
34536
34537	    return a[0];
34538	  } : function (value, direction) {
34539	    var snapped = snap(value);
34540	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
34541	  };
34542	},
34543	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
34544	  return function (value, st) {
34545	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
34546	  };
34547	},
34548	    _multiListener = function _multiListener(func, element, types, callback) {
34549	  return types.split(",").forEach(function (type) {
34550	    return func(element, type, callback);
34551	  });
34552	},
34553	    _addListener = function _addListener(element, type, func) {
34554	  return element.addEventListener(type, func, {
34555	    passive: true
34556	  });
34557	},
34558	    _removeListener = function _removeListener(element, type, func) {
34559	  return element.removeEventListener(type, func);
34560	},
34561	    _markerDefaults = {
34562	  startColor: "green",
34563	  endColor: "red",
34564	  indent: 0,
34565	  fontSize: "16px",
34566	  fontWeight: "normal"
34567	},
34568	    _defaults = {
34569	  toggleActions: "play",
34570	  anticipatePin: 0
34571	},
34572	    _keywords = {
34573	  top: 0,
34574	  left: 0,
34575	  center: 0.5,
34576	  bottom: 1,
34577	  right: 1
34578	},
34579	    _offsetToPx = function _offsetToPx(value, size) {
34580	  if (_isString(value)) {
34581	    var eqIndex = value.indexOf("="),
34582	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
34583
34584	    if (~eqIndex) {
34585	      value.indexOf("%") > eqIndex && (relative *= size / 100);
34586	      value = value.substr(0, eqIndex - 1);
34587	    }
34588
34589	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
34590	  }
34591
34592	  return value;
34593	},
34594	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
34595	  var startColor = _ref5.startColor,
34596	      endColor = _ref5.endColor,
34597	      fontSize = _ref5.fontSize,
34598	      indent = _ref5.indent,
34599	      fontWeight = _ref5.fontWeight;
34600
34601	  var e = _doc.createElement("div"),
34602	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
34603	      isScroller = type.indexOf("scroller") !== -1,
34604	      parent = useFixedPosition ? _body : container,
34605	      isStart = type.indexOf("start") !== -1,
34606	      color = isStart ? startColor : endColor,
34607	      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;";
34608
34609	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
34610	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
34611	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
34612	  e._isStart = isStart;
34613	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
34614	  e.style.cssText = css;
34615	  e.innerText = name || name === 0 ? type + "-" + name : type;
34616	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
34617	  e._offset = e["offset" + direction.op.d2];
34618
34619	  _positionMarker(e, 0, direction, isStart);
34620
34621	  return e;
34622	},
34623	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
34624	  var vars = {
34625	    display: "block"
34626	  },
34627	      side = direction[flipped ? "os2" : "p2"],
34628	      oppositeSide = direction[flipped ? "p2" : "os2"];
34629	  marker._isFlipped = flipped;
34630	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
34631	  vars[direction.a] = flipped ? "1px" : 0;
34632	  vars["border" + side + _Width] = 1;
34633	  vars["border" + oppositeSide + _Width] = 0;
34634	  vars[direction.p] = start + "px";
34635	  gsap.set(marker, vars);
34636	},
34637	    _triggers = [],
34638	    _ids = {},
34639	    _sync = function _sync() {
34640	  return _getTime() - _lastScrollTime > 20 && _updateAll();
34641	},
34642	    _onScroll = function _onScroll() {
34643	  var time = _getTime();
34644
34645	  if (_lastScrollTime !== time) {
34646	    _updateAll();
34647
34648	    _lastScrollTime || _dispatch("scrollStart");
34649	    _lastScrollTime = time;
34650	  } else if (!_request) {
34651	    _request = _raf(_updateAll);
34652	  }
34653	},
34654	    _onResize = function _onResize() {
34655	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
34656	},
34657	    _listeners = {},
34658	    _emptyArray = [],
34659	    _media = [],
34660	    _creatingMedia,
34661	    _lastMediaTick,
34662	    _onMediaChange = function _onMediaChange(e) {
34663	  var tick = gsap.ticker.frame,
34664	      matches = [],
34665	      i = 0,
34666	      index;
34667
34668	  if (_lastMediaTick !== tick || _startup) {
34669	    _revertAll();
34670
34671	    for (; i < _media.length; i += 4) {
34672	      index = _win.matchMedia(_media[i]).matches;
34673
34674	      if (index !== _media[i + 3]) {
34675	        _media[i + 3] = index;
34676	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
34677	      }
34678	    }
34679
34680	    _revertRecorded();
34681
34682	    for (i = 0; i < matches.length; i++) {
34683	      index = matches[i];
34684	      _creatingMedia = _media[index];
34685	      _media[index + 2] = _media[index + 1](e);
34686	    }
34687
34688	    _creatingMedia = 0;
34689	    _coreInitted && _refreshAll(0, 1);
34690	    _lastMediaTick = tick;
34691
34692	    _dispatch("matchMedia");
34693	  }
34694	},
34695	    _softRefresh = function _softRefresh() {
34696	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
34697	},
34698	    _dispatch = function _dispatch(type) {
34699	  return _listeners[type] && _listeners[type].map(function (f) {
34700	    return f();
34701	  }) || _emptyArray;
34702	},
34703	    _savedStyles = [],
34704	    _revertRecorded = function _revertRecorded(media) {
34705	  for (var i = 0; i < _savedStyles.length; i += 5) {
34706	    if (!media || _savedStyles[i + 4] === media) {
34707	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
34708	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
34709	      _savedStyles[i + 3].uncache = 1;
34710	    }
34711	  }
34712	},
34713	    _revertAll = function _revertAll(kill, media) {
34714	  var trigger;
34715
34716	  for (_i = 0; _i < _triggers.length; _i++) {
34717	    trigger = _triggers[_i];
34718
34719	    if (!media || trigger.media === media) {
34720	      if (kill) {
34721	        trigger.kill(1);
34722	      } else {
34723	        trigger.revert();
34724	      }
34725	    }
34726	  }
34727
34728	  media && _revertRecorded(media);
34729	  media || _dispatch("revert");
34730	},
34731	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 34732-35066
34732	  return _scrollers.forEach(function (obj) {
34733	    return typeof obj === "function" && (obj.rec = 0);
34734	  });
34735	},
34736	    _refreshingAll,
34737	    _refreshAll = function _refreshAll(force, skipRevert) {
34738	  if (_lastScrollTime && !force) {
34739	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34740
34741	    return;
34742	  }
34743
34744	  _refreshingAll = true;
34745
34746	  var refreshInits = _dispatch("refreshInit");
34747
34748	  _sort && ScrollTrigger.sort();
34749	  skipRevert || _revertAll();
34750
34751	  _triggers.forEach(function (t) {
34752	    return t.refresh();
34753	  });
34754
34755	  refreshInits.forEach(function (result) {
34756	    return result && result.render && result.render(-1);
34757	  });
34758
34759	  _clearScrollMemory();
34760
34761	  _resizeDelay.pause();
34762
34763	  _refreshingAll = false;
34764
34765	  _dispatch("refresh");
34766	},
34767	    _lastScroll = 0,
34768	    _direction = 1,
34769	    _updateAll = function _updateAll() {
34770	  if (!_refreshingAll) {
34771	    var l = _triggers.length,
34772	        time = _getTime(),
34773	        recordVelocity = time - _time1 >= 50,
34774	        scroll = l && _triggers[0].scroll();
34775
34776	    _direction = _lastScroll > scroll ? -1 : 1;
34777	    _lastScroll = scroll;
34778
34779	    if (recordVelocity) {
34780	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34781	        _lastScrollTime = 0;
34782
34783	        _dispatch("scrollEnd");
34784	      }
34785
34786	      _time2 = _time1;
34787	      _time1 = time;
34788	    }
34789
34790	    if (_direction < 0) {
34791	      _i = l;
34792
34793	      while (_i-- > 0) {
34794	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34795	      }
34796
34797	      _direction = 1;
34798	    } else {
34799	      for (_i = 0; _i < l; _i++) {
34800	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34801	      }
34802	    }
34803
34804	    _request = 0;
34805	  }
34806	},
34807	    _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"],
34808	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34809	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34810	  _setState(state);
34811
34812	  var cache = pin._gsap;
34813
34814	  if (cache.spacerIsNative) {
34815	    _setState(cache.spacerState);
34816	  } else if (pin.parentNode === spacer) {
34817	    var parent = spacer.parentNode;
34818
34819	    if (parent) {
34820	      parent.insertBefore(pin, spacer);
34821	      parent.removeChild(spacer);
34822	    }
34823	  }
34824	},
34825	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34826	  if (pin.parentNode !== spacer) {
34827	    var i = _propNamesToCopy.length,
34828	        spacerStyle = spacer.style,
34829	        pinStyle = pin.style,
34830	        p;
34831
34832	    while (i--) {
34833	      p = _propNamesToCopy[i];
34834	      spacerStyle[p] = cs[p];
34835	    }
34836
34837	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34838	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34839	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34840	    spacerStyle.overflow = "visible";
34841	    spacerStyle.boxSizing = "border-box";
34842	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34843	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34844	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34845
34846	    _setState(spacerState);
34847
34848	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34849	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34850	    pinStyle[_padding] = cs[_padding];
34851	    pin.parentNode.insertBefore(spacer, pin);
34852	    spacer.appendChild(pin);
34853	  }
34854	},
34855	    _capsExp = /([A-Z])/g,
34856	    _setState = function _setState(state) {
34857	  if (state) {
34858	    var style = state.t.style,
34859	        l = state.length,
34860	        i = 0,
34861	        p,
34862	        value;
34863	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34864
34865	    for (; i < l; i += 2) {
34866	      value = state[i + 1];
34867	      p = state[i];
34868
34869	      if (value) {
34870	        style[p] = value;
34871	      } else if (style[p]) {
34872	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34873	      }
34874	    }
34875	  }
34876	},
34877	    _getState = function _getState(element) {
34878	  var l = _stateProps.length,
34879	      style = element.style,
34880	      state = [],
34881	      i = 0;
34882
34883	  for (; i < l; i++) {
34884	    state.push(_stateProps[i], style[_stateProps[i]]);
34885	  }
34886
34887	  state.t = element;
34888	  return state;
34889	},
34890	    _copyState = function _copyState(state, override, omitOffsets) {
34891	  var result = [],
34892	      l = state.length,
34893	      i = omitOffsets ? 8 : 0,
34894	      p;
34895
34896	  for (; i < l; i += 2) {
34897	    p = state[i];
34898	    result.push(p, p in override ? override[p] : state[i + 1]);
34899	  }
34900
34901	  result.t = state.t;
34902	  return result;
34903	},
34904	    _winOffsets = {
34905	  left: 0,
34906	  top: 0
34907	},
34908	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34909	  _isFunction(value) && (value = value(self));
34910
34911	  if (_isString(value) && value.substr(0, 3) === "max") {
34912	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34913	  }
34914
34915	  var time = containerAnimation ? containerAnimation.time() : 0,
34916	      p1,
34917	      p2,
34918	      element;
34919	  containerAnimation && containerAnimation.seek(0);
34920
34921	  if (!_isNumber(value)) {
34922	    _isFunction(trigger) && (trigger = trigger(self));
34923	    var offsets = value.split(" "),
34924	        bounds,
34925	        localOffset,
34926	        globalOffset,
34927	        display;
34928	    element = _getTarget(trigger) || _body;
34929	    bounds = _getBounds(element) || {};
34930
34931	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34932	      display = element.style.display;
34933	      element.style.display = "block";
34934	      bounds = _getBounds(element);
34935	      display ? element.style.display = display : element.style.removeProperty("display");
34936	    }
34937
34938	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
34939	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
34940	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
34941	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
34942	    scrollerSize -= scrollerSize - globalOffset;
34943	  } else if (markerScroller) {
34944	    _positionMarker(markerScroller, scrollerSize, direction, true);
34945	  }
34946
34947	  if (marker) {
34948	    var position = value + scrollerSize,
34949	        isStart = marker._isStart;
34950	    p1 = "scroll" + direction.d2;
34951
34952	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
34953
34954	    if (useFixedPosition) {
34955	      scrollerBounds = _getBounds(markerScroller);
34956	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
34957	    }
34958	  }
34959
34960	  if (containerAnimation && element) {
34961	    p1 = _getBounds(element);
34962	    containerAnimation.seek(scrollerMax);
34963	    p2 = _getBounds(element);
34964	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
34965	    value = value / containerAnimation._caScrollDist * scrollerMax;
34966	  }
34967
34968	  containerAnimation && containerAnimation.seek(time);
34969	  return containerAnimation ? value : Math.round(value);
34970	},
34971	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
34972	    _reparent = function _reparent(element, parent, top, left) {
34973	  if (element.parentNode !== parent) {
34974	    var style = element.style,
34975	        p,
34976	        cs;
34977
34978	    if (parent === _body) {
34979	      element._stOrig = style.cssText;
34980	      cs = _getComputedStyle(element);
34981
34982	      for (p in cs) {
34983	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
34984	          style[p] = cs[p];
34985	        }
34986	      }
34987
34988	      style.top = top;
34989	      style.left = left;
34990	    } else {
34991	      style.cssText = element._stOrig;
34992	    }
34993
34994	    gsap.core.getCache(element).uncache = 1;
34995	    parent.appendChild(element);
34996	  }
34997	},
34998	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
34999	  var getScroll = _getScrollFunc(scroller, direction),
35000	      prop = "_scroll" + direction.p2,
35001	      lastScroll1,
35002	      lastScroll2,
35003	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
35004	    var tween = getTween.tween,
35005	        onComplete = vars.onComplete,
35006	        modifiers = {};
35007	    tween && tween.kill();
35008	    lastScroll1 = Math.round(initialValue);
35009	    vars[prop] = scrollTo;
35010	    vars.modifiers = modifiers;
35011
35012	    modifiers[prop] = function (value) {
35013	      value = _round(getScroll());
35014
35015	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
35016	        tween.kill();
35017	        getTween.tween = 0;
35018	      } else {
35019	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
35020	      }
35021
35022	      lastScroll2 = lastScroll1;
35023	      return lastScroll1 = _round(value);
35024	    };
35025
35026	    vars.onComplete = function () {
35027	      getTween.tween = 0;
35028	      onComplete && onComplete.call(tween);
35029	    };
35030
35031	    tween = getTween.tween = gsap.to(scroller, vars);
35032	    return tween;
35033	  };
35034
35035	  scroller[prop] = getScroll;
35036	  scroller.addEventListener("wheel", function () {
35037	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
35038	  }, {
35039	    passive: true
35040	  });
35041	  return getTween;
35042	};
35043
35044	_horizontal.op = _vertical;
35045	var ScrollTrigger = function () {
35046	  function ScrollTrigger(vars, animation) {
35047	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
35048	    this.init(vars, animation);
35049	  }
35050
35051	  var _proto = ScrollTrigger.prototype;
35052
35053	  _proto.init = function init(vars, animation) {
35054	    this.progress = this.start = 0;
35055	    this.vars && this.kill(1);
35056
35057	    if (!_enabled) {
35058	      this.update = this.refresh = this.kill = _passThrough;
35059	      return;
35060	    }
35061
35062	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
35063	      trigger: vars
35064	    } : vars, _defaults);
35065
35066	    var _vars = vars,
35067	        onUpdate = _vars.onUpdate,
35068	        toggleClass = _vars.toggleClass,
35069	        id = _vars.id,
35070	        onToggle = _vars.onToggle,
35071	        onRefresh = _vars.onRefresh,
35072	        scrub = _vars.scrub,
35073	        trigger = _vars.trigger,
35074	        pin = _vars.pin,
35075	        pinSpacing = _vars.pinSpacing,
35076	        invalidateOnRefresh = _vars.invalidateOnRefresh,
35077	        anticipatePin = _vars.anticipatePin,
35078	        onScrubComplete = _vars.onScrubComplete,
35079	        onSnapComplete = _vars.onSnapComplete,
35080	        once = _vars.once,
35081	        snap = _vars.snap,
35082	        pinReparent = _vars.pinReparent,
35083	        pinSpacer = _vars.pinSpacer,
35084	        containerAnimation = _vars.containerAnimation,
35085	        fastScrollEnd = _vars.fastScrollEnd,
35086	        preventOverlaps = _vars.preventOverlaps,
35087	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
35088	        isToggle = !scrub && scrub !== 0,
35089	        scroller = _getTarget(vars.scroller || _win),
35090	        scrollerCache = gsap.core.getCache(scroller),
35091	        isViewport = _isViewport(scroller),
35092	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
35093	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
35094	        toggleActions = isToggle && vars.toggleActions.split(" "),
35095	        markers = "markers" in vars ? vars.markers : _defaults.markers,
35096	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
35097	        self = this,
35098	        onRefreshInit = vars.onRefreshInit && function () {
35099	      return vars.onRefreshInit(self);
35100	    },
35101	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
35102	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
35103	        lastSnap = 0,
35104	        scrollFunc = _getScrollFunc(scroller, direction),
35105	        tweenTo,
35106	        pinCache,
35107	        snapFunc,
35108	        scroll1,
35109	        scroll2,
35110	        start,
35111	        end,
35112	        markerStart,
35113	        markerEnd,
35114	        markerStartTrigger,
35115	        markerEndTrigger,
35116	        markerVars,
35117	        change,
35118	        pinOriginalState,
35119	        pinActiveState,
35120	        pinState,
35121	        spacer,
35122	        offset,
35123	        pinGetter,
35124	        pinSetter,
35125	        pinStart,
35126	        pinChange,
35127	        spacingStart,
35128	        spacerState,
35129	        markerStartSetter,
35130	        markerEndSetter,
35131	        cs,
35132	        snap1,
35133	        snap2,
35134	        scrubTween,
35135	        scrubSmooth,
35136	        snapDurClamp,
35137	        snapDelayedCall,
35138	        prevProgress,
35139	        prevScroll,
35140	        prevAnimProgress,
35141	        caMarkerSetter;
35142
35143	    self.media = _creatingMedia;
35144	    anticipatePin *= 45;
35145	    self.scroller = scroller;
35146	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
35147	    scroll1 = scrollFunc();
35148	    self.vars = vars;
35149	    animation = animation || vars.animation;
35150	    "refreshPriority" in vars && (_sort = 1);
35151	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
35152	      top: _getTweenCreator(scroller, _vertical),
35153	      left: _getTweenCreator(scroller, _horizontal)
35154	    };
35155	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
35156
35157	    if (animation) {
35158	      animation.vars.lazy = false;
35159	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
35160	      self.animation = animation.pause();
35161	      animation.scrollTrigger = self;
35162	      scrubSmooth = _isNumber(scrub) && scrub;
35163	      scrubSmooth && (scrubTween = gsap.to(animation, {
35164	        ease: "power3",
35165	        duration: scrubSmooth,
35166	        onComplete: function onComplete() {
35167	          return onScrubComplete && onScrubComplete(self);
35168	        }
35169	      }));
35170	      snap1 = 0;
35171	      id || (id = animation.vars.id);
35172	    }
35173
35174	    _triggers.push(self);
35175
35176	    if (snap) {
35177	      if (!_isObject(snap) || snap.push) {
35178	        snap = {
35179	          snapTo: snap
35180	        };
35181	      }
35182
35183	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
35184	        scrollBehavior: "auto"
35185	      });
35186	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
35187	        return _snapDirectional(snap.snapTo)(value, st.direction);
35188	      } : gsap.utils.snap(snap.snapTo);
35189	      snapDurClamp = snap.duration || {
35190	        min: 0.1,
35191	        max: 2
35192	      };
35193	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
35194	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
35195	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
35196	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
35197	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
35198	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
35199	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
35200	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
35201	              scroll = scrollFunc(),
35202	              endScroll = Math.round(start + endValue * change),
35203	              _snap = snap,
35204	              onStart = _snap.onStart,
35205	              _onInterrupt = _snap.onInterrupt,
35206	              _onComplete = _snap.onComplete,
35207	              tween = tweenTo.tween;
35208
35209	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
35210	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
35211	              return;
35212	            }
35213
35214	            if (snap.inertia === false) {
35215	              change1 = endValue - self.progress;
35216	            }
35217
35218	            tweenTo(endScroll, {
35219	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
35220	              ease: snap.ease || "power3",
35221	              data: _abs(endScroll - scroll),
35222	              onInterrupt: function onInterrupt() {
35223	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
35224	              },
35225	              onComplete: function onComplete() {
35226	                lastSnap = scrollFunc();
35227	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
35228	                onSnapComplete && onSnapComplete(self);
35229	                _onComplete && _onComplete(self);
35230	              }
35231	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
35232	            onStart && onStart(self, tweenTo.tween);
35233	          }
35234	        } else if (self.isActive) {
35235	          snapDelayedCall.restart(true);
35236	        }
35237	      }).pause();
35238	    }
35239
35240	    id && (_ids[id] = self);
35241	    trigger = self.trigger = _getTarget(trigger || pin);
35242	    pin = pin === true ? trigger : _getTarget(pin);
35243	    _isString(toggleClass) && (toggleClass = {
35244	      targets: trigger,
35245	      className: toggleClass
35246	    });
35247
35248	    if (pin) {
35249	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
35250	      self.pin = pin;
35251	      vars.force3D !== false && gsap.set(pin, {
35252	        force3D: true
35253	      });
35254	      pinCache = gsap.core.getCache(pin);
35255
35256	      if (!pinCache.spacer) {
35257	        if (pinSpacer) {
35258	          pinSpacer = _getTarget(pinSpacer);
35259	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
35260	          pinCache.spacerIsNative = !!pinSpacer;
35261	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
35262	        }
35263
35264	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
35265	        spacer.classList.add("pin-spacer");
35266	        id && spacer.classList.add("pin-spacer-" + id);
35267	        pinCache.pinState = pinOriginalState = _getState(pin);
35268	      } else {
35269	        pinOriginalState = pinCache.pinState;
35270	      }
35271
35272	      self.spacer = spacer = pinCache.spacer;
35273	      cs = _getComputedStyle(pin);
35274	      spacingStart = cs[pinSpacing + direction.os2];
35275	      pinGetter = gsap.getProperty(pin);
35276	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
35277
35278	      _swapPinIn(pin, spacer, cs);
35279
35280	      pinState = _getState(pin);
35281	    }
35282
35283	    if (markers) {
35284	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
35285	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
35286	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
35287	      offset = markerStartTrigger["offset" + direction.op.d2];
35288	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35289	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35290	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
35291
35292	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
35293	        _makePositionable(isViewport ? _body : scroller);
35294
35295	        gsap.set([markerStartTrigger, markerEndTrigger], {
35296	          force3D: true
35297	        });
35298	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
35299	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
35300	      }
35301	    }
35302
35303	    if (containerAnimation) {
35304	      var oldOnUpdate = containerAnimation.vars.onUpdate,
35305	          oldParams = containerAnimation.vars.onUpdateParams;
35306	      containerAnimation.eventCallback("onUpdate", function () {
35307	        self.update(0, 0, 1);
35308	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
35309	      });
35310	    }
35311
35312	    self.previous = function () {
35313	      return _triggers[_triggers.indexOf(self) - 1];
35314	    };
35315
35316	    self.next = function () {
35317	      return _triggers[_triggers.indexOf(self) + 1];
35318	    };
35319
35320	    self.revert = function (revert) {
35321	      var r = revert !== false || !self.enabled,
35322	          prevRefreshing = _refreshing;
35323
35324	      if (r !== self.isReverted) {
35325	        if (r) {
35326	          self.scroll.rec || (self.scroll.rec = scrollFunc());
35327	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
35328	          prevProgress = self.progress;
35329	          prevAnimProgress = animation && animation.progress();
35330	        }
35331
35332	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35333	          return m.style.display = r ? "none" : "block";
35334	        });
35335	        r && (_refreshing = 1);
35336	        self.update(r);
35337	        _refreshing = prevRefreshing;
35338	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
35339	        self.isReverted = r;
35340	      }
35341	    };
35342
35343	    self.refresh = function (soft, force) {
35344	      if ((_refreshing || !self.enabled) && !force) {
35345	        return;
35346	      }
35347
35348	      if (pin && soft && _lastScrollTime) {
35349	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
35350
35351	        return;
35352	      }
35353
35354	      _refreshing = 1;
35355	      scrubTween && scrubTween.pause();
35356	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
35357	      self.isReverted || self.revert();
35358
35359	      var size = getScrollerSize(),
35360	          scrollerBounds = getScrollerOffsets(),
35361	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
35362	          offset = 0,
35363	          otherPinOffset = 0,
35364	          parsedEnd = vars.end,
35365	          parsedEndTrigger = vars.endTrigger || trigger,
35366	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
35367	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
35368	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
35369	          i = triggerIndex,
35370	          cs,
35371	          bounds,
35372	          scroll,
35373	          isVertical,
35374	          override,
35375	          curTrigger,
35376	          curPin,
35377	          oppositeScroll,
35378	          initted,
35379	          revertedPins;
35380
35381	      while (i--) {
35382	        curTrigger = _triggers[i];
35383	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
35384	        curPin = curTrigger.pin;
35385
35386	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
35387	          revertedPins || (revertedPins = []);
35388	          revertedPins.unshift(curTrigger);
35389	          curTrigger.revert();
35390	        }
35391	      }
35392
35393	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
35394	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
35395	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
35396
35397	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
35398	        if (~parsedEnd.indexOf(" ")) {
35399	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
35400	        } else {
35401	          offset = _offsetToPx(parsedEnd.substr(2), size);
35402	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
35403	          parsedEndTrigger = trigger;
35404	        }
35405	      }
35406
35407	      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;
35408	      change = end - start || (start -= 0.01) && 0.001;
35409	      offset = 0;
35410	      i = triggerIndex;
35411
35412	      while (i--) {
35413	        curTrigger = _triggers[i];
35414	        curPin = curTrigger.pin;
35415
35416	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
35417	          cs = curTrigger.end - curTrigger.start;
35418	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
35419	          curPin === pin && (otherPinOffset += cs);
35420	        }
35421	      }
35422
35423	      start += offset;
35424	      end += offset;
35425	      self._pinPush = otherPinOffset;
35426
35427	      if (markerStart && offset) {
35428	        cs = {};
35429	        cs[direction.a] = "+=" + offset;
35430	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
35431	        gsap.set([markerStart, markerEnd], cs);
35432	      }
35433
35434	      if (pin) {
35435	        cs = _getComputedStyle(pin);
35436	        isVertical = direction === _vertical;
35437	        scroll = scrollFunc();
35438	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
35439	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
35440
35441	        _swapPinIn(pin, spacer, cs);
35442
35443	        pinState = _getState(pin);
35444	        bounds = _getBounds(pin, true);
35445	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
35446
35447	        if (pinSpacing) {
35448	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
35449	          spacerState.t = spacer;
35450	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
35451	          i && spacerState.push(direction.d, i + _px);
35452
35453	          _setState(spacerState);
35454
35455	          useFixedPosition && scrollFunc(prevScroll);
35456	        }
35457
35458	        if (useFixedPosition) {
35459	          override = {
35460	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
35461	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
35462	            boxSizing: "border-box",
35463	            position: "fixed"
35464	          };
35465	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
35466	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
35467	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
35468	          override[_padding] = cs[_padding];
35469	          override[_padding + _Top] = cs[_padding + _Top];
35470	          override[_padding + _Right] = cs[_padding + _Right];
35471	          override[_padding + _Bottom] = cs[_padding + _Bottom];
35472	          override[_padding + _Left] = cs[_padding + _Left];
35473	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
35474	        }
35475
35476	        if (animation) {
35477	          initted = animation._initted;
35478
35479	          _suppressOverwrites(1);
35480
35481	          animation.render(animation.duration(), true, true);
35482	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
35483	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
35484	          animation.render(0, true, true);
35485	          initted || animation.invalidate();
35486
35487	          _suppressOverwrites(0);
35488	        } else {
35489	          pinChange = change;
35490	        }
35491	      } else if (trigger && scrollFunc() && !containerAnimation) {
35492	        bounds = trigger.parentNode;
35493
35494	        while (bounds && bounds !== _body) {
35495	          if (bounds._pinOffset) {
35496	            start -= bounds._pinOffset;
35497	            end -= bounds._pinOffset;
35498	          }
35499
35500	          bounds = bounds.parentNode;
35501	        }
35502	      }
35503
35504	      revertedPins && revertedPins.forEach(function (t) {
35505	        return t.revert(false);
35506	      });
35507	      self.start = start;
35508	      self.end = end;
35509	      scroll1 = scroll2 = scrollFunc();
35510
35511	      if (!containerAnimation) {
35512	        scroll1 < prevScroll && scrollFunc(prevScroll);
35513	        self.scroll.rec = 0;
35514	      }
35515
35516	      self.revert(false);
35517	      _refreshing = 0;
35518	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
35519
35520	      if (prevProgress !== self.progress) {
35521	        animation && !isToggle && animation.totalProgress(prevProgress, true);
35522	        self.progress = prevProgress;
35523	        self.update(0, 0, 1);
35524	      }
35525
35526	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
35527	      onRefresh && onRefresh(self);
35528	    };
35529
35530	    self.getVelocity = function () {
35531	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
35532	    };
35533
35534	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 35535-35773
35535	      _endAnimation(self.callbackAnimation);
35536
35537	      if (animation) {
35538	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
35539	      }
35540	    };
35541
35542	    self.getTrailing = function (name) {
35543	      var i = _triggers.indexOf(self),
35544	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
35545
35546	      return _isString(name) ? a.filter(function (t) {
35547	        return t.vars.preventOverlaps === name;
35548	      }) : a;
35549	    };
35550
35551	    self.update = function (reset, recordVelocity, forceFake) {
35552	      if (containerAnimation && !forceFake && !reset) {
35553	        return;
35554	      }
35555
35556	      var scroll = self.scroll(),
35557	          p = reset ? 0 : (scroll - start) / change,
35558	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
35559	          prevProgress = self.progress,
35560	          isActive,
35561	          wasActive,
35562	          toggleState,
35563	          action,
35564	          stateChanged,
35565	          toggled,
35566	          isAtMax,
35567	          isTakingAction;
35568
35569	      if (recordVelocity) {
35570	        scroll2 = scroll1;
35571	        scroll1 = containerAnimation ? scrollFunc() : scroll;
35572
35573	        if (snap) {
35574	          snap2 = snap1;
35575	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
35576	        }
35577	      }
35578
35579	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
35580
35581	      if (clipped !== prevProgress && self.enabled) {
35582	        isActive = self.isActive = !!clipped && clipped < 1;
35583	        wasActive = !!prevProgress && prevProgress < 1;
35584	        toggled = isActive !== wasActive;
35585	        stateChanged = toggled || !!clipped !== !!prevProgress;
35586	        self.direction = clipped > prevProgress ? 1 : -1;
35587	        self.progress = clipped;
35588
35589	        if (stateChanged && !_refreshing) {
35590	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
35591
35592	          if (isToggle) {
35593	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
35594	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
35595	          }
35596	        }
35597
35598	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
35599	          return t.endAnimation();
35600	        }));
35601
35602	        if (!isToggle) {
35603	          if (scrubTween && !_refreshing && !_startup) {
35604	            scrubTween.vars.totalProgress = clipped;
35605	            scrubTween.invalidate().restart();
35606	          } else if (animation) {
35607	            animation.totalProgress(clipped, !!_refreshing);
35608	          }
35609	        }
35610
35611	        if (pin) {
35612	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
35613
35614	          if (!useFixedPosition) {
35615	            pinSetter(pinStart + pinChange * clipped);
35616	          } else if (stateChanged) {
35617	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
35618
35619	            if (pinReparent) {
35620	              if (!reset && (isActive || isAtMax)) {
35621	                var bounds = _getBounds(pin, true),
35622	                    _offset = scroll - start;
35623
35624	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
35625	              } else {
35626	                _reparent(pin, spacer);
35627	              }
35628	            }
35629
35630	            _setState(isActive || isAtMax ? pinActiveState : pinState);
35631
35632	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
35633	          }
35634	        }
35635
35636	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
35637	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
35638	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
35639	        });
35640	        onUpdate && !isToggle && !reset && onUpdate(self);
35641
35642	        if (stateChanged && !_refreshing) {
35643	          if (isToggle) {
35644	            if (isTakingAction) {
35645	              if (action === "complete") {
35646	                animation.pause().totalProgress(1);
35647	              } else if (action === "reset") {
35648	                animation.restart(true).pause();
35649	              } else if (action === "restart") {
35650	                animation.restart(true);
35651	              } else {
35652	                animation[action]();
35653	              }
35654	            }
35655
35656	            onUpdate && onUpdate(self);
35657	          }
35658
35659	          if (toggled || !_limitCallbacks) {
35660	            onToggle && toggled && _callback(self, onToggle);
35661	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35662	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
35663
35664	            if (!toggled) {
35665	              toggleState = clipped === 1 ? 1 : 3;
35666	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35667	            }
35668	          }
35669
35670	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
35671	            _endAnimation(self.callbackAnimation);
35672
35673	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
35674	          }
35675	        } else if (isToggle && onUpdate && !_refreshing) {
35676	          onUpdate(self);
35677	        }
35678	      }
35679
35680	      if (markerEndSetter) {
35681	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
35682	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
35683	        markerEndSetter(n);
35684	      }
35685
35686	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
35687	    };
35688
35689	    self.enable = function (reset, refresh) {
35690	      if (!self.enabled) {
35691	        self.enabled = true;
35692
35693	        _addListener(scroller, "resize", _onResize);
35694
35695	        _addListener(scroller, "scroll", _onScroll);
35696
35697	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
35698
35699	        if (reset !== false) {
35700	          self.progress = prevProgress = 0;
35701	          scroll1 = scroll2 = lastSnap = scrollFunc();
35702	        }
35703
35704	        refresh !== false && self.refresh();
35705	      }
35706	    };
35707
35708	    self.getTween = function (snap) {
35709	      return snap && tweenTo ? tweenTo.tween : scrubTween;
35710	    };
35711
35712	    self.disable = function (reset, allowAnimation) {
35713	      if (self.enabled) {
35714	        reset !== false && self.revert();
35715	        self.enabled = self.isActive = false;
35716	        allowAnimation || scrubTween && scrubTween.pause();
35717	        prevScroll = 0;
35718	        pinCache && (pinCache.uncache = 1);
35719	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
35720
35721	        if (snapDelayedCall) {
35722	          snapDelayedCall.pause();
35723	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
35724	        }
35725
35726	        if (!isViewport) {
35727	          var i = _triggers.length;
35728
35729	          while (i--) {
35730	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
35731	              return;
35732	            }
35733	          }
35734
35735	          _removeListener(scroller, "resize", _onResize);
35736
35737	          _removeListener(scroller, "scroll", _onScroll);
35738	        }
35739	      }
35740	    };
35741
35742	    self.kill = function (revert, allowAnimation) {
35743	      self.disable(revert, allowAnimation);
35744	      scrubTween && scrubTween.kill();
35745	      id && delete _ids[id];
35746
35747	      var i = _triggers.indexOf(self);
35748
35749	      _triggers.splice(i, 1);
35750
35751	      i === _i && _direction > 0 && _i--;
35752	      i = 0;
35753
35754	      _triggers.forEach(function (t) {
35755	        return t.scroller === self.scroller && (i = 1);
35756	      });
35757
35758	      i || (self.scroll.rec = 0);
35759
35760	      if (animation) {
35761	        animation.scrollTrigger = null;
35762	        revert && animation.render(-1);
35763	        allowAnimation || animation.kill();
35764	      }
35765
35766	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35767	        return m.parentNode && m.parentNode.removeChild(m);
35768	      });
35769
35770	      if (pin) {
35771	        pinCache && (pinCache.uncache = 1);
35772	        i = 0;
35773
35774	        _triggers.forEach(function (t) {
35775	          return t.pin === pin && i++;
35776	        });
35777
35778	        i || (pinCache.spacer = 0);
35779	      }
35780	    };
35781
35782	    self.enable(false, false);
35783	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35784	      return start || end || self.refresh();
35785	    }) && (change = 0.01) && (start = end = 0);
35786	  };
35787
35788	  ScrollTrigger.register = function register(core) {
35789	    if (!_coreInitted) {
35790	      gsap = core || _getGSAP();
35791
35792	      if (_windowExists() && window.document) {
35793	        _win = window;
35794	        _doc = document;
35795	        _docEl = _doc.documentElement;
35796	        _body = _doc.body;
35797	      }
35798
35799	      if (gsap) {
35800	        _toArray = gsap.utils.toArray;
35801	        _clamp = gsap.utils.clamp;
35802	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35803	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35804
35805	        if (_body) {
35806	          _raf = _win.requestAnimationFrame || function (f) {
35807	            return setTimeout(f, 16);
35808	          };
35809
35810	          _addListener(_win, "wheel", _onScroll);
35811
35812	          _root = [_win, _doc, _docEl, _body];
35813
35814	          _addListener(_doc, "scroll", _onScroll);
35815
35816	          var bodyStyle = _body.style,
35817	              border = bodyStyle.borderTopStyle,
35818	              bounds;
35819	          bodyStyle.borderTopStyle = "solid";
35820	          bounds = _getBounds(_body);
35821	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35822	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35823	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35824	          _syncInterval = setInterval(_sync, 200);
35825	          gsap.delayedCall(0.5, function () {
35826	            return _startup = 0;
35827	          });
35828
35829	          _addListener(_doc, "touchcancel", _passThrough);
35830
35831	          _addListener(_body, "touchstart", _passThrough);
35832
35833	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35834	            return _pointerIsDown = 1;
35835	          });
35836
35837	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35838	            return _pointerIsDown = 0;
35839	          });
35840
35841	          _transformProp = gsap.utils.checkPrefix("transform");
35842
35843	          _stateProps.push(_transformProp);
35844
35845	          _coreInitted = _getTime();
35846	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35847	          _autoRefresh = [_doc, "visibilitychange", function () {
35848	            var w = _win.innerWidth,
35849	                h = _win.innerHeight;
35850
35851	            if (_doc.hidden) {
35852	              _prevWidth = w;
35853	              _prevHeight = h;
35854	            } else if (_prevWidth !== w || _prevHeight !== h) {
35855	              _onResize();
35856	            }
35857	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35858	            return _lastScrollTime || _refreshAll();
35859	          }, _win, "resize", _onResize];
35860
35861	          _iterateAutoRefresh(_addListener);
35862	        }
35863	      }
35864	    }
35865
35866	    return _coreInitted;
35867	  };
35868
35869	  ScrollTrigger.defaults = function defaults(config) {
35870	    for (var p in config) {
35871	      _defaults[p] = config[p];
35872	    }
35873	  };
35874
35875	  ScrollTrigger.kill = function kill() {
35876	    _enabled = 0;
35877
35878	    _triggers.slice(0).forEach(function (trigger) {
35879	      return trigger.kill(1);
35880	    });
35881	  };
35882
35883	  ScrollTrigger.config = function config(vars) {
35884	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35885	    var ms = vars.syncInterval;
35886	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35887
35888	    if ("autoRefreshEvents" in vars) {
35889	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35890	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35891	    }
35892	  };
35893
35894	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35895	    var t = _getTarget(target),
35896	        i = _scrollers.indexOf(t),
35897	        isViewport = _isViewport(t);
35898
35899	    if (~i) {
35900	      _scrollers.splice(i, isViewport ? 6 : 2);
35901	    }
35902
35903	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35904	  };
35905
35906	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35907	    var mq, p, i, func, result;
35908
35909	    for (p in vars) {
35910	      i = _media.indexOf(p);
35911	      func = vars[p];
35912	      _creatingMedia = p;
35913
35914	      if (p === "all") {
35915	        func();
35916	      } else {
35917	        mq = _win.matchMedia(p);
35918
35919	        if (mq) {
35920	          mq.matches && (result = func());
35921
35922	          if (~i) {
35923	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35924	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35925	          } else {
35926	            i = _media.length;
35927
35928	            _media.push(p, func, result);
35929
35930	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35931	          }
35932
35933	          _media[i + 3] = mq.matches;
35934	        }
35935	      }
35936
35937	      _creatingMedia = 0;
35938	    }
35939
35940	    return _media;
35941	  };
35942
35943	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
35944	    query || (_media.length = 0);
35945	    query = _media.indexOf(query);
35946	    query >= 0 && _media.splice(query, 4);
35947	  };
35948
35949	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
35950	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
35951	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
35952	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
35953	  };
35954
35955	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
35956	    _isString(element) && (element = _getTarget(element));
35957	    var bounds = element.getBoundingClientRect(),
35958	        size = bounds[horizontal ? _width : _height],
35959	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
35960	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
35961	  };
35962
35963	  return ScrollTrigger;
35964	}();
35965	ScrollTrigger.version = "3.8.0";
35966
35967	ScrollTrigger.saveStyles = function (targets) {
35968	  return targets ? _toArray(targets).forEach(function (target) {
35969	    if (target && target.style) {
35970	      var i = _savedStyles.indexOf(target);
35971
35972	      i >= 0 && _savedStyles.splice(i, 5);
35973
35974	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
35975	    }
35976	  }) : _savedStyles;
35977	};
35978
35979	ScrollTrigger.revert = function (soft, media) {
35980	  return _revertAll(!soft, media);
35981	};
35982
35983	ScrollTrigger.create = function (vars, animation) {
35984	  return new ScrollTrigger(vars, animation);
35985	};
35986
35987	ScrollTrigger.refresh = function (safe) {
35988	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
35989	};
35990
35991	ScrollTrigger.update = _updateAll;
35992	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
35993
35994	ScrollTrigger.maxScroll = function (element, horizontal) {
35995	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
35996	};
35997
35998	ScrollTrigger.getScrollFunc = function (element, horizontal) {
35999	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
36000	};
36001
36002	ScrollTrigger.getById = function (id) {
36003	  return _ids[id];
36004	};
36005
36006	ScrollTrigger.getAll = function () {
36007	  return _triggers.slice(0);
36008	};
36009
36010	ScrollTrigger.isScrolling = function () {
36011	  return !!_lastScrollTime;
36012	};
36013
36014	ScrollTrigger.snapDirectional = _snapDirectional;
36015
36016	ScrollTrigger.addEventListener = function (type, callback) {
36017	  var a = _listeners[type] || (_listeners[type] = []);
36018	  ~a.indexOf(callback) || a.push(callback);
36019	};
36020
36021	ScrollTrigger.removeEventListener = function (type, callback) {
36022	  var a = _listeners[type],
36023	      i = a && a.indexOf(callback);
36024	  i >= 0 && a.splice(i, 1);
36025	};
36026
36027	ScrollTrigger.batch = function (targets, vars) {
36028	  var result = [],
36029	      varsCopy = {},
36030	      interval = vars.interval || 0.016,
36031	      batchMax = vars.batchMax || 1e9,
36032	      proxyCallback = function proxyCallback(type, callback) {
36033	    var elements = [],
36034	        triggers = [],
36035	        delay = gsap.delayedCall(interval, function () {
36036	      callback(elements, triggers);
36037	      elements = [];
36038	      triggers = [];
36039	    }).pause();
36040	    return function (self) {
36041	      elements.length || delay.restart(true);
36042	      elements.push(self.trigger);
36043	      triggers.push(self);
36044	      batchMax <= elements.length && delay.progress(1);
36045	    };
36046	  },
36047	      p;
36048
36049	  for (p in vars) {
36050	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
36051	  }
36052
36053	  if (_isFunction(batchMax)) {
36054	    batchMax = batchMax();
36055
36056	    _addListener(ScrollTrigger, "refresh", function () {
36057	      return batchMax = vars.batchMax();
36058	    });
36059	  }
36060
36061	  _toArray(targets).forEach(function (target) {
36062	    var config = {};
36063
36064	    for (p in varsCopy) {
36065	      config[p] = varsCopy[p];
36066	    }
36067
36068	    config.trigger = target;
36069	    result.push(ScrollTrigger.create(config));
36070	  });
36071
36072	  return result;
36073	};
36074
36075	ScrollTrigger.sort = function (func) {
36076	  return _triggers.sort(func || function (a, b) {
36077	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
36078	  });
36079	};
36080
36081	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
36082
36083	exports.ScrollTrigger = ScrollTrigger;
36084	exports.default = ScrollTrigger;
36085
36086	Object.defineProperty(exports, '__esModule', { value: true });
36087
36088})));
36089
36090/* ========================================================================
36091 * Bootstrap: collapse.js v3.1.1
36092 * http://getbootstrap.com/javascript/#collapse
36093 * ========================================================================
36094 * Copyright 2011-2014 Twitter, Inc.
36095 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36096 * ======================================================================== */
36097
36098
36099+function ($) {
36100	'use strict';
36101
36102	// COLLAPSE PUBLIC CLASS DEFINITION
36103	// ================================
36104
36105	var Collapse = function (element, options) {
36106		this.$element      = $(element)
36107		this.options       = $.extend({}, Collapse.DEFAULTS, options)
36108		this.transitioning = null
36109
36110		if (this.options.parent) this.$parent = $(this.options.parent)
36111		if (this.options.toggle) this.toggle()
36112	}
36113
36114	Collapse.DEFAULTS = {
36115		toggle: true
36116	}
36117
36118	Collapse.prototype.dimension = function () {
36119		var hasWidth = this.$element.hasClass('width')
36120		return hasWidth ? 'width' : 'height'
36121	}
36122
36123	Collapse.prototype.show = function () {
36124		if (this.transitioning || this.$element.hasClass('in')) return
36125
36126		var startEvent = $.Event('show.bs.collapse')
36127		this.$element.trigger(startEvent)
36128		if (startEvent.isDefaultPrevented()) return
36129
36130		var actives = this.$parent && this.$parent.find('> .panel > .in')
36131
36132		if (actives && actives.length) {
36133			var hasData = actives.data('bs.collapse')
36134			if (hasData && hasData.transitioning) return
36135			//START UNCODE EDIT
36136			var parentNoToggle = this.$parent.data('no-toggle')
36137			if (!parentNoToggle) {
36138				actives.collapse('hide')
36139			}
36140			//END UNCODE EDIT
36141			hasData || actives.data('bs.collapse', null)
36142		}
36143
36144		var dimension = this.dimension()
36145
36146		this.$element
36147			.removeClass('collapse')
36148			.addClass('collapsing')[dimension](0)
36149
36150		this.transitioning = 1
36151
36152		var complete = function (e) {
36153			if (e && e.target != this.$element[0]) return
36154			this.$element
36155				.removeClass('collapsing')
36156				.addClass('collapse in')[dimension]('auto')
36157			this.transitioning = 0
36158			this.$element.trigger('shown.bs.collapse')
36159		}
36160
36161		if (!$.support.transition) return complete.call(this)
36162
36163		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
36164
36165		this.$element
36166			.one($.support.transition.end, $.proxy(complete, this))
36167			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
36168	}
36169
36170	Collapse.prototype.hide = function () {
36171		if (this.transitioning || !this.$element.hasClass('in')) return
36172
36173		var startEvent = $.Event('hide.bs.collapse')
36174		this.$element.trigger(startEvent)
36175		if (startEvent.isDefaultPrevented()) return
36176
36177		var dimension = this.dimension()
36178
36179		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
36180
36181		this.$element
36182			.addClass('collapsing')
36183			.removeClass('collapse')
36184			.removeClass('in')
36185
36186		this.transitioning = 1
36187
36188		var complete = function (e) {
36189			if (e && e.target != this.$element[0]) return
36190			this.transitioning = 0
36191			this.$element
36192				.trigger('hidden.bs.collapse')
36193				.removeClass('collapsing')
36194				.addClass('collapse')
36195		}
36196
36197		if (!$.support.transition) return complete.call(this)
36198
36199		this.$element
36200			[dimension](0)
36201			.one($.support.transition.end, $.proxy(complete, this))
36202			.emulateTransitionEnd(350)
36203	}
36204
36205	Collapse.prototype.toggle = function () {
36206		this[this.$element.hasClass('in') ? 'hide' : 'show']()
36207	}
36208
36209
36210	// COLLAPSE PLUGIN DEFINITION
36211	// ==========================
36212
36213	var old = $.fn.collapse
36214
36215	$.fn.collapse = function (option) {
36216		return this.each(function () {
36217			var $this   = $(this)
36218			var data    = $this.data('bs.collapse')
36219			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
36220
36221			if (!data && options.toggle && option == 'show') option = !option
36222			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
36223			if (typeof option == 'string') data[option]()
36224		})
36225	}
36226
36227	$.fn.collapse.Constructor = Collapse
36228
36229
36230	// COLLAPSE NO CONFLICT
36231	// ====================
36232
36233	$.fn.collapse.noConflict = function () {
36234		$.fn.collapse = old
36235		return this
36236	}
36237
36238
36239	// COLLAPSE DATA-API
36240	// =================
36241
36242	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
36243		var $this   = $(this), href
36244		var target  = $this.attr('data-target')
36245				|| e.preventDefault()
36246				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
36247		//Edited by Uncode to replace ID in panel [START]
36248		var _target = href.replace(/^#/, "");
36249		if ( $('[data-id="' + _target + '"]').length ) {
36250			var $target = $('[data-id="' + _target + '"]')
36251		} else {
36252			var $target = $(target)
36253		}
36254		//Edited by Uncode to replace ID in panel [END]
36255		var data    = $target.data('bs.collapse')
36256		var option  = data ? 'toggle' : $this.data()
36257		var parent  = $this.attr('data-parent')
36258		var $parent = parent && $(parent)
36259
36260		if (!data || !data.transitioning) {
36261			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
36262			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
36263		}
36264
36265		$target.collapse(option)
36266	})
36267
36268}(jQuery);
36269
36270/* ========================================================================
36271 * Bootstrap: tab.js v3.1.1
36272 * http://getbootstrap.com/javascript/#tabs
36273 * ========================================================================
36274 * Copyright 2011-2014 Twitter, Inc.
36275 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36276 * ======================================================================== */
36277
36278
36279+function ($) {
36280  'use strict';
36281
36282  // TAB CLASS DEFINITION
36283  // ====================
36284
36285  var Tab = function (element) {
36286    this.element = $(element)
36287  }
36288
36289  Tab.prototype.show = function () {
36290    var $this    = this.element
36291    var $ul      = $this.closest('ul:not(.dropdown-menu)')
36292    var selector = $this.data('target')
36293
36294    if (!selector) {
36295      selector = $this.attr('href')
36296      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
36297    }
36298
36299    if ($this.parent('li').hasClass('active')) return
36300
36301    var previous = $ul.find('.active:last a')[0]
36302    var e        = $.Event('show.bs.tab', {
36303      relatedTarget: previous
36304    })
36305
36306    $this.trigger(e)
36307
36308    if (e.isDefaultPrevented()) return
36309
36310    //Edited by Uncode to replace ID in panel [START]
36311    var _target = selector.replace(/^#/, "");
36312    if ( $('[data-id="' + _target + '"]').length )
36313      var $target = $('[data-id="' + _target + '"]')
36314    else
36315      var $target = $(selector)
36316    //Edited by Uncode to replace ID in panel [END]
36317
36318    this.activate($this.parent('li'), $ul)
36319    this.activate($target, $target.parent(), function () {
36320      $this.trigger({
36321        type: 'shown.bs.tab',
36322        relatedTarget: previous
36323      })
36324    })
36325  }
36326
36327  Tab.prototype.activate = function (element, container, callback) {
36328    var $active    = container.find('> .active').add(container.find('> .active > .active'))
36329    var transition = callback
36330      && $.support.transition
36331      && $active.hasClass('fade')
36332
36333    function next() {
36334      $active
36335        .removeClass('active')
36336        .find('> .dropdown-menu > .active')
36337        .removeClass('active')
36338
36339      $active
36340        .find('.tab-excerpt').slideUp();
36341
36342      element.addClass('active')
36343      $('.tab-excerpt', element).slideDown();
36344
36345      //if (transition) {
36346        element[0].offsetWidth // reflow for transition
36347        element.add($active).addClass('in')
36348      /*} else {
36349        element.removeClass('fade')
36350      }*/
36351
36352      if (element.parent('.dropdown-menu')) {
36353        element.closest('li.dropdown').addClass('active')
36354      }
36355
36356      callback && callback()
36357    }
36358
36359    transition ?
36360      $active
36361        .one($.support.transition.end, next)
36362        .emulateTransitionEnd(150) :
36363      next()
36364
36365    $active.removeClass('in')
36366  }
36367
36368
36369  // TAB PLUGIN DEFINITION
36370  // =====================
36371
36372  var old = $.fn.tab
36373
36374  $.fn.tab = function ( option ) {
36375    return this.each(function () {
36376      var $this = $(this)
36377      var data  = $this.data('bs.tab')
36378
36379      if (!data) $this.data('bs.tab', (data = new Tab(this)))
36380      if (typeof option == 'string') data[option]()
36381    })
36382  }
36383
36384  $.fn.tab.Constructor = Tab
36385
36386
36387  // TAB NO CONFLICT
36388  // ===============
36389
36390  $.fn.tab.noConflict = function () {
36391    $.fn.tab = old
36392    return this
36393  }
36394
36395
36396  // TAB DATA-API
36397  // ============
36398
36399  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
36400    e.preventDefault()
36401    $(this).tab('show')
36402  })
36403
36404}(jQuery);
36405
36406/* ========================================================================
36407 * Bootstrap: tooltip.js v3.1.1
36408 * http://getbootstrap.com/javascript/#tooltip
36409 * Inspired by the original jQuery.tipsy by Jason Frame
36410 * ========================================================================
36411 * Copyright 2011-2014 Twitter, Inc.
36412 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36413 * ======================================================================== */
36414
36415
36416+function ($) {
36417  'use strict';
36418
36419  // TOOLTIP PUBLIC CLASS DEFINITION
36420  // ===============================
36421
36422  var Tooltip = function (element, options) {
36423    this.type       =
36424    this.options    =
36425    this.enabled    =
36426    this.timeout    =
36427    this.hoverState =
36428    this.$element   = null
36429
36430    this.init('tooltip', element, options)
36431  }
36432
36433  Tooltip.DEFAULTS = {
36434    animation: true,
36435    placement: 'top',
36436    selector: false,
36437    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
36438    trigger: 'hover focus',
36439    title: '',
36440    delay: 0,
36441    html: false,
36442    container: false,
36443    viewport: {
36444      selector: 'body',
36445      padding: 0
36446    }
36447  }
36448
36449  Tooltip.prototype.init = function (type, element, options) {
36450    this.enabled   = true
36451    this.type      = type
36452    this.$element  = $(element)
36453    this.options   = this.getOptions(options)
36454    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
36455
36456    var triggers = this.options.trigger.split(' ')
36457
36458    for (var i = triggers.length; i--;) {
36459      var trigger = triggers[i]
36460
36461      if (trigger == 'click') {
36462        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
36463      } else if (trigger != 'manual') {
36464        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
36465        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
36466
36467        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
36468        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
36469      }
36470    }
36471
36472    this.options.selector ?
36473      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
36474      this.fixTitle()
36475  }
36476
36477  Tooltip.prototype.getDefaults = function () {
36478    return Tooltip.DEFAULTS
36479  }
36480
36481  Tooltip.prototype.getOptions = function (options) {
36482    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
36483
36484    if (options.delay && typeof options.delay == 'number') {
36485      options.delay = {
36486        show: options.delay,
36487        hide: options.delay
36488      }
36489    }
36490
36491    return options
36492  }
36493
36494  Tooltip.prototype.getDelegateOptions = function () {
36495    var options  = {}
36496    var defaults = this.getDefaults()
36497
36498    this._options && $.each(this._options, function (key, value) {
36499      if (defaults[key] != value) options[key] = value
36500    })
36501
36502    return options
36503  }
36504
36505  Tooltip.prototype.enter = function (obj) {
36506    var self = obj instanceof this.constructor ?
36507      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36508
36509    clearTimeout(self.timeout)
36510
36511    self.hoverState = 'in'
36512
36513    if (!self.options.delay || !self.options.delay.show) return self.show()
36514
36515    self.timeout = setTimeout(function () {
36516      if (self.hoverState == 'in') self.show()
36517    }, self.options.delay.show)
36518  }
36519
36520  Tooltip.prototype.leave = function (obj) {
36521    var self = obj instanceof this.constructor ?
36522      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36523
36524    clearTimeout(self.timeout)
36525
36526    self.hoverState = 'out'
36527
36528    if (!self.options.delay || !self.options.delay.hide) return self.hide()
36529
36530    self.timeout = setTimeout(function () {
36531      if (self.hoverState == 'out') self.hide()
36532    }, self.options.delay.hide)
36533  }
36534
36535  Tooltip.prototype.show = function () {
36536    var e = $.Event('show.bs.' + this.type)
36537
36538    if (this.hasContent() && this.enabled) {
36539      this.$element.trigger(e)
36540
36541      if (e.isDefaultPrevented()) return
36542      var that = this;
36543
36544      var $tip = this.tip()
36545
36546      this.setContent()
36547
36548      if (this.options.animation) $tip.addClass('fade')
36549
36550      var placement = typeof this.options.placement == 'function' ?
36551        this.options.placement.call(this, $tip[0], this.$element[0]) :
36552        this.options.placement
36553
36554      var autoToken = /\s?auto?\s?/i
36555      var autoPlace = autoToken.test(placement)
36556      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
36557
36558      $tip
36559        .detach()
36560        .cs
36560s({ top: 0, left: 0, display: 'block' })
36561        .addClass(placement)
36562
36563      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
36564
36565      var pos          = this.getPosition()
36566      var actualWidth  = $tip[0].offsetWidth
36567      var actualHeight = $tip[0].offsetHeight
36568
36569      if (autoPlace) {
36570        var orgPlacement = placement
36571        var $parent      = this.$element.parent()
36572        var parentDim    = this.getPosition($parent)
36573
36574        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
36575                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
36576                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
36577                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
36578                    placement
36579
36580        $tip
36581          .removeClass(orgPlacement)
36582          .addClass(placement)
36583      }
36584
36585      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
36586
36587      this.applyPlacement(calculatedOffset, placement)
36588      this.hoverState = null
36589
36590      var complete = function() {
36591        that.$element.trigger('shown.bs.' + that.type)
36592      }
36593
36594      $.support.transition && this.$tip.hasClass('fade') ?
36595        $tip
36596          .one($.support.transition.end, complete)
36597          .emulateTransitionEnd(150) :
36598        complete()
36599    }
36600  }
36601
36602  Tooltip.prototype.applyPlacement = function (offset, placement) {
36603    var $tip   = this.tip()
36604    var width  = $tip[0].offsetWidth
36605    var height = $tip[0].offsetHeight
36606
36607    // manually read margins because getBoundingClientRect includes difference
36608    var marginTop = parseInt($tip.css('margin-top'), 10)
36609    var marginLeft = parseInt($tip.css('margin-left'), 10)
36610
36611    // we must check for NaN for ie 8/9
36612    if (isNaN(marginTop))  marginTop  = 0
36613    if (isNaN(marginLeft)) marginLeft = 0
36614
36615    offset.top  = offset.top  + marginTop
36616    offset.left = offset.left + marginLeft
36617
36618    // $.fn.offset doesn't round pixel values
36619    // so we use setOffset directly with our own function B-0
36620    $.offset.setOffset($tip[0], $.extend({
36621      using: function (props) {
36622        $tip.css({
36623          top: Math.round(props.top),
36624          left: Math.round(props.left)
36625        })
36626      }
36627    }, offset), 0)
36628
36629    $tip.addClass('in')
36630
36631    // check to see if placing tip in new offset caused the tip to resize itself
36632    var actualWidth  = $tip[0].offsetWidth
36633    var actualHeight = $tip[0].offsetHeight
36634
36635    if (placement == 'top' && actualHeight != height) {
36636      offset.top = offset.top + height - actualHeight
36637    }
36638
36639    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
36640
36641    if (delta.left) offset.left += delta.left
36642    else offset.top += delta.top
36643
36644    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
36645    var arrowPosition       = delta.left ? 'left'        : 'top'
36646    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
36647
36648    $tip.offset(offset)
36649    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
36650  }
36651
36652  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
36653    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
36654  }
36655
36656  Tooltip.prototype.setContent = function () {
36657    var $tip  = this.tip()
36658    var title = this.getTitle()
36659
36660    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
36661    $tip.removeClass('fade in top bottom left right')
36662  }
36663
36664  Tooltip.prototype.hide = function () {
36665    var that = this
36666    var $tip = this.tip()
36667    var e    = $.Event('hide.bs.' + this.type)
36668
36669    function complete() {
36670      if (that.hoverState != 'in') $tip.detach()
36671      that.$element.trigger('hidden.bs.' + that.type)
36672    }
36673
36674    this.$element.trigger(e)
36675
36676    if (e.isDefaultPrevented()) return
36677
36678    $tip.removeClass('in')
36679
36680    $.support.transition && this.$tip.hasClass('fade') ?
36681      $tip
36682        .one($.support.transition.end, complete)
36683        .emulateTransitionEnd(150) :
36684      complete()
36685
36686    this.hoverState = null
36687
36688    return this
36689  }
36690
36691  Tooltip.prototype.fixTitle = function () {
36692    var $e = this.$element
36693    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
36694      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
36695    }
36696  }
36697
36698  Tooltip.prototype.hasContent = function () {
36699    return this.getTitle()
36700  }
36701
36702  Tooltip.prototype.getPosition = function ($element) {
36703    $element   = $element || this.$element
36704    var el     = $element[0]
36705    var isBody = el.tagName == 'BODY'
36706    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
36707      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
36708      width:  isBody ? $(window).width()  : $element.outerWidth(),
36709      height: isBody ? $(window).height() : $element.outerHeight()
36710    }, isBody ? {top: 0, left: 0} : $element.offset())
36711  }
36712
36713  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
36714    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
36715           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
36716           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
36717        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
36718
36719  }
36720
36721  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
36722    var delta = { top: 0, left: 0 }
36723    if (!this.$viewport) return delta
36724
36725    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
36726    var viewportDimensions = this.getPosition(this.$viewport)
36727
36728    if (/right|left/.test(placement)) {
36729      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
36730      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
36731      if (topEdgeOffset < viewportDimensions.top) { // top overflow
36732        delta.top = viewportDimensions.top - topEdgeOffset
36733      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
36734        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
36734EdgeOffset
36735      }
36736    } else {
36737      var leftEdgeOffset  = pos.left - viewportPadding
36738      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
36739      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
36740        delta.left = viewportDimensions.left - leftEdgeOffset
36741      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
36742        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
36743      }
36744    }
36745
36746    return delta
36747  }
36748
36749  Tooltip.prototype.getTitle = function () {
36750    var title
36751    var $e = this.$element
36752    var o  = this.options
36753
36754    title = $e.attr('data-original-title')
36755      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
36756
36757    return title
36758  }
36759
36760  Tooltip.prototype.tip = function () {
36761    return this.$tip = this.$tip || $(this.options.template)
36762  }
36763
36764  Tooltip.prototype.arrow = function () {
36765    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
36766  }
36767
36768  Tooltip.prototype.validate = function () {
36769    if (!this.$element[0].parentNode) {
36770      this.hide()
36771      this.$element = null
36772      this.options  = null
36773    }
36774  }
36775
36776  Tooltip.prototype.enable = function () {
36777    this.enabled = true
36778  }
36779
36780  Tooltip.prototype.disable = function () {
36781    this.enabled = false
36782  }
36783
36784  Tooltip.prototype.toggleEnabled = function () {
36785    this.enabled = !this.enabled
36786  }
36787
36788  Tooltip.prototype.toggle = function (e) {
36789    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36790    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36791  }
36792
36793  Tooltip.prototype.destroy = function () {
36794    clearTimeout(this.timeout)
36795    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36796  }
36797
36798
36799  // TOOLTIP PLUGIN DEFINITION
36800  // =========================
36801
36802  var old = $.fn.tooltip
36803
36804  $.fn.tooltip = function (option) {
36805    return this.each(function () {
36806      var $this   = $(this)
36807      var data    = $this.data('bs.tooltip')
36808      var options = typeof option == 'object' && option
36809
36810      if (!data && option == 'destroy') return
36811      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36812      if (typeof option == 'string') data[option]()
36813    })
36814  }
36815
36816  $.fn.tooltip.Constructor = Tooltip
36817
36818
36819  // TOOLTIP NO CONFLICT
36820  // ===================
36821
36822  $.fn.tooltip.noConflict = function () {
36823    $.fn.tooltip = old
36824    return this
36825  }
36826
36827}(jQuery);
36828
36829/* ========================================================================
36830 * Bootstrap: transition.js v3.1.1
36831 * http://getbootstrap.com/javascript/#transitions
36832 * ========================================================================
36833 * Copyright 2011-2014 Twitter, Inc.
36834 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36835 * ======================================================================== */
36836
36837
36838+function ($) {
36839  'use strict';
36840
36841  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36842  // ============================================================
36843
36844  function transitionEnd() {
36845    var el = document.createElement('bootstrap')
36846
36847    var transEndEventNames = {
36848      WebkitTransition : 'webkitTransitionEnd',
36849      MozTransition    : 'transitionend',
36850      OTransition      : 'oTransitionEnd otransitionend',
36851      transition       : 'transitionend'
36852    }
36853
36854    for (var name in transEndEventNames) {
36855      if (el.style[name] !== undefined) {
36856        return { end: transEndEventNames[name] }
36857      }
36858    }
36859
36860    return false // explicit for ie8 (  ._.)
36861  }
36862
36863  // http://blog.alexmaccaw.com/css-transitions
36864  $.fn.emulateTransitionEnd = function (duration) {
36865    var called = false, $el = this
36866    $(this).one($.support.transition.end, function () { called = true })
36867    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36868    setTimeout(callback, duration)
36869    return this
36870  }
36871
36872  $(function () {
36873    $.support.transition = transitionEnd()
36874  })
36875
36876}(jQuery);
36877
36878
36879// ------------------------------------------
36880// Rellax.js
36881// Buttery smooth parallax library
36882// Copyright (c) 2016 Moe Amaya (@moeamaya)
36883// MIT license
36884//
36885// Thanks to Paraxify.js and Jaime Cabllero
36886// for parallax concepts
36887// ------------------------------------------
36888
36889(function (root, factory) {
36890	if (typeof define === 'function' && define.amd) {
36891		// AMD. Register as an anonymous module.
36892		define([], factory);
36893	} else if (typeof module === 'object' && module.exports) {
36894		// Node. Does not work with strict CommonJS, but
36895		// only CommonJS-like environments that support module.exports,
36896		// like Node.
36897		module.exports = factory();
36898	} else {
36899		// Browser globals (root is window)
36900		root.Rellax = factory();
36901	}
36902}(typeof window !== "undefined" ? window : global, function () {
36903	var Rellax = function(el, options){
36904		"use strict";
36905
36906		var self = Object.create(Rellax.prototype);
36907
36908		var posY = 0;
36909		var screenY = 0;
36910		var posX = 0;
36911		var screenX = 0;
36912		var blocks = [];
36913		var pause = true;
36914
36915		// check what requestAnimationFrame to use, and if
36916		// it's not supported, use the onscroll event
36917		var loop = window.requestAnimationFrame ||
36918			window.webkitRequestAnimationFrame ||
36919			window.mozRequestAnimationFrame ||
36920			window.msRequestAnimationFrame ||
36921			window.oRequestAnimationFrame ||
36922			function(callback){ return setTimeout(callback, 1000 / 60); };
36923
36924		// store the id for later use
36925		var loopId = null;
36926
36927		// Test via a getter in the options object to see if the passive property is accessed
36928		var supportsPassive = false;
vendor: 10,724 bytes, lines 36929-37230
36929		try {
36930			var opts = Object.defineProperty({}, 'passive', {
36931				get: function() {
36932					supportsPassive = true;
36933				}
36934			});
36935			window.addEventListener("testPassive", null, opts);
36936			window.removeEventListener("testPassive", null, opts);
36937		} catch (e) {}
36938
36939		// check what cancelAnimation method to use
36940		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
36941
36942		// check which transform property to use
36943		var transformProp = window.transformProp || (function(){
36944				var testEl = document.createElement('div');
36945				if (testEl.style.transform === null) {
36946					var vendors = ['Webkit', 'Moz', 'ms'];
36947					for (var vendor in vendors) {
36948						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
36949							return vendors[vendor] + 'Transform';
36950						}
36951					}
36952				}
36953				return 'transform';
36954			})();
36955
36956		// Default Settings
36957		self.options = {
36958			speed: -2,
36959			verticalSpeed: null,
36960			horizontalSpeed: null,
36961			breakpoints: [576, 768, 1201],
36962			center: false,
36963			wrapper: null,
36964			relativeToWrapper: false,
36965			round: true,
36966			vertical: true,
36967			horizontal: false,
36968			verticalScrollAxis: "y",
36969			horizontalScrollAxis: "x",
36970			callback: function() {},
36971		};
36972
36973		// User defined options (might have more in the future)
36974		if (options){
36975			Object.keys(options).forEach(function(key){
36976				self.options[key] = options[key];
36977			});
36978		}
36979
36980		function validateCustomBreakpoints () {
36981			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
36982				var isAscending = true;
36983				var isNumerical = true;
36984				var lastVal;
36985				self.options.breakpoints.forEach(function (i) {
36986					if (typeof i !== 'number') isNumerical = false;
36987					if (lastVal !== null) {
36988						if (i < lastVal) isAscending = false;
36989					}
36990					lastVal = i;
36991				});
36992				if (isAscending && isNumerical) return;
36993			}
36994			// revert defaults if set incorrectly
36995			self.options.breakpoints = [576, 768, 1201];
36996			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
36997		}
36998
36999		if (options && options.breakpoints) {
37000			validateCustomBreakpoints();
37001		}
37002
37003		// By default, rellax class
37004		if (!el) {
37005			el = '.rellax';
37006		}
37007
37008		// check if el is a className or a node
37009		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
37010
37011		// Now query selector
37012		if (elements.length > 0) {
37013			self.elems = elements;
37014		}
37015
37016		// The elements don't exist
37017		else {
37018			console.warn("Rellax: The elements you're trying to select don't exist.");
37019			return;
37020		}
37021
37022		// Has a wrapper and it exists
37023		if (self.options.wrapper) {
37024			if (!self.options.wrapper.nodeType) {
37025				var wrapper = document.querySelector(self.options.wrapper);
37026
37027				if (wrapper) {
37028					self.options.wrapper = wrapper;
37029				} else {
37030					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
37031					return;
37032				}
37033			}
37034		}
37035
37036		// set a placeholder for the current breakpoint
37037		var currentBreakpoint;
37038
37039		// helper to determine current breakpoint
37040		var getCurrentBreakpoint = function (w) {
37041			var bp = self.options.breakpoints;
37042			if (w < bp[0]) return 'xs';
37043			if (w >= bp[0] && w < bp[1]) return 'sm';
37044			if (w >= bp[1] && w < bp[2]) return 'md';
37045			return 'lg';
37046		};
37047
37048		// Get and cache initial position of all elements
37049		var cacheBlocks = function() {
37050			for (var i = 0; i < self.elems.length; i++){
37051				var block = createBlock(self.elems[i]);
37052				blocks.push(block);
37053			}
37054		};
37055
37056
37057		// Let's kick this script off
37058		// Build array for cached element values
37059		var init = function() {
37060			for (var i = 0; i < blocks.length; i++){
37061				self.elems[i].style.cssText = blocks[i].style;
37062			}
37063
37064			blocks = [];
37065
37066			screenY = window.innerHeight;
37067			screenX = window.innerWidth;
37068			currentBreakpoint = getCurrentBreakpoint(screenX);
37069
37070			setPosition();
37071
37072			cacheBlocks();
37073
37074			animate();
37075
37076			// If paused, unpause and set listener for window resizing events
37077			if (pause) {
37078				window.addEventListener('resize', init);
37079				pause = false;
37080				// Start the loop
37081				update();
37082			}
37083		};
37084
37085		// We want to cache the parallax blocks'
37086		// values: base, top, height, speed
37087		// el: is dom object, return: el cache values
37088		var createBlock = function(el) {
37089			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
37090			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
37091			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
37092			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
37093			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
37094			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
37095			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
37096			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
37097			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
37098			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
37099			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
37100			var dataMin = el.getAttribute( 'data-rellax-min' );
37101			var dataMax = el.getAttribute( 'data-rellax-max' );
37102			var dataMinX = el.getAttribute('data-rellax-min-x');
37103			var dataMaxX = el.getAttribute('data-rellax-max-x');
37104			var dataMinY = el.getAttribute('data-rellax-min-y');
37105			var dataMaxY = el.getAttribute('data-rellax-max-y');
37106			var mapBreakpoints;
37107			var breakpoints = true;
37108
37109			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
37110				breakpoints = false;
37111			} else {
37112				mapBreakpoints = {
37113					'xs': dataXsSpeed,
37114					'sm': dataMobileSpeed,
37115					'md': dataTabletSpeed,
37116					'lg': dataDesktopSpeed
37117				};
37118			}
37119
37120			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
37121			// ensures elements are positioned based on HTML layout.
37122			//
37123			// If the element has the percentage attribute, the posY and posX needs to be
37124			// the current scroll position's value, so that the elements are still positioned based on HTML layout
37125			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37126			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
37127			if (self.options.relativeToWrapper) {
37128				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37129				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
37130			}
37131			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
37132			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;
37133
37134			var blockTop = posY + el.getBoundingClientRect().top;
37135			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
37136
37137			var blockLeft = posX + el.getBoundingClientRect().left;
37138			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
37139
37140			// apparently parallax equation everyone uses
37141			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
37142			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
37143			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
37144
37145			// Optional individual block speed as data attr, otherwise global speed
37146			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
37147			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
37148			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
37149
37150			// Optional individual block movement axis direction as data attr, otherwise global movement direction
37151			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
37152			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
37153
37154			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
37155
37156			// ~~Store non-translate3d transforms~~
37157			// Store inline styles and extract transforms
37158			var style = el.style.cssText;
37159			var transform = '';
37160
37161			// Check if there's an inline styled transform
37162			var searchResult = /transform\s*:/i.exec(style);
37163			if (searchResult) {
37164				// Get the index of the transform
37165				var index = searchResult.index;
37166
37167				// Trim the style to the transform point and get the following semi-colon index
37168				var trimmedStyle = style.slice(index);
37169				var delimiter = trimmedStyle.indexOf(';');
37170
37171				// Remove "transform" string and save the attribute
37172				if (delimiter) {
37173					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
37174				} else {
37175					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
37176				}
37177			}
37178
37179			return {
37180				baseX: bases.x,
37181				baseY: bases.y,
37182				top: blockTop,
37183				left: blockLeft,
37184				height: blockHeight,
37185				width: blockWidth,
37186				speed: speed,
37187				verticalSpeed: verticalSpeed,
37188				horizontalSpeed: horizontalSpeed,
37189				verticalScrollAxis: verticalScrollAxis,
37190				horizontalScrollAxis: horizontalScrollAxis,
37191				style: style,
37192				transform: transform,
37193				zindex: dataZindex,
37194				min: dataMin,
37195				max: dataMax,
37196				minX: dataMinX,
37197				maxX: dataMaxX,
37198				minY: dataMinY,
37199				maxY: dataMaxY
37200			};
37201		};
37202
37203		// set scroll position (posY, posX)
37204		// side effect method is not ideal, but okay for now
37205		// returns true if the scroll changed, false if nothing happened
37206		var setPosition = function() {
37207			var oldY = posY;
37208			var oldX = posX;
37209
37210			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37211			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
37212			// If option relativeToWrapper is true, use relative wrapper value instead.
37213			if (self.options.relativeToWrapper) {
37214				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37215				posY = scrollPosY - self.options.wrapper.offsetTop;
37216			}
37217
37218
37219			if (oldY != posY && self.options.vertical) {
37220				// scroll changed, return true
37221				return true;
37222			}
37223
37224			if (oldX != posX && self.options.horizontal) {
37225				// scroll changed, return true
37226				return true;
37227			}
37228
37229			// scroll did not change
37230			return false;
37231		};
37232
37233		// Ahh a pure function, gets new transform value
37234		// based on scrollPosition and speed
37235		// Allow for decimal pixel values
37236		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
37237			var result = {};
37238			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
37239			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
37240
37241			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
37242			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
37243
37244			return result;
37245		};
37246
37247		// Remove event listeners and loop again
37248		var deferredUpdate = function() {
37249			window.removeEventListener('resize', deferredUpdate);
37250			window.removeEventListener('orientationchange', deferredUpdate);
37251			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
37252			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
37253
37254			// loop again
37255			loopId = loop(update);
37256		};
37257
37258		// Loop
37259		var update = function() {
37260			if (setPosition() && pause === false) {
37261				animate();
37262
37263				// loop again
37264				loopId = loop(update);
37265			} else {
37266				loopId = null;
37267
37268				// Don't animate until we get a position updating event
37269				window.addEventListener('resize', deferredUpdate);
37270				window.addEventListener('orientationchange', deferredUpdate);
37271				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
37272				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
37273			}
37274		};
37275
37276		// Transform3d on parallax element
37277		var animate = function() {
37278			var positions;
37279			for (var i = 0; i < self.elems.length; i++){
37280				// Determine relevant movement directions
37281				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
37282				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
37283				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
37284				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
37285				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
37286				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
37287
37288				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
37289				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
37290
37291				// Subtracting initialize value, so element stays in same spot as HTML
37292				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
37293				var positionY = positions.y - blocks[i].baseY;
37294				var positionX = positions.x - blocks[i].baseX;
37295
37296				// The next two "if" blocks go like this:
37297				// Check if a limit is defined (first "min", then "max");
37298				// Check if we need to change the Y or the X
37299				// (Currently working only if just one of the axes is enabled)
37300				// Then, check if the new position is inside the allowed limit
37301				// If so, use new position. If not, set position to limit.
37302
37303				// Check if a min limit is defined
37304				if (blocks[i].min !== null) {
37305					if (self.options.vertical && !self.options.horizontal) {
37306						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
37307					}
37308					if (self.options.horizontal && !self.options.vertical) {
37309						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
37310					}
37311				}
37312
37313				// Check if directional min limits are defined
37314				if (blocks[i].minY != null) {
37315						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
37316				}
37317				if (blocks[i].minX != null) {
37318						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
37319				}
37320
37321				// Check if a max limit is defined
37322				if (blocks[i].max !== null) {
37323					if (self.options.vertical && !self.options.horizontal) {
37324						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
37325					}
37326					if (self.options.horizontal && !self.options.vertical) {
37327						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
37328					}
37329				}
37330
37331				// Check if directional max limits are defined
37332				if (blocks[i].maxY != null) {
37333						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
37334				}
37335				if (blocks[i].maxX != null) {
37336						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
37337				}
37338
37339				var zindex = blocks[i].zindex;
37340
37341				// Move that element
37342				// (Set the new translation and append initial inline transforms.)
37343				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
37344				self.elems[i].style[transformProp] = translate;
37345			}
37346			self.options.callback(positions);
37347		};
37348
37349		self.destroy = function() {
37350			for (var i = 0; i < self.elems.length; i++){
37351				self.elems[i].style.cssText = blocks[i].style;
37352			}
37353
37354			// Remove resize event listener if not pause, and pause
37355			if (!pause) {
37356				window.removeEventListener('resize', init);
37357				pause = true;
37358			}
37359
37360			// Clear the animation loop to prevent possible memory leak
37361			clearLoop(loopId);
37362			loopId = null;
37363		};
37364
37365		// Init
37366		init();
37367
37368		// Allow to recalculate the initial values whenever we want
37369		self.refresh = init;
37370
37371		return self;
37372	};
37373	return Rellax;
37374}));
37375
37376/*
37377 * OKVideo by OKFocus v2.3.2
37378 * http://okfoc.us
37379 *
37380 * Copyright 2014, OKFocus
37381 * Licensed under the MIT license.
37382 *
37383 */
37384var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
37385// youtube player ready
37386function onYouTubeIframeAPIReady() {
37387	YTplayers = new Array();
37388	jQuery('.uncode-video-container.video').each(function() {
37389		var playerY;
37390		if (jQuery(this).attr('data-provider') == 'youtube') {
37391			var id = jQuery(this).attr('data-id'),
37392				start = jQuery(this).attr('data-start'),
37393				end = jQuery(this).attr('data-end');
37394			start = typeof start && start !== null ? start : 0;
37395			end = typeof end && end !== null ? end : 0;
37396			options = jQuery(window).data('okoptions-' + id);
37397			if ( typeof options === 'undefined' ) {
37398				return true;
37399			}
37400			options.time = jQuery(this).attr('data-t');
37401			playerY = new YT.Player('okplayer-' + id, {
37402				videoId: options.video ? options.video.id : null,
37403				playerVars: {
37404					'autohide': 1,
37405					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
37406					'disablekb': 1,
37407					'cc_load_policy': options.captions,
37408					'controls': 0,
37409					'enablejsapi': 1,
37410					'fs': 0,
37411					'modestbranding': 1,
37412					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
37413					'iv_load_policy': options.annotations,
37414					'loop': options.loop,
37415					'showinfo': 0,
37416					'rel': 0,
37417					'wmode': 'opaque',
37418					'hd': options.hd,
37419					'mute': 1,
37420					'start': start,
37421					'end': end
37422				},
37423				events: {
37424					'onReady': OKEvents.yt.ready,
37425					'onStateChange': OKEvents.yt.onStateChange,
37426					'onError': OKEvents.yt.error
37427				}
37428			});
37429			YTplayers[id] = playerY;
37430			playerY.videoId = id;
37431		}
37432
37433	});
37434}
37435// vimeo player ready
37436function vimeoPlayerReady(id) {
37437	options = jQuery(window).data('okoptions-' + id);
37438	if ( typeof options === 'undefined' ) {
37439		return true;
37440	}
37441	var jIframe = options.jobject,
37442		iframe = jIframe[0];
37443
37444	jIframe.attr('src', jIframe.data('src'));
37445	var playerV = new Vimeo.Player(iframe);
37446	// hide player until Vimeo hides controls...
37447	playerV.on('loaded', function(e) {
37448		OKEvents.v.onReady(iframe);
37449		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
37450		if (carouselContainer.length) {
37451			UNCODE.owlPlayVideo(carouselContainer);
37452		}
37453		// "Do not try to add listeners or call functions before receiving this event."
37454		if (OKEvents.utils.isMobile()) {
37455			// mobile devices cannot listen for play event
37456			OKEvents.v.onPlay(playerV);
37457		} else {
37458			playerV.on('play', function(){
37459				OKEvents.v.onPlay(playerV);
37460				jQuery(window).trigger('okevents.v.play', [playerV]);
37461			});
37462			playerV.on('pause', function(){
37463				OKEvents.v.onPause;
37464				jQuery(window).trigger('okevents.v.pause', [playerV]);
37465			});
37466			playerV.on('ended', function(){
37467				OKEvents.v.onFinish
37468				jQuery(window).trigger('okevents.v.ended', [playerV]);
37469			});
37470		}
37471		if (options.time != null) {
37472			var optsTimeStr = (options.time).replace('t=', ''),
37473				timeV = '';
37474
37475			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
37476				var timeArr = optsTimeStr.split(/([^\d.-])/);
37477				for ( var i = 0; i < timeArr.length; i++ ) {
37478					if ( timeArr[i] === 'h' ) {
37479						timeV += parseFloat(timeArr[i-1]) * 3600;
37480					} else if ( timeArr[i] === 'm' ) {
37481						timeV += parseFloat(timeArr[i-1]) * 60;
37482					} else if ( timeArr[i] === 's' ) {
37483						timeV += parseFloat(timeArr[i-1]);
37484					}
37485				}
37486			} else {
37487				timeV = optsTimeStr;
37488			}
37489
37490			playerV.setCurrentTime(timeV);
37491		}
37492
37493		playerV.setVolume(0);
37494		playerV.play();
37495		jQuery(iframe).css({
37496			visibility: 'visible',
37497			opacity: 1
37498		});
37499		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37500		jQuery(iframe).closest('#page-header').addClass('video-started');
37501		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37502
37503		jQuery(window).trigger('okevents.v.loaded', [playerV]);
37504	});
37505}
37506OKEvents = {
37507	yt: {
37508		ready: function(event) {
37509			var id = event.target.videoId,
37510				$video = jQuery('#okplayer-' + id),
37511				options = jQuery(window).data('okoptions-' + id);
37512			if ( typeof options === 'undefined' ) {
37513				return true;
37514			}
37515			youtubePlayers[id] = event.target;
37516			event.target.setVolume(options.volume);
37517			if (options.autoplay === 1) {
37518				if (options.playlist.list) {
37519					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
37520				} else {
37521					var inCarousel = $video.closest('.owl-item');
37522					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
37523						if (options.time != null) {
37524							event.target.seekTo(parseInt(options.time));
37525						}
37526						event.target.playVideo();
37527					} else {
37528						event.target.pauseVideo();
37529					}
37530				}
37531			}
37532			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
37533
37534			$video.closest('[data-provider]').on('uncode-resume', function(){
37535				if (options.time != null) {
37536					event.target.seekTo(parseInt(options.time)).playVideo();
37537				} else {
37538					event.target.seekTo(0).playVideo();
37539				}
37540			});
37541
37542			$video.closest('[data-provider]').on('uncode-pause', function(){
37543				if (options.time != null) {
37544					event.target.seekTo(parseInt(options.time)).pauseVideo();
37545				} else {
37546					event.target.seekTo(0).pauseVideo();
37547				}
37548			});
37549			jQuery(window).trigger('okevents.y.loaded', [event]);
37550		},
37551		onStateChange: function(event) {
37552			var id = event.target.videoId,
37553				$video = jQuery('#okplayer-' + id),
37554				options = jQuery(window).data('okoptions-' + id);
37555			if ( typeof options === 'undefined' ) {
37556				return true;
37557			}
37558			youtubePlayers[id] = event.target;
37559			event.target.setVolume(options.volume);
37560			var $fluid = $video.closest('.fluid-object'),
37561				$tmb = $video.closest('.tmb'),
37562				setTime;
37563			switch (event.data) {
37564				case -1:
37565					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
37566					break;
37567				case 0:
37568					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
37569					options.loop && event.target.playVideo();
37570					break;
37571				case 1:
37572					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37573					setTimeout(function() {
37574						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
37575						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37576						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
37577						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37578					}, 300);
37579				break;
37580				case 2:
37581					OKEvents.utils.isFunction(options.onPause) && options.onPause();
37582					break;
37583				case 3:
37584					OKEvents.utils.isFunction(options.buffering) && options.buffering();
37585					break;
37586				case 5:
37587					OKEvents.utils.isFunction(options.cued) && options.cued();
37588					break;
37589				default:
37590					throw "OKVideo: received invalid data from YT player.";
37591			}
37592
37593			jQuery(window).trigger('okevents.y.change', [event]);
37594		},
37595		error: function(event) {
37596			throw event;
37597		}
37598	},
37599	v: {
37600		onReady: function(target) {
37601			if ( typeof options === 'undefined' ) {
37602				return true;
37603			}
37604			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
37605		},
37606		onPlay: function(player) {
37607			if ( typeof options === 'undefined' ) {
37608				return true;
37609			}
37610			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
37611			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37612			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37613			jQuery(player.element).closest('#page-header').addClass('video-started');
37614			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37615		},
37616		onPause: function() {
37617			if ( typeof options === 'undefined' ) {
37618				return true;
37619			}
37620			OKEvents.utils.isFunction(options.onPause) && options.onPause();
37621		},
37622		onFinish: function() {
37623			if ( typeof options === 'undefined' ) {
37624				return true;
37625			}
37626			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
37627		}
37628	},
37629	utils: {
37630		isFunction: function(func) {
37631			if (typeof func === 'function') {
37632				return true;
37633			} else {
37634				return false;
37635			}
37636		},
37637		isMobile: function() {
37638			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
37639				return true;
37640			} else {
37641				return false;
37642			}
37643		}
37644	}
37645};
37646
37647/**
37648 * vivus - JavaScript library to make drawing animation on SVG
37649 * @version v0.4.4
37650 * @link https://github.com/maxwellito/vivus
37651 * @license MIT
37652 */
37653
37654'use strict';
37655
37656(function () {
37657
37658  'use strict';
37659
37660/**
37661 * Pathformer
37662 * Beta version
37663 *
37664 * Take any SVG version 1.1 and transform
37665 * child elements to 'path' elements
37666 *
37667 * This code is purely forked from
37668 * https://github.com/Waest/SVGPathConverter
37669 */
37670
37671/**
37672 * Class constructor
37673 *
37674 * @param {DOM|String} element Dom element of the SVG or id of it
37675 */
37676function Pathformer(element) {
37677  // Test params
37678  if (typeof element === 'undefined') {
37679	throw new Error('Pathformer [constructor]: "element" parameter is required');
37680  }
37681
37682  // Set the element
37683  if (element.constructor === String) {
37684	element = document.getElementById(element);
37685	if (!element) {
37686	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
37687	}
37688  }
37689  if (element instanceof window.SVGElement ||
37690	  element instanceof window.SVGGElement ||
37691	  /^svg$/i.test(element.nodeName)) {
37692	this.el = element;
37693  } else {
37694	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
37695  }
37696
37697  // Start
37698  this.scan(element);
37699}
37700
37701/**
37702 * List of tags which can be transformed
37703 * to path elements
37704 *
37705 * @type {Array}
37706 */
37707Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
37708
37709/**
37710 * List of attribute names which contain
37711 * data. This array list them to check if
37712 * they contain bad values, like percentage.
37713 *
37714 * @type {Array}
37715 */
37716Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 37716-38514
37716y1', 'y2'];
37717
37718/**
37719 * Finds the elements compatible for transform
37720 * and apply the liked method
37721 *
37722 * @param  {object} options Object from the constructor
37723 */
37724Pathformer.prototype.scan = function (svg) {
37725  var fn, element, pathData, pathDom,
37726	  elements = svg.querySelectorAll(this.TYPES.join(','));
37727
37728  for (var i = 0; i < elements.length; i++) {
37729	element = elements[i];
37730	fn = this[element.tagName.toLowerCase() + 'ToPath'];
37731	pathData = fn(this.parseAttr(element.attributes));
37732	pathDom = this.pathMaker(element, pathData);
37733	element.parentNode.replaceChild(pathDom, element);
37734  }
37735};
37736
37737
37738/**
37739 * Read `line` element to extract and transform
37740 * data, to make it ready for a `path` object.
37741 *
37742 * @param  {DOMelement} element Line element to transform
37743 * @return {object}			 Data for a `path` element
37744 */
37745Pathformer.prototype.lineToPath = function (element) {
37746  var newElement = {},
37747	  x1 = element.x1 || 0,
37748	  y1 = element.y1 || 0,
37749	  x2 = element.x2 || 0,
37750	  y2 = element.y2 || 0;
37751
37752  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
37753  return newElement;
37754};
37755
37756/**
37757 * Read `rect` element to extract and transform
37758 * data, to make it ready for a `path` object.
37759 * The radius-border is not taken in charge yet.
37760 * (your help is more than welcomed)
37761 *
37762 * @param  {DOMelement} element Rect element to transform
37763 * @return {object}             Data for a `path` element
37764 */
37765Pathformer.prototype.rectToPath = function (element) {
37766  var newElement = {},
37767      x      = parseFloat(element.x)      || 0,
37768      y      = parseFloat(element.y)      || 0,
37769      width  = parseFloat(element.width)  || 0,
37770      height = parseFloat(element.height) || 0;
37771
37772  if (element.rx || element.ry) {
37773    var rx = parseInt(element.rx, 10) || -1,
37774        ry = parseInt(element.ry, 10) || -1;
37775    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
37776    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
37777
37778    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
37779                   'L ' + (x + width - rx) + ',' + y + ' ' +
37780                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
37781                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
37782                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
37783                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
37784                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
37785                   'L ' + x + ',' + (y + ry) + ' ' +
37786                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
37787  }
37788  else {
37789    newElement.d = 'M' + x + ' ' + y + ' ' +
37790                   'L' + (x + width) + ' ' + y + ' ' +
37791                   'L' + (x + width) + ' ' + (y + height) + ' ' +
37792                   'L' + x + ' ' + (y + height) + ' Z';
37793  }
37794  return newElement;
37795};
37796
37797/**
37798 * Read `polyline` element to extract and transform
37799 * data, to make it ready for a `path` object.
37800 *
37801 * @param  {DOMelement} element Polyline element to transform
37802 * @return {object}             Data for a `path` element
37803 */
37804Pathformer.prototype.polylineToPath = function (element) {
37805  var newElement = {},
37806      points = element.points.trim().split(' '),
37807      i, path;
37808
37809  // Reformatting if points are defined without commas
37810  if (element.points.indexOf(',') === -1) {
37811    var formattedPoints = [];
37812    for (i = 0; i < points.length; i+=2) {
37813      formattedPoints.push(points[i] + ',' + points[i+1]);
37814    }
37815    points = formattedPoints;
37816  }
37817
37818  // Generate the path.d value
37819  path = 'M' + points[0];
37820  for(i = 1; i < points.length; i++) {
37821    if (points[i].indexOf(',') !== -1) {
37822      path += 'L' + points[i];
37823    }
37824  }
37825  newElement.d = path;
37826  return newElement;
37827};
37828
37829/**
37830 * Read `polygon` element to extract and transform
37831 * data, to make it ready for a `path` object.
37832 * This method rely on polylineToPath, because the
37833 * logic is similar. The path created is just closed,
37834 * so it needs an 'Z' at the end.
37835 *
37836 * @param  {DOMelement} element Polygon element to transform
37837 * @return {object}             Data for a `path` element
37838 */
37839Pathformer.prototype.polygonToPath = function (element) {
37840  var newElement = Pathformer.prototype.polylineToPath(element);
37841
37842  newElement.d += 'Z';
37843  return newElement;
37844};
37845
37846/**
37847 * Read `ellipse` element to extract and transform
37848 * data, to make it ready for a `path` object.
37849 *
37850 * @param  {DOMelement} element ellipse element to transform
37851 * @return {object}             Data for a `path` element
37852 */
37853Pathformer.prototype.ellipseToPath = function (element) {
37854  var newElement = {},
37855      rx = parseFloat(element.rx) || 0,
37856      ry = parseFloat(element.ry) || 0,
37857      cx = parseFloat(element.cx) || 0,
37858      cy = parseFloat(element.cy) || 0,
37859      startX = cx - rx,
37860      startY = cy,
37861      endX = parseFloat(cx) + parseFloat(rx),
37862      endY = cy;
37863
37864  newElement.d = 'M' + startX + ',' + startY +
37865                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37866                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37867  return newElement;
37868};
37869
37870/**
37871 * Read `circle` element to extract and transform
37872 * data, to make it ready for a `path` object.
37873 *
37874 * @param  {DOMelement} element Circle element to transform
37875 * @return {object}             Data for a `path` element
37876 */
37877Pathformer.prototype.circleToPath = function (element) {
37878  var newElement = {},
37879      r  = parseFloat(element.r)  || 0,
37880      cx = parseFloat(element.cx) || 0,
37881      cy = parseFloat(element.cy) || 0,
37882      startX = cx - r,
37883      startY = cy,
37884      endX = parseFloat(cx) + parseFloat(r),
37885      endY = cy;
37886
37887  newElement.d =  'M' + startX + ',' + startY +
37888                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37889                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37890  return newElement;
37891};
37892
37893/**
37894 * Create `path` elements form original element
37895 * and prepared objects
37896 *
37897 * @param  {DOMelement} element  Original element to transform
37898 * @param  {object} pathData     Path data (from `toPath` methods)
37899 * @return {DOMelement}          Path element
37900 */
37901Pathformer.prototype.pathMaker = function (element, pathData) {
37902  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37903  for(i = 0; i < element.attributes.length; i++) {
37904    attr = element.attributes[i];
37905    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37906      pathTag.setAttribute(attr.name, attr.value);
37907    }
37908  }
37909  for(i in pathData) {
37910    pathTag.setAttribute(i, pathData[i]);
37911  }
37912  return pathTag;
37913};
37914
37915/**
37916 * Parse attributes of a DOM element to
37917 * get an object of attribute => value
37918 *
37919 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37920 * @return {object}                  Object of attributes
37921 */
37922Pathformer.prototype.parseAttr = function (element) {
37923  var attr, output = {};
37924  for (var i = 0; i < element.length; i++) {
37925    attr = element[i];
37926    // Check if no data attribute contains '%', or the transformation is impossible
37927    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37928      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37929    }
37930    output[attr.name] = attr.value;
37931  }
37932  return output;
37933};
37934
37935  'use strict';
37936
37937var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37938
37939/**
37940 * Vivus
37941 * Beta version
37942 *
37943 * Take any SVG and make the animation
37944 * to give give the impression of live drawing
37945 *
37946 * This in more than just inspired from codrops
37947 * At that point, it's a pure fork.
37948 */
37949
37950/**
37951 * Class constructor
37952 * option structure
37953 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
37954 *   duration: <int> (in frames)
37955 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
37956 *   delay: <int> (delay between the drawing of first and last path)
37957 *   dashGap <integer> whitespace extra margin between dashes
37958 *   pathTimingFunction <function> timing animation function for each path element of the SVG
37959 *   animTimingFunction <function> timing animation function for the complete SVG
37960 *   forceRender <boolean> force the browser to re-render all updated path items
37961 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
37962 *
37963 * The attribute 'type' is by default on 'delayed'.
37964 *  - 'delayed'
37965 *    all paths are draw at the same time but with a
37966 *    little delay between them before start
37967 *  - 'sync'
37968 *    all path are start and finish at the same time
37969 *  - 'oneByOne'
37970 *    only one path is draw at the time
37971 *    the end of the first one will trigger the draw
37972 *    of the next one
37973 *
37974 * All these values can be overwritten individually
37975 * for each path item in the SVG
37976 * The value of frames will always take the advantage of
37977 * the duration value.
37978 * If you fail somewhere, an error will be thrown.
37979 * Good luck.
37980 *
37981 * @constructor
37982 * @this {Vivus}
37983 * @param {DOM|String}   element  Dom element of the SVG or id of it
37984 * @param {Object}       options  Options about the animation
37985 * @param {Function}     callback Callback for the end of the animation
37986 */
37987function Vivus (element, options, callback) {
37988
37989  setupEnv();
37990
37991  // Setup
37992  this.isReady = false;
37993  this.setElement(element, options);
37994  this.setOptions(options);
37995  this.setCallback(callback);
37996
37997  if (this.isReady) {
37998    this.init();
37999  }
38000}
38001
38002/**
38003 * Timing functions
38004 **************************************
38005 *
38006 * Default functions to help developers.
38007 * It always take a number as parameter (between 0 to 1) then
38008 * return a number (between 0 and 1)
38009 */
38010Vivus.LINEAR          = function (x) {return x;};
38011Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
38012Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
38013Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
38014Vivus.EASE_OUT_BOUNCE = function (x) {
38015  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
38016    rate = Math.pow(base,1.5),
38017    rateR = Math.pow(1 - x, 2),
38018    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
38019  return (1- rateR) + (progress * rateR);
38020};
38021
38022
38023/**
38024 * Setters
38025 **************************************
38026 */
38027
38028/**
38029 * Check and set the element in the instance
38030 * The method will not return anything, but will throw an
38031 * error if the parameter is invalid
38032 *
38033 * @param {DOM|String}   element  SVG Dom element or id of it
38034 */
38035Vivus.prototype.setElement = function (element, options) {
38036  var onLoad, self;
38037
38038  // Basic check
38039  if (typeof element === 'undefined') {
38040    throw new Error('Vivus [constructor]: "element" parameter is required');
38041  }
38042
38043  // Set the element
38044  if (element.constructor === String) {
38045    element = document.getElementById(element);
38046    if (!element) {
38047      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
38048    }
38049  }
38050  this.parentEl = element;
38051
38052  // Load the SVG with XMLHttpRequest and extract the SVG
38053  if (options && options.file) {
38054    var self = this;
38055    onLoad = function (e) {
38056      var domSandbox = document.createElement('div');
38057      domSandbox.innerHTML = this.responseText;
38058
38059      var svgTag = domSandbox.querySelector('svg');
38060      if (!svgTag) {
38061        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
38062      }
38063
38064      self.el = svgTag
38065      self.el.setAttribute('width', '100%');
38066      self.el.setAttribute('height', '100%');
38067      self.parentEl.appendChild(self.el)
38068      self.isReady = true;
38069      self.init();
38070      self = null;
38071    }
38072
38073    var oReq = new window.XMLHttpRequest();
38074    oReq.addEventListener('load', onLoad);
38075    oReq.open('GET', options.file);
38076    oReq.send();
38077    return;
38078  }
38079
38080  switch (element.constructor) {
38081  case window.SVGSVGElement:
38082  case window.SVGElement:
38083  case window.SVGGElement:
38084    this.el = element;
38085    this.isReady = true;
38086    break;
38087
38088  case window.HTMLObjectElement:
38089    self = this;
38090    onLoad = function (e) {
38091      if (self.isReady) {
38092        return;
38093      }
38094      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
38095      if (!self.el && e) {
38096        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
38097      }
38098      else if (self.el) {
38099        if (element.getAttribute('built-by-vivus')) {
38100          self.parentEl.insertBefore(self.el, element);
38101          self.parentEl.removeChild(element);
38102          self.el.setAttribute('width', '100%');
38103          self.el.setAttribute('height', '100%');
38104        }
38105        self.isReady = true;
38106        self.init();
38107        self = null;
38108      }
38109    };
38110
38111    if (!onLoad()) {
38112      element.addEventListener('load', onLoad);
38113    }
38114    break;
38115
38116  default:
38117    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
38118  }
38119};
38120
38121/**
38122 * Set up user option to the instance
38123 * The method will not return anything, but will throw an
38124 * error if the parameter is invalid
38125 *
38126 * @param  {object} options Object from the constructor
38127 */
38128Vivus.prototype.setOptions = function (options) {
38129  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
38130  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
38131
38132  // Basic check
38133  if (options !== undefined && options.constructor !== Object) {
38134    throw new Error('Vivus [constructor]: "options" parameter must be an object');
38135  }
38136  else {
38137    options = options || {};
38138  }
38139
38140  // Set the animation type
38141  if (options.type && allowedTypes.indexOf(options.type) === -1) {
38142    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
38143  }
38144  else {
38145    this.type = options.type || allowedTypes[0];
38146  }
38147
38148  // Set the start type
38149  if (options.start && allowedStarts.indexOf(options.start) === -1) {
38150    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
38151  }
38152  else {
38153    this.start = options.start || allowedStarts[0];
38154  }
38155
38156  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
38157  this.duration     = parsePositiveInt(options.duration, 120);
38158  this.delay        = parsePositiveInt(options.delay, null);
38159  //Uncode addition
38160  this.delayStart   = parsePositiveInt(options.delayStart, null);
38161  //#END
38162  this.dashGap      = parsePositiveInt(options.dashGap, 1);
38163  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
38164  this.reverseStack = !!options.reverseStack;
38165  this.selfDestroy  = !!options.selfDestroy;
38166  this.onReady      = options.onReady;
38167  this.map          = [];
38168  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
38169
38170  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
38171
38172  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
38173  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
38174
38175  if (this.delay >= this.duration) {
38176    throw new Error('Vivus [constructor]: delay must be shorter than duration');
38177  }
38178};
38179
38180/**
38181 * Set up callback to the instance
38182 * The method will not return enything, but will throw an
38183 * error if the parameter is invalid
38184 *
38185 * @param  {Function} callback Callback for the animation end
38186 */
38187Vivus.prototype.setCallback = function (callback) {
38188  // Basic check
38189  if (!!callback && callback.constructor !== Function) {
38190    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
38191  }
38192  this.callback = callback || function () {};
38193};
38194
38195
38196/**
38197 * Core
38198 **************************************
38199 */
38200
38201/**
38202 * Map the svg, path by path.
38203 * The method return nothing, it just fill the
38204 * `map` array. Each item in this array represent
38205 * a path element from the SVG, with informations for
38206 * the animation.
38207 *
38208 * ```
38209 * [
38210 *   {
38211 *     el: <DOMobj> the path element
38212 *     length: <number> length of the path line
38213 *     startAt: <number> time start of the path animation (in frames)
38214 *     duration: <number> path animation duration (in frames)
38215 *   },
38216 *   ...
38217 * ]
38218 * ```
38219 *
38220 */
38221Vivus.prototype.mapping = function () {
38222  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
38223  timePoint = totalLength = lengthMeter = 0;
38224  paths = this.el.querySelectorAll('path');
38225
38226  for (i = 0; i < paths.length; i++) {
38227    path = paths[i];
38228    if (this.isInvisible(path)) {
38229      continue;
38230    }
38231    pathObj = {
38232      el: path,
38233      length: Math.ceil(path.getTotalLength())
38234    };
38235    // Test if the path length is correct
38236    if (isNaN(pathObj.length)) {
38237      if (window.console && console.warn) {
38238        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
38239      }
38240      continue;
38241    }
38242    this.map.push(pathObj);
38243    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
38244    path.style.strokeDashoffset = pathObj.length + this.dashGap;
38245    pathObj.length += this.dashGap;
38246    totalLength += pathObj.length;
38247
38248    this.renderPath(i);
38249  }
38250
38251  totalLength = totalLength === 0 ? 1 : totalLength;
38252  this.delay = this.delay === null ? this.duration / 3 : this.delay;
38253  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
38254
38255  // Reverse stack if asked
38256  if (this.reverseStack) {
38257    this.map.reverse();
38258  }
38259
38260  for (i = 0; i < this.map.length; i++) {
38261    pathObj = this.map[i];
38262
38263    switch (this.type) {
38264    case 'delayed':
38265      pathObj.startAt = this.delayUnit * i;
38266      pathObj.duration = this.duration - this.delay;
38267      break;
38268
38269    case 'oneByOne':
38270      pathObj.startAt = lengthMeter / totalLength * this.duration;
38271      pathObj.duration = pathObj.length / totalLength * this.duration;
38272      break;
38273
38274    case 'sync':
38275    case 'async':
38276    case 'nsync':
38277      pathObj.startAt = 0;
38278      pathObj.duration = this.duration;
38279      break;
38280
38281    case 'scenario-sync':
38282      path = pathObj.el;
38283      pAttrs = this.parseAttr(path);
38284      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
38285      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38286      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
38287      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38288      break;
38289
38290    case 'scenario':
38291      path = pathObj.el;
38292      pAttrs = this.parseAttr(path);
38293      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
38294      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38295      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38296      break;
38297    }
38298    lengthMeter += pathObj.length;
38299    this.frameLength = this.frameLength || this.duration;
38300  }
38301};
38302
38303/**
38304 * Interval method to draw the SVG from current
38305 * position of the animation. It update the value of
38306 * `currentFrame` and re-trace the SVG.
38307 *
38308 * It use this.handle to store the requestAnimationFrame
38309 * and clear it one the animation is stopped. So this
38310 * attribute can be used to know if the animation is
38311 * playing.
38312 *
38313 * Once the animation at the end, this method will
38314 * trigger the Vivus callback.
38315 *
38316 */
38317Vivus.prototype.drawer = function () {
38318  var self = this;
38319  this.currentFrame += this.speed;
38320
38321  if (this.currentFrame <= 0) {
38322    this.stop();
38323    this.reset();
38324  } else if (this.currentFrame >= this.frameLength) {
38325    this.stop();
38326    this.currentFrame = this.frameLength;
38327    this.trace();
38328    if (this.selfDestroy) {
38329      this.destroy();
38330    }
38331  } else {
38332    this.trace();
38333    this.handle = requestAnimFrame(function () {
38334      self.drawer();
38335    });
38336    return;
38337  }
38338
38339  this.callback(this);
38340  if (this.instanceCallback) {
38341    this.instanceCallback(this);
38342    this.instanceCallback = null;
38343  }
38344};
38345
38346/**
38347 * Draw the SVG at the current instant from the
38348 * `currentFrame` value. Here is where most of the magic is.
38349 * The trick is to use the `strokeDashoffset` style property.
38350 *
38351 * For optimisation reasons, a new property called `progress`
38352 * is added in each item of `map`. This one contain the current
38353 * progress of the path element. Only if the new value is different
38354 * the new value will be applied to the DOM element. This
38355 * method save a lot of resources to re-render the SVG. And could
38356 * be improved if the animation couldn't be played forward.
38357 *
38358 */
38359Vivus.prototype.trace = function () {
38360  var i, progress, path, currentFrame;
38361  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
38362  for (i = 0; i < this.map.length; i++) {
38363    path = this.map[i];
38364    progress = (currentFrame - path.startAt) / path.duration;
38365    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
38366    if (path.progress !== progress) {
38367      path.progress = progress;
38368      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
38369      this.renderPath(i);
38370    }
38371  }
38372};
38373
38374/**
38375 * Method forcing the browser to re-render a path element
38376 * from it's index in the map. Depending on the `forceRender`
38377 * value.
38378 * The trick is to replace the path element by it's clone.
38379 * This practice is not recommended because it's asking more
38380 * ressources, too much DOM manupulation..
38381 * but it's the only way to let the magic happen on IE.
38382 * By default, this fallback is only applied on IE.
38383 *
38384 * @param  {Number} index Path index
38385 */
38386Vivus.prototype.renderPath = function (index) {
38387  if (this.forceRender && this.map && this.map[index]) {
38388    var pathObj = this.map[index],
38389        newPath = pathObj.el.cloneNode(true);
38390    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
38391    pathObj.el = newPath;
38392  }
38393};
38394
38395/**
38396 * When the SVG object is loaded and ready,
38397 * this method will continue the initialisation.
38398 *
38399 * This this mainly due to the case of passing an
38400 * object tag in the constructor. It will wait
38401 * the end of the loading to initialise.
38402 *
38403 */
38404Vivus.prototype.init = function () {
38405  // Set object variables
38406  this.frameLength = 0;
38407  this.currentFrame = 0;
38408  this.map = [];
38409
38410  // Start
38411  new Pathformer(this.el);
38412  this.mapping();
38413  this.starter();
38414
38415  if (this.onReady) {
38416    this.onReady(this);
38417  }
38418};
38419
38420/**
38421 * Trigger to start of the animation.
38422 * Depending on the `start` value, a different script
38423 * will be applied.
38424 *
38425 * If the `start` value is not valid, an error will be thrown.
38426 * Even if technically, this is impossible.
38427 *
38428 */
38429Vivus.prototype.starter = function () {
38430  switch (this.start) {
38431  case 'manual':
38432    return;
38433
38434  case 'autostart':
38435    this.play();
38436    break;
38437
38438  case 'inViewport':
38439    var self = this,
38440    listener = function () {
38441      if (self.isInViewport(self.parentEl, 1)) {
38442        self.play();
38443        window.removeEventListener('scroll', listener);
38444        //Uncode addition
38445        window.removeEventListener('fp-slide-changed', listener);
38446        window.removeEventListener('fp-slide-scroll', listener);
38447        //#END
38448      }
38449    };
38450    window.addEventListener('scroll', listener);
38451    //Uncode addition
38452    window.addEventListener('fp-slide-changed', listener);
38453    window.addEventListener('fp-slide-scroll', listener);
38454    //#END
38455    listener();
38456    break;
38457  }
38458};
38459
38460
38461/**
38462 * Controls
38463 **************************************
38464 */
38465
38466/**
38467 * Get the current status of the animation between
38468 * three different states: 'start', 'progress', 'end'.
38469 * @return {string} Instance status
38470 */
38471Vivus.prototype.getStatus = function () {
38472  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
38473};
38474
38475/**
38476 * Reset the instance to the initial state : undraw
38477 * Be careful, it just reset the animation, if you're
38478 * playing the animation, this won't stop it. But just
38479 * make it start from start.
38480 *
38481 */
38482Vivus.prototype.reset = function () {
38483  return this.setFrameProgress(0);
38484};
38485
38486/**
38487 * Set the instance to the final state : drawn
38488 * Be careful, it just set the animation, if you're
38489 * playing the animation on rewind, this won't stop it.
38490 * But just make it start from the end.
38491 *
38492 */
38493Vivus.prototype.finish = function () {
38494  return this.setFrameProgress(1);
38495};
38496
38497/**
38498 * Set the level of progress of the drawing.
38499 *
38500 * @param {number} progress Level of progress to set
38501 */
38502Vivus.prototype.setFrameProgress = function (progress) {
38503  progress = Math.min(1, Math.max(0, progress));
38504  this.currentFrame = Math.round(this.frameLength * progress);
38505  this.trace();
38506  return this;
38507};
38508
38509/**
38510 * Play the animation at the desired speed.
38511 * Speed must be a valid number (no zero).
38512 * By default, the speed value is 1.
38513 * But a negative value is accepted to go forward.
38514 *
38515 * And works with float too.
38516 * But don't forget we are in JavaScript, se be nice
38517 * with him and give him a 1/2^x value.
38518 *
38519 * @param  {number} speed Animation speed [optional]
38520 */
38521Vivus.prototype.play = function (speed, callback) {
38522  this.instanceCallback = null;
38523
38524  if (speed && typeof speed === 'function') {
38525    this.instanceCallback = speed; // first parameter is actually the callback function
38526    speed = null;
38527  }
38528  else if (speed && typeof speed !== 'number') {
38529    throw new Error('Vivus [play]: invalid speed');
38530  }
38531  // if the first parameter wasn't the callback, check if the seconds was
38532  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
38533    this.instanceCallback = callback;
38534  }
38535
38536
38537  this.speed = speed || 1;
38538  //Uncode addition
38539  if (!this.handle) {
38540    var $this = this,
38541    delay = (this.delayStart != null) ? this.delayStart : 0;
38542    setTimeout(function() {
38543      $this.drawer();
38544    }, delay);
38545  }
38546  //#END
38547  return this;
38548};
38549
38550/**
38551 * Stop the current animation, if on progress.
38552 * Should not trigger any error.
38553 *
38554 */
38555Vivus.prototype.stop = function () {
38556  if (this.handle) {
38557    cancelAnimFrame(this.handle);
38558    this.handle = null;
38559  }
38560  return this;
38561};
38562
38563/**
38564 * Destroy the instance.
38565 * Remove all bad styling attributes on all
38566 * path tags
38567 *
38568 */
38569Vivus.prototype.destroy = function () {
38570  this.stop();
38571  var i, path;
38572  for (i = 0; i < this.map.length; i++) {
38573    path = this.map[i];
38574    path.el.style.strokeDashoffset = null;
38575    path.el.style.strokeDasharray = null;
38576    this.renderPath(i);
38577  }
38578};
38579
38580
38581/**
38582 * Utils methods
38583 * include methods from Codrops
38584 **************************************
38585 */
38586
38587/**
38588 * Method to best guess if a path should added into
38589 * the animation or not.
38590 *
38591 * 1. Use the `data-vivus-ignore` attribute if set
38592 * 2. Check if the instance must ignore invisible paths
38593 * 3. Check if the path is visible
38594 *
38595 * For now the visibility checking is unstable.
38596 * It will be used for a beta phase.
38597 *
38598 * Other improvments are planned. Like detecting
38599 * is the path got a stroke or a valid opacity.
38600 */
38601Vivus.prototype.isInvisible = function (el) {
38602  var rect,
38603    ignoreAttr = el.getAttribute('data-ignore');
38604
38605  if (ignoreAttr !== null) {
38606    return ignoreAttr !== 'false';
38607  }
38608
38609  if (this.ignoreInvisible) {
38610    rect = el.getBoundingClientRect();
38611    return !rect.width && !rect.height;
38612  }
38613  else {
38614    return false;
38615  }
38616};
38617
38618/**
38619 * Parse attributes of a DOM element to
38620 * get an object of {attributeName => attributeValue}
38621 *
38622 * @param  {object} element DOM element to parse
38623 * @return {object}         Object of attributes
38624 */
38625Vivus.prototype.parseAttr = function (element) {
38626  var attr, output = {};
38627  if (element && element.attributes) {
38628    for (var i = 0; i < element.attributes.length; i++) {
38629      attr = element.attributes[i];
38630      output[attr.name] = attr.value;
38631    }
38632  }
38633  return output;
38634};
38635
38636/**
38637 * Reply if an element is in the page viewport
38638 *
38639 * @param  {object} el Element to observe
38640 * @param  {number} h  Percentage of height
38641 * @return {boolean}
38642 */
38643Vivus.prototype.isInViewport = function (el, h) {
38644  var scrolled   = this.scrollY(),
38645    viewed       = scrolled + this.getViewportH(),
38646    elBCR        = el.getBoundingClientRect(),
38647    elHeight     = elBCR.height,
38648    elTop        = scrolled + elBCR.top,
38649    elBottom     = elTop + elHeight;
38650
38651  // if 0, the element is considered in the viewport as soon as it enters.
38652  // if 1, the element is considered in the viewport only when it's fully inside
38653  // value in percentage (1 >= h >= 0)
38654  h = h || 0;
38655
38656  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
38657};
38658
38659
38660/**
38661 * Get the viewport height in pixels
38662 *
38663 * @return {integer} Viewport height
38664 */
38665Vivus.prototype.getViewportH = function () {
38666  var client = this.docElem.clientHeight,
38667    inner = window.innerHeight;
38668
38669  if (client < inner) {
38670    return inner;
38671  }
38672  else {
38673    return client;
38674  }
38675};
38676
38677/**
38678 * Get the page Y offset
38679 *
38680 * @return {integer} Page Y offset
38681 */
38682Vivus.prototype.scrollY = function () {
38683  return window.pageYOffset || this.docElem.scrollTop;
38684};
38685
38686setupEnv = function () {
38687
38688  if (Vivus.prototype.docElem) {
38689    return;
38690  }
38691
38692  /**
38693   * Alias for document element
38694   *
38695   * @type {DOMelement}
38696   */
38697  Vivus.prototype.docElem = window.document.documentElement;
38698
38699  /**
38700   * Alias for `requestAnimationFrame` or
38701   * `setTimeout` function for deprecated browsers.
38702   *
38703   */
38704  requestAnimFrame = (function () {
38705    return (
38706      window.requestAnimationFrame       ||
38707      window.webkitRequestAnimationFrame ||
38708      window.mozRequestAnimationFrame    ||
38709      window.oRequestAnimationFrame      ||
38710      window.msRequestAnimationFrame     ||
38711      function(/* function */ callback){
38712        return window.setTimeout(callback, 1000 / 60);
38713      }
38714    );
38715  })();
38716
38717  /**
38718   * Alias for `cancelAnimationFrame` or
38719   * `cancelTimeout` function for deprecated browsers.
38720   *
38721   */
38722  cancelAnimFrame = (function () {
38723    return (
38724      window.cancelAnimationFrame       ||
38725      window.webkitCancelAnimationFrame ||
38726      window.mozCancelAnimationFrame    ||
38727      window.oCancelAnimationFrame      ||
38728      window.msCancelAnimationFrame     ||
38729      function(id){
38730        return window.clearTimeout(id);
38731      }
38732    );
38733  })();
38734};
38735
38736/**
38737 * Parse string to integer.
38738 * If the number is not positive or null
38739 * the method will return the default value
38740 * or 0 if undefined
38741 *
38742 * @param {string} value String to parse
38743 * @param {*}
38743 defaultValue Value to return if the result parsed is invalid
38744 * @return {number}
38745 *
38746 */
38747parsePositiveInt = function (value, defaultValue) {
38748  var output = parseInt(value, 10);
38749  return (output >= 0) ? output : defaultValue;
38750};
38751
38752
38753  if (typeof define === 'function' && define.amd) {
38754    // AMD. Register as an anonymous module.
38755    define([], function() {
38756      return Vivus;
38757    });
38758  } else if (typeof exports === 'object') {
38759    // Node. Does not work with strict CommonJS, but
38760    // only CommonJS-like environments that support module.exports,
38761    // like Node.
38762    module.exports = Vivus;
38763  } else {
38764    // Browser globals
38765    window.Vivus = Vivus;
38766  }
38767
38768}());

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.