PageSourceSearch

https://durangodiner.com/wp-content/themes/uncode/library/js/plugins.js?ver=1943821353

js durangodiner.com collected 2026-09-26 14:15:12 UTC 1,288,223 bytes, 38,774 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          title: 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_whatsapp = function() {
26935    return this.popup('https://api.whatsapp.com/send', {
26936      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
26937    });
26938  }
26939
26940  Share.prototype.network_email = function() {
26941    return this.popup('mailto:', {
26942      subject: this.config.networks.email.title,
26943      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
26944    });
26945  };
26946
26947  Share.prototype.inject_icons = function() {
26948  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
26949  };
26950
26951  Share.prototype.inject_fonts = function() {
26952   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
26953  };
26954
26955  Share.prototype.inject_stylesheet = function(url) {
26956    var link;
26957    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
26958      link = document.createElement("link");
26959      link.setAttribute("rel", "stylesheet");
26960      link.setAttribute("href", url);
26961      return this.el.head.appendChild(link);
26962    }
26963  };
26964
26965  Share.prototype.inject_css = function(instance) {
26966    var css, meta, selector, style;
26967    selector = "." + (instance.getAttribute('class').split(" ").join("."));
26968    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
26969      this.config.selector = selector;
26970      css = getStyles(this.config);
26971      style = document.createElement("style");
26972      style.type = "text/css";
26973      if (style.styleSheet) {
26974        style.styleSheet.cssText = css;
26975      } else {
26976        style.appendChild(document.createTextNode(css));
26977      }
26978      this.el.head.appendChild(style);
26979      delete this.config.selector;
26980      meta = document.createElement("meta");
26981      meta.setAttribute("name", "sharer" + selector);
26982      return this.el.head.appendChild(meta);
26983    }
26984  };
26985
26986  Share.prototype.inject_html = function(instance) {
26987    //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>";
26988    return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-whatsapp' data-network='whatsapp' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>";
26989  };
26990
26991  Share.prototype.inject_facebook_sdk = function() {
26992    var fb_root, script;
26993    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
26994      script = document.createElement("script");
26995      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')";
26996      fb_root = document.createElement("div");
26997      fb_root.id = "fb-root";
26998      this.el.body.appendChild(fb_root);
26999      return this.el.body.appendChild(script);
27000    }
27001  };
27002
27003  Share.prototype.hook = function(type, network, instance) {
27004    var fn, opts;
27005    fn = this.config.networks[network][type];
27006    if (typeof fn === "function") {
27007      opts = fn.call(this.config.networks[network], instance);
27008      if (opts !== void 0) {
27009        opts = this.normalize_filter_config_updates(opts);
27010        this.extend(this.config.networks[network], opts, true);
27011        this.normalize_network_configuration();
27012      }
27013    }
27014  };
27015
27016  Share.prototype.default_title = function() {
27017    var content;
27018    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27019      return encodeURIComponent(content.getAttribute('content'));
27020    } else if (content = document.querySelector('title')) {
27021      return encodeURIComponent(content.innerText);
27022    }
27023  };
27024
27025  Share.prototype.default_image = function() {
27026    var content;
27027    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27028      return content.getAttribute('content');
27029    }
27030  };
27031
27032  Share.prototype.default_description = function() {
27033    var content;
27034    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27035      return encodeURIComponent(content.getAttribute('content'));
27036    } else {
27037      return '';
27038    }
27039  };
27040
27041  Share.prototype.set_global_configuration = function() {
27042    var display, network, option, options, _ref, _results;
27043    _ref = this.config.networks;
27044    _results = [];
27045    for (network in _ref) {
27046      options = _ref[network];
27047      for (option in options) {
27048        if (this.config.networks[network][option] == null) {
27049          this.config.networks[network][option] = this.config[option];
27050        }
27051      }
27052      if (this.config.networks[network].enabled) {
27053        display = 'block';
27054        this.config.enabled_networks += 1;
27055      } else {
27056        display = 'none';
27057      }
27058      _results.push(this.config.networks[network].display = display);
27059    }
27060    return _results;
27061  };
27062
27063  Share.prototype.normalize_network_configuration = function() {
27064    if (!this.config.networks.facebook.app_id) {
27065      this.config.networks.facebook.load_sdk = false;
27066    }
27067    if (!this.is_encoded(this.config.networks.twitter.description)) {
27068      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
27069    }
27070    if (typeof this.config.networks.facebook.app_id === 'number') {
27071      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
27072    }
27073  };
27074
27075  Share.prototype.normalize_filter_config_updates = function(opts) {
27076    if (this.config.networks.facebook.app_id !== opts.app_id) {
27077      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.");
27078      delete opts.app_id;
27079    }
27080    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
27081      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.");
27082      delete opts.app_id;
27083    }
27084    return opts;
27085  };
27086
27087  return Share;
27088
27089})(ShareUtils);
27090 return Share;
27091});
27092
27093// Generated by CoffeeScript 1.9.2
27094
27095// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
27096
27097(function() {
27098  var $, win;
27099
27100  $ = this.jQuery || window.jQuery;
27101
27102  win = $(window);
27103
27104  $.fn.stick_in_parent = function(opts) {
27105    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
27106    if (opts == null) {
27107      opts = {};
27108    }
27109    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;
27110    if (offset_top == null) {
27111      offset_top = 0;
27112    }
27113    if (parent_selector == null) {
27114      parent_selector = void 0;
27115    }
27116    if (inner_scrolling == null) {
27117      inner_scrolling = true;
27118    }
27119    if (sticky_class == null) {
27120      sticky_class = "is_stuck";
27121    }
27122    doc = $(document);
27123    if (enable_bottoming == null) {
27124      enable_bottoming = true;
27125    }
27126    outer_width = function(el) {
27127      var _el, computed, w;
27128      if (window.getComputedStyle) {
27129        _el = el[0];
27130        computed = window.getComputedStyle(el[0]);
27131        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
27132        if (computed.getPropertyValue("box-sizing") !== "border-box") {
27133          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
27134        }
27135        return w;
27136      } else {
27137        return el.outerWidth(true);
27138      }
27139    };
27140    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
27141      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
27142      if (elm.data("sticky_kit")) {
27143        return;
27144      }
27145      elm.data("sticky_kit", true);
27146      last_scroll_height = doc.height();
27147      parent = elm.parent();
27148      if (parent_selector != null) {
27149        parent = parent.closest(parent_selector);
27150      }
27151      if (!parent.length) {
27152        throw "failed to find stick parent";
27153      }
27154      fixed = false;
27155      bottomed = false;
27156      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
27157      if (spacer) {
27158        spacer.css('position', elm.css('position'));
27159      }
27160      recalc = function() {
27161        var border_top, padding_top, restore;
27162        if (detached) {
27163          return;
27164        }
27165        last_scroll_height = doc.height();
27166        border_top = parseInt(parent.css("border-top-width"), 10);
27167        padding_top = parseInt(parent.css("padding-top"), 10);
27168        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
27169        parent_top = parent.offset().top + border_top + padding_top;
27170        parent_height = parent.height();
27171        if (fixed) {
27172          fixed = false;
vendor: 6,068 bytes, lines 27173-27367
27173          bottomed = false;
27174          if (manual_spacer == null) {
27175            elm.insertAfter(spacer);
27176            spacer.detach();
27177          }
27178          elm.css({
27179            position: "",
27180            top: "",
27181            width: "",
27182            bottom: ""
27183          }).removeClass(sticky_class);
27184          restore = true;
27185        }
27186        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
27187        height = elm.outerHeight(true);
27188        el_float = elm.css("float");
27189        if (spacer) {
27190          spacer.css({
27191            width: outer_width(elm),
27192            height: height,
27193            display: elm.css("display"),
27194            "vertical-align": elm.css("vertical-align"),
27195            "float": el_float
27196          });
27197        }
27198        if (restore) {
27199          return tick();
27200        }
27201      };
27202      recalc();
27203      if (height === parent_height) {
27204        return;
27205      }
27206      last_pos = void 0;
27207      offset = offset_top;
27208      recalc_counter = recalc_every;
27209      tick = function() {
27210        var css, delta, recalced, scroll, will_bottom, win_height;
27211        if (detached) {
27212          return;
27213        }
27214        recalced = false;
27215        if (recalc_counter != null) {
27216          recalc_counter -= 1;
27217          if (recalc_counter <= 0) {
27218            recalc_counter = recalc_every;
27219            recalc();
27220            recalced = true;
27221          }
27222        }
27223        if (!recalced && doc.height() !== last_scroll_height) {
27224          recalc();
27225          recalced = true;
27226        }
27227        scroll = win.scrollTop();
27228        if (last_pos != null) {
27229          delta = scroll - last_pos;
27230        }
27231        last_pos = scroll;
27232        if (fixed) {
27233          if (enable_bottoming) {
27234            will_bottom = scroll + height + offset > parent_height + parent_top;
27235            if (bottomed && !will_bottom) {
27236              bottomed = false;
27237              elm.css({
27238                position: "fixed",
27239                bottom: "",
27240                top: offset
27241              }).trigger("sticky_kit:unbottom");
27242            }
27243          }
27244          if (scroll < top) {
27245            fixed = false;
27246            offset = offset_top;
27247            if (manual_spacer == null) {
27248              if (el_float === "left" || el_float === "right") {
27249                elm.insertAfter(spacer);
27250              }
27251              spacer.detach();
27252            }
27253            css = {
27254              position: "",
27255              width: "",
27256              top: ""
27257            };
27258            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
27259          }
27260          if (inner_scrolling) {
27261            win_height = win.height();
27262            if (height + offset_top > win_height) {
27263              if (!bottomed) {
27264                offset -= delta;
27265                offset = Math.max(win_height - height, offset);
27266                offset = Math.min(offset_top, offset);
27267                if (fixed) {
27268                  elm.css({
27269                    top: offset + "px"
27270                  });
27271                }
27272              }
27273            }
27274          }
27275        } else {
27276          if (scroll > top) {
27277            fixed = true;
27278            css = {
27279              position: "fixed",
27280              top: offset
27281            };
27282            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
27283            elm.css(css).addClass(sticky_class);
27284            if (manual_spacer == null) {
27285              elm.after(spacer);
27286              if (el_float === "left" || el_float === "right") {
27287                spacer.append(elm);
27288              }
27289            }
27290            elm.trigger("sticky_kit:stick");
27291          }
27292        }
27293        if (fixed && enable_bottoming) {
27294          if (will_bottom == null) {
27295            will_bottom = scroll + height + offset > parent_height + parent_top;
27296          }
27297          if (!bottomed && will_bottom) {
27298            bottomed = true;
27299            if (parent.css("position") === "static") {
27300              parent.css({
27301                position: "relative"
27302              });
27303            }
27304            return elm.css({
27305              position: "absolute",
27306              bottom: padding_bottom,
27307              top: "auto"
27308            }).trigger("sticky_kit:bottom");
27309          }
27310        }
27311      };
27312      recalc_and_tick = function() {
27313        recalc();
27314        return tick();
27315      };
27316      detach = function() {
27317        detached = true;
27318        win.off("touchmove", tick);
27319        win.off("scroll", tick);
27320        win.off("resize", recalc_and_tick);
27321        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
27322        elm.off("sticky_kit:detach", detach);
27323        elm.removeData("sticky_kit");
27324        elm.css({
27325          position: "",
27326          bottom: "",
27327          top: "",
27328          width: ""
27329        });
27330        parent.position("position", "");
27331        if (fixed) {
27332          if (manual_spacer == null) {
27333            if (el_float === "left" || el_float === "right") {
27334              elm.insertAfter(spacer);
27335            }
27336            spacer.remove();
27337          }
27338          return elm.removeClass(sticky_class);
27339        }
27340      };
27341      win.on("touchmove", tick);
27342      win.on("scroll", tick);
27343      win.on("resize", recalc_and_tick);
27344      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
27345      elm.on("sticky_kit:detach", detach);
27346      return setTimeout(tick, 0);
27347    };
27348    for (i = 0, len = this.length; i < len; i++) {
27349      elm = this[i];
27350      fn($(elm));
27351    }
27352    return this;
27353  };
27354
27355}).call(this);
27356/* ==========================================================================
27357 * bootstrap-tab-history.js
27358 * Author: Michael Narayan <[email protected]>
27359 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
27360 * ==========================================================================
27361 * Licensed under the Apache License, Version 2.0 (the "License"); you may
27362 * not use this file except in compliance with the License. You may obtain a
27363 * copy of the License at
27364 *
27365 * http://www.apache.org/licenses/LICENSE-2.0
27366 *
27367 * Unless required by applicable law or agreed to in writing, softw
27367are
27368 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
27369 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
27370 * License for the specific language governing permissions and limitations
27371 * under the License.
27372 * ========================================================================== */
27373
27374/* ========================================================================== */
27375/* JSHint directives                                                          */
27376/*                                                                            */
27377/* global BootstrapTabHistory: true                                           */
27378/*                                                                            */
27379/* global document                                                            */
27380/* global jQuery                                                              */
27381/* global history                                                             */
27382/* global window                                                              */
27383/* ========================================================================== */
27384
27385/**
27386 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
27387 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
27388 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
27389 *
27390 * See the README for additional information.
27391 *
27392 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
27393 */
27394
27395BootstrapTabHistory = {
27396  options: {
27397    /**
27398     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
27399     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
27400     *
27401     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
27402     *
27403     * @public
27404     * @type {?number}
27405     */
27406    defaultAnchorYOffset: 0,
27407    /**
27408     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
27409     *
27410     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
27411     *
27412     * @public
27413     * @type {string}
27414     */
27415    defaultChanger: 'replace',
27416    /**
27417     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
27418     * `null` is passed as the third parameter to these calls.
27419     *
27420     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
27421     *
27422     * @public
27423     * @type {boolean}
27424     */
27425    defaultUpdateURL: false,
27426    /**
27427     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
27428     * load.
27429     *
27430     * @public
27431     * @type {boolean}
27432     */
27433    showTabsBasedOnAnchor: true
27434  }
27435};
27436
27437(function () {
27438  'use strict';
27439
27440  jQuery(function () {
27441    if(history && history.pushState && history.replaceState) {
27442      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27443
27444      if(bootstrapTabHistory) {
27445        showTabsBasedOnState(bootstrapTabHistory);
27446      } else {
27447        showTabsBasedOnAnchor();
27448      }
27449
27450      backfillHistoryState();
27451
27452      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
27453      jQuery(window).on('popstate', onPopState);
27454    } else {
27455      showTabsBasedOnAnchor();
27456    }
27457  });
27458
27459  /**
27460   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
27461   *
27462   * @type {boolean}
27463   */
27464  var showingTabsBasedOnState = false;
27465
27466  /**
27467   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
27468   * `history.back` handling when `data-tab-history-update-url` is true.
27469   */
27470  function backfillHistoryState() {
27471    var newState = null;
27472
27473    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
27474      var $activeTabElement = jQuery(this);
27475      var selector = getTabSelector($activeTabElement);
27476
27477      if(selector) {
27478        var tabGroup = getTabGroup($activeTabElement);
27479
27480        if(tabGroup) {
27481          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
27482        }
27483      }
27484    });
27485
27486    if(newState) {
27487      history.replaceState(newState, '', null);
27488    }
27489  }
27490
27491  /**
27492   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
27493   * said bootstrapTabHistory attribute.
27494   *
27495   * @param {?object} existingState
27496   * @param {!string} tabGroup
27497   * @param {!string} selector
27498   * @returns {!object}
27499   */
27500  function createNewHistoryState(existingState, tabGroup, selector) {
27501    // Clone history.state and ensure it has a bootstrapTabHistory entry.
27502    var newState = jQuery.extend(true, {}, existingState, {
27503      bootstrapTabHistory: {}
27504    });
27505
27506    newState.bootstrapTabHistory[tabGroup] = selector;
27507
27508    return newState;
27509  }
27510
27511  /**
27512   * @param {jQuery} $tab
27513   * @returns {?string}
27514   */
27515  function getTabGroup($tab) {
27516    return parseTruthyAttributeValue($tab.data('tab-history'));
27517  }
27518
27519  /**
27520   * @param {jQuery} $tab
27521   * @returns {?string}
27522   */
27523  function getTabSelector($tab) {
27524    return $tab.data('target') || $tab.attr('href');
27525  }
27526
27527  /**
27528   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
27529   *
27530   * @param {jQuery.Event} shownEvt
27531   */
27532  function onShownTab(shownEvt) {
27533    if(!showingTabsBasedOnState) {
27534      var $activatedTab = jQuery(shownEvt.target);
27535      if ( $activatedTab.hasClass('panel-collapse') )
27536        $activatedTab = $activatedTab.closest('.panel').find('a');
27537      var selector = getTabSelector($activatedTab);
27538
27539      if(selector) {
27540        var tabGroup = getTabGroup($activatedTab);
27541
27542        if(tabGroup) {
27543          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
27544          var newState = createNewHistoryState(history.state, tabGroup, selector);
27545          var updateURL = (function ($activatedTab) {
27546            if(selector[0] === '#') {
27547              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
27548
27549              if(elementUpdateURLOption === undefined) {
27550                return BootstrapTabHistory.options.defaultUpdateURL;
27551              } else {
27552                return elementUpdateURLOption;
27553              }
27554            } else {
27555              return false;
27556            }
27557          })($activatedTab);
27558
27559          switch(historyChanger) {
27560            case 'push':
27561              history.pushState(newState, '', updateURL ? selector : null);
27562              break;
27563            case 'replace':
27564              history.replaceState(newState, '', updateURL ? selector : null);
27565              break;
27566            default:
27567              throw new Error('Unknown tab-history-changer: ' + historyChanger);
27568          }
27569        }
27570      }
27571    }
27572  }
27573
27574  /**
27575   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
27576   */
27577  function onPopState() {
27578    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27579
27580    if(bootstrapTabHistory) {
27581      showTabsBasedOnState(bootstrapTabHistory);
27582    }
27583  }
27584
27585  /**
27586   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
27587   *
27588   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
27589   *
27590   * @param {*} value
27591   * @returns {*}
27592   */
27593  function parseTruthyAttributeValue(value) {
27594    if(value) {
27595      return value;
27596    } else if(value === '') {
27597      return true;
27598    } else {
27599      return value;
27600    }
27601  }
27602
27603  /**
27604   * Show tabs based upon the anchor component of `window.location`.
27605   */
27606  function showTabsBasedOnAnchor() {
27607    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
27608      var anchor = window.location && window.location.hash;
27609
27610      if(anchor) {
27611        var $tabElement = showTabForSelector(anchor);
27612
27613        if($tabElement && window.addEventListener && window.removeEventListener) {
27614          var anchorYOffset = (function ($tabElement) {
27615            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
27616
27617            if(elementSetting === undefined) {
27618              return BootstrapTabHistory.options.defaultAnchorYOffset;
27619            } else {
27620              return elementSetting;
27621            }
27622          })($tabElement);
27623
27624          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
27625          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
27626          //   `history.state` object should have been used (unless the browser did not support the modern History API).
27627          if(anchorYOffset || anchorYOffset === 0) {
27628            var scrollListener = function resetAnchorScroll () {
27629              window.removeEventListener('scroll', scrollListener);
27630              window.scrollTo(0, anchorYOffset);
27631            };
27632
27633            window.addEventListener('scroll', scrollListener);
27634          }
27635        }
27636      }
27637    }
27638  }
27639
27640  /**
27641   * Show a tab which corresponds to the provided selector.
27642   *
27643   * @param {string} selector - A CSS selector.
27644   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
27645   */
27646  function showTabForSelector(selector) {
27647    var $tabElement = (function (selector) {
27648      var $ret = null;
27649
27650      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
27651        var $potentialTab = jQuery(this);
27652
27653        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
27654          $ret = $potentialTab;
27655          return false;
vendor: 43,483 bytes, lines 27656-28872
27656        } else {
27657         return null;
27658        }
27659      });
27660
27661      return $ret;
27662    })(selector);
27663
27664    if($tabElement) {
27665      if ( !$tabElement.parent().hasClass('active') ) {
27666        $tabElement.trigger('click');
27667      }
27668      //$tabElement.tab('show');
27669    }
27670
27671    return $tabElement;
27672  }
27673
27674  /**
27675   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
27676   *
27677   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
27678   */
27679  function showTabsBasedOnState(bootstrapTabHistory) {
27680    showingTabsBasedOnState = true;
27681
27682    try {
27683      for(var k in bootstrapTabHistory) {
27684        if(bootstrapTabHistory.hasOwnProperty(k)) {
27685          showTabForSelector(bootstrapTabHistory[k]);
27686        }
27687      }
27688    } finally {
27689      showingTabsBasedOnState = false;
27690    }
27691  }
27692})();
27693
27694/*!
27695 * justifiedGallery - v3.8.1
27696 * http://miromannino.github.io/Justified-Gallery/
27697 * Copyright (c) 2020 Miro Mannino
27698 * Licensed under the MIT license.
27699 */
27700(function (factory) {
27701  if (typeof define === 'function' && define.amd) {
27702    // AMD. Register as an anonymous module.
27703    define(['jquery'], factory);
27704  } else if (typeof module === 'object' && module.exports) {
27705    // Node/CommonJS
27706    module.exports = function (root, jQuery) {
27707      if (jQuery === undefined) {
27708        // require('jQuery') returns a factory that requires window to
27709        // build a jQuery instance, we normalize how we use modules
27710        // that require this pattern but the window provided is a noop
27711        // if it's defined (how jquery works)
27712        if (typeof window !== 'undefined') {
27713          jQuery = require('jquery');
27714        }
27715        else {
27716          jQuery = require('jquery')(root);
27717        }
27718      }
27719      factory(jQuery);
27720      return jQuery;
27721    };
27722  } else {
27723    // Browser globals
27724    factory(jQuery);
27725  }
27726}(function ($) {
27727
27728  /**
27729   * Justified Gallery controller constructor
27730   *
27731   * @param $gallery the gallery to build
27732   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
27733   * @constructor
27734   */
27735  var JustifiedGallery = function ($gallery, settings) {
27736
27737    this.settings = settings;
27738    this.checkSettings();
27739
27740    this.imgAnalyzerTimeout = null;
27741    this.entries = null;
27742    this.buildingRow = {
27743      entriesBuff: [],
27744      width: 0,
27745      height: 0,
27746      aspectRatio: 0
27747    };
27748    this.lastFetchedEntry = null;
27749    this.lastAnalyzedIndex = -1;
27750    this.yield = {
27751      every: 2, // do a flush every n flushes (must be greater than 1)
27752      flushed: 0 // flushed rows without a yield
27753    };
27754    this.border = settings.border >= 0 ? settings.border : settings.margins;
27755    this.maxRowHeight = this.retrieveMaxRowHeight();
27756    this.suffixRanges = this.retrieveSuffixRanges();
27757    this.offY = this.border;
27758    this.rows = 0;
27759    this.spinner = {
27760      phase: 0,
27761      timeSlot: 150,
27762      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
27763      intervalId: null
27764    };
27765    this.scrollBarOn = false;
27766    this.checkWidthIntervalId = null;
27767    this.galleryWidth = $gallery.width();
27768    this.$gallery = $gallery;
27769
27770  };
27771
27772  /** @returns {String} the best suffix given the width and the height */
27773  JustifiedGallery.prototype.getSuffix = function (width, height) {
27774    var longestSide, i;
27775    longestSide = (width > height) ? width : height;
27776    for (i = 0; i < this.suffixRanges.length; i++) {
27777      if (longestSide <= this.suffixRanges[i]) {
27778        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27779      }
27780    }
27781    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27782  };
27783
27784  /**
27785   * Remove the suffix from the string
27786   *
27787   * @returns {string} a new string without the suffix
27788   */
27789  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27790    return str.substring(0, str.length - suffix.length);
27791  };
27792
27793  /**
27794   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27795   */
27796  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27797    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27798  };
27799
27800  /**
27801   * Get the used suffix of a particular url
27802   *
27803   * @param str
27804   * @returns {String} return the used suffix
27805   */
27806  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27807    for (var si in this.settings.sizeRangeSuffixes) {
27808      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27809        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27810        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27811      }
27812    }
27813    return '';
27814  };
27815
27816  /**
27817   * Given an image src, with the width and the height, returns the new image src with the
27818   * best suffix to show the best quality thumbnail.
27819   *
27820   * @returns {String} the suffix to use
27821   */
27822  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27823    var newImageSrc;
27824
27825    if (this.settings.thumbnailPath) {
27826      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27827    } else {
27828      var matchRes = imageSrc.match(this.settings.extension);
27829      var ext = (matchRes !== null) ? matchRes[0] : '';
27830      newImageSrc = imageSrc.replace(this.settings.extension, '');
27831      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27832      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27833    }
27834
27835    return newImageSrc;
27836  };
27837
27838  /**
27839   * Shows the images that is in the given entry
27840   *
27841   * @param $entry the entry
27842   * @param callback the callback that is called when the show animation is finished
27843   */
27844  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27845    if (this.settings.cssAnimation) {
27846      $entry.addClass('jg-entry-visible');
27847      if (callback) callback();
27848    } else {
27849      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27850      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27851    }
27852  };
27853
27854  /**
27855   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27856   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27857   *
27858   * @param $image the image to analyze
27859   * @returns {String} the extracted src
27860   */
27861  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27862    var imageSrc = $image.data('safe-src');
27863    var imageSrcLoc = 'data-safe-src';
27864    // Begin Uncode edit
27865    if (typeof imageSrc === 'undefined') {
27866    	var imageCurrentSrc = $image[0].currentSrc;
27867    	if (imageCurrentSrc) {
27868    		imageSrc = imageCurrentSrc;
27869    	} else {
27870    		imageSrc = $image.attr('src');
27871    	}
27872		imageSrcLoc = 'src';
27873    }
27874    // End Uncode edit
27875    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27876    $image.data('jg.src', imageSrc); // this will change overtime
27877    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27878    return imageSrc;
27879  };
27880
27881  /** @returns {jQuery} the image in the given entry */
27882  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27883    var $img = $entry.find(this.settings.imgSelector);
27884    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27885    return $img.length === 0 ? null : $img;
27886  };
27887
27888  /** @returns {jQuery} the caption in the given entry */
27889  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27890    var $caption = $entry.find('> .jg-caption');
27891    return $caption.length === 0 ? null : $caption;
27892  };
27893
27894  /**
27895   * Display the entry
27896   *
27897   * @param {jQuery} $entry the entry to display
27898   * @param {int} x the x position where the entry must be positioned
27899   * @param y the y position where the entry must be positioned
27900   * @param imgWidth the image width
27901   * @param imgHeight the image height
27902   * @param rowHeight the row height of the row that owns the entry
27903   */
27904  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27905    $entry.width(imgWidth);
27906    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27907    $entry.css('top', Math.floor(y));//hacked by Uncode
27908    $entry.css('left', x);
27909
27910    var $image = this.imgFromEntry($entry);
27911    if ($image !== null) {
27912      $image.css('width', imgWidth);
27913      $image.css('height', imgHeight);
27914      $image.css('margin-left', - imgWidth / 2);
27915      $image.css('margin-top', - imgHeight / 2);
27916
27917      // Image reloading for an high quality of thumbnails
27918      var imageSrc = $image.data('jg.src');
27919      if (imageSrc) {
27920        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27921
27922        $image.one('error', function () {
27923           this.resetImgSrc($image); //revert to the original thumbnail
27924        });
27925
27926        var loadNewImage = function () {
27927          // if (imageSrc !== newImageSrc) {
27928            $image.attr('src', imageSrc);
27929          // }
27930        };
27931
27932        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27933          this.onImageEvent(imageSrc, (function() {
27934            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27935            $entry.data('jg.loaded', true);
27936          }).bind(this));
27937        } else {
27938          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27939        }
27940
27941      }
27942
27943    } else {
27944      this.showImg($entry);
27945    }
27946
27947    this.displayEntryCaption($entry);
27948  };
27949
27950  /**
27951   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
27952   * or the 'title' attributes.
27953   *
27954   * @param {jQuery} $entry the entry to process
27955   */
27956  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
27957    var $image = this.imgFromEntry($entry);
27958    if ($image !== null && this.settings.captions) {
27959      var $imgCaption = this.captionFromEntry($entry);
27960
27961      // Create it if it doesn't exists
27962      if ($imgCaption === null) {
27963        var caption = $image.attr('alt');
27964        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
27965        if (this.isValidCaption(caption)) { // Create only we found something
27966          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
27967          $entry.append($imgCaption);
27968          $entry.data('jg.createdCaption', true);
27969        }
27970      }
27971
27972      // Create events (we check again the $imgCaption because it can be still inexistent)
27973      if ($imgCaption !== null) {
27974        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
27975        this.addCaptionEventsHandlers($entry);
27976      }
27977    } else {
27978      this.removeCaptionEventsHandlers($entry);
27979    }
27980  };
27981
27982  /**
27983   * Validates the caption
27984   *
27985   * @param caption The caption that should be validated
27986   * @return {boolean} Validation result
27987   */
27988  JustifiedGallery.prototype.isValidCaption = function (caption) {
27989    return (typeof caption !== 'undefined' && caption.length > 0);
27990  };
27991
27992  /**
27993   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
27994   * It shows the caption using jQuery (or using CSS if it is configured so)
27995   *
27996   * @param {Event} eventObject the event object
27997   */
27998  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
27999    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28000    if (this.settings.cssAnimation) {
28001      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28002    } else {
28003      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28004        this.settings.captionSettings.visibleOpacity);
28005    }
28006  };
28007
28008  /**
28009   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28010   * It hides the caption using jQuery (or using CSS if it is configured so)
28011   *
28012   * @param {Event} eventObject the event object
28013   */
28014  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28015    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28016    if (this.settings.cssAnimation) {
28017      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28018    } else {
28019      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28020        this.settings.captionSettings.nonVisibleOpacity);
28021    }
28022  };
28023
28024  /**
28025   * Add the handlers of the entry for the caption
28026   *
28027   * @param $entry the entry to modify
28028   */
28029  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28030    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28031    if (typeof captionMouseEvents === 'undefined') {
28032      captionMouseEvents = {
28033        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28034        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28035      };
28036      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28037      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28038      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28039    }
28040  };
28041
28042  /**
28043   * Remove the handlers of the entry for the caption
28044   *
28045   * @param $entry the entry to modify
28046   */
28047  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28048    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28049    if (typeof captionMouseEvents !== 'undefined') {
28050      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28051      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28052      $entry.removeData('jg.captionMouseEvents');
28053    }
28054  };
28055
28056  /**
28057   * Clear the building row data to be used for a new row
28058   */
28059  JustifiedGallery.prototype.clearBuildingRow = function () {
28060    this.buildingRow.entriesBuff = [];
28061    this.buildingRow.aspectRatio = 0;
28062    this.buildingRow.width = 0;
28063  };
28064
28065  /**
28066   * Justify the building row, preparing it to
28067   *
28068   * @param isLastRow
28069   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28070   * @returns a boolean to know if the row has been justified or not
28071   */
28072  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
28073    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
28074    var minHeight = 0;
28075    var availableWidth = this.galleryWidth - 2 * this.border - (
28076      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28077    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
28078    var defaultRowHeight = this.settings.rowHeight;
28079    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
28080
28081    //Skip the last row if we can't justify it and the lastRow == 'hide'
28082    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
28083      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28084        $entry = this.buildingRow.entriesBuff[i];
28085        if (this.settings.cssAnimation)
28086          $entry.removeClass('jg-entry-visible');
28087        else {
28088          $entry.stop().fadeTo(0, 0.1);
28089          $entry.find('> img, > a > img').fadeTo(0, 0);
28090        }
28091      }
28092      return -1;
28093    }
28094
28095    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
28096    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
28097      justify = false;
28098
28099      if (this.rows > 0) {
28100        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
28101        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
28102      }
28103    }
28104
28105    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28106      $entry = this.buildingRow.entriesBuff[i];
28107      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28108
28109      if (justify) {
28110        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
28111        newImgH = rowHeight;
28112      } else {
28113        newImgW = defaultRowHeight * imgAspectRatio;
28114        newImgH = defaultRowHeight;
28115      }
28116
28117      availableWidth -= Math.round(newImgW);
28118      $entry.data('jg.jwidth', Math.round(newImgW));
28119      $entry.data('jg.jheight', Math.ceil(newImgH));
28120      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
28121    }
28122
28123    this.buildingRow.height = minHeight;
28124    return justify;
28125  };
28126
28127  /**
28128   * Flush a row: justify it, modify the gallery height accordingly to the row height
28129   *
28130   * @param isLastRow
28131   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28132   */
28133  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
28134    var settings = this.settings;
28135    var $entry, buildingRowRes, offX = this.border, i;
28136
28137    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
28138    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
28139      this.clearBuildingRow();
28140      return;
28141    }
28142
28143    if (this.maxRowHeight) {
28144      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
28145    }
28146
28147    //Align last (unjustified) row
28148    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
28149      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
28150
28151      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28152        $entry = this.buildingRow.entriesBuff[i];
28153        availableWidth -= $entry.data('jg.jwidth');
28154      }
28155
28156      if (settings.lastRow === 'center')
28157        offX += Math.round(availableWidth / 2);
28158      else if (settings.lastRow === 'right')
28159        offX += availableWidth;
28160    }
28161
28162    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
28163    for (i = 0; i <= lastEntryIdx; i++) {
28164      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
28165      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
28166      offX += $entry.data('jg.jwidth') + settings.margins;
28167    }
28168
28169    //Gallery Height
28170    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
28171    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
28172
28173    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
28174      //Ready for a new row
28175      this.offY += this.buildingRow.height + settings.margins;
28176      this.rows += 1;
28177      this.clearBuildingRow();
28178      this.settings.triggerEvent.call(this, 'jg.rowflush');
28179    }
28180  };
28181
28182
28183  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
28184  var galleryPrevStaticHeight = 0;
28185
28186  JustifiedGallery.prototype.rememberGalleryHeight = function () {
28187    galleryPrevStaticHeight = this.$gallery.height();
28188    this.$gallery.height(galleryPrevStaticHeight);
28189  };
28190
28191  // grow only
28192  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
28193    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
28194    this.$gallery.height(galleryPrevStaticHeight);
28195  };
28196
28197  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
28198    galleryPrevStaticHeight = height;
28199    this.$gallery.height(height);
28200  };
28201
28202  /**
28203   * Checks the width of the gallery container, to know if a new justification is needed
28204   */
28205  JustifiedGallery.prototype.checkWidth = function () {
28206    this.checkWidthIntervalId = setInterval($.proxy(function () {
28207
28208      // if the gallery is not currently visible, abort.
28209      if (!this.$gallery.is(":visible")) return;
28210
28211      var galleryWidth = parseFloat(this.$gallery.width());
28212      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
28213        this.galleryWidth = galleryWidth;
28214        this.rewind();
28215
28216        this.rememberGalleryHeight();
28217
28218        // Restart to analyze
28219        this.startImgAnalyzer(true);
28220      }
28221    }, this), this.settings.refreshTime);
28222  };
28223
28224  /**
28225   * @returns {boolean} a boolean saying if the spinner is active or not
28226   */
28227  JustifiedGallery.prototype.isSpinnerActive = function () {
28228    return this.spinner.intervalId !== null;
28229  };
28230
28231  /**
28232   * @returns {int} the spinner height
28233   */
28234  JustifiedGallery.prototype.getSpinnerHeight = function () {
28235    return this.spinner.$el.innerHeight();
28236  };
28237
28238  /**
28239   * Stops the spinner animation and modify the gallery height to exclude the spinner
28240   */
28241  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
28242    clearInterval(this.spinner.intervalId);
28243    this.spinner.intervalId = null;
28244    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
28245    this.spinner.$el.detach();
28246  };
28247
28248  /**
28249   * Starts the spinner animation
28250   */
28251  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
28252    var spinnerContext = this.spinner;
28253    var $spinnerPoints = spinnerContext.$el.find('span');
28254    clearInterval(spinnerContext.intervalId);
28255    this.$gallery.append(spinnerContext.$el);
28256    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
28257    spinnerContext.intervalId = setInterval(function () {
28258      if (spinnerContext.phase < $spinnerPoints.length) {
28259        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
28260      } else {
28261        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
28262      }
28263      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
28264    }, spinnerContext.timeSlot);
28265  };
28266
28267  /**
28268   * Rewind the image analysis to start from the first entry.
28269   */
28270  JustifiedGallery.prototype.rewind = function () {
28271    this.lastFetchedEntry = null;
28272    this.lastAnalyzedIndex = -1;
28273    this.offY = this.border;
28274    this.rows = 0;
28275    this.clearBuildingRow();
28276  };
28277
28278  /**
28279   * @returns {String} `settings.selector` rejecting spinner element
28280   */
28281  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
28282    return this.settings.selector + ', div:not(.jg-spinner)';
28283  };
28284
28285  /**
28286   * @returns {Array} all entries matched by `settings.selector`
28287   */
28288  JustifiedGallery.prototype.getAllEntries = function () {
28289    var selector = this.getSelectorWithoutSpinner();
28290    return this.$gallery.children(selector).toArray();
28291  };
28292
28293  /**
28294   * Update the entries searching it from the justified gallery HTML element
28295   *
28296   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
28297   * @returns {boolean} true if some entries has been founded
28298   */
28299  JustifiedGallery.prototype.updateEntries = function (norewind) {
28300    var newEntries;
28301
28302    if (norewind && this.lastFetchedEntry != null) {
28303      var selector = this.getSelectorWithoutSpinner();
28304      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
28305    } else {
28306      this.entries = [];
28307      newEntries = this.getAllEntries();
28308    }
28309
28310    if (newEntries.length > 0) {
28311
28312      // Sort or randomize
28313      if ($.isFunction(this.settings.sort)) {
28314        newEntries = this.sortArray(newEntries);
28315      } else if (this.settings.randomize) {
28316        newEntries = this.shuffleArray(newEntries);
28317      }
28318      this.lastFetchedEntry = newEntries[newEntries.length - 1];
28319
28320      // Filter
28321      if (this.settings.filter) {
28322        newEntries = this.filterArray(newEntries);
28323      } else {
28324        this.resetFilters(newEntries);
28325      }
28326
28327    }
28328
28329    this.entries = this.entries.concat(newEntries);
28330    return true;
28331  };
28332
28333  /**
28334   * Apply the entries order to the DOM, iterating the entries and appending the images
28335   *
28336   * @param entries the entries that has been modified and that must be re-ordered in the DOM
28337   */
28338  JustifiedGallery.prototype.insertToGallery = function (entries) {
28339    var that = this;
28340    $.each(entries, function () {
28341      $(this).appendTo(that.$gallery);
28342    });
28343  };
28344
28345  /**
28346   * Shuffle the array using the Fisher-Yates shuffle algorithm
28347   *
28348   * @param a the array to shuffle
28349   * @return the shuffled array
28350   */
28351  JustifiedGallery.prototype.shuffleArray = function (a) {
28352    var i, j, temp;
28353    for (i = a.length - 1; i > 0; i--) {
28354      j = Math.floor(Math.random() * (i + 1));
28355      temp = a[i];
28356      a[i] = a[j];
28357      a[j] = temp;
28358    }
28359    this.insertToGallery(a);
28360    return a;
28361  };
28362
28363  /**
28364   * Sort the array using settings.comparator as comparator
28365   *
28366   * @param a the array to sort (it is sorted)
28367   * @return the sorted array
28368   */
28369  JustifiedGallery.prototype.sortArray = function (a) {
28370    a.sort(this.settings.sort);
28371    this.insertToGallery(a);
28372    return a;
28373  };
28374
28375  /**
28376   * Reset the filters removing the 'jg-filtered' class from all the entries
28377   *
28378   * @param a the array to reset
28379   */
28380  JustifiedGallery.prototype.resetFilters = function (a) {
28381    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
28382  };
28383
28384  /**
28385   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
28386   *
28387   * @param a the array to filter
28388   * @return the filtered array
28389   */
28390  JustifiedGallery.prototype.filterArray = function (a) {
28391    var settings = this.settings;
28392    if ($.type(settings.filter) === 'string') {
28393      // Filter only keeping the entries passed in the string
28394      return a.filter(function (el) {
28395        var $el = $(el);
28396        if ($el.is(settings.filter)) {
28397          $el.removeClass('jg-filtered');
28398          return true;
28399        } else {
28400          $el.addClass('jg-filtered').removeClass('jg-visible');
28401          return false;
28402        }
28403      });
28404    } else if ($.isFunction(settings.filter)) {
28405      // Filter using the passed function
28406      var filteredArr = a.filter(settings.filter);
28407      for (var i = 0; i < a.length; i++) {
28408        if (filteredArr.indexOf(a[i]) === -1) {
28409          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
28410        } else {
28411          $(a[i]).removeClass('jg-filtered');
28412        }
28413      }
28414      return filteredArr;
28415    }
28416  };
28417
28418  /**
28419   * Revert the image src to the default value.
28420   */
28421  JustifiedGallery.prototype.resetImgSrc = function ($img) {
28422    if ($img.data('jg.originalSrcLoc') === 'src') {
28423      $img.attr('src', $img.data('jg.originalSrc'));
28424    } else {
28425      $img.attr('src', '');
28426    }
28427  };
28428
28429  /**
28430   * Destroy the Justified Gallery instance.
28431   *
28432   * It clears all the css properties added in the style attributes. We doesn't backup the original
28433   * values for those css attributes, because it costs (performance) and because in general one
28434   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
28435   * classes). Creating a backup is also difficult because JG could be called multiple times and
28436   * with different style attributes.
28437   */
28438  JustifiedGallery.prototype.destroy = function () {
28439    clearInterval(this.checkWidthIntervalId);
28440    this.stopImgAnalyzerStarter();
28441
28442    // Get fresh entries list since filtered entries are absent in `this.entries`
28443    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
28444      var $entry = $(entry);
28445
28446      // Reset entry style
28447      $entry.css('width', '');
28448      $entry.css('height', '');
28449      $entry.css('top', '');
28450      $entry.css('left', '');
28451      $entry.data('jg.loaded', undefined);
28452      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
28453
28454      // Reset image style
28455      var $img = this.imgFromEntry($entry);
28456      if ($img) {
28457        $img.css('width', '');
28458        $img.css('height', '');
28459        $img.css('margin-left', '');
28460        $img.css('margin-top', '');
28461        this.resetImgSrc($img);
28462        $img.data('jg.originalSrc', undefined);
28463        $img.data('jg.originalSrcLoc', undefined);
28464        $img.data('jg.src', undefined);
28465      }
28466
28467      // Remove caption
28468      this.removeCaptionEventsHandlers($entry);
28469      var $caption = this.captionFromEntry($entry);
28470      if ($entry.data('jg.createdCaption')) {
28471        // remove also the caption element (if created by jg)
28472        $entry.data('jg.createdCaption', undefined);
28473        if ($caption !== null) $caption.remove();
28474      } else {
28475        if ($caption !== null) $caption.fadeTo(0, 1);
28476      }
28477
28478    }, this));
28479
28480    this.$gallery.css('height', '');
28481    this.$gallery.removeClass('justified-gallery');
28482    this.$gallery.data('jg.controller', undefined);
28483    this.settings.triggerEvent.call(this, 'jg.destroy');
28484  };
28485
28486  /**
28487   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
28488   *
28489   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
28490   */
28491  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
28492    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
28493      var $entry = $(this.entries[i]);
28494      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
28495        var availableWidth = this.galleryWidth - 2 * this.border - (
28496          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28497        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28498
28499        this.buildingRow.entriesBuff.push($entry);
28500        this.buildingRow.aspectRatio += imgAspectRatio;
28501        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
28502        this.lastAnalyzedIndex = i;
28503
28504        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
28505          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28506
28507          if (++this.yield.flushed >= this.yield.every) {
28508            this.startImgAnalyzer(isForResize);
28509            return;
28510          }
28511        }
28512      } else if ($entry.data('jg.loaded') !== 'error') {
28513        return;
28514      }
28515    }
28516
28517    // Last row flush (the row is not full)
28518    if (this.buildingRow.entriesBuff.length > 0) {
28519      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28520    }
28521
28522    if (this.isSpinnerActive()) {
28523      this.stopLoadingSpinnerAnimation();
28524    }
28525
28526    /* Stop, if there is, the timeout to start the analyzeImages.
28527     This is because an image can be set loaded, and the timeout can be set,
28528     but this image can be analyzed yet.
28529     */
28530    this.stopImgAnalyzerStarter();
28531
28532    this.setGalleryFinalHeight(this.galleryHeightToSet);
28533
28534    //On complete callback
28535    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
28536  };
28537
28538  /**
28539   * Stops any ImgAnalyzer starter (that has an assigned timeout)
28540   */
28541  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
28542    this.yield.flushed = 0;
28543    if (this.imgAnalyzerTimeout !== null) {
28544      clearTimeout(this.imgAnalyzerTimeout);
28545      this.imgAnalyzerTimeout = null;
28546    }
28547  };
28548
28549  /**
28550   * Starts the image analyzer. It is not immediately called to let the browser to update the view
28551   *
28552   * @param isForResize specifies if the image analyzer must be called for resizing or not
28553   */
28554  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
28555    var that = this;
28556    this.stopImgAnalyzerStarter();
28557    this.imgAnalyzerTimeout = setTimeout(function () {
28558      that.analyzeImages(isForResize);
28559    }, 0.001); // we can't start it immediately due to a IE different behaviour
28560  };
28561
28562  /**
28563   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
28564   * because some browsers, with a 404 set complete = true.
28565   *
28566   * @param imageSrc the image src to load
28567   * @param onLoad callback that is called when the image has been loaded
28568   * @param onError callback that is called in case of an error
28569   */
28570  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
28571    if (!onLoad && !onError) return;
28572
28573    var memImage = new Image();
28574    var $memImage = $(memImage);
28575    if (onLoad) {
28576      $memImage.one('load', function () {
28577        $memImage.off('load error');
28578        onLoad(memImage);
28579      });
28580    }
28581    if (onError) {
28582      $memImage.one('error', function () {
28583        $memImage.off('load error');
28584        onError(memImage);
28585      });
28586    }
28587    memImage.src = imageSrc;
28588  };
28589
28590  /**
28591   * Init of Justified Gallery controlled
28592   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
28593   */
28594  JustifiedGallery.prototype.init = function () {
28595    var imagesToLoad = false, skippedImages = false, that = this;
28596    $.each(this.entries, function (index, entry) {
28597      var $entry = $(entry);
28598      var $image = that.imgFromEntry($entry);
28599
28600      $entry.addClass('jg-entry');
28601
28602      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
28603
28604        // Link Rel global overwrite
28605        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
28606
28607        // Link Target global overwrite
28608        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
28609
28610        if ($image !== null) {
28611
28612          // Image src
28613          var imageSrc = that.extractImgSrcFromImage($image);
28614
28615          /* If we have the height and the width, we don't wait that the image is loaded,
28616             but we start directly with the justification */
28617          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
28618            var width = parseFloat($image.attr('width'));
28619            var height = parseFloat($image.attr('height'));
28620            if ($image.prop('tagName') === 'svg') {
28621              width = parseFloat($image[0].getBBox().width);
28622              height = parseFloat($image[0].getBBox().height);
28623            }
28624            if (!isNaN(width) && !isNaN(height)) {
28625              $entry.data('jg.width', width);
28626              $entry.data('jg.height', height);
28627              $entry.data('jg.loaded', 'skipped');
28628              skippedImages = true;
28629              that.startImgAnalyzer(false);
28630              return true; // continue
28631            }
28632          }
28633
28634          $entry.data('jg.loaded', false);
28635          imagesToLoad = true;
28636
28637          // Spinner start
28638          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
28639
28640          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
28641            $entry.data('jg.width', loadImg.width);
28642            $entry.data('jg.height', loadImg.height);
28643            $entry.data('jg.loaded', true);
28644            that.startImgAnalyzer(false);
28645          }, function () { // image load error
28646            $entry.data('jg.loaded', 'error');
28647            that.startImgAnalyzer(false);
28648          });
28649
28650        } else {
28651          $entry.data('jg.loaded', true);
28652          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
28653          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
28654        }
28655
28656      }
28657
28658    });
28659
28660    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
28661    this.checkWidth();
28662  };
28663
28664  /**
28665   * Checks that it is a valid number. If a string is passed it is converted to a number
28666   *
28667   * @param settingContainer the object that contains the setting (to allow the conversion)
28668   * @param settingName the setting name
28669   */
28670  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
28671    if ($.type(settingContainer[settingName]) === 'string') {
28672      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
28673    }
28674
28675    if ($.type(settingContainer[settingName]) === 'number') {
28676      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
28677    } else {
28678      throw settingName + ' must be a number';
28679    }
28680  };
28681
28682  /**
28683   * Checks the sizeRangeSuffixes and, if necessary, converts
28684   * its keys from string (e.g. old settings with 'lt100') to int.
28685   */
28686  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
28687    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
28688      throw 'sizeRangeSuffixes must be defined and must be an object';
28689    }
28690
28691    var suffixRanges = [];
28692    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28693      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
28694    }
28695
28696    var newSizeRngSuffixes = { 0: '' };
28697    for (var i = 0; i < suffixRanges.length; i++) {
28698      if ($.type(suffixRanges[i]) === 'string') {
28699        try {
28700          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
28701          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28702        } catch (e) {
28703          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
28704        }
28705      } else {
28706        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28707      }
28708    }
28709
28710    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
28711  };
28712
28713  /**
28714   * check and convert the maxRowHeight setting
28715   * requires rowHeight to be already set
28716   * TODO: should be always called when only rowHeight is changed
28717   * @return number or null
28718   */
28719  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
28720    var newMaxRowHeight = null;
28721    var rowHeight = this.settings.rowHeight;
28722
28723    if ($.type(this.settings.maxRowHeight) === 'string') {
28724      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
28725        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
28726      } else {
28727        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
28728      }
28729    } else if ($.type(this.settings.maxRowHeight) === 'number') {
28730      newMaxRowHeight = this.settings.maxRowHeight;
28731    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
28732      return null;
28733    } else {
28734      throw 'maxRowHeight must be a number or a percentage';
28735    }
28736
28737    // check if the converted value is not a number
28738    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
28739
28740    // check values, maxRowHeight must be >= rowHeight
28741    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
28742
28743    return newMaxRowHeight;
28744  };
28745
28746  /**
28747   * Checks the settings
28748   */
28749  JustifiedGallery.prototype.checkSettings = function () {
28750    this.checkSizeRangesSuffixes();
28751
28752    this.checkOrConvertNumber(this.settings, 'rowHeight');
28753    this.checkOrConvertNumber(this.settings, 'margins');
28754    this.checkOrConvertNumber(this.settings, 'border');
28755    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
28756
28757    var lastRowModes = [
28758      'justify',
28759      'nojustify',
28760      'left',
28761      'center',
28762      'right',
28763      'hide'
28764    ];
28765    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
28766      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
28767    }
28768
28769    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28770    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28771      throw 'justifyThreshold must be in the interval [0,1]';
28772    }
28773    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28774      throw 'cssAnimation must be a boolean';
28775    }
28776
28777    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28778    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28779
28780    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28781    if (this.settings.captionSettings.visibleOpacity < 0 ||
28782      this.settings.captionSettings.visibleOpacity > 1) {
28783      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28784    }
28785
28786    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28787    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28788      this.settings.captionSettings.nonVisibleOpacity > 1) {
28789      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28790    }
28791
28792    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28793    this.checkOrConvertNumber(this.settings, 'refreshTime');
28794    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28795    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28796    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28797
28798    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28799      throw 'sort must be false or a comparison function';
28800    }
28801
28802    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28803      $.type(this.settings.filter) !== 'string') {
28804      throw 'filter must be false, a string or a filter function';
28805    }
28806  };
28807
28808  /**
28809   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28810   * @returns {Array} sorted suffix ranges
28811   */
28812  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28813    var suffixRanges = [];
28814    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28815      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28816    }
28817    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28818    return suffixRanges;
28819  };
28820
28821  /**
28822   * Update the existing settings only changing some of them
28823   *
28824   * @param newSettings the new settings (or a subgroup of them)
28825   */
28826  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28827    // In this case Justified Gallery has been called again changing only some options
28828    this.settings = $.extend({}, this.settings, newSettings);
28829    this.checkSettings();
28830
28831    // As reported in the settings: negative value = same as margins, 0 = disabled
28832    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28833
28834    this.maxRowHeight = this.retrieveMaxRowHeight();
28835    this.suffixRanges = this.retrieveSuffixRanges();
28836  };
28837
28838  JustifiedGallery.prototype.defaults = {
28839    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28840        {
28841          100: '_t',  // used when longest is less than 100px
28842          240: '_m',  // used when longest is between 101px and 240px
28843          320: '_n',  // ...
28844          500: '',
28845          640: '_z',
28846          1024: '_b'  // used as else case because it is the last
28847        }
28848    */
28849    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28850    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28851    current path, width and height */
28852    rowHeight: 120, // required? required to be > 0?
28853    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28854    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28855    // can't exceed 3 * rowHeight)
28856    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28857    margins: 1,
28858    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28859
28860    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28861
28862    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28863                             * (i.e. lastRow setting is not considered) */
28864    waitThumbnailsLoad: true,
28865    captions: true,
28866    cssAnimation: true,
28867    imagesAnimationDuration: 500, // ignored with css animations
28868    captionSettings: { // ignored with css animations
28869      animationDuration: 500,
28870      visibleOpacity: 0.7,
28871      nonVisibleOpacity: 0.0
28872    },
28873    rel: null, // rewrite the rel of each analyzed links
28874    target: null, // rewrite the target of all links
28875    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28876    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28877    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28878    randomize: false,
28879    rtl: false, // right-to-left mode
28880    sort: false, /*
28881      - false: to do not sort
28882      - function: to sort them using the function as comparator (see Array.prototype.sort())
28883    */
28884    filter: false, /*
28885      - false, null or undefined: for a disabled filter
28886      - a string: an entry is kept if entry.is(filter string) returns true
28887                  see jQuery's .is() function for further information
28888      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28889                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28890    */
28891    selector: 'a', // The selector that is used to know what are the entries of the gallery
28892    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28893    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28894      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28895    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28896  };
28897
28898
28899  /**
28900   * Justified Gallery plugin for jQuery
28901   *
28902   * Events
28903   *  - jg.complete : called when all the gallery has been created
28904   *  - jg.resize : called when the gallery has been resized
28905   *  - jg.rowflush : when a new row appears
28906   *
28907   * @param arg the action (or the settings) passed when the plugin is called
28908   * @returns {*} the object itself
28909   */
28910  $.fn.justifiedGallery = function (arg) {
28911    return this.each(function (index, gallery) {
28912
28913      var $gallery = $(gallery);
28914      $gallery.addClass('justified-gallery');
28915
28916      var controller = $gallery.data('jg.controller');
28917      if (typeof controller === 'undefined') {
28918        // Create controller and assign it to the object data
28919        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28920          if (arg === 'destroy') return; // Just a call to an unexisting object
28921          throw 'The argument must be an object';
28922        }
28923        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28924        $gallery.data('jg.controller', controller);
28925      } else if (arg === 'norewind') {
28926        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28927        // ... left to be more readable
28928      } else if (arg === 'destroy') {
28929        controller.destroy();
28930        return;
28931      } else {
28932        // In this case Justified Gallery has been called again changing only some options
28933        controller.updateSettings(arg);
28934        controller.rewind();
28935      }
28936
28937      // Update the entries list
28938      if (!controller.updateEntries(arg === 'norewind')) return;
28939
28940      // Init justified gallery
28941      controller.init();
28942
28943    });
28944  };
28945
28946}));
28947
28948/*!
28949* Customized version of iScroll.js 0.0.1
28950* It fixes bugs affecting its integration with fullpage.js
28951*/
28952/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
28953(function (window, document, Math) {
28954var rAF = window.requestAnimationFrame  ||
28955    window.webkitRequestAnimationFrame  ||
28956    window.mozRequestAnimationFrame     ||
28957    window.oRequestAnimationFrame       ||
28958    window.msRequestAnimationFrame      ||
28959    function (callback) { window.setTimeout(callback, 1000 / 60); };
28960
28961var utils = (function () {
28962    var me = {};
28963
28964    var _elementStyle = document.createElement('div').style;
28965    var _vendor = (function () {
28966        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
28967            transform,
28968            i = 0,
28969            l = vendors.length;
28970
28971        for ( ; i < l; i++ ) {
28972            transform = vendors[i] + 'ransform';
28973            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
28974        }
28975
28976        return false;
vendor: 5,154 bytes, lines 28977-29129
28977    })();
28978
28979    function _prefixStyle (style) {
28980        if ( _vendor === false ) return false;
28981        if ( _vendor === '' ) return style;
28982        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
28983    }
28984
28985    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
28986
28987    me.extend = function (target, obj) {
28988        for ( var i in obj ) {
28989            target[i] = obj[i];
28990        }
28991    };
28992
28993    me.addEvent = function (el, type, fn, capture) {
28994        el.addEventListener(type, fn, !!capture);
28995    };
28996
28997    me.removeEvent = function (el, type, fn, capture) {
28998        el.removeEventListener(type, fn, !!capture);
28999    };
29000
29001    me.prefixPointerEvent = function (pointerEvent) {
29002        return window.MSPointerEvent ?
29003            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29004            pointerEvent;
29005    };
29006
29007    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29008        var distance = current - start,
29009            speed = Math.abs(distance) / time,
29010            destination,
29011            duration;
29012
29013        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29014
29015        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29016        duration = speed / deceleration;
29017
29018        if ( destination < lowerMargin ) {
29019            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29020            distance = Math.abs(destination - current);
29021            duration = distance / speed;
29022        } else if ( destination > 0 ) {
29023            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29024            distance = Math.abs(current) + destination;
29025            duration = distance / speed;
29026        }
29027
29028        return {
29029            destination: Math.round(destination),
29030            duration: duration
29031        };
29032    };
29033
29034    var _transform = _prefixStyle('transform');
29035
29036    me.extend(me, {
29037        hasTransform: _transform !== false,
29038        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29039        hasTouch: 'ontouchstart' in window,
29040        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29041        hasTransition: _prefixStyle('transition') in _elementStyle
29042    });
29043
29044    /*
29045    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29046    - galaxy S2 is ok
29047    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29048    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29049   - galaxy S3 is badAndroid (stock brower, webview)
29050     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29051   - galaxy S4 is badAndroid (stock brower, webview)
29052     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29053   - galaxy S5 is OK
29054     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29055   - galaxy S6 is OK
29056     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29057  */
29058    me.isBadAndroid = (function() {
29059        var appVersion = window.navigator.appVersion;
29060        // Android browser is not a chrome browser.
29061        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29062            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
29063            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
29064                return parseFloat(safariVersion[1]) < 535.19;
29065            } else {
29066                return true;
29067            }
29068        } else {
29069            return false;
29070        }
29071    })();
29072
29073    me.extend(me.style = {}, {
29074        transform: _transform,
29075        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
29076        transitionDuration: _prefixStyle('transitionDuration'),
29077        transitionDelay: _prefixStyle('transitionDelay'),
29078        transformOrigin: _prefixStyle('transformOrigin')
29079    });
29080
29081    me.hasClass = function (e, c) {
29082        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
29083        return re.test(e.className);
29084    };
29085
29086    me.addClass = function (e, c) {
29087        if ( me.hasClass(e, c) ) {
29088            return;
29089        }
29090
29091        var newclass = e.className.split(' ');
29092        newclass.push(c);
29093        e.className = newclass.join(' ');
29094    };
29095
29096    me.removeClass = function (e, c) {
29097        if ( !me.hasClass(e, c) ) {
29098            return;
29099        }
29100
29101        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
29102        e.className = e.className.replace(re, ' ');
29103    };
29104
29105    me.offset = function (el) {
29106        var left = -el.offsetLeft,
29107            top = -el.offsetTop;
29108
29109        // jshint -W084
29110        while (el = el.offsetParent) {
29111            left -= el.offsetLeft;
29112            top -= el.offsetTop;
29113        }
29114        // jshint +W084
29115
29116        return {
29117            left: left,
29118            top: top
29119        };
29120    };
29121
29122    me.preventDefaultException = function (el, exceptions) {
29123        for ( var i in exceptions ) {
29124            if ( exceptions[i].test(el[i]) ) {
29125                return true;
29126            }
29127        }
29128
29129        return false;
vendor: 5,660 bytes, lines 29130-29295
29130    };
29131
29132    me.extend(me.eventType = {}, {
29133        touchstart: 1,
29134        touchmove: 1,
29135        touchend: 1,
29136
29137        mousedown: 2,
29138        mousemove: 2,
29139        mouseup: 2,
29140
29141        pointerdown: 3,
29142        pointermove: 3,
29143        pointerup: 3,
29144
29145        MSPointerDown: 3,
29146        MSPointerMove: 3,
29147        MSPointerUp: 3
29148    });
29149
29150    me.extend(me.ease = {}, {
29151        quadratic: {
29152            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
29153            fn: function (k) {
29154                return k * ( 2 - k );
29155            }
29156        },
29157        circular: {
29158            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)
29159            fn: function (k) {
29160                return Math.sqrt( 1 - ( --k * k ) );
29161            }
29162        },
29163        back: {
29164            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
29165            fn: function (k) {
29166                var b = 4;
29167                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
29168            }
29169        },
29170        bounce: {
29171            style: '',
29172            fn: function (k) {
29173                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
29174                    return 7.5625 * k * k;
29175                } else if ( k < ( 2 / 2.75 ) ) {
29176                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
29177                } else if ( k < ( 2.5 / 2.75 ) ) {
29178                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
29179                } else {
29180                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
29181                }
29182            }
29183        },
29184        elastic: {
29185            style: '',
29186            fn: function (k) {
29187                var f = 0.22,
29188                    e = 0.4;
29189
29190                if ( k === 0 ) { return 0; }
29191                if ( k == 1 ) { return 1; }
29192
29193                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
29194            }
29195        }
29196    });
29197
29198    me.tap = function (e, eventName) {
29199        var ev = document.createEvent('Event');
29200        ev.initEvent(eventName, true, true);
29201        ev.pageX = e.pageX;
29202        ev.pageY = e.pageY;
29203        e.target.dispatchEvent(ev);
29204    };
29205
29206    me.click = function (e) {
29207        var target = e.target,
29208            ev;
29209
29210        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
29211            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
29212            // initMouseEvent is deprecated.
29213            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
29214            ev.initEvent('click', true, true);
29215            ev.view = e.view || window;
29216            ev.detail = 1;
29217            ev.screenX = target.screenX || 0;
29218            ev.screenY = target.screenY || 0;
29219            ev.clientX = target.clientX || 0;
29220            ev.clientY = target.clientY || 0;
29221            ev.ctrlKey = !!e.ctrlKey;
29222            ev.altKey = !!e.altKey;
29223            ev.shiftKey = !!e.shiftKey;
29224            ev.metaKey = !!e.metaKey;
29225            ev.button = 0;
29226            ev.relatedTarget = null;
29227            ev._constructed = true;
29228            target.dispatchEvent(ev);
29229        }
29230    };
29231
29232    return me;
29233})();
29234function IScroll (el, options) {
29235    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
29236    this.scroller = this.wrapper.children[0];
29237    this.scrollerStyle = this.scroller.style;       // cache style for better performance
29238
29239    this.options = {
29240
29241        resizeScrollbars: true,
29242
29243        mouseWheelSpeed: 20,
29244
29245        snapThreshold: 0.334,
29246
29247// INSERT POINT: OPTIONS
29248        disablePointer : !utils.hasPointer,
29249        disableTouch : utils.hasPointer || !utils.hasTouch,
29250        disableMouse : utils.hasPointer || utils.hasTouch,
29251        startX: 0,
29252        startY: 0,
29253        scrollY: true,
29254        directionLockThreshold: 5,
29255        momentum: true,
29256
29257        bounce: true,
29258        bounceTime: 600,
29259        bounceEasing: '',
29260
29261        preventDefault: true,
29262        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
29263
29264        HWCompositing: true,
29265        useTransition: true,
29266        useTransform: true,
29267        bindToWrapper: typeof window.onmousedown === "undefined"
29268    };
29269
29270    for ( var i in options ) {
29271        this.options[i] = options[i];
29272    }
29273
29274    // Normalize options
29275    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
29276
29277    this.options.useTransition = utils.hasTransition && this.options.useTransition;
29278    this.options.useTransform = utils.hasTransform && this.options.useTransform;
29279
29280    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
29281    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
29282
29283    // If you want eventPassthrough I have to lock one of the axes
29284    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
29285    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
29286
29287    // With eventPassthrough we also need lockDirection mechanism
29288    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
29289    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
29290
29291    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
29292
29293    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
29294
29295    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 29296-29467
29296        this.options.tap = 'tap';
29297    }
29298
29299    // https://github.com/cubiq/iscroll/issues/1029
29300    if (!this.options.useTransition && !this.options.useTransform) {
29301        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
29302            this.scrollerStyle.position = "relative";
29303        }
29304    }
29305
29306    if ( this.options.shrinkScrollbars == 'scale' ) {
29307        this.options.useTransition = false;
29308    }
29309
29310    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
29311
29312// INSERT POINT: NORMALIZATION
29313
29314    // Some defaults
29315    this.x = 0;
29316    this.y = 0;
29317    this.directionX = 0;
29318    this.directionY = 0;
29319    this._events = {};
29320
29321// INSERT POINT: DEFAULTS
29322
29323    this._init();
29324    this.refresh();
29325
29326    this.scrollTo(this.options.startX, this.options.startY);
29327    this.enable();
29328}
29329
29330IScroll.prototype = {
29331    version: '5.2.0',
29332
29333    _init: function () {
29334        this._initEvents();
29335
29336        if ( this.options.scrollbars || this.options.indicators ) {
29337            this._initIndicators();
29338        }
29339
29340        if ( this.options.mouseWheel ) {
29341            this._initWheel();
29342        }
29343
29344        if ( this.options.snap ) {
29345            this._initSnap();
29346        }
29347
29348        if ( this.options.keyBindings ) {
29349            this._initKeys();
29350        }
29351
29352// INSERT POINT: _init
29353
29354    },
29355
29356    destroy: function () {
29357        this._initEvents(true);
29358        clearTimeout(this.resizeTimeout);
29359        this.resizeTimeout = null;
29360        this._execEvent('destroy');
29361    },
29362
29363    _transitionEnd: function (e) {
29364        if ( e.target != this.scroller || !this.isInTransition ) {
29365            return;
29366        }
29367
29368        this._transitionTime();
29369        if ( !this.resetPosition(this.options.bounceTime) ) {
29370            this.isInTransition = false;
29371            this._execEvent('scrollEnd');
29372        }
29373    },
29374
29375    _start: function (e) {
29376        // React to left mouse button only
29377        if ( utils.eventType[e.type] != 1 ) {
29378          // for button property
29379          // http://unixpapa.com/js/mouse.html
29380          var button;
29381        if (!e.which) {
29382          /* IE case */
29383          button = (e.button < 2) ? 0 :
29384                   ((e.button == 4) ? 1 : 2);
29385        } else {
29386          /* All others */
29387          button = e.button;
29388        }
29389            if ( button !== 0 ) {
29390                return;
29391            }
29392        }
29393
29394        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
29395            return;
29396        }
29397
29398        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29399            e.preventDefault();
29400        }
29401
29402        var point = e.touches ? e.touches[0] : e,
29403            pos;
29404
29405        this.initiated  = utils.eventType[e.type];
29406        this.moved      = false;
29407        this.distX      = 0;
29408        this.distY      = 0;
29409        this.directionX = 0;
29410        this.directionY = 0;
29411        this.directionLocked = 0;
29412
29413        this.startTime = utils.getTime();
29414
29415        if ( this.options.useTransition && this.isInTransition ) {
29416            this._transitionTime();
29417            this.isInTransition = false;
29418            pos = this.getComputedPosition();
29419            this._translate(Math.round(pos.x), Math.round(pos.y));
29420            this._execEvent('scrollEnd');
29421        } else if ( !this.options.useTransition && this.isAnimating ) {
29422            this.isAnimating = false;
29423            this._execEvent('scrollEnd');
29424        }
29425
29426        this.startX    = this.x;
29427        this.startY    = this.y;
29428        this.absStartX = this.x;
29429        this.absStartY = this.y;
29430        this.pointX    = point.pageX;
29431        this.pointY    = point.pageY;
29432
29433        this._execEvent('beforeScrollStart');
29434    },
29435
29436    _move: function (e) {
29437        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29438            return;
29439        }
29440
29441        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
29442            e.preventDefault();
29443        }
29444
29445        var point       = e.touches ? e.touches[0] : e,
29446            deltaX      = point.pageX - this.pointX,
29447            deltaY      = point.pageY - this.pointY,
29448            timestamp   = utils.getTime(),
29449            newX, newY,
29450            absDistX, absDistY;
29451
29452        this.pointX     = point.pageX;
29453        this.pointY     = point.pageY;
29454
29455        this.distX      += deltaX;
29456        this.distY      += deltaY;
29457        absDistX        = Math.abs(this.distX);
29458        absDistY        = Math.abs(this.distY);
29459
29460        // We need to move at least 10 pixels for the scrolling to initiate
29461        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
29462            return;
29463        }
29464
29465        // If you are scrolling in one direction lock the other
29466        if ( !this.directionLocked && !this.options.freeScroll ) {
29467            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 29468-29654
29468                this.directionLocked = 'h';     // lock horizontally
29469            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
29470                this.directionLocked = 'v';     // lock vertically
29471            } else {
29472                this.directionLocked = 'n';     // no lock
29473            }
29474        }
29475
29476        if ( this.directionLocked == 'h' ) {
29477            if ( this.options.eventPassthrough == 'vertical' ) {
29478                e.preventDefault();
29479            } else if ( this.options.eventPassthrough == 'horizontal' ) {
29480                this.initiated = false;
29481                return;
29482            }
29483
29484            deltaY = 0;
29485        } else if ( this.directionLocked == 'v' ) {
29486            if ( this.options.eventPassthrough == 'horizontal' ) {
29487                e.preventDefault();
29488            } else if ( this.options.eventPassthrough == 'vertical' ) {
29489                this.initiated = false;
29490                return;
29491            }
29492
29493            deltaX = 0;
29494        }
29495
29496        deltaX = this.hasHorizontalScroll ? deltaX : 0;
29497        deltaY = this.hasVerticalScroll ? deltaY : 0;
29498
29499        newX = this.x + deltaX;
29500        newY = this.y + deltaY;
29501
29502        // Slow down if outside of the boundaries
29503        if ( newX > 0 || newX < this.maxScrollX ) {
29504            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
29505        }
29506        if ( newY > 0 || newY < this.maxScrollY ) {
29507            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
29508        }
29509
29510        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
29511        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
29512
29513        if ( !this.moved ) {
29514            this._execEvent('scrollStart');
29515        }
29516
29517        this.moved = true;
29518
29519        this._translate(newX, newY);
29520
29521/* REPLACE START: _move */
29522
29523        if ( timestamp - this.startTime > 300 ) {
29524            this.startTime = timestamp;
29525            this.startX = this.x;
29526            this.startY = this.y;
29527        }
29528
29529/* REPLACE END: _move */
29530
29531    },
29532
29533    _end: function (e) {
29534        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29535            return;
29536        }
29537
29538        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29539            e.preventDefault();
29540        }
29541
29542        var point = e.changedTouches ? e.changedTouches[0] : e,
29543            momentumX,
29544            momentumY,
29545            duration = utils.getTime() - this.startTime,
29546            newX = Math.round(this.x),
29547            newY = Math.round(this.y),
29548            distanceX = Math.abs(newX - this.startX),
29549            distanceY = Math.abs(newY - this.startY),
29550            time = 0,
29551            easing = '';
29552
29553        this.isInTransition = 0;
29554        this.initiated = 0;
29555        this.endTime = utils.getTime();
29556
29557        // reset if we are outside of the boundaries
29558        if ( this.resetPosition(this.options.bounceTime) ) {
29559            return;
29560        }
29561
29562        this.scrollTo(newX, newY);  // ensures that the last position is rounded
29563
29564        // we scrolled less than 10 pixels
29565        if ( !this.moved ) {
29566            if ( this.options.tap ) {
29567                utils.tap(e, this.options.tap);
29568            }
29569
29570            if ( this.options.click ) {
29571                utils.click(e);
29572            }
29573
29574            this._execEvent('scrollCancel');
29575            return;
29576        }
29577
29578        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
29579            this._execEvent('flick');
29580            return;
29581        }
29582
29583        // start momentum animation if needed
29584        if ( this.options.momentum && duration < 300 ) {
29585            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 };
29586            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 };
29587            newX = momentumX.destination;
29588            newY = momentumY.destination;
29589            time = Math.max(momentumX.duration, momentumY.duration);
29590            this.isInTransition = 1;
29591        }
29592
29593
29594        if ( this.options.snap ) {
29595            var snap = this._nearestSnap(newX, newY);
29596            this.currentPage = snap;
29597            time = this.options.snapSpeed || Math.max(
29598                    Math.max(
29599                        Math.min(Math.abs(newX - snap.x), 1000),
29600                        Math.min(Math.abs(newY - snap.y), 1000)
29601                    ), 300);
29602            newX = snap.x;
29603            newY = snap.y;
29604
29605            this.directionX = 0;
29606            this.directionY = 0;
29607            easing = this.options.bounceEasing;
29608        }
29609
29610// INSERT POINT: _end
29611
29612        if ( newX != this.x || newY != this.y ) {
29613            // change easing function when scroller goes out of the boundaries
29614            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
29615                easing = utils.ease.quadratic;
29616            }
29617
29618            this.scrollTo(newX, newY, time, easing);
29619            return;
29620        }
29621
29622        this._execEvent('scrollEnd');
29623    },
29624
29625    _resize: function () {
29626        var that = this;
29627
29628        clearTimeout(this.resizeTimeout);
29629
29630        this.resizeTimeout = setTimeout(function () {
29631            that.refresh();
29632        }, this.options.resizePolling);
29633    },
29634
29635    resetPosition: function (time) {
29636        var x = this.x,
29637            y = this.y;
29638
29639        time = time || 0;
29640
29641        if ( !this.hasHorizontalScroll || this.x > 0 ) {
29642            x = 0;
29643        } else if ( this.x < this.maxScrollX ) {
29644            x = this.maxScrollX;
29645        }
29646
29647        if ( !this.hasVerticalScroll || this.y > 0 ) {
29648            y = 0;
29649        } else if ( this.y < this.maxScrollY ) {
29650            y = this.maxScrollY;
29651        }
29652
29653        if ( x == this.x && y == this.y ) {
29654            return false;
vendor: 5,509 bytes, lines 29655-29859
29655        }
29656
29657        this.scrollTo(x, y, time, this.options.bounceEasing);
29658
29659        return true;
29660    },
29661
29662    disable: function () {
29663        this.enabled = false;
29664    },
29665
29666    enable: function () {
29667        this.enabled = true;
29668    },
29669
29670    refresh: function () {
29671        var rf = this.wrapper.offsetHeight;     // Force reflow
29672
29673        this.wrapperWidth   = this.wrapper.clientWidth;
29674        this.wrapperHeight  = this.wrapper.clientHeight;
29675
29676/* REPLACE START: refresh */
29677
29678        this.scrollerWidth  = this.scroller.offsetWidth;
29679        this.scrollerHeight = this.scroller.offsetHeight;
29680
29681        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
29682        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
29683
29684/* REPLACE END: refresh */
29685
29686        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
29687        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
29688
29689        if ( !this.hasHorizontalScroll ) {
29690            this.maxScrollX = 0;
29691            this.scrollerWidth = this.wrapperWidth;
29692        }
29693
29694        if ( !this.hasVerticalScroll ) {
29695            this.maxScrollY = 0;
29696            this.scrollerHeight = this.wrapperHeight;
29697        }
29698
29699        this.endTime = 0;
29700        this.directionX = 0;
29701        this.directionY = 0;
29702
29703        this.wrapperOffset = utils.offset(this.wrapper);
29704
29705        this._execEvent('refresh');
29706
29707        this.resetPosition();
29708
29709// INSERT POINT: _refresh
29710
29711    },
29712
29713
29714    on: function (type, fn) {
29715        if ( !this._events[type] ) {
29716            this._events[type] = [];
29717        }
29718
29719        this._events[type].push(fn);
29720    },
29721
29722    off: function (type, fn) {
29723        if ( !this._events[type] ) {
29724            return;
29725        }
29726
29727        var index = this._events[type].indexOf(fn);
29728
29729        if ( index > -1 ) {
29730            this._events[type].splice(index, 1);
29731        }
29732    },
29733
29734    _execEvent: function (type) {
29735        if ( !this._events[type] ) {
29736            return;
29737        }
29738
29739        var i = 0,
29740            l = this._events[type].length;
29741
29742        if ( !l ) {
29743            return;
29744        }
29745
29746        for ( ; i < l; i++ ) {
29747            this._events[type][i].apply(this, [].slice.call(arguments, 1));
29748        }
29749    },
29750
29751    scrollBy: function (x, y, time, easing) {
29752        x = this.x + x;
29753        y = this.y + y;
29754        time = time || 0;
29755
29756        this.scrollTo(x, y, time, easing);
29757    },
29758
29759    scrollTo: function (x, y, time, easing) {
29760        easing = easing || utils.ease.circular;
29761
29762        this.isInTransition = this.options.useTransition && time > 0;
29763        var transitionType = this.options.useTransition && easing.style;
29764        if ( !time || transitionType ) {
29765                if(transitionType) {
29766                    this._transitionTimingFunction(easing.style);
29767                    this._transitionTime(time);
29768                }
29769            this._translate(x, y);
29770        } else {
29771            this._animate(x, y, time, easing.fn);
29772        }
29773    },
29774
29775    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29776        el = el.nodeType ? el : this.scroller.querySelector(el);
29777
29778        if ( !el ) {
29779            return;
29780        }
29781
29782        var pos = utils.offset(el);
29783
29784        pos.left -= this.wrapperOffset.left;
29785        pos.top  -= this.wrapperOffset.top;
29786
29787        // if offsetX/Y are true we center the element to the screen
29788        if ( offsetX === true ) {
29789            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29790        }
29791        if ( offsetY === true ) {
29792            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29793        }
29794
29795        pos.left -= offsetX || 0;
29796        pos.top  -= offsetY || 0;
29797
29798        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29799        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29800
29801        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29802
29803        this.scrollTo(pos.left, pos.top, time, easing);
29804    },
29805
29806    _transitionTime: function (time) {
29807        if (!this.options.useTransition) {
29808            return;
29809        }
29810        time = time || 0;
29811        var durationProp = utils.style.transitionDuration;
29812        if(!durationProp) {
29813            return;
29814        }
29815
29816        this.scrollerStyle[durationProp] = time + 'ms';
29817
29818        if ( !time && utils.isBadAndroid ) {
29819            this.scrollerStyle[durationProp] = '0.0001ms';
29820            // remove 0.0001ms
29821            var self = this;
29822            rAF(function() {
29823                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29824                    self.scrollerStyle[durationProp] = '0s';
29825                }
29826            });
29827        }
29828
29829
29830        if ( this.indicators ) {
29831            for ( var i = this.indicators.length; i--; ) {
29832                this.indicators[i].transitionTime(time);
29833            }
29834        }
29835
29836
29837// INSERT POINT: _transitionTime
29838
29839    },
29840
29841    _transitionTimingFunction: function (easing) {
29842        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29843
29844
29845        if ( this.indicators ) {
29846            for ( var i = this.indicators.length; i--; ) {
29847                this.indicators[i].transitionTimingFunction(easing);
29848            }
29849        }
29850
29851
29852// INSERT POINT: _transitionTimingFunction
29853
29854    },
29855
29856    _translate: function (x, y) {
29857        //Uncode addition
29858        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29859            return false;
vendor: 9,939 bytes, lines 29860-30171
29860
29861        if ( this.options.useTransform ) {
29862
29863/* REPLACE START: _translate */
29864
29865            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29866
29867/* REPLACE END: _translate */
29868
29869        } else {
29870            x = Math.round(x);
29871            y = Math.round(y);
29872            this.scrollerStyle.left = x + 'px';
29873            this.scrollerStyle.top = y + 'px';
29874        }
29875
29876        this.x = x;
29877        this.y = y;
29878
29879
29880        if ( this.indicators ) {
29881            for ( var i = this.indicators.length; i--; ) {
29882                this.indicators[i].updatePosition();
29883            }
29884        }
29885
29886        //Uncode addition
29887        var uncodevent = new CustomEvent('fp-slide-scroll');
29888        window.dispatchEvent(uncodevent);
29889
29890// INSERT POINT: _translate
29891
29892    },
29893
29894    _initEvents: function (remove) {
29895        var eventType = remove ? utils.removeEvent : utils.addEvent,
29896            target = this.options.bindToWrapper ? this.wrapper : window;
29897
29898        eventType(window, 'orientationchange', this);
29899        eventType(window, 'resize', this);
29900
29901        if ( this.options.click ) {
29902            eventType(this.wrapper, 'click', this, true);
29903        }
29904
29905        if ( !this.options.disableMouse ) {
29906            eventType(this.wrapper, 'mousedown', this);
29907            eventType(target, 'mousemove', this);
29908            eventType(target, 'mousecancel', this);
29909            eventType(target, 'mouseup', this);
29910        }
29911
29912        if ( utils.hasPointer && !this.options.disablePointer ) {
29913            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29914            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29915            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29916            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29917        }
29918
29919        if ( utils.hasTouch && !this.options.disableTouch ) {
29920            eventType(this.wrapper, 'touchstart', this);
29921            eventType(target, 'touchmove', this);
29922            eventType(target, 'touchcancel', this);
29923            eventType(target, 'touchend', this);
29924        }
29925
29926        eventType(this.scroller, 'transitionend', this);
29927        eventType(this.scroller, 'webkitTransitionEnd', this);
29928        eventType(this.scroller, 'oTransitionEnd', this);
29929        eventType(this.scroller, 'MSTransitionEnd', this);
29930    },
29931
29932    getComputedPosition: function () {
29933        var matrix = window.getComputedStyle(this.scroller, null),
29934            x, y;
29935
29936        if ( this.options.useTransform ) {
29937            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29938            x = +(matrix[12] || matrix[4]);
29939            y = +(matrix[13] || matrix[5]);
29940        } else {
29941            x = +matrix.left.replace(/[^-\d.]/g, '');
29942            y = +matrix.top.replace(/[^-\d.]/g, '');
29943        }
29944
29945        return { x: x, y: y };
29946    },
29947    _initIndicators: function () {
29948        var interactive = this.options.interactiveScrollbars,
29949            customStyle = typeof this.options.scrollbars != 'string',
29950            indicators = [],
29951            indicator;
29952
29953        var that = this;
29954
29955        this.indicators = [];
29956
29957        if ( this.options.scrollbars ) {
29958            // Vertical scrollbar
29959            if ( this.options.scrollY ) {
29960                indicator = {
29961                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
29962                    interactive: interactive,
29963                    defaultScrollbars: true,
29964                    customStyle: customStyle,
29965                    resize: this.options.resizeScrollbars,
29966                    shrink: this.options.shrinkScrollbars,
29967                    fade: this.options.fadeScrollbars,
29968                    listenX: false
29969                };
29970
29971                this.wrapper.appendChild(indicator.el);
29972                indicators.push(indicator);
29973            }
29974
29975            // Horizontal scrollbar
29976            if ( this.options.scrollX ) {
29977                indicator = {
29978                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
29979                    interactive: interactive,
29980                    defaultScrollbars: true,
29981                    customStyle: customStyle,
29982                    resize: this.options.resizeScrollbars,
29983                    shrink: this.options.shrinkScrollbars,
29984                    fade: this.options.fadeScrollbars,
29985                    listenY: false
29986                };
29987
29988                this.wrapper.appendChild(indicator.el);
29989                indicators.push(indicator);
29990            }
29991        }
29992
29993        if ( this.options.indicators ) {
29994            // TODO: check concat compatibility
29995            indicators = indicators.concat(this.options.indicators);
29996        }
29997
29998        for ( var i = indicators.length; i--; ) {
29999            this.indicators.push( new Indicator(this, indicators[i]) );
30000        }
30001
30002        // TODO: check if we can use array.map (wide compatibility and performance issues)
30003        function _indicatorsMap (fn) {
30004            if (that.indicators) {
30005                for ( var i = that.indicators.length; i--; ) {
30006                    fn.call(that.indicators[i]);
30007                }
30008            }
30009        }
30010
30011        if ( this.options.fadeScrollbars ) {
30012            this.on('scrollEnd', function () {
30013                _indicatorsMap(function () {
30014                    this.fade();
30015                });
30016            });
30017
30018            this.on('scrollCancel', function () {
30019                _indicatorsMap(function () {
30020                    this.fade();
30021                });
30022            });
30023
30024            this.on('scrollStart', function () {
30025                _indicatorsMap(function () {
30026                    this.fade(1);
30027                });
30028            });
30029
30030            this.on('beforeScrollStart', function () {
30031                _indicatorsMap(function () {
30032                    this.fade(1, true);
30033                });
30034            });
30035        }
30036
30037
30038        this.on('refresh', function () {
30039            _indicatorsMap(function () {
30040                this.refresh();
30041            });
30042        });
30043
30044        this.on('destroy', function () {
30045            _indicatorsMap(function () {
30046                this.destroy();
30047            });
30048
30049            delete this.indicators;
30050        });
30051    },
30052
30053    _initWheel: function () {
30054        utils.addEvent(this.wrapper, 'wheel', this);
30055        utils.addEvent(this.wrapper, 'mousewheel', this);
30056        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30057
30058        this.on('destroy', function () {
30059            clearTimeout(this.wheelTimeout);
30060            this.wheelTimeout = null;
30061            utils.removeEvent(this.wrapper, 'wheel', this);
30062            utils.removeEvent(this.wrapper, 'mousewheel', this);
30063            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
30064        });
30065    },
30066
30067    _wheel: function (e) {
30068        if ( !this.enabled ) {
30069            return;
30070        }
30071
30072        var wheelDeltaX, wheelDeltaY,
30073            newX, newY,
30074            that = this;
30075
30076        if ( this.wheelTimeout === undefined ) {
30077            that._execEvent('scrollStart');
30078        }
30079
30080        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
30081        clearTimeout(this.wheelTimeout);
30082        this.wheelTimeout = setTimeout(function () {
30083            if(!that.options.snap) {
30084                that._execEvent('scrollEnd');
30085            }
30086            that.wheelTimeout = undefined;
30087        }, 400);
30088
30089        if ( 'deltaX' in e ) {
30090            if (e.deltaMode === 1) {
30091                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
30092                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
30093            } else {
30094                wheelDeltaX = -e.deltaX;
30095                wheelDeltaY = -e.deltaY;
30096            }
30097        } else if ( 'wheelDeltaX' in e ) {
30098            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
30099            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
30100        } else if ( 'wheelDelta' in e ) {
30101            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
30102        } else if ( 'detail' in e ) {
30103            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
30104        } else {
30105            return;
30106        }
30107
30108        wheelDeltaX *= this.options.invertWheelDirection;
30109        wheelDeltaY *= this.options.invertWheelDirection;
30110
30111        if ( !this.hasVerticalScroll ) {
30112            wheelDeltaX = wheelDeltaY;
30113            wheelDeltaY = 0;
30114        }
30115
30116        if ( this.options.snap ) {
30117            newX = this.currentPage.pageX;
30118            newY = this.currentPage.pageY;
30119
30120            if ( wheelDeltaX > 0 ) {
30121                newX--;
30122            } else if ( wheelDeltaX < 0 ) {
30123                newX++;
30124            }
30125
30126            if ( wheelDeltaY > 0 ) {
30127                newY--;
30128            } else if ( wheelDeltaY < 0 ) {
30129                newY++;
30130            }
30131
30132            this.goToPage(newX, newY);
30133
30134            return;
30135        }
30136
30137        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
30138        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
30139
30140        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
30141        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
30142
30143        if ( newX > 0 ) {
30144            newX = 0;
30145        } else if ( newX < this.maxScrollX ) {
30146            newX = this.maxScrollX;
30147        }
30148
30149        if ( newY > 0 ) {
30150            newY = 0;
30151        } else if ( newY < this.maxScrollY ) {
30152            newY = this.maxScrollY;
30153        }
30154
30155        this.scrollTo(newX, newY, 0);
30156
30157// INSERT POINT: _wheel
30158    },
30159
30160    _initSnap: function () {
30161        this.currentPage = {};
30162
30163        if ( typeof this.options.snap == 'string' ) {
30164            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
30165        }
30166
30167        this.on('refresh', function () {
30168            var i = 0, l,
30169                m = 0, n,
30170                cx, cy,
30171                x = 0, y,
vendor: 7,339 bytes, lines 30172-30425
30172                stepX = this.options.snapStepX || this.wrapperWidth,
30173                stepY = this.options.snapStepY || this.wrapperHeight,
30174                el;
30175
30176            this.pages = [];
30177
30178            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
30179                return;
30180            }
30181
30182            if ( this.options.snap === true ) {
30183                cx = Math.round( stepX / 2 );
30184                cy = Math.round( stepY / 2 );
30185
30186                while ( x > -this.scrollerWidth ) {
30187                    this.pages[i] = [];
30188                    l = 0;
30189                    y = 0;
30190
30191                    while ( y > -this.scrollerHeight ) {
30192                        this.pages[i][l] = {
30193                            x: Math.max(x, this.maxScrollX),
30194                            y: Math.max(y, this.maxScrollY),
30195                            width: stepX,
30196                            height: stepY,
30197                            cx: x - cx,
30198                            cy: y - cy
30199                        };
30200
30201                        y -= stepY;
30202                        l++;
30203                    }
30204
30205                    x -= stepX;
30206                    i++;
30207                }
30208            } else {
30209                el = this.options.snap;
30210                l = el.length;
30211                n = -1;
30212
30213                for ( ; i < l; i++ ) {
30214                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
30215                        m = 0;
30216                        n++;
30217                    }
30218
30219                    if ( !this.pages[m] ) {
30220                        this.pages[m] = [];
30221                    }
30222
30223                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
30224                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
30225                    cx = x - Math.round(el[i].offsetWidth / 2);
30226                    cy = y - Math.round(el[i].offsetHeight / 2);
30227
30228                    this.pages[m][n] = {
30229                        x: x,
30230                        y: y,
30231                        width: el[i].offsetWidth,
30232                        height: el[i].offsetHeight,
30233                        cx: cx,
30234                        cy: cy
30235                    };
30236
30237                    if ( x > this.maxScrollX ) {
30238                        m++;
30239                    }
30240                }
30241            }
30242
30243            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
30244
30245            // Update snap threshold if needed
30246            if ( this.options.snapThreshold % 1 === 0 ) {
30247                this.snapThresholdX = this.options.snapThreshold;
30248                this.snapThresholdY = this.options.snapThreshold;
30249            } else {
30250                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
30251                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
30252            }
30253        });
30254
30255        this.on('flick', function () {
30256            var time = this.options.snapSpeed || Math.max(
30257                    Math.max(
30258                        Math.min(Math.abs(this.x - this.startX), 1000),
30259                        Math.min(Math.abs(this.y - this.startY), 1000)
30260                    ), 300);
30261
30262            this.goToPage(
30263                this.currentPage.pageX + this.directionX,
30264                this.currentPage.pageY + this.directionY,
30265                time
30266            );
30267        });
30268    },
30269
30270    _nearestSnap: function (x, y) {
30271        if ( !this.pages.length ) {
30272            return { x: 0, y: 0, pageX: 0, pageY: 0 };
30273        }
30274
30275        var i = 0,
30276            l = this.pages.length,
30277            m = 0;
30278
30279        // Check if we exceeded the snap threshold
30280        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
30281            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
30282            return this.currentPage;
30283        }
30284
30285        if ( x > 0 ) {
30286            x = 0;
30287        } else if ( x < this.maxScrollX ) {
30288            x = this.maxScrollX;
30289        }
30290
30291        if ( y > 0 ) {
30292            y = 0;
30293        } else if ( y < this.maxScrollY ) {
30294            y = this.maxScrollY;
30295        }
30296
30297        for ( ; i < l; i++ ) {
30298            if ( x >= this.pages[i][0].cx ) {
30299                x = this.pages[i][0].x;
30300                break;
30301            }
30302        }
30303
30304        l = this.pages[i].length;
30305
30306        for ( ; m < l; m++ ) {
30307            if ( y >= this.pages[0][m].cy ) {
30308                y = this.pages[0][m].y;
30309                break;
30310            }
30311        }
30312
30313        if ( i == this.currentPage.pageX ) {
30314            i += this.directionX;
30315
30316            if ( i < 0 ) {
30317                i = 0;
30318            } else if ( i >= this.pages.length ) {
30319                i = this.pages.length - 1;
30320            }
30321
30322            x = this.pages[i][0].x;
30323        }
30324
30325        if ( m == this.currentPage.pageY ) {
30326            m += this.directionY;
30327
30328            if ( m < 0 ) {
30329                m = 0;
30330            } else if ( m >= this.pages[0].length ) {
30331                m = this.pages[0].length - 1;
30332            }
30333
30334            y = this.pages[0][m].y;
30335        }
30336
30337        return {
30338            x: x,
30339            y: y,
30340            pageX: i,
30341            pageY: m
30342        };
30343    },
30344
30345    goToPage: function (x, y, time, easing) {
30346        easing = easing || this.options.bounceEasing;
30347
30348        if ( x >= this.pages.length ) {
30349            x = this.pages.length - 1;
30350        } else if ( x < 0 ) {
30351            x = 0;
30352        }
30353
30354        if ( y >= this.pages[x].length ) {
30355            y = this.pages[x].length - 1;
30356        } else if ( y < 0 ) {
30357            y = 0;
30358        }
30359
30360        var posX = this.pages[x][y].x,
30361            posY = this.pages[x][y].y;
30362
30363        time = time === undefined ? this.options.snapSpeed || Math.max(
30364            Math.max(
30365                Math.min(Math.abs(posX - this.x), 1000),
30366                Math.min(Math.abs(posY - this.y), 1000)
30367            ), 300) : time;
30368
30369        this.currentPage = {
30370            x: posX,
30371            y: posY,
30372            pageX: x,
30373            pageY: y
30374        };
30375
30376        this.scrollTo(posX, posY, time, easing);
30377    },
30378
30379    next: function (time, easing) {
30380        var x = this.currentPage.pageX,
30381            y = this.currentPage.pageY;
30382
30383        x++;
30384
30385        if ( x >= this.pages.length && this.hasVerticalScroll ) {
30386            x = 0;
30387            y++;
30388        }
30389
30390        this.goToPage(x, y, time, easing);
30391    },
30392
30393    prev: function (time, easing) {
30394        var x = this.currentPage.pageX,
30395            y = this.currentPage.pageY;
30396
30397        x--;
30398
30399        if ( x < 0 && this.hasVerticalScroll ) {
30400            x = 0;
30401            y--;
30402        }
30403
30404        this.goToPage(x, y, time, easing);
30405    },
30406
30407    _initKeys: function (e) {
30408        // default key bindings
30409        var keys = {
30410            pageUp: 33,
30411            pageDown: 34,
30412            end: 35,
30413            home: 36,
30414            left: 37,
30415            up: 38,
30416            right: 39,
30417            down: 40
30418        };
30419        var i;
30420
30421        // if you give me characters I give you keycode
30422        if ( typeof this.options.keyBindings == 'object' ) {
30423            for ( i in this.options.keyBindings ) {
30424                if ( typeof this.options.keyBindings[i] == 'string' ) {
30425                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 30425-30778
30425deAt(0);
30426                }
30427            }
30428        } else {
30429            this.options.keyBindings = {};
30430        }
30431
30432        for ( i in keys ) {
30433            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
30434        }
30435
30436        utils.addEvent(window, 'keydown', this);
30437
30438        this.on('destroy', function () {
30439            utils.removeEvent(window, 'keydown', this);
30440        });
30441    },
30442
30443    _key: function (e) {
30444        if ( !this.enabled ) {
30445            return;
30446        }
30447
30448        var snap = this.options.snap,   // we are using this alot, better to cache it
30449            newX = snap ? this.currentPage.pageX : this.x,
30450            newY = snap ? this.currentPage.pageY : this.y,
30451            now = utils.getTime(),
30452            prevTime = this.keyTime || 0,
30453            acceleration = 0.250,
30454            pos;
30455
30456        if ( this.options.useTransition && this.isInTransition ) {
30457            pos = this.getComputedPosition();
30458
30459            this._translate(Math.round(pos.x), Math.round(pos.y));
30460            this.isInTransition = false;
30461        }
30462
30463        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
30464
30465        switch ( e.keyCode ) {
30466            case this.options.keyBindings.pageUp:
30467                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30468                    newX += snap ? 1 : this.wrapperWidth;
30469                } else {
30470                    newY += snap ? 1 : this.wrapperHeight;
30471                }
30472                break;
30473            case this.options.keyBindings.pageDown:
30474                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30475                    newX -= snap ? 1 : this.wrapperWidth;
30476                } else {
30477                    newY -= snap ? 1 : this.wrapperHeight;
30478                }
30479                break;
30480            case this.options.keyBindings.end:
30481                newX = snap ? this.pages.length-1 : this.maxScrollX;
30482                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
30483                break;
30484            case this.options.keyBindings.home:
30485                newX = 0;
30486                newY = 0;
30487                break;
30488            case this.options.keyBindings.left:
30489                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
30490                break;
30491            case this.options.keyBindings.up:
30492                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
30493                break;
30494            case this.options.keyBindings.right:
30495                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
30496                break;
30497            case this.options.keyBindings.down:
30498                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
30499                break;
30500            default:
30501                return;
30502        }
30503
30504        if ( snap ) {
30505            this.goToPage(newX, newY);
30506            return;
30507        }
30508
30509        if ( newX > 0 ) {
30510            newX = 0;
30511            this.keyAcceleration = 0;
30512        } else if ( newX < this.maxScrollX ) {
30513            newX = this.maxScrollX;
30514            this.keyAcceleration = 0;
30515        }
30516
30517        if ( newY > 0 ) {
30518            newY = 0;
30519            this.keyAcceleration = 0;
30520        } else if ( newY < this.maxScrollY ) {
30521            newY = this.maxScrollY;
30522            this.keyAcceleration = 0;
30523        }
30524
30525        this.scrollTo(newX, newY, 0);
30526
30527        this.keyTime = now;
30528    },
30529
30530    _animate: function (destX, destY, duration, easingFn) {
30531        var that = this,
30532            startX = this.x,
30533            startY = this.y,
30534            startTime = utils.getTime(),
30535            destTime = startTime + duration;
30536
30537        function step () {
30538            var now = utils.getTime(),
30539                newX, newY,
30540                easing;
30541
30542            if ( now >= destTime ) {
30543                that.isAnimating = false;
30544                that._translate(destX, destY);
30545
30546                if ( !that.resetPosition(that.options.bounceTime) ) {
30547                    that._execEvent('scrollEnd');
30548                }
30549
30550                return;
30551            }
30552
30553            now = ( now - startTime ) / duration;
30554            easing = easingFn(now);
30555            newX = ( destX - startX ) * easing + startX;
30556            newY = ( destY - startY ) * easing + startY;
30557            that._translate(newX, newY);
30558
30559            if ( that.isAnimating ) {
30560                rAF(step);
30561            }
30562        }
30563
30564        this.isAnimating = true;
30565        step();
30566    },
30567    handleEvent: function (e) {
30568        switch ( e.type ) {
30569            case 'touchstart':
30570            case 'pointerdown':
30571            case 'MSPointerDown':
30572            case 'mousedown':
30573                this._start(e);
30574                break;
30575            case 'touchmove':
30576            case 'pointermove':
30577            case 'MSPointerMove':
30578            case 'mousemove':
30579                this._move(e);
30580                break;
30581            case 'touchend':
30582            case 'pointerup':
30583            case 'MSPointerUp':
30584            case 'mouseup':
30585            case 'touchcancel':
30586            case 'pointercancel':
30587            case 'MSPointerCancel':
30588            case 'mousecancel':
30589                this._end(e);
30590                break;
30591            case 'orientationchange':
30592            case 'resize':
30593                this._resize();
30594                break;
30595            case 'transitionend':
30596            case 'webkitTransitionEnd':
30597            case 'oTransitionEnd':
30598            case 'MSTransitionEnd':
30599                this._transitionEnd(e);
30600                break;
30601            case 'wheel':
30602            case 'DOMMouseScroll':
30603            case 'mousewheel':
30604                this._wheel(e);
30605                break;
30606            case 'keydown':
30607                this._key(e);
30608                break;
30609            case 'click':
30610                if ( this.enabled && !e._constructed ) {
30611                    e.preventDefault();
30612                    e.stopPropagation();
30613                }
30614                break;
30615        }
30616    }
30617};
30618function createDefaultScrollbar (direction, interactive, type) {
30619    var scrollbar = document.createElement('div'),
30620        indicator = document.createElement('div');
30621
30622    if ( type === true ) {
30623        scrollbar.style.cssText = 'position:absolute;z-index:9999';
30624        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';
30625    }
30626
30627    indicator.className = 'iScrollIndicator';
30628
30629    if ( direction == 'h' ) {
30630        if ( type === true ) {
30631            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
30632            indicator.style.height = '100%';
30633        }
30634        scrollbar.className = 'iScrollHorizontalScrollbar';
30635    } else {
30636        if ( type === true ) {
30637            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
30638            indicator.style.width = '100%';
30639        }
30640        scrollbar.className = 'iScrollVerticalScrollbar';
30641    }
30642
30643    scrollbar.style.cssText += ';overflow:hidden';
30644
30645    if ( !interactive ) {
30646        scrollbar.style.pointerEvents = 'none';
30647    }
30648
30649    scrollbar.appendChild(indicator);
30650
30651    return scrollbar;
30652}
30653
30654function Indicator (scroller, options) {
30655    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
30656    this.wrapperStyle = this.wrapper.style;
30657    this.indicator = this.wrapper.children[0];
30658    this.indicatorStyle = this.indicator.style;
30659    this.scroller = scroller;
30660
30661    this.options = {
30662        listenX: true,
30663        listenY: true,
30664        interactive: false,
30665        resize: true,
30666        defaultScrollbars: false,
30667        shrink: false,
30668        fade: false,
30669        speedRatioX: 0,
30670        speedRatioY: 0
30671    };
30672
30673    for ( var i in options ) {
30674        this.options[i] = options[i];
30675    }
30676
30677    this.sizeRatioX = 1;
30678    this.sizeRatioY = 1;
30679    this.maxPosX = 0;
30680    this.maxPosY = 0;
30681
30682    if ( this.options.interactive ) {
30683        if ( !this.options.disableTouch ) {
30684            utils.addEvent(this.indicator, 'touchstart', this);
30685            utils.addEvent(window, 'touchend', this);
30686        }
30687        if ( !this.options.disablePointer ) {
30688            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30689            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
30690        }
30691        if ( !this.options.disableMouse ) {
30692            utils.addEvent(this.indicator, 'mousedown', this);
30693            utils.addEvent(window, 'mouseup', this);
30694        }
30695    }
30696
30697    if ( this.options.fade ) {
30698        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
30699        var durationProp = utils.style.transitionDuration;
30700        if(!durationProp) {
30701            return;
30702        }
30703        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
30704        // remove 0.0001ms
30705        var self = this;
30706        if(utils.isBadAndroid) {
30707            rAF(function() {
30708                if(self.wrapperStyle[durationProp] === '0.0001ms') {
30709                    self.wrapperStyle[durationProp] = '0s';
30710                }
30711            });
30712        }
30713        this.wrapperStyle.opacity = '0';
30714    }
30715}
30716
30717Indicator.prototype = {
30718    handleEvent: function (e) {
30719        switch ( e.type ) {
30720            case 'touchstart':
30721            case 'pointerdown':
30722            case 'MSPointerDown':
30723            case 'mousedown':
30724                this._start(e);
30725                break;
30726            case 'touchmove':
30727            case 'pointermove':
30728            case 'MSPointerMove':
30729            case 'mousemove':
30730                this._move(e);
30731                break;
30732            case 'touchend':
30733            case 'pointerup':
30734            case 'MSPointerUp':
30735            case 'mouseup':
30736            case 'touchcancel':
30737            case 'pointercancel':
30738            case 'MSPointerCancel':
30739            case 'mousecancel':
30740                this._end(e);
30741                break;
30742        }
30743    },
30744
30745    destroy: function () {
30746        if ( this.options.fadeScrollbars ) {
30747            clearTimeout(this.fadeTimeout);
30748            this.fadeTimeout = null;
30749        }
30750        if ( this.options.interactive ) {
30751            utils.removeEvent(this.indicator, 'touchstart', this);
30752            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30753            utils.removeEvent(this.indicator, 'mousedown', this);
30754
30755            utils.removeEvent(window, 'touchmove', this);
30756            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30757            utils.removeEvent(window, 'mousemove', this);
30758
30759            utils.removeEvent(window, 'touchend', this);
30760            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
30761            utils.removeEvent(window, 'mouseup', this);
30762        }
30763
30764        if ( this.options.defaultScrollbars ) {
30765            this.wrapper.parentNode.removeChild(this.wrapper);
30766        }
30767    },
30768
30769    _start: function (e) {
30770        var point = e.touches ? e.touches[0] : e;
30771
30772        e.preventDefault();
30773        e.stopPropagation();
30774
30775        this.transitionTime();
30776
30777        this.initiated = true;
30778        this.moved = false;
vendor: 9,615 bytes, lines 30779-31037
30779        this.lastPointX = point.pageX;
30780        this.lastPointY = point.pageY;
30781
30782        this.startTime  = utils.getTime();
30783
30784        if ( !this.options.disableTouch ) {
30785            utils.addEvent(window, 'touchmove', this);
30786        }
30787        if ( !this.options.disablePointer ) {
30788            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30789        }
30790        if ( !this.options.disableMouse ) {
30791            utils.addEvent(window, 'mousemove', this);
30792        }
30793
30794        this.scroller._execEvent('beforeScrollStart');
30795    },
30796
30797    _move: function (e) {
30798        var point = e.touches ? e.touches[0] : e,
30799            deltaX, deltaY,
30800            newX, newY,
30801            timestamp = utils.getTime();
30802
30803        if ( !this.moved ) {
30804            this.scroller._execEvent('scrollStart');
30805        }
30806
30807        this.moved = true;
30808
30809        deltaX = point.pageX - this.lastPointX;
30810        this.lastPointX = point.pageX;
30811
30812        deltaY = point.pageY - this.lastPointY;
30813        this.lastPointY = point.pageY;
30814
30815        newX = this.x + deltaX;
30816        newY = this.y + deltaY;
30817
30818        this._pos(newX, newY);
30819
30820// INSERT POINT: indicator._move
30821
30822        e.preventDefault();
30823        e.stopPropagation();
30824    },
30825
30826    _end: function (e) {
30827        if ( !this.initiated ) {
30828            return;
30829        }
30830
30831        this.initiated = false;
30832
30833        e.preventDefault();
30834        e.stopPropagation();
30835
30836        utils.removeEvent(window, 'touchmove', this);
30837        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30838        utils.removeEvent(window, 'mousemove', this);
30839
30840        if ( this.scroller.options.snap ) {
30841            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30842
30843            var time = this.options.snapSpeed || Math.max(
30844                    Math.max(
30845                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30846                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30847                    ), 300);
30848
30849            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30850                this.scroller.directionX = 0;
30851                this.scroller.directionY = 0;
30852                this.scroller.currentPage = snap;
30853                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30854            }
30855        }
30856
30857        if ( this.moved ) {
30858            this.scroller._execEvent('scrollEnd');
30859        }
30860    },
30861
30862    transitionTime: function (time) {
30863        time = time || 0;
30864        var durationProp = utils.style.transitionDuration;
30865        if(!durationProp) {
30866            return;
30867        }
30868
30869        this.indicatorStyle[durationProp] = time + 'ms';
30870
30871        if ( !time && utils.isBadAndroid ) {
30872            this.indicatorStyle[durationProp] = '0.0001ms';
30873            // remove 0.0001ms
30874            var self = this;
30875            rAF(function() {
30876                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30877                    self.indicatorStyle[durationProp] = '0s';
30878                }
30879            });
30880        }
30881    },
30882
30883    transitionTimingFunction: function (easing) {
30884        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30885    },
30886
30887    refresh: function () {
30888        this.transitionTime();
30889
30890        if ( this.options.listenX && !this.options.listenY ) {
30891            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30892        } else if ( this.options.listenY && !this.options.listenX ) {
30893            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30894        } else {
30895            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30896        }
30897
30898        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30899            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30900            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30901
30902            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30903                if ( this.options.listenX ) {
30904                    this.wrapper.style.right = '8px';
30905                } else {
30906                    this.wrapper.style.bottom = '8px';
30907                }
30908            }
30909        } else {
30910            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30911            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30912
30913            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30914                if ( this.options.listenX ) {
30915                    this.wrapper.style.right = '2px';
30916                } else {
30917                    this.wrapper.style.bottom = '2px';
30918                }
30919            }
30920        }
30921
30922        var r = this.wrapper.offsetHeight;  // force refresh
30923
30924        if ( this.options.listenX ) {
30925            this.wrapperWidth = this.wrapper.clientWidth;
30926            if ( this.options.resize ) {
30927                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30928                this.indicatorStyle.width = this.indicatorWidth + 'px';
30929            } else {
30930                this.indicatorWidth = this.indicator.clientWidth;
30931            }
30932
30933            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30934
30935            if ( this.options.shrink == 'clip' ) {
30936                this.minBoundaryX = -this.indicatorWidth + 8;
30937                this.maxBoundaryX = this.wrapperWidth - 8;
30938            } else {
30939                this.minBoundaryX = 0;
30940                this.maxBoundaryX = this.maxPosX;
30941            }
30942
30943            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
30944        }
30945
30946        if ( this.options.listenY ) {
30947            this.wrapperHeight = this.wrapper.clientHeight;
30948            if ( this.options.resize ) {
30949                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
30950                this.indicatorStyle.height = this.indicatorHeight + 'px';
30951            } else {
30952                this.indicatorHeight = this.indicator.clientHeight;
30953            }
30954
30955            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30956
30957            if ( this.options.shrink == 'clip' ) {
30958                this.minBoundaryY = -this.indicatorHeight + 8;
30959                this.maxBoundaryY = this.wrapperHeight - 8;
30960            } else {
30961                this.minBoundaryY = 0;
30962                this.maxBoundaryY = this.maxPosY;
30963            }
30964
30965            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
30966            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
30967        }
30968
30969        this.updatePosition();
30970    },
30971
30972    updatePosition: function () {
30973        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
30974            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
30975
30976        if ( !this.options.ignoreBoundaries ) {
30977            if ( x < this.minBoundaryX ) {
30978                if ( this.options.shrink == 'scale' ) {
30979                    this.width = Math.max(this.indicatorWidth + x, 8);
30980                    this.indicatorStyle.width = this.width + 'px';
30981                }
30982                x = this.minBoundaryX;
30983            } else if ( x > this.maxBoundaryX ) {
30984                if ( this.options.shrink == 'scale' ) {
30985                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
30986                    this.indicatorStyle.width = this.width + 'px';
30987                    x = this.maxPosX + this.indicatorWidth - this.width;
30988                } else {
30989                    x = this.maxBoundaryX;
30990                }
30991            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
30992                this.width = this.indicatorWidth;
30993                this.indicatorStyle.width = this.width + 'px';
30994            }
30995
30996            if ( y < this.minBoundaryY ) {
30997                if ( this.options.shrink == 'scale' ) {
30998                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
30999                    this.indicatorStyle.height = this.height + 'px';
31000                }
31001                y = this.minBoundaryY;
31002            } else if ( y > this.maxBoundaryY ) {
31003                if ( this.options.shrink == 'scale' ) {
31004                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31005                    this.indicatorStyle.height = this.height + 'px';
31006                    y = this.maxPosY + this.indicatorHeight - this.height;
31007                } else {
31008                    y = this.maxBoundaryY;
31009                }
31010            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31011                this.height = this.indicatorHeight;
31012                this.indicatorStyle.height = this.height + 'px';
31013            }
31014        }
31015
31016        this.x = x;
31017        this.y = y;
31018
31019        if ( this.scroller.options.useTransform ) {
31020            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31021        } else {
31022            this.indicatorStyle.left = x + 'px';
31023            this.indicatorStyle.top = y + 'px';
31024        }
31025    },
31026
31027    _pos: function (x, y) {
31028        if ( x < 0 ) {
31029            x = 0;
31030        } else if ( x > this.maxPosX ) {
31031            x = this.maxPosX;
31032        }
31033
31034        if ( y < 0 ) {
31035            y = 0;
31036        } else if ( y > this.maxPosY ) {
31037            y = this.maxPosY;
31038        }
31039
31040        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31041        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31042
31043        this.scroller.scrollTo(x, y);
31044    },
31045
31046    fade: function (val, hold) {
31047        if ( hold && !this.visible ) {
31048            return;
31049        }
31050
31051        clearTimeout(this.fadeTimeout);
31052        this.fadeTimeout = null;
31053
31054        var time = val ? 250 : 500,
31055            delay = val ? 0 : 300;
31056
31057        val = val ? '1' : '0';
31058
31059        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31060
31061        this.fadeTimeout = setTimeout((function (val) {
31062            this.wrapperStyle.opacity = val;
31063            this.visible = +val;
31064        }).bind(this, val), delay);
31065    }
31066};
31067
31068IScroll.utils = utils;
31069
31070if ( typeof module != 'undefined' && module.exports ) {
31071    module.exports = IScroll;
31072} else if ( typeof define == 'function' && define.amd ) {
31073        define( function () { return IScroll; } );
31074} else {
31075    window.IScroll = IScroll;
31076}
31077
31078})(window, document, Math);
31079/*!
31080 * fullPage 2.9.4
31081 * https://github.com/alvarotrigo/fullPage.js
31082 * @license MIT licensed
31083 *
31084 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
31085 */
31086(function(global, factory) {
31087    'use strict';
31088    if (typeof define === 'function' && define.amd) {
31089        define(['jquery'], function($) {
31090          return factory($, global, global.document, global.Math);
31091        });
31092    } else if (typeof exports === "object" && exports) {
31093        module.exports = factory(require('jquery'), global, global.document, global.Math);
31094    } else {
31095        factory(jQuery, global, global.document, global.Math);
31096    }
31097})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
31098    'use strict';
31099
31100    // keeping central set of classnames and selectors
31101    var WRAPPER =               'fullpage-wrapper';
31102    var WRAPPER_SEL =           '.' + WRAPPER;
31103
31104    // slimscroll
31105    var SCROLLABLE =            'fp-scrollable';
31106    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
31107
31108    // util
31109    var RESPONSIVE =            'fp-responsive';
31110    var NO_TRANSITION =         'fp-notransition';
31111    var DESTROYED =             'fp-destroyed';
31112    var ENABLED =               'fp-enabled';
31113    var VIEWING_PREFIX =        'fp-viewing';
31114    var ACTIVE =                'active';
31115    var ACTIVE_SEL =            '.' + ACTIVE;
31116    var COMPLETELY =            'fp-completely';
31117    var COMPLETELY_SEL =        '.' + COMPLETELY;
31118
31119    // section
31120    var SECTION_DEFAULT_SEL =   '.section';
31121    var SECTION =               'fp-section';
31122    var SECTION_SEL =           '.' + SECTION;
31123    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
31124    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
31125    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
31126    var TABLE_CELL =            'fp-tableCell';
31127    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
31128    var AUTO_HEIGHT =           'fp-auto-height';
31129    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
31130    var NORMAL_SCROLL =         'fp-normal-scroll';
31131    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
31132
31133    // section nav
31134    var SECTION_NAV =           'fp-nav';
31135    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
31136    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
31137    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
31138    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
31139
31140    // slide
31141    var SLIDE_DEFAULT_SEL =     '.slide';
31142    var SLIDE =                 'fp-slide';
31143    var SLIDE_SEL =             '.' + SLIDE;
31144    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
31145    var SLIDES_WRAPPER =        'fp-slides';
31146    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
31147    var SLIDES_CONTAINER =      'fp-slidesContainer';
31148    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
31149    var TABLE =                 'fp-table';
31150
31151    // slide nav
31152    var SLIDES_NAV =            'fp-slidesNav';
31153    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
31154    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
31155    var SLIDES_ARROW =          'fp-controlArrow';
31156    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
31157    var SLIDES_PREV =           'fp-prev';
31158    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
31159    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
31160    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
31161    var SLIDES_NEXT =           'fp-next';
31162    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
31163    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
31164    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
31165
31166    var $window = $(window);
31167    var $document = $(document);
31168
31169    // Default options for iScroll.js used when using scrollOverflow
31170    var iscrollOptions = {
31171        scrollbars: true,
31172        mouseWheel: true,
31173        hideScrollbars: false,
31174        fadeScrollbars: false,
31175        disableMouse: true,
31176        interactiveScrollbars: true,
31177        bounce: false,
31178    };
31179
31180    $.fn.fullpage = function(options) {
31181        //only once my friend!
31182        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
31183
31184        // common jQuery objects
31185        var $htmlBody = $('html, body');
31186        var $body = $('body');
31187
31188        var FP = $.fn.fullpage;
31189
31190        // Creating some defaults, extending them with any options that were provided
31191        options = $.extend({
31192            //navigation
31193            menu: false,
31194            anchors:[],
31195            lockAnchors: false,
31196            navigation: false,
31197            navigationPosition: 'right',
31198            navigationTooltips: [],
31199            showActiveTooltip: false,
31200            slidesNavigation: false,
31201            slidesNavPosition: 'bottom',
31202            scrollBar: false,
31203            hybrid: false,
31204
31205            //scrolling
31206            css3: true,
31207            scrollingSpeed: 700,
31208            autoScrolling: true,
31209            fitToSection: true,
31210            fitToSectionDelay: 1000,
31211            easing: 'easeInOutCubic',
31212            easingcss3: 'ease',
31213            loopBottom: false,
31214            loopTop: false,
31215            loopHorizontal: true,
31216            continuousVertical: false,
31217            continuousHorizontal: false,
31218            scrollHorizontally: false,
31219            interlockedSlides: false,
31220            dragAndMove: false,
31221            offsetSections: false,
31222            resetSliders: false,
31223            fadingEffect: false,
31224            normalScrollElements: null,
31225            scrollOverflow: false,
31226            scrollOverflowReset: false,
31227            scrollOverflowHandler: iscrollHandler,
31228            scrollOverflowOptions: null,
31229            touchSensitivity: 5,
31230            normalScrollElementTouchThreshold: 5,
31231            bigSectionsDestination: null,
31232
31233            //Accessibility
31234            keyboardScrolling: true,
31235            animateAnchor: true,
31236            recordHistory: true,
31237
31238            //design
31239            controlArrows: true,
31240            controlArrowColor: '#fff',
31241            verticalCentered: true,
31242            sectionsColor : [],
31243            paddingTop: 0,
31244            paddingBottom: 0,
31245            fixedElements: null,
31246            responsive: 0, //backwards compabitility with responsiveWiddth
31247            responsiveWidth: 0,
31248            responsiveHeight: 0,
31249            responsiveSlides: false,
31250            parallax: false,
31251            parallaxOptions: {
31252                type: 'reveal',
31253                percentage: 62,
31254                property: 'translate'
31255            },
31256
31257            //Custom selectors
31258            sectionSelector: SECTION_DEFAULT_SEL,
31259            slideSelector: SLIDE_DEFAULT_SEL,
31260
31261            //events
31262            afterLoad: null,
31263            onLeave: null,
31264            afterRender: null,
31265            afterResize: null,
31266            afterReBuild: null,
31267            afterSlideLoad: null,
31268            onSlideLeave: null,
31269            afterResponsive: null,
31270
31271            lazyLoading: true
31272        }, options);
31273
31274        //flag to avoid very fast sliding for landscape sliders
31275        var slideMoving = false;
31276
31277        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
31278        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
31279        var container = $(this);
31280        var windowsHeight = $window.height();
31281        var isResizing = false;
31282        var isWindowFocused = true;
31283        var lastScrolledDestiny;
31284        var lastScrolledSlide;
31285        var canScroll = true;
31286        var scrollings = [];
31287        var controlPressed;
31288        var startingSection;
31289        var isScrollAllowed = {};
31290        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
31291        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
31292        var MSPointer = getMSPointer();
31293        var events = {
31294            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
31295            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
31296        };
31297
31298        //cheks for passive event support
31299        //added by Uncode from new fullPage updates
31300        var g_supportsPassive = false;
31301        try {
31302          var opts = Object.defineProperty({}, 'passive', {
31303            get: function() {
31304              g_supportsPassive = true;
31305            }
31306          });
31307          window.addEventListener("testPassive", null, opts);
31308          window.removeEventListener("testPassive", null, opts);
31309        } catch (e) {}
31310
31311        //timeouts
31312        var resizeId;
31313        var afterSectionLoadsId;
31314        var afterSlideLoadsId;
31315        var scrollId;
31316        var scrollId2;
31317        var keydownId;
31318        var originals = $.extend(true, {}, options); //deep copy
31319
31320        //Uncode addition
31321        var $masthead = $('#masthead');
31322        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
31323        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
31324        var bodyBorder = UNCODE.bodyBorder;
31325        var adminBarHeight = UNCODE.adminBarHeight;
31326
31327        displayWarnings();
31328
31329        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
31330        iscrollOptions.click = isTouch; // see #2035
31331
31332        //extending iScroll options with the user custom ones
31333        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
31334
31335        //easeInOutCubic animation included in the plugin
31336        $.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;}});
31337
31338        /**
31339        * Sets the autoScroll option.
31340        * It changes the scroll bar visibility and the history of the site as a result.
31341        */
31342        function setAutoScrolling(value, type){
31343            //removing the transformation
31344            if(!value){
31345                silentScroll(0);
31346            }
31347
31348            setVariableState('autoScrolling', value, type);
31349
31350            var element = $(SECTION_ACTIVE_SEL);
31351
31352            if(options.autoScrolling && !options.scrollBar){
31353                $htmlBody.css({
31354                    'overflow' : 'hidden !important',
31355                    'height' : '100%'
31356                });
31357
31358                //Uncode addition
31359                //setRecordHistory(originals.recordHistory, 'internal');
31360
31361                //for IE touch devices
31362                container.css({
31363                    '-ms-touch-action': 'none',
31364                    'touch-action': 'none'
31365                });
31366
31367                if(element.length){
31368                    //moving the container up
31369                    silentScroll(element.position().top);
31370                }
31371
31372            }else{
31373                $htmlBody.css({
31374                    'overflow' : 'visible !important',
31375                    'height' : 'initial'
31376                });
31377
31378                //Uncode addition
31379                //setRecordHistory(false, 'internal');
31380
31381                //for IE touch devices
31382                container.css({
31383                    '-ms-touch-action': '',
31384                    'touch-action': ''
31385                });
31386
31387                //scrolling the page to the section with no animation
31388                if (element.length) {
31389                    $htmlBody.scrollTop(element.position().top);
31390                }
31391            }
31392        }
31393
31394        /**
31395        * Defines wheter to record the history for each hash change in the URL.
31396        */
31397        function setRecordHistory(value, type){
31398            setVariableState('recordHistory', value, type);
31399        }
31400
31401        /**
31402        * Defines the scrolling speed
31403        */
31404        function setScrollingSpeed(value, type){
31405            setVariableState('scrollingSpeed', value, type);
31406        }
31407
31408        /**
31409        * Sets fitToSection
31410        */
31411        function setFitToSection(value, type){
31412            setVariableState('fitToSection', value, type);
31413        }
31414
31415        /**
31416        * Sets lockAnchors
31417        */
31418        function setLockAnchors(value){
31419            options.lockAnchors = value;
31420        }
31421
31422        /**
31423        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
31424        */
31425        function setMouseWheelScrolling(value){
31426            if(value){
31427                addMouseWheelHandler();
31428                addMiddleWheelHandler();
31429            }else{
31430                removeMouseWheelHandler();
31431                removeMiddleWheelHandler();
31432            }
31433        }
31434
31435        /**
31436        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
31437        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
31438        *
31439        * @param directions string containing the direction or directions separated by comma.
31440        */
31441        function setAllowScrolling(value, directions){
31442            if(typeof directions !== 'undefined'){
31443                directions = directions.replace(/ /g,'').split(',');
31444
31445                $.each(directions, function (index, direction){
31446                    setIsScrollAllowed(value, direction, 'm');
31447                });
31448            }
31449            else if(value){
31450                setMouseWheelScrolling(true);
31451                addTouchHandler();
31452            }else{
31453                setMouseWheelScrolling(false);
31454                removeTouchHandler();
31455            }
31456        }
31457
31458        /**
31459        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
31460        */
31461        function setKeyboardScrolling(value, directions){
31462            if(typeof directions !== 'undefined'){
31463                directions = directions.replace(/ /g,'').split(',');
31464
31465                $.each(directions, function (index, direction){
31466                    setIsScrollAllowed(value, direction, 'k');
31467                });
31468            }else{
31469                options.keyboardScrolling = value;
31470            }
31471        }
31472
31473        /**
31474        * Moves the page up one section.
31475        */
31476        function moveSectionUp(){
31477            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
31478
31479            //looping to the bottom if there's no more sections above
31480            if (!prev.length && (options.loopTop || options.continuousVertical)) {
31481                prev = $(SECTION_SEL).last();
31482            }
31483
31484            if (prev.length) {
31485                scrollPage(prev, null, true);
31486            }
31487        }
31488
31489        /**
31490        * Moves the page down one section.
31491        */
31492        function moveSectionDown(){
31493            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
31494
31495            //looping to the top if there's no more sections below
31496            if(!next.length &&
31497                (options.loopBottom || options.continuousVertical)){
31498                next = $(SECTION_SEL).first();
31499            }
31500
31501            if(next.length){
31502                scrollPage(next, null, false);
31503            }
31504        }
31505
31506        /**
31507        * Moves the page to the given section and slide with no animation.
31508        * Anchors or index positions can be used as params.
31509        */
31510        function silentMoveTo(sectionAnchor, slideAnchor){
31511            setScrollingSpeed (0, 'internal');
31512            moveTo(sectionAnchor, slideAnchor);
31513            setScrollingSpeed (originals.scrollingSpeed, 'internal');
31514        }
31515
31516        /**
31517        * Moves the page to the given section and slide.
31518        * Anchors or index positions can be used as params.
31519        */
31520        function moveTo(sectionAnchor, slideAnchor){
31521            var destiny = getSectionByAnchor(sectionAnchor);
31522
31523            if (typeof slideAnchor !== 'undefined'){
31524                scrollPageAndSlide(sectionAnchor, slideAnchor);
31525            }else if(destiny.length > 0){
31526                scrollPage(destiny);
31527            }
31528        }
31529
31530        /**
31531        * Slides right the slider of the active section.
31532        * Optional `section` param.
31533        */
31534        function moveSlideRight(section){
31535            moveSlide('right', section);
31536        }
31537
31538        /**
31539        * Slides left the slider of the active section.
31540        * Optional `section` param.
31541        */
31542        function moveSlideLeft(section){
31543            moveSlide('left', section);
31544        }
31545
31546        /**
31547         * When resizing is finished, we adjust the slides sizes and positions
31548         */
31549        function reBuild(resizing){
31550            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
31551
31552            isResizing = true;
31553
31554            windowsHeight = $window.height();  //updating global var
31555
31556            $(SECTION_SEL).each(function(){
31557                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
31558                var slides = $(this).find(SLIDE_SEL);
31559
31560                //adjusting the height of the table-cell for IE and Firefox
31561                if(options.verticalCentered){
31562                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
31563                }
31564
31565                $(this).css('height', windowsHeight + 'px');
31566
31567                //resizing the scrolling divs
31568                if(options.scrollOverflow){
31569                    if(slides.length){
31570                        slides.each(function(){
31571                            createScrollBar($(this));
31572                        });
31573                    }else{
31574                        createScrollBar($(this));
31575                    }
31576                }
31577
31578                //adjusting the position fo the FULL WIDTH slides...
31579                if (slides.length > 1) {
31580                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
31581                }
31582            });
31583
31584            var activeSection = $(SECTION_ACTIVE_SEL);
31585            var sectionIndex = activeSection.index(SECTION_SEL);
31586
31587            //isn't it the first section?
31588            if(sectionIndex){
31589                //adjusting the position for the current section
31590                silentMoveTo(sectionIndex + 1);
31591            }
31592
31593            isResizing = false;
31594            // Uncode change
31595            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
31596            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
31597            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
31598        }
31599
31600        /**
31601        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
31602        * are smaller than the set limit values.
31603        */
31604        function setResponsive(active){
31605            var isResponsive = $body.hasClass(RESPONSIVE);
31606
31607            if(active){
31608                if(!isResponsive){
31609                    setAutoScrolling(false, 'internal');
31610                    setFitToSection(false, 'internal');
31611                    $(SECTION_NAV_SEL).hide();
31612                    $body.addClass(RESPONSIVE);
31613                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31614                }
31615            }
31616            else if(isResponsive){
31617                setAutoScrolling(originals.autoScrolling, 'internal');
31618                setFitToSection(originals.autoScrolling, 'internal');
31619                $(SECTION_NAV_SEL).show();
31620                $body.removeClass(RESPONSIVE);
31621                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31622            }
31623        }
31624
31625        if($(this).length){
31626            //public functions
31627            FP.setAutoScrolling = setAutoScrolling;
31628            FP.setRecordHistory = setRecordHistory;
31629            FP.setScrollingSpeed = setScrollingSpeed;
31630            FP.setFitToSection = setFitToSection;
31631            FP.setLockAnchors = setLockAnchors;
31632            FP.setMouseWheelScrolling = setMouseWheelScrolling;
31633            FP.setAllowScrolling = setAllowScrolling;
31634            FP.setKeyboardScrolling = setKeyboardScrolling;
31635            FP.moveSectionUp = moveSectionUp;
31636            FP.moveSectionDown = moveSectionDown;
31637            FP.silentMoveTo = silentMoveTo;
31638            FP.moveTo = moveTo;
31639            FP.moveSlideRight = moveSlideRight;
31640            FP.moveSlideLeft = moveSlideLeft;
31641            FP.fitToSection = fitToSection;
31642            FP.reBuild = reBuild;
31643            FP.setResponsive = setResponsive;
31644            FP.destroy = destroy;
31645
31646            init();
31647
31648            bindEvents();
31649        }
31650
31651        function init(){
31652            //if css3 is not supported, it will use jQuery animations
31653            if(options.css3){
31654                options.css3 = support3d();
31655            }
31656
31657            options.scrollBar = options.scrollBar || options.hybrid;
31658
31659            setOptionsFromDOM();
31660            prepareDom();
31661            setAllowScrolling(true);
31662            setAutoScrolling(options.autoScrolling, 'internal');
31663            responsive();
31664
31665            //setting the class for the body element
31666            setBodyClass();
31667
31668            //Uncode addition
31669            // if(document.readyState === 'complete'){
31670            //     scrollToAnchor();
31671            // }
31672            // $window.on('load', scrollToAnchor);
31673        }
31674
31675        function bindEvents(){
31676            $window
31677                //when scrolling...
31678                //.on('scroll', scrollHandler)
31679
31680                //detecting any change on the URL to scroll to the given anchor link
31681                //(a way to detect back history button as we play with the hashes on the URL)
31682                .on('hashchange', hashChangeHandler)
31683
31684                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
31685                .blur(blurHandler)
31686
31687                //when resizing the site, we adjust the heights of the sections, slimScroll...
31688                .resize(resizeHandler);
31689
31690            $document
31691                //Sliding with arrow keys, both, vertical and horizontal
31692                .keydown(keydownHandler)
31693
31694                //to prevent scrolling while zooming
31695                .keyup(keyUpHandler)
31696
31697                //Scrolls to the section when clicking the navigation bullet
31698                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
31699
31700                //Scrolls the slider to the given slide destination for the given section
31701                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
31702
31703                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
31704
31705            //Scrolling horizontally when clicking on the slider controls.
31706            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
31707
31708            /**
31709            * Applying normalScroll elements.
31710            * Ignoring the scrolls over the specified selectors.
31711            */
31712            if(options.normalScrollElements){
31713                $document.on('mouseenter', options.normalScrollElements, function () {
31714                    setMouseWheelScrolling(false);
31715                });
31716
31717                $document.on('mouseleave', options.normalScrollElements, function(){
31718                    setMouseWheelScrolling(true);
31719                });
31720            }
31721        }
31722
31723        /**
31724        * Setting options from DOM elements if they are not provided.
31725        */
31726        function setOptionsFromDOM(){
31727            var sections = container.find(options.sectionSelector);
31728
31729            //no anchors option? Checking for them in the DOM attributes
31730            if(!options.anchors.length){
31731                options.anchors = sections.filter('[data-anchor]').map(function(){
31732                    return $(this).data('anchor').toString();
31733                }).get();
31734            }
31735
31736            //no tooltips option? Checking for them in the DOM attributes
31737            if(!options.navigationTooltips.length){
31738                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
31739                    return $(this).data('tooltip').toString();
31740                }).get();
31741            }
31742        }
31743
31744        /**
31745        * Works over the DOM structure to set it up for the current fullpage options.
31746        */
31747        function prepareDom(){
31748            container.css({
31749                'height': '100%',
31750                'position': 'relative'
31751            });
31752
31753            //adding a class to recognize the container internally in the code
31754            container.addClass(WRAPPER);
31755            $('html').addClass(ENABLED);
31756
31757            windowsHeight = $window.height();
31758
31759            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
31760
31761            addInternalSelectors();
31762
31763             //styling the sections / slides / menu
31764            $(SECTION_SEL).each(function(index){
31765                var section = $(this);
31766                var slides = section.find(SLIDE_SEL);
31767                var numSlides = slides.length;
31768
31769                styleSection(section, index);
31770                styleMenu(section, index);
31771
31772                // if there's any slide
31773                if (numSlides > 0) {
31774                    styleSlides(section, slides, numSlides);
31775                }else{
31776                    if(options.verticalCentered){
31777                        addTableClass(section);
31778                    }
31779                }
31780            });
31781
31782            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31783            if(options.fixedElements && options.css3){
31784                $(options.fixedElements).appendTo($body);
31785            }
31786
31787            //vertical centered of the navigation + active bullet
31788            if(options.navigation){
31789                addVerticalNavigation();
31790            }
31791
31792            enableYoutubeAPI();
31793
31794            if(options.scrollOverflow){
31795                if(document.readyState === 'complete'){
31796                    createScrollBarHandler();
31797                }
31798                //after DOM and images are loaded
31799                $window.on('load', createScrollBarHandler);
31800            }else{
31801                afterRenderActions();
31802            }
31803        }
31804
31805        /**
31806        * Styles the horizontal slides for a section.
31807        */
31808        function styleSlides(section, slides, numSlides){
31809            var sliderWidth = numSlides * 100;
31810            var slideWidth = 100 / numSlides;
31811
31812            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31813            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31814
31815            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31816
31817            if(numSlides > 1){
31818                if(options.controlArrows){
31819                    createSlideArrows(section);
31820                }
31821
31822                if(options.slidesNavigation){
31823                    addSlidesNavigation(section, numSlides);
31824                }
31825            }
31826
31827            slides.each(function(index) {
31828                $(this).css('width', slideWidth + '%');
31829
31830                if(options.verticalCentered){
31831                    addTableClass($(this));
31832                }
31833            });
31834
31835            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31836
31837            //if the slide won't be an starting point, the default will be the first one
31838            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31838ide by default.
31839            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31840                silentLandscapeScroll(startingSlide, 'internal');
31841            }else{
31842                slides.eq(0).addClass(ACTIVE);
31843            }
31844        }
31845
31846        /**
31847        * Styling vertical sections
31848        */
31849        function styleSection(section, index){
31850            //if no active section is defined, the 1st one will be the default one
31851            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31852                section.addClass(ACTIVE);
31853            }
31854            startingSection = $(SECTION_ACTIVE_SEL);
31855
31856            section.css('height', windowsHeight + 'px');
31857
31858            if(options.paddingTop){
31859                section.css('padding-top', options.paddingTop);
31860            }
31861
31862            if(options.paddingBottom){
31863                section.css('padding-bottom', options.paddingBottom);
31864            }
31865
31866            if (typeof options.sectionsColor[index] !==  'undefined') {
31867                section.css('background-color', options.sectionsColor[index]);
31868            }
31869
31870            if (typeof options.anchors[index] !== 'undefined') {
31871                section.attr('data-anchor', options.anchors[index]);
31872            }
31873        }
31874
31875        /**
31876        * Sets the data-anchor attributes to the menu elements and activates the current one.
31877        */
31878        function styleMenu(section, index){
31879            if (typeof options.anchors[index] !== 'undefined') {
31880                //activating the menu / nav element on load
31881                if(section.hasClass(ACTIVE)){
31882                    activateMenuAndNav(options.anchors[index], index);
31883                }
31884            }
31885
31886            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31887            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31888                $(options.menu).appendTo($body);
31889            }
31890        }
31891
31892        /**
31893        * Adds internal classes to be able to provide customizable selectors
31894        * keeping the link with the style sheet.
31895        */
31896        function addInternalSelectors(){
31897            container.find(options.sectionSelector).addClass(SECTION);
31898            container.find(options.slideSelector).addClass(SLIDE);
31899        }
31900
31901        /**
31902        * Creates the control arrows for the given section
31903        */
31904        function createSlideArrows(section){
31905            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31906
31907            if(options.controlArrowColor!='#fff'){
31908                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31909                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31910            }
31911
31912            if(!options.loopHorizontal){
31913                section.find(SLIDES_ARROW_PREV_SEL).hide();
31914            }
31915        }
31916
31917        /**
31918        * Creates a vertical navigation bar.
31919        */
31920        function addVerticalNavigation(){
31921            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31922            var nav = $(SECTION_NAV_SEL);
31923
31924            nav.addClass(function() {
31925                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31926            });
31927
31928            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31929                var link = '';
31930                if (options.anchors.length) {
31931                    link = options.anchors[i];
31932                }
31933
31934                var li = '<li><a href="#' + link + '"><span></span></a>';
31935
31936                // Only add tooltip if needed (defined by user)
31937                var tooltip = options.navigationTooltips[i];
31938
31939                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31940                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31941                }
31942
31943                li += '</li>';
31944
31945                nav.find('ul').append(li);
31946            }
31947
31948            //centering it vertically
31949            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
31950
31951            //activating the current active section
31952            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
31953        }
31954
31955        /**
31956        * Creates the slim scroll scrollbar for the sections and slides inside them.
31957        */
31958        function createScrollBarHandler(){
31959            $(SECTION_SEL).each(function(){
31960                var slides = $(this).find(SLIDE_SEL);
31961
31962                if(slides.length){
31963                    slides.each(function(){
31964                        createScrollBar($(this));
31965                    });
31966                }else{
31967                    createScrollBar($(this));
31968                }
31969
31970            });
31971            afterRenderActions();
31972        }
31973
31974        /*
31975        * Enables the Youtube videos API so we can control their flow if necessary.
31976        */
31977        function enableYoutubeAPI(){
31978            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
31979                addURLParam($(this), 'enablejsapi=1');
31980            });
31981        }
31982
31983        /**
31984        * Adds a new parameter and its value to the `src` of a given element
31985        */
31986        function addURLParam(element, newParam){
31987            var originalSrc = element.attr('src');
31988            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
31989        }
31990
31991        /*
31992        * Returns the prefix sign to use for a new parameter in an existen URL.
31993        *
31994        * @return {String}  ? | &
31995        */
31996        function getUrlParamSign(url){
31997            return ( !/\?/.test( url ) ) ? '?' : '&';
31998        }
31999
32000        /**
32001        * Actions and callbacks to fire afterRender
32002        */
32003        function afterRenderActions(){
32004            var section = $(SECTION_ACTIVE_SEL);
32005
32006            section.addClass(COMPLETELY);
32007
32008            if(options.scrollOverflowHandler.afterRender){
32009                options.scrollOverflowHandler.afterRender(section);
32010            }
32011            lazyLoad(section);
32012            playMedia(section);
32013            options.scrollOverflowHandler.afterLoad();
32014
32015            if(isDestinyTheStartingSection()){
32016                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32017            }
32018
32019            // Uncode change
32020            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32021            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32022        }
32023
32024        /**
32025        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32026        */
32027        function isDestinyTheStartingSection(){
32028            var anchors =  window.location.hash.replace('#', '').split('/');
32029            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32030
32031            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32032        }
32033
32034
32035        var isScrolling = false;
32036        var lastScroll = 0;
32037
32038        //when scrolling...
32039        function scrollHandler(){
32040            var currentSection;
32041
32042            if(!options.autoScrolling || options.scrollBar){
32043                var currentScroll = $window.scrollTop();
32044                var scrollDirection = getScrollDirection(currentScroll);
32045                var visibleSectionIndex = 0;
32046                var screen_mid = currentScroll + ($window.height() / 2.0);
32047                var isAtBottom = $body.height() - $window.height() === currentScroll;
32048                var sections =  document.querySelectorAll(SECTION_SEL);
32049
32050                //when using `auto-height` for a small last section it won't be centered in the viewport
32051                if(isAtBottom){
32052                    visibleSectionIndex = sections.length - 1;
32053                }
32054                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32055                else if(!currentScroll){
32056                    visibleSectionIndex = 0;
32057                }
32058
32059                //taking the section which is showing more content in the viewport
32060                else{
32061                    for (var i = 0; i < sections.length; ++i) {
32062                        var section = sections[i];
32063
32064                        // Pick the the last section which passes the middle line of the screen.
32065                        if (section.offsetTop <= screen_mid)
32066                        {
32067                            visibleSectionIndex = i;
32068                        }
32069                    }
32070                }
32071
32072                if(isCompletelyInViewPort(scrollDirection)){
32073                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
32074                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32075                    }
32076                }
32077
32078                //geting the last one, the current one on the screen
32079                currentSection = $(sections).eq(visibleSectionIndex);
32080
32081                //setting the visible section as active when manually scrolling
32082                //executing only once the first time we reach the section
32083                if(!currentSection.hasClass(ACTIVE)){
32084                    isScrolling = true;
32085                    var leavingSection = $(SECTION_ACTIVE_SEL);
32086                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
32087                    var yMovement = getYmovement(currentSection);
32088                    var anchorLink  = currentSection.data('anchor');
32089                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
32090                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
32091                    var slideIndex;
32092                    var slideAnchorLink;
32093
32094                    if(activeSlide.length){
32095                        slideAnchorLink = activeSlide.data('anchor');
32096                        slideIndex = activeSlide.index();
32097                    }
32098
32099                    if(canScroll){
32100                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32101
32102                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
32103                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
32104
32105                        stopMedia(leavingSection);
32106                        lazyLoad(currentSection);
32107                        playMedia(currentSection);
32108
32109                        activateMenuAndNav(anchorLink, sectionIndex - 1);
32110
32111                        if(options.anchors.length){
32112                            //needed to enter in hashChange event when using the menu with anchor links
32113                            lastScrolledDestiny = anchorLink;
32114                        }
32115                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
32116                    }
32117
32118                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
32119                    clearTimeout(scrollId);
32120                    scrollId = setTimeout(function(){
32121                        isScrolling = false;
32122                    }, 100);
32123                }
32124
32125                if(options.fitToSection){
32126                    //for the auto adjust of the viewport to fit a whole section
32127                    clearTimeout(scrollId2);
32128
32129                    scrollId2 = setTimeout(function(){
32130                        //checking it again in case it changed during the delay
32131                        if(options.fitToSection){
32132                            fitToSection();
32133                        }
32134                    }, options.fitToSectionDelay);
32135                }
32136            }
32137        }
32138
32139        /**
32140        * Fits the site to the nearest active section
32141        */
32142        function fitToSection(){
32143            //checking fitToSection again in case it was set to false before the timeout delay
32144            if(canScroll){
32145                //allows to scroll to an active section and
32146                //if the section is already active, we prevent firing callbacks
32147                isResizing = true;
32148
32149                scrollPage($(SECTION_ACTIVE_SEL));
32150                isResizing = false;
32151            }
32152        }
32153
32154        /**
32155        * Determines whether the active section has seen in its whole or not.
32156        */
32157        function isCompletelyInViewPort(movement){
32158            var top = $(SECTION_ACTIVE_SEL).position().top;
32159            var bottom = top + $window.height();
32160
32161            if(movement == 'up'){
32162                return bottom >= ($window.scrollTop() + $window.height());
32163            }
32164            return top <= $window.scrollTop();
32165        }
32166
32167        /**
32168        * Gets the directon of the the scrolling fired by the scroll event.
32169        */
32170        function getScrollDirection(currentScroll){
32171            var direction = currentScroll > lastScroll ? 'down' : 'up';
32172
32173            lastScroll = currentScroll;
32174
32175            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
32176            previousDestTop = currentScroll;
32177
32178            return direction;
32179        }
32180
32181        /**
32182        * Determines the way of scrolling up or down:
32183        * by 'automatically' scrolling a section or by using the default and normal scrolling.
32184        */
32185        function scrolling(type, scrollable){
32186            if (!isScrollAllowed.m[type]){
32187                return;
32188            }
32189            var check = (type === 'down') ? 'bottom' : 'top';
32190            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
32191
32192            if(scrollable.length > 0 ){
32193                //is the scrollbar at the start/end of the scroll?
32194                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
32195                    scrollSection();
32196                }else{
32197                    return true;
32198                }
32199            }else{
32200                // moved up/down
32201                scrollSection();
32202            }
32203        }
32204
32205        /*
32206        * Preventing bouncing in iOS #2285
32207        */
32208        function preventBouncing(event){
32209            var e = event.originalEvent;
32210            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
32211                //preventing the easing on iOS devices
32212                event.preventDefault();
32213            }
32214        }
32215
32216        var touchStartY = 0;
32217        var touchStartX = 0;
32218        var touchEndY = 0;
32219        var touchEndX = 0;
32220
32221        /* Detecting touch events
32222
32223        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
32224        * This way, the touchstart and the touch moves shows an small difference between them which is the
32225        * used one to determine the direction.
32226        */
32227        function touchMoveHandler(event){
32228            var e = event.originalEvent;
32229            var activeSection = $(e.target).closest(SECTION_SEL);
32230
32231            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
32232            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
32233
32234                if(options.autoScrolling){
32235                    //preventing the easing on iOS devices
32236                    event.preventDefault();
32237                }
32238
32239                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32240                var touchEvents = getEventsPage(e);
32241
32242                touchEndY = touchEvents.y;
32243                touchEndX = touchEvents.x;
32244
32245                //if movement in the X axys is greater than in the Y and the currect section has slides...
32246                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
32247
32248                    //is the movement greater than the minimum resistance to scroll?
32249                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
32250                        if (touchStartX > touchEndX) {
32251                            if(isScrollAllowed.m.right){
32252                                moveSlideRight(activeSection); //next
32253                            }
32254                        } else {
32255                            if(isScrollAllowed.m.left){
32256                                moveSlideLeft(activeSection); //prev
32257                            }
32258                        }
32259                    }
32260                }
32261
32262                //vertical scrolling (only when autoScrolling is enabled)
32263                else if(options.autoScrolling && canScroll){
32264
32265                    //is the movement greater than the minimum resistance to scroll?
32266                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
32267                        if (touchStartY > touchEndY) {
32268                            scrolling('down', scrollable);
32269                        } else if (touchEndY > touchStartY) {
32270                            scrolling('up', scrollable);
32271                        }
32272                    }
32273                }
32274            }
32275        }
32276
32277        /**
32278         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
32279         * Currently works well for iOS - Android might need some testing
32280         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
32281         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
32282         * @return {boolean} true if there is a match to options.normalScrollElements
32283         */
32284        function checkParentForNormalScrollElement (el, hop) {
32285            hop = hop || 0;
32286            var parent = $(el).parent();
32287
32288            if (hop < options.normalScrollElementTouchThreshold &&
32289                parent.is(options.normalScrollElements) ) {
32290                return true;
32291            } else if (hop == options.normalScrollElementTouchThreshold) {
32292                return false;
32293            } else {
32294                return checkParentForNormalScrollElement(parent, ++hop);
32295            }
32296        }
32297
32298        /**
32299        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
32300        * this way we make sure that is really a touch event what IE is detecting.
32301        */
32302        function isReallyTouch(e){
32303            //if is not IE   ||  IE is detecting `touch` or `pen`
32304            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
32305        }
32306
32307        /**
32308        * Handler for the touch start event.
32309        */
32310        function touchStartHandler(event){
32311            var e = event.originalEvent;
32312
32313            //stopping the auto scroll to adjust to a section
32314            if(options.fitToSection){
32315                $htmlBody.stop();
32316            }
32317
32318            if(isReallyTouch(e)){
32319                var touchEvents = getEventsPage(e);
32320                touchStartY = touchEvents.y;
32321                touchStartX = touchEvents.x;
32322            }
32323        }
32324
32325        /**
32326        * Gets the average of the last `number` elements of the given array.
32327        */
32328        function getAverage(elements, number){
32329            var sum = 0;
32330
32331            //taking `number` elements from the end to make the average, if there are not enought, 1
32332            var lastElements = elements.slice(Math.max(elements.length - number, 1));
32333
32334            for(var i = 0; i < lastElements.length; i++){
32335                sum = sum + lastElements[i];
32336            }
32337
32338            return Math.ceil(sum/number);
32339        }
32340
32341        /**
32342         * Detecting mousewheel scrolling
32343         *
32344         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
32345         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
32346         */
32347        var prevTime = new Date().getTime();
32348
32349        function MouseWheelHandler(e) {
32350            var curTime = new Date().getTime();
32351            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
32352
32353            //autoscrolling and not zooming?
32354            if(options.autoScrolling && !controlPressed && !isNormalScroll){
32355                // cross-browser wheel delta
32356                e = e || window.event;
32357                var value = e.wheelDelta || -e.deltaY || -e.detail;
32358                var delta = Math.max(-1, Math.min(1, value));
32359
32360                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
32361                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
32362
32363                //Limiting the array to 150 (lets not waste memory!)
32364                if(scrollings.length > 149){
32365                    scrollings.shift();
32366                }
32367
32368                //keeping record of the previous scrollings
32369                scrollings.push(Math.abs(value));
32370
32371                //preventing to scroll the site on mouse wheel when scrollbar is present
32372                if(options.scrollBar){
32373                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
32374                }
32375
32376                var activeSection = $(SECTION_ACTIVE_SEL);
32377                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32378
32379                //time difference between the last scroll and the current one
32380                var timeDiff = curTime-prevTime;
32381                prevTime = curTime;
32382
32383                //haven't they scrolled in a while?
32384                //(enough to be consider a different scrolling action to scroll another section)
32385                if(timeDiff > 200){
32386                    //emptying the array, we dont care about old scrollings for our averages
32387                    scrollings = [];
32388                }
32389
32390                if(canScroll){
32391                    var averageEnd = getAverage(scrollings, 10);
32392                    var averageMiddle = getAverage(scrollings, 70);
32393                    var isAccelerating = averageEnd >= averageMiddle;
32394
32395                    //to avoid double swipes...
32396                    if(isAccelerating && isScrollingVertically){
32397                        //scrolling down?
32398                        if (delta < 0) {
32399                            scrolling('down', scrollable);
32400
32401                        //scrolling up?
32402                        }else {
32403                            scrolling('up', scrollable);
32404                        }
32405                    }
32406                }
32407
32408                return false;
32409            }
32410
32411            if(options.fitToSection){
32412                //stopping the auto scroll to adjust to a section
32413                $htmlBody.stop();
32414            }
32415        }
32416
32417        /**
32418        * Slides a slider to the given direction.
32419        * Optional `section` param.
32420        */
32421        function moveSlide(direction, section){
32422            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
32423            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
32424            var numSlides = slides.find(SLIDE_SEL).length;
32425
32426            // more than one slide needed and nothing should be sliding
32427            if (!slides.length || slideMoving || numSlides < 2) {
32428                return;
32429            }
32430
32431            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
32432            var destiny = null;
32433
32434            if(direction === 'left'){
32435                destiny = currentSlide.prev(SLIDE_SEL);
32436            }else{
32437                destiny = currentSlide.next(SLIDE_SEL);
32438            }
32439
32440            //isn't there a next slide in the secuence?
32441            if(!destiny.length){
32442                //respect loopHorizontal settin
32443                if (!options.loopHorizontal) return;
32444
32445                if(direction === 'left'){
32446                    destiny = currentSlide.siblings(':last');
32447                }else{
32448                    destiny = currentSlide.siblings(':first');
32449                }
32450            }
32451
32452            slideMoving = true;
32453
32454            landscapeScroll(slides, destiny, direction);
32455        }
32456
32457        /**
32458        * Maintains the active slides in the viewport
32459        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
32460        */
32461        function keepSlidesPosition(){
32462            $(SLIDE_ACTIVE_SEL).each(function(){
32463                silentLandscapeScroll($(this), 'internal');
32464            });
32465        }
32466
32467        var previousDestTop = 0;
32468        /**
32469        * Returns the destination Y position based on the scrolling direction and
32470        * the height of the section.
32471        */
32472        function getDestinationPosition(element){
32473            var elemPosition = element.position();
32474
32475            //top of the desination will be at the top of the viewport
32476            var position = elemPosition.top;
32477            var isScrollingDown =  elemPosition.top > previousDestTop;
32478            var sectionBottom = position - windowsHeight + element.outerHeight();
32479            var bigSectionsDestination = options.bigSectionsDestination;
32480
32481            //Uncode addition
32482            var containerH = container.outerHeight();
32483            var containerPosition = container.offset();
32484
32485            //########### Commented by Uncode - START ###########
32486            //is the destination element bigger than the viewport?
32487            // if(element.outerHeight() > windowsHeight){
32488            //     //scrolling up?
32489            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
32490            //         position = sectionBottom;
32491            //     }
32492            // }
32493
32494            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
32495            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
32496            //     //The bottom of the destination will be at the bottom of the viewport
32497            //     position = sectionBottom;
32498            // }
32499            //########### Commented by Uncode - END ###########
32500
32501            //Uncode addition
32502            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
32503                position += 18;
32504            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
32505                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
32506            }
32507
32508            /*
32509            Keeping record of the last scrolled position to determine the scrolling direction.
32510            No conventional methods can be used as the scroll bar might not be present
32511            AND the section might not be active if it is auto-height and didnt reach the middle
32512            of the viewport.
32513            */
32514            previousDestTop = position;
32515            return position;
32516        }
32517
32518        /**
32519        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
32520        */
32521        function scrollPage(element, callback, isMovementUp){
32522            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
32523
32524            var dtop = getDestinationPosition(element);
32525            var slideAnchorLink;
32526            var slideIndex;
32527
32528            //local variables
32529            var v = {
32530                element: element,
32531                callback: callback,
32532                isMovementUp: isMovementUp,
32533                dtop: dtop,
32534                yMovement: getYmovement(element),
32535                anchorLink: element.data('anchor'),
32536                sectionIndex: element.index(SECTION_SEL),
32537                activeSlide: element.find(SLIDE_ACTIVE_SEL),
32538                activeSection: $(SECTION_ACTIVE_SEL),
32539                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
32540
32541                //caching the value of isResizing at the momment the function is called
32542                //because it will be checked later inside a setTimeout and the value might change
32543                localIsResizing: isResizing
32544            };
32545
32546            //quiting when destination scroll is the same as the current one
32547            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
32548
32549            if(v.activeSlide.length){
32550                slideAnchorLink = v.activeSlide.data('anchor');
32551                slideIndex = v.activeSlide.index();
32552            }
32553
32554            // If continuousVertical && we need to wrap around
32555            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
32556                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
32557                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
32558
32559                v = createInfiniteSections(v);
32560            }
32561
32562            //callback (onLeave) if the site is not just resizing and readjusting the slides
32563            if($.isFunction(options.onLeave) && !v.localIsResizing){
32564                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
32565                    return;
32566                }
32567            }
32568
32569            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
32570            if(!v.localIsResizing){
32571                stopMedia(v.activeSection);
32572            }
32573
32574            options.scrollOverflowHandler.beforeLeave();
32575            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32576            lazyLoad(element);
32577            options.scrollOverflowHandler.onLeave();
32578
32579
32580            //preventing from activating the MouseWheelHandler event
32581            //more than once if the page is scrolling
32582            canScroll = false;
32583
32584            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
32585
32586            performMovement(v);
32587
32588            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
32589            lastScrolledDestiny = v.anchorLink;
32590
32591            //avoid firing it twice (as it does also on scroll)
32592            activateMenuAndNav(v.anchorLink, v.sectionIndex);
32593        }
32594
32595        /**
32596        * Performs the vertical movement (by CSS3 or by jQuery)
32597        */
32598        function performMovement(v){
32599            // using CSS3 translate functionality
32600            if (options.css3 && options.autoScrolling && !options.scrollBar) {
32601
32602                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32603                // that's why we round it to 0.
32604                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
32605                transformContainer(translate3d, true);
32606
32607                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
32608                //scrollingSpeed to change in case of using silentMoveTo();
32609                if(options.scrollingSpeed){
32610                    clearTimeout(afterSectionLoadsId);
32611                    afterSectionLoadsId = setTimeout(function () {
32612                        afterSectionLoads(v);
32613                    }, options.scrollingSpeed);
32614                }else{
32615                    afterSectionLoads(v);
32616                }
32617            }
32618
32619            // using jQuery animate
32620            else{
32621                var scrollSettings = getScrollSettings(v);
32622
32623                $(scrollSettings.element).animate(
32624                    scrollSettings.options,
32625                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
32626                    if(options.scrollBar){
32627
32628                        /* Hack!
32629                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
32630                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
32631
32632                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
32633                        */
32634                        setTimeout(function(){
32635                            afterSectionLoads(v);
32636                        },30);
32637                    }else{
32638                        afterSectionLoads(v);
32639                    }
32640                });
32641            }
32642        }
32643
32644        /**
32645        * Gets the scrolling settings depending on the plugin autoScrolling option
32646        */
32647        function getScrollSettings(v){
32648            var scroll = {};
32649
32650            if(options.autoScrolling && !options.scrollBar){
32651                scroll.options = { 'top': -v.dtop};
32652                scroll.element = WRAPPER_SEL;
32653            }else{
32654                scroll.options = { 'scrollTop': v.dtop};
32655                scroll.element = 'html, body';
32656            }
32657
32658            return scroll;
32659        }
32660
32661        /**
32662        * Adds sections before or after the current one to create the infinite effect.
32663        */
32664        function createInfiniteSections(v){
32665            // Scrolling down
32666            if (!v.isMovementUp) {
32667                // Move all previous sections to after the active section
32668                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
32669            }
32670            else { // Scrolling up
32671                // Move all next sections to before the active section
32672                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
32673            }
32674
32675            // Maintain the displayed position (now that we changed the element order)
32676            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32677
32678            // Maintain the active slides visible in the viewport
32679            keepSlidesPosition();
32680
32681            // save for later the elements that still need to be reordered
32682            v.wrapAroundElements = v.activeSection;
32683
32684            // Recalculate animation variables
32685            v.dtop = v.element.position().top;
32686            v.yMovement = getYmovement(v.element);
32687
32688            return v;
32689        }
32690
32691        /**
32692        * Fix section order after continuousVertical changes have been animated
32693        */
32694        function continuousVerticalFixSectionOrder (v) {
32695            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
32696            // finish moving the elements around so the direct navigation will function more simply
32697            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
32698                return;
32699            }
32700
32701            if (v.isMovementUp) {
32702                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
32703            }
32704            else {
32705                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
32706            }
32707
32708            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32709
32710            // Maintain the active slides visible in the viewport
32711            keepSlidesPosition();
32712        }
32713
32714
32715        /**
32716        * Actions to do once the section is loaded.
32717        */
32718        function afterSectionLoads (v){
32719            continuousVerticalFixSectionOrder(v);
32720
32721            //callback (afterLoad) if the site is not just resizing and readjusting the slides
32722            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
32723            options.scrollOverflowHandler.afterLoad();
32724
32725            if(!v.localIsResizing){
32726                playMedia(v.element);
32727            }
32728
32729            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32730
32731            canScroll = true;
32732
32733            $.isFunction(v.callback) && v.callback.call(this);
32734        }
32735
32736        /**
32737        * Sets the value for the given attribute from the `data-` attribute with the same suffix
32738        * ie: data-srcset ==> srcset  |  data-src ==> src
32739        */
32740        function setSrc(element, attribute){
32741            element
32742                .attr(attribute, element.data(attribute))
32743                .removeAttr('data-' + attribute);
32744        }
32745
32746        /**
32747        * Lazy loads image, video and audio elements.
32748        */
32749        function lazyLoad(destiny){
32750            if (!options.lazyLoading){
32751                return;
32752            }
32753
32754            var panel = getSlideOrSection(destiny);
32755            var element;
32756
32757            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
32758                element = $(this);
32759
32760                $.each(['src', 'srcset'], function(index, type){
32761                    var attribute = element.attr('data-' + type);
32762                    if(typeof attribute !== 'undefined' && attribute){
32763                        setSrc(element, type);
32764                    }
32765                });
32766
32767                if(element.is('source')){
32768                    element.closest('video').get(0).load();
32769                }
32770            });
32771        }
32772
32773        /**
32774        * Plays video and audio elements.
32775        */
32776        function playMedia(destiny){
32777            var panel = getSlideOrSection(destiny);
32778
32779            //playing HTML5 media elements
32780            panel.find('video, audio').each(function(){
32781                var element = $(this).get(0);
32782
32783                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32784                    element.play();
32785                }
32786            });
32787
32788            //youtube videos
32789            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32790                var element = $(this).get(0);
32791
32792                if ( element.hasAttribute('data-autoplay') ){
32793                    playYoutube(element);
32794                }
32795
32796                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32797                element.onload = function() {
32798                    if ( element.hasAttribute('data-autoplay') ){
32799                        playYoutube(element);
32800                    }
32801                };
32802            });
32803        }
32804
32805        /**
32806        * Plays a youtube video
32807        */
32808        function playYoutube(element){
32809            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32810        }
32811
32812        /**
32813        * Stops video and audio elements.
32814        */
32815        function stopMedia(destiny){
32816            var panel = getSlideOrSection(destiny);
32817
32818            //stopping HTML5 media elements
32819            panel.find('video, audio').each(function(){
32820                var element = $(this).get(0);
32821
32822                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32823                    element.pause();
32824                }
32825            });
32826
32827            //youtube videos
32828            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32829                var element = $(this).get(0);
32830
32831                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32832                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32833                }
32834            });
32835        }
32836
32837        /**
32838        * Gets the active slide (or section) for the given section
32839        */
32840        function getSlideOrSection(destiny){
32841            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32842            if( slide.length ) {
32843                destiny = $(slide);
32844            }
32845
32846            return destiny;
32847        }
32848
32849        /**
32850        * Scrolls to the anchor in the URL when loading the site
32851        */
32852        function scrollToAnchor(){
32853            //getting the anchor link in the URL and deleting the `#`
32854            var value =  window.location.hash.replace('#', '').split('/');
32855            var sectionAnchor = decodeURIComponent(value[0]);
32856            var slideAnchor = decodeURIComponent(value[1]);
32857
32858            if(sectionAnchor){  //if theres any #
32859                if(options.animateAnchor){
32860                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32861                }else{
32862                    silentMoveTo(sectionAnchor, slideAnchor);
32863                }
32864            }
32865        }
32866
32867        /**
32868        * Detecting any change on the URL to scroll to the given anchor link
32869        * (a way to detect back history button as we play with the hashes on the URL)
32870        */
32871        function hashChangeHandler(){
32872            if(!isScrolling && !options.lockAnchors){
32873                var value =  window.location.hash.replace('#', '').split('/');
32874                var sectionAnchor = decodeURIComponent(value[0]);
32875                var slideAnchor = decodeURIComponent(value[1]);
32876
32877                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32878                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32879                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32880
32881
32882                if(sectionAnchor.length){
32883                    /*in order to call scrollpage() only once for each destination at a time
32884                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32885                    event is fired on every scroll too.*/
32886                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32887                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32888                    }
32889                }
32890            }
32891        }
32892
32893        //Sliding with arrow keys, both, vertical and horizontal
32894        function keydownHandler(e) {
32895
32896            clearTimeout(keydownId);
32897
32898            var activeElement = $(':focus');
32899
32900            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32901                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32902                options.keyboardScrolling && options.autoScrolling){
32903                var keyCode = e.which;
32904
32905                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32906                var keyControls = [40, 38, 32, 33, 34];
32907                if($.inArray(keyCode, keyControls) > -1){
32908                    e.preventDefault();
32909                }
32910
32911                controlPressed = e.ctrlKey;
32912
32913                keydownId = setTimeout(function(){
32914                    onkeydown(e);
32915                },150);
32916            }
32917        }
32918
32919        function tooltipTextHandler(){
32920            $(this).prev().trigger('click');
32921        }
32922
32923        //to prevent scrolling while zooming
32924        function keyUpHandler(e){
32925            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32926                controlPressed = e.ctrlKey;
32927            }
32928        }
32929
32930        //binding the mousemove when the mouse's middle button is released
32931        function mouseDownHandler(e){
32932            //middle button
32933            if (e.which == 2){
32934                oldPageY = e.pageY;
32935                container.on('mousemove', mouseMoveHandler);
32936            }
32937        }
32938
32939        //unbinding the mousemove when the mouse's middle button is released
32940        function mouseUpHandler(e){
32941            //middle button
32942            if (e.which == 2){
32943                container.off('mousemove');
32944            }
32945        }
32946
32947        //Scrolling horizontally when clicking on the slider controls.
32948        function slideArrowHandler(){
32949            var section = $(this).closest(SECTION_SEL);
32950
32951            if ($(this).hasClass(SLIDES_PREV)) {
32952                if(isScrollAllowed.m.left){
32953                    moveSlideLeft(section);
32954                }
32955            } else {
32956                if(isScrollAllowed.m.right){
32957                    moveSlideRight(section);
32958                }
32959            }
32960        }
32961
32962        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
32963        function blurHandler(){
32964            isWindowFocused = false;
32965            controlPressed = false;
32966        }
32967
32968        //Scrolls to the section when clicking the navigation bullet
32969        function sectionBulletHandler(e){
32970            e.preventDefault();
32971            var index = $(this).parent().index();
32972            scrollPage($(SECTION_SEL).eq(index));
32973        }
32974
32975        //Scrolls the slider to the given slide destination for the given section
32976        function slideBulletHandler(e){
32977            e.preventDefault();
32978            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
32979            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
32980
32981            landscapeScroll(slides, destiny);
32982        }
32983
32984        /**
32985        * Keydown event
32986        */
32987        function onkeydown(e){
32988            var shiftPressed = e.shiftKey;
32989
32990            //do nothing if we can not scroll or we are not using horizotnal key arrows.
32991            if(!canScroll && [37,39].indexOf(e.which) < 0){
32992                return;
32993            }
32994
32995            switch (e.which) {
32996                //up
32997                case 38:
32998                case 33:
32999                    if(isScrollAllowed.k.up){
33000                        moveSectionUp();
33001                    }
33002                    break;
33003
33004                //down
33005                case 32: //spacebar
33006                    if(shiftPressed && isScrollAllowed.k.up){
33007                        moveSectionUp();
33008                        break;
33009                    }
33010                /* falls through */
33011                case 40:
33012                case 34:
33013                    if(isScrollAllowed.k.down){
33014                        moveSectionDown();
33015                    }
33016                    break;
33017
33018                //Home
33019                case 36:
33020                    if(isScrollAllowed.k.up){
33021                        moveTo(1);
33022                    }
33023                    break;
33024
33025                //End
33026                case 35:
33027                     if(isScrollAllowed.k.down){
33028                        moveTo( $(SECTION_SEL).length );
33029                    }
33030                    break;
33031
33032                //left
33033                case 37:
33034                    if(isScrollAllowed.k.left){
33035                        moveSlideLeft();
33036                    }
33037                    break;
33038
33039                //right
33040                case 39:
33041                    if(isScrollAllowed.k.right){
33042                        moveSlideRight();
33043                    }
33044                    break;
33045
33046                default:
33047                    return; // exit this handler for other keys
33048            }
33049        }
33050
33051        /**
33052        * Detecting the direction of the mouse movement.
33053        * Used only for the middle button of the mouse.
33054        */
33055        var oldPageY = 0;
33056        function mouseMoveHandler(e){
33057            if(canScroll){
33058                // moving up
33059                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33060                    moveSectionUp();
33061                }
33062
33063                // moving down
33064                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
33065                    moveSectionDown();
33066                }
33067            }
33068            oldPageY = e.pageY;
33069        }
33070
33071        /**
33072        * Scrolls horizontal sliders.
33073        */
33074        function landscapeScroll(slides, destiny, direction){
33075            var section = slides.closest(SECTION_SEL);
33076            var v = {
33077                slides: slides,
33078                destiny: destiny,
33079                direction: direction,
33080                destinyPos: destiny.position(),
33081                slideIndex: destiny.index(),
33082                section: section,
33083                sectionIndex: section.index(SECTION_SEL),
33084                anchorLink: section.data('anchor'),
33085                slidesNav: section.find(SLIDES_NAV_SEL),
33086                slideAnchor:  getAnchor(destiny),
33087                prevSlide: section.find(SLIDE_ACTIVE_SEL),
33088                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
33089
33090                //caching the value of isResizing at the momment the function is called
33091                //because it will be checked later inside a setTimeout and the value might change
33092                localIsResizing: isResizing
33093            };
33094            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
33095            v.direction = v.direction ? v.direction : v.xMovement;
33096
33097            //important!! Only do it when not resizing
33098            if(!v.localIsResizing){
33099                //preventing from scrolling to the next/prev section when using scrollHorizontally
33100                canScroll = false;
33101            }
33102
33103            if(options.onSlideLeave){
33104
33105                //if the site is not just resizing and readjusting the slides
33106                if(!v.localIsResizing && v.xMovement!=='none'){
33107                    if($.isFunction( options.onSlideLeave )){
33108                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
33109                            slideMoving = false;
33110                            return;
33111                        }
33112                    }
33113                }
33114            }
33115
33116            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33117
33118            if(!v.localIsResizing){
33119                stopMedia(v.prevSlide);
33120                lazyLoad(destiny);
33121            }
33122
33123            if(!options.loopHorizontal && options.controlArrows){
33124                //hidding it for the fist slide, showing for the rest
33125                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
33126
33127                //hidding it for the last slide, showing for the rest
33128                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
33129            }
33130
33131            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
33132            if(section.hasClass(ACTIVE) && !v.localIsResizing){
33133                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
33134            }
33135
33136            performHorizontalMove(slides, v, true);
33137        }
33138
33139
33140        function afterSlideLoads(v){
33141            activeSlidesNavigation(v.slidesNav, v.slideIndex);
33142
33143            //if the site is not just resizing and readjusting the slides
33144            if(!v.localIsResizing){
33145                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
33146
33147                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
33148                //and to prevent double scroll right after a windows resize
33149                canScroll = true;
33150
33151                playMedia(v.destiny);
33152            }
33153
33154            //letting them slide again
33155            slideMoving = false;
33156        }
33157
33158        /**
33159        * Performs the horizontal movement. (CSS3 or jQuery)
33160        *
33161        * @param fireCallback {Bool} - determines whether or not to fire the callback
33162        */
33163        function performHorizontalMove(slides, v, fireCallback){
33164            var destinyPos = v.destinyPos;
33165
33166            if(options.css3){
33167                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
33168
33169                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
33170
33171                afterSlideLoadsId = setTimeout(function(){
33172                    fireCallback && afterSlideLoads(v);
33173                }, options.scrollingSpeed, options.easing);
33174            }else{
33175                slides.animate({
33176                    scrollLeft : Math.round(destinyPos.left)
33177                }, options.scrollingSpeed, options.easing, function() {
33178
33179                    fireCallback && afterSlideLoads(v);
33180                });
33181            }
33182        }
33183
33184        /**
33185        * Sets the state for the horizontal bullet navigations.
33186        */
33187        function activeSlidesNavigation(slidesNav, slideIndex){
33188            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
33189            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
33190        }
33191
33192        var previousHeight = windowsHeight;
33193
33194        //when resizing the site, we adjust the heights of the sections, slimScroll...
33195        function resizeHandler(){
33196            //checking if it needs to get responsive
33197            responsive();
33198
33199            // rebuild immediately on touch devices
33200            if (isTouchDevice) {
33201                var activeElement = $(document.activeElement);
33202
33203                //if the keyboard is NOT visible
33204                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
33205                    var currentHeight = $window.height();
33206
33207                    //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)
33208                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
33209                        reBuild(true);
33210                        previousHeight = currentHeight;
33211                    }
33212                }
33213            }else{
33214                //in order to call the functions only when the resize is finished
33215                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
33216                clearTimeout(resizeId);
33217
33218                resizeId = setTimeout(function(){
33219                    reBuild(true);
33220                }, 350);
33221            }
33222        }
33223
33224        /**
33225        * Checks if the site needs to get responsive and disables autoScrolling if so.
33226        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
33227        */
33228        function responsive(){
33229            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
33230            var heightLimit = options.responsiveHeight;
33231
33232            //only calculating what we need. Remember its called on the resize event.
33233            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
33234            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
33235
33236            if(widthLimit && heightLimit){
33237                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
33238            }
33239            else if(widthLimit){
33240                setResponsive(isBreakingPointWidth);
33241            }
33242            else if(heightLimit){
33243                setResponsive(isBreakingPointHeight);
33244            }
33245        }
33246
33247        /**
33248        * Adds transition animations for the given element
33249        */
33250        function addAnimation(container, element){
33251            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
33252
33253            container.removeClass(NO_TRANSITION);
33254            return container.css({
33255                '-webkit-transition': transition,
33256                'transition': transition
33257            });
33258        }
33259
33260        /**
33261        * Remove transition animations for the given element
33262        */
33263        function removeAnimation(element){
33264            return element.addClass(NO_TRANSITION);
33265        }
33266
33267        /**
33268        * Activating the vertical navigation bullets according to the given slide name.
33269        */
33270        function activateNavDots(name, sectionIndex){
33271            if(options.navigation){
33272                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
33273                if(name){
33274                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
33275                }else{
33276                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
33277                }
33278            }
33279        }
33280
33281        /**
33282        * Activating the website main menu elements according to the given slide name.
33283        */
33284        function activateMenuElement(name){
33285            if(options.menu){
33286                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
33287                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
33288            }
33289        }
33290
33291        /**
33292        * Sets to active the current menu and vertical nav items.
33293        */
33294        function activateMenuAndNav(anchor, index){
33295            activateMenuElement(anchor);
33296            activateNavDots(anchor, index);
33297        }
33298
33299        /**
33300        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
33301        * from the current section.
33302        */
33303        function getYmovement(destiny){
33304            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
33305            var toIndex = destiny.index(SECTION_SEL);
33306            if( fromIndex == toIndex){
33307                return 'none';
33308            }
33309            if(fromIndex > toIndex){
33310                return 'up';
33311            }
33312            return 'down';
33313        }
33314
33315        /**
33316        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
33317        * from the current slide.
33318        */
33319        function getXmovement(fromIndex, toIndex){
33320            if( fromIndex == toIndex){
33321                return 'none';
33322            }
33323            if(fromIndex > toIndex){
33324                return 'left';
33325            }
33326            return 'right';
33327        }
33328
33329        /**
33330        * Checks if the element needs scrollbar and if the user wants to apply it.
33331        * If so it creates it.
33332        *
33333        * @param {Object} element   jQuery object of the section or slide
33334        */
33335        function createScrollBar(element){
33336            //User doesn't want scrollbar here? Sayonara baby!
33337            if(element.hasClass('fp-noscroll')) return;
33338
33339            //needed to make `scrollHeight` work under Opera 12
33340            element.css('overflow', 'hidden');
33341
33342            var scrollOverflowHandler = options.scrollOverflowHandler;
33343            var wrap = scrollOverflowHandler.wrapContent();
33344            //in case element is a slide
33345            var section = element.closest(SECTION_SEL);
33346            var scrollable = scrollOverflowHandler.scrollable(element);
33347            var contentHeight;
33348
33349            //if there was scroll, the contentHeight will be the one in the scrollable section
33350            if(scrollable.length){
33351                contentHeight = scrollOverflowHandler.scrollHeight(element);
33352            }else{
33353                contentHeight = element.get(0).scrollHeight;
33354                if(options.verticalCentered){
33355                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
33356                }
33357            }
33358
33359            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
33360
33361            //needs scroll?
33362            if ( contentHeight > scrollHeight) {
33363                //did we already have an scrollbar ? Updating it
33364                if(scrollable.length){
33365                    scrollOverflowHandler.update(element, scrollHeight);
33366                }
33367                //creating the scrolling
33368                else{
33369                    if(options.verticalCentered){
33370                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
33371                    }else{
33372                        element.wrapInner(wrap);
33373                    }
33374                    scrollOverflowHandler.create(element, scrollHeight);
33375                }
33376            }
33377            //removing the scrolling when it is not necessary anymore
33378            else{
33379                scrollOverflowHandler.remove(element);
33380            }
33381
33382            //undo
33383            element.css('overflow', '');
33384        }
33385
33386        function addTableClass(element){
33387            //In case we are styling for the 2nd time as in with reponsiveSlides
33388            if(!element.hasClass(TABLE)){
33389                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
33390            }
33391        }
33392
33393        function getTableHeight(element){
33394            var sectionHeight = windowsHeight;
33395
33396            if(options.paddingTop || options.paddingBottom){
33397                var section = element;
33398                if(!section.hasClass(SECTION)){
33399                    section = element.closest(SECTION_SEL);
33400                }
33401
33402                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
33403                sectionHeight = (windowsHeight - paddings);
33404            }
33405
33406            return sectionHeight;
33407        }
33408
33409        /**
33410        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
33411        */
33412        function transformContainer(translate3d, animated){
33413            if(animated){
33414                addAnimation(container);
33415            }else{
33416                removeAnimation(container);
33417            }
33418
33419            container.css(getTransforms(translate3d));
33420
33421            //syncronously removing the class after the animation has been applied.
33422            setTimeout(function(){
33423                container.removeClass(NO_TRANSITION);
33424            },10);
33425        }
33426
33427        /**
33428        * Gets a section by its anchor / index
33429        */
33430        function getSectionByAnchor(sectionAnchor){
33431            if(!sectionAnchor) return [];
33432
33433            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
33434            if(!section.length){
33435                section = $(SECTION_SEL).eq( sectionAnchor -1);
33436            }
33437
33438            return section;
33439        }
33440
33441        /**
33442        * Gets a slide inside a given section by its anchor / index
33443        */
33444        function getSlideByAnchor(slideAnchor, section){
33445            var slides = section.find(SLIDES_WRAPPER_SEL);
33446            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
33447
33448            if(!slide.length){
33449                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
33450            }
33451
33452            return slide;
33453        }
33454
33455        /**
33456        * Scrolls to the given section and slide anchors
33457        */
33458        function scrollPageAndSlide(destiny, slide){
33459            var section = getSectionByAnchor(destiny);
33460
33461            //do nothing if there's no section with the given anchor name
33462            if(!section.length) return;
33463
33464            //default slide
33465            if (typeof slide === 'undefined') {
33466                slide = 0;
33467            }
33468
33469            //we need to scroll to the section and then to the slide
33470            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
33471                scrollPage(section, function(){
33472                    scrollSlider(section, slide);
33473                });
33474            }
33475            //if we were already in the section
33476            else{
33477                scrollSlider(section, slide);
33478            }
33479        }
33480
33481        /**
33482        * Scrolls the slider to the given slide destination for the given section
33483        */
33484        function scrollSlider(section, slideAnchor){
33485            if(typeof slideAnchor !== 'undefined'){
33486                var slides = section.find(SLIDES_WRAPPER_SEL);
33487                var destiny =  getSlideByAnchor(slideAnchor, section);
33488
33489                if(destiny.length){
33490                    landscapeScroll(slides, destiny);
33491                }
33492            }
33493        }
33494
33495        /**
33496        * Creates a landscape navigation bar with dots for horizontal sliders.
33497        */
33498        function addSlidesNavigation(section, numSlides){
33499            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
33500            var nav = section.find(SLIDES_NAV_SEL);
33501
33502            //top or bottom
33503            nav.addClass(options.slidesNavPosition);
33504
33505            for(var i=0; i< numSlides; i++){
33506                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
33507            }
33508
33509            //centering it
33510            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
33511
33512            nav.find('li').first().find('a').addClass(ACTIVE);
33513        }
33514
33515
33516        /**
33517        * Sets the state of the website depending on the active section/slide.
33518        * It changes the URL hash when needed and updates the body class.
33519        */
33520        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
33521            var sectionHash = '';
33522
33523            if(options.anchors.length && !options.lockAnchors){
33524
33525                //isn't it the first slide?
33526                if(slideIndex){
33527                    if(typeof anchorLink !== 'undefined'){
33528                        sectionHash = anchorLink;
33529                    }
33530
33531                    //slide without anchor link? We take the index instead.
33532                    if(typeof slideAnchor === 'undefined'){
33533                        slideAnchor = slideIndex;
33534                    }
33535
33536                    lastScrolledSlide = slideAnchor;
33537                    setUrlHash(sectionHash + '/' + slideAnchor);
33538
33539                //first slide won't have slide anchor, just the section one
33540                }else if(typeof slideIndex !== 'undefined'){
33541                    lastScrolledSlide = slideAnchor;
33542                    setUrlHash(anchorLink);
33543                }
33544
33545                //section without slides
33546                else{
33547                    setUrlHash(anchorLink);
33548                }
33549            }
33550
33551            setBodyClass();
33552        }
33553
33554        /**
33555        * Sets the URL hash.
33556        */
33557        function setUrlHash(url){
33558            //Uncode addition
33559            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
33560                return false;
33561
33562            if(options.recordHistory){
33563                location.hash = url;
33564            }else{
33565                //Uncode addition
33566                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
33567                // if(isTouchDevice || isTouch){
33568                //     window.history.replaceState(undefined, undefined, '#' + url);
33569                // }else{
33570                //     var baseUrl = window.location.href.split('#')[0];
33571                //     window.location.replace( baseUrl + '#' + url );
33572                // }
33573                return false;
33574            }
33575        }
33576
33577        /**
33578        * Gets the anchor for the given slide / section. Its index will be used if there's none.
33579        */
33580        function getAnchor(element){
33581            var anchor = element.data('anchor');
33582            var index = element.index();
33583
33584            //Slide without anchor link? We take the index instead.
33585            if(typeof anchor === 'undefined'){
33586                anchor = index;
33587            }
33588
33589            return anchor;
33590        }
33591
33592        /**
33593        * Sets a class for the body of the page depending on the active section / slide
33594        */
33595        function setBodyClass(){
33596            var section = $(SECTION_ACTIVE_SEL);
33597            var slide = section.find(SLIDE_ACTIVE_SEL);
33598
33599            var sectionAnchor = getAnchor(section);
33600            var slideAnchor = getAnchor(slide);
33601
33602            var text = String(sectionAnchor);
33603
33604            if(slide.length){
33605                text = text + '-' + slideAnchor;
33606            }
33607
33608            //changing slash for dash to make it a valid CSS style
33609            text = text.replace('/', '-').replace('#','');
33610
33611            //removing previous anchor classes
33612            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
33613            $body[0].className = $body[0].className.replace(classRe, '');
33614
33615            //adding the current anchor
33616            $body.addClass(VIEWING_PREFIX + '-' + text);
33617        }
33618
33619        /**
33620        * Checks for translate3d support
33621        * @return boolean
33622        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
33623        */
33624        function support3d() {
33625            var el = document.createElement('p'),
33626                has3d,
33627                transforms = {
33628                    'webkitTransform':'-webkit-transform',
33629                    'OTransform':'-o-transform',
33630                    'msTransform':'-ms-transform',
33631                    'MozTransform':'-moz-transform',
33632                    'transform':'transform'
33633                };
33634
33635            // Add it to the body to get the computed style.
33636            document.body.insertBefore(el, null);
33637
33638            for (var t in transforms) {
33639                if (el.style[t] !== undefined) {
33640                    el.style[t] = 'translate3d(1px,1px,1px)';
33641                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
33642                }
33643            }
33644
33645            document.body.removeChild(el);
33646
33647            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
33648        }
33649
33650        /**
33651        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
33652        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
33653        */
33654        function removeMouseWheelHandler(){
33655            if (document.addEventListener) {
33656                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
33657                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
33658                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
33659            } else {
33660                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
33661            }
33662        }
33663
33664        /**
33665        * Adds the auto scrolling action for the mouse wheel and trackpad.
33666        * After this function is called, the mousewheel and trackpad movements will scroll through sections
33667        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
33668        */
33669        function addMouseWheelHandler(){
33670            var prefix = '';
33671            var _addEventListener;
33672
33673            if (window.addEventListener){
33674                _addEventListener = "addEventListener";
33675            }else{
33676                _addEventListener = "attachEvent";
33677                prefix = 'on';
33678            }
33679
33680             // detect available wheel event
33681            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
33682                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
33683                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
33684            var passiveEvent = g_supportsPassive ? {passive: false }
33684: false;
33685
33686
33687            if(support == 'DOMMouseScroll'){
33688                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
33689            }
33690
33691            //handle MozMousePixelScroll in older Firefox
33692            else{
33693                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
33694            }
33695        }
33696
33697        /**
33698        * Binding the mousemove when the mouse's middle button is pressed
33699        */
33700        function addMiddleWheelHandler(){
33701            container
33702                .on('mousedown', mouseDownHandler)
33703                .on('mouseup', mouseUpHandler);
33704        }
33705
33706        /**
33707        * Unbinding the mousemove when the mouse's middle button is released
33708        */
33709        function removeMiddleWheelHandler(){
33710            container
33711                .off('mousedown', mouseDownHandler)
33712                .off('mouseup', mouseUpHandler);
33713        }
33714
33715        /**
33716        * Adds the possibility to auto scroll through sections on touch devices.
33717        */
33718        function addTouchHandler(){
33719            if(isTouchDevice || isTouch){
33720                if(options.autoScrolling){
33721                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
33722                }
33723
33724                $(WRAPPER_SEL)
33725                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
33726                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
33727            }
33728        }
33729
33730        /**
33731        * Removes the auto scrolling for touch devices.
33732        */
33733        function removeTouchHandler(){
33734            if(isTouchDevice || isTouch){
33735                $(WRAPPER_SEL)
33736                    .off(events.touchstart)
33737                    .off(events.touchmove);
33738            }
33739        }
33740
33741        /*
33742        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
33743        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
33744        */
33745        function getMSPointer(){
33746            var pointer;
33747
33748            //IE >= 11 & rest of browsers
33749            if(window.PointerEvent){
33750                pointer = { down: 'pointerdown', move: 'pointermove'};
33751            }
33752
33753            //IE < 11
33754            else{
33755                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
33756            }
33757
33758            return pointer;
33759        }
33760
33761        /**
33762        * Gets the pageX and pageY properties depending on the browser.
33763        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
33764        */
33765        function getEventsPage(e){
33766            var events = [];
33767
33768            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
33769            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33770
33771            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33772            if(isTouch && isReallyTouch(e) && options.scrollBar){
33773                events.y = e.touches[0].pageY;
33774                events.x = e.touches[0].pageX;
33775            }
33776
33777            return events;
33778        }
33779
33780        /**
33781        * Slides silently (with no animation) the active slider to the given slide.
33782        * @param noCallback {bool} true or defined -> no callbacks
33783        */
33784        function silentLandscapeScroll(activeSlide, noCallbacks){
33785            setScrollingSpeed (0, 'internal');
33786
33787            if(typeof noCallbacks !== 'undefined'){
33788                //preventing firing callbacks afterSlideLoad etc.
33789                isResizing = true;
33790            }
33791
33792            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33793
33794            if(typeof noCallbacks !== 'undefined'){
33795                isResizing = false;
33796            }
33797
33798            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33799        }
33800
33801        /**
33802        * Scrolls silently (with no animation) the page to the given Y position.
33803        */
33804        function silentScroll(top){
33805            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33806            // that's why we round it to 0.
33807            var roundedTop = Math.round(top);
33808
33809            if (options.css3 && options.autoScrolling && !options.scrollBar){
33810                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33811                transformContainer(translate3d, false);
33812            }
33813            else if(options.autoScrolling && !options.scrollBar){
33814                container.css('top', -roundedTop);
33815            }
33816            else{
33817                $htmlBody.scrollTop(roundedTop);
33818            }
33819        }
33820
33821        /**
33822        * Returns the cross-browser transform string.
33823        */
33824        function getTransforms(translate3d){
33825            return {
33826                '-webkit-transform': translate3d,
33827                '-moz-transform': translate3d,
33828                '-ms-transform':translate3d,
33829                'transform': translate3d
33830            };
33831        }
33832
33833        /**
33834        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33835        * @type  m (mouse) or k (keyboard)
33836        */
33837        function setIsScrollAllowed(value, direction, type){
33838            switch (direction){
33839                case 'up': isScrollAllowed[type].up = value; break;
33840                case 'down': isScrollAllowed[type].down = value; break;
33841                case 'left': isScrollAllowed[type].left = value; break;
33842                case 'right': isScrollAllowed[type].right = value; break;
33843                case 'all':
33844                    if(type == 'm'){
33845                        setAllowScrolling(value);
33846                    }else{
33847                        setKeyboardScrolling(value);
33848                    }
33849            }
33850        }
33851
33852        /*
33853        * Destroys fullpage.js plugin events and optinally its html markup and styles
33854        */
33855        function destroy(all){
33856            setAutoScrolling(false, 'internal');
33857            setAllowScrolling(false);
33858            setKeyboardScrolling(false);
33859            container.addClass(DESTROYED);
33860
33861            clearTimeout(afterSlideLoadsId);
33862            clearTimeout(afterSectionLoadsId);
33863            clearTimeout(resizeId);
33864            clearTimeout(scrollId);
33865            clearTimeout(scrollId2);
33866
33867            $window
33868                .off('scroll', scrollHandler)
33869                .off('hashchange', hashChangeHandler)
33870                .off('resize', resizeHandler);
33871
33872            $document
33873                .off('click touchstart', SECTION_NAV_SEL + ' a')
33874                .off('mouseenter', SECTION_NAV_SEL + ' li')
33875                .off('mouseleave', SECTION_NAV_SEL + ' li')
33876                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33877                .off('mouseover', options.normalScrollElements)
33878                .off('mouseout', options.normalScrollElements);
33879
33880            $(SECTION_SEL)
33881                .off('click touchstart', SLIDES_ARROW_SEL);
33882
33883            clearTimeout(afterSlideLoadsId);
33884            clearTimeout(afterSectionLoadsId);
33885
33886            //lets make a mess!
33887            if(all){
33888                destroyStructure();
33889            }
33890        }
33891
33892        /*
33893        * Removes inline styles added by fullpage.js
33894        */
33895        function destroyStructure(){
33896            //reseting the `top` or `translate` properties to 0
33897            silentScroll(0);
33898
33899            //loading all the lazy load content
33900            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33901                setSrc($(this), 'src');
33902            });
33903
33904            container.find('img[data-srcset]').each(function(){
33905                setSrc($(this), 'srcset');
33906            });
33907
33908            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33909
33910            //removing inline styles
33911            $(SECTION_SEL).css( {
33912                'height': '',
33913                'background-color' : '',
33914                'padding': ''
33915            });
33916
33917            $(SLIDE_SEL).css( {
33918                'width': ''
33919            });
33920
33921            container.css({
33922                'height': '',
33923                'position': '',
33924                '-ms-touch-action': '',
33925                'touch-action': ''
33926            });
33927
33928            $htmlBody.css({
33929                'overflow': '',
33930                'height': ''
33931            });
33932
33933            // remove .fp-enabled class
33934            $('html').removeClass(ENABLED);
33935
33936            // remove .fp-responsive class
33937            $body.removeClass(RESPONSIVE);
33938
33939            // remove all of the .fp-viewing- classes
33940            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33941                if (className.indexOf(VIEWING_PREFIX) === 0) {
33942                    $body.removeClass(className);
33943                }
33944            });
33945
33946            //removing added classes
33947            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
33948                options.scrollOverflowHandler.remove($(this));
33949                $(this).removeClass(TABLE + ' ' + ACTIVE);
33950            });
33951
33952            removeAnimation(container);
33953
33954            //Unwrapping content
33955            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
33956                //unwrap not being use in case there's no child element inside and its just text
33957                $(this).replaceWith(this.childNodes);
33958            });
33959
33960            //removing the applied transition from the fullpage wrapper
33961            container.css({
33962                '-webkit-transition': 'none',
33963                'transition': 'none'
33964            });
33965
33966            //scrolling the page to the top with no animation
33967            $htmlBody.scrollTop(0);
33968
33969            //removing selectors
33970            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
33971            $.each(usedSelectors, function(index, value){
33972                $('.' + value).removeClass(value);
33973            });
33974        }
33975
33976        /*
33977        * Sets the state for a variable with multiple states (original, and temporal)
33978        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
33979        * This function is used to keep track of both states, the original and the temporal one.
33980        * If type is not 'internal', then we assume the user is globally changing the variable.
33981        */
33982        function setVariableState(variable, value, type){
33983            options[variable] = value;
33984            if(type !== 'internal'){
33985                originals[variable] = value;
33986            }
33987        }
33988
33989        /**
33990        * Displays warnings
33991        */
33992        function displayWarnings(){
33993            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
33994            //UNCODE.addition
33995            // if($('html').hasClass(ENABLED)){
33996            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
33997            //     return;
33998            // }
33999
34000            // Disable mutually exclusive settings
34001            //UNCODE.addition
34002            // if (options.continuousVertical &&
34003            //     (options.loopTop || options.loopBottom)) {
34004            //     options.continuousVertical = false;
34005            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34006            // }
34007
34008            // if(options.scrollBar && options.scrollOverflow){
34009            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34010            // }
34011
34012            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34013            //     options.continuousVertical = false;
34014            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34015            // }
34016
34017            //using extensions? Wrong file!
34018            $.each(extensions, function(index, extension){
34019                //is the option set to true?
34020                if(options[extension]){
34021                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34022                }
34023            });
34024
34025            //anchors can not have the same value as any element ID or NAME
34026            $.each(options.anchors, function(index, name){
34027
34028                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34029                var nameAttr = $document.find('[name]').filter(function() {
34030                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34031                });
34032
34033                var idAttr = $document.find('[id]').filter(function() {
34034                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34035                });
34036
34037                if(idAttr.length || nameAttr.length ){
34038                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34039                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34040                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34041                }
34042            });
34043        }
34044
34045        /**
34046        * Shows a message in the console of the given type.
34047        */
34048        function showError(type, text){
34049            console && console[type] && console[type]('fullPage: ' + text);
34050        }
34051
34052    }; //end of $.fn.fullpage
34053
34054    if(typeof IScroll !== 'undefined'){
34055        /*
34056        * Turns iScroll `mousewheel` option off dynamically
34057        * https://github.com/cubiq/iscroll/issues/1036
34058        */
34059        IScroll.prototype.wheelOn = function () {
34060            this.wrapper.addEventListener('wheel', this);
34061            this.wrapper.addEventListener('mousewheel', this);
34062            this.wrapper.addEventListener('DOMMouseScroll', this);
34063        };
34064
34065        /*
34066        * Turns iScroll `mousewheel` option on dynamically
34067        * https://github.com/cubiq/iscroll/issues/1036
34068        */
34069        IScroll.prototype.wheelOff = function () {
34070            this.wrapper.removeEventListener('wheel', this);
34071            this.wrapper.removeEventListener('mousewheel', this);
34072            this.wrapper.removeEventListener('DOMMouseScroll', this);
34073        };
34074    }
34075
34076    /**
34077     * An object to handle overflow scrolling.
34078     * This uses jquery.slimScroll to accomplish overflow scrolling.
34079     * It is possible to pass in an alternate scrollOverflowHandler
34080     * to the fullpage.js option that implements the same functions
34081     * as this handler.
34082     *
34083     * @type {Object}
34084     */
34085    var iscrollHandler = {
34086        refreshId: null,
34087        iScrollInstances: [],
34088
34089        // Enables or disables the mouse wheel for the active section or all slides in it
34090        toggleWheel: function(value){
34091            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
34092            scrollable.each(function(){
34093                var iScrollInstance = $(this).data('iscrollInstance');
34094                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
34095                    if(value){
34096                        iScrollInstance.wheelOn();
34097                    }
34098                    else{
34099                        iScrollInstance.wheelOff();
34100                    }
34101                }
34102            });
34103        },
34104
34105        /**
34106        * Turns off iScroll for the destination section.
34107        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
34108        * scroll the destination section/slide before the sections animations ends.
34109        */
34110        onLeave: function(){
34111            iscrollHandler.toggleWheel(false);
34112        },
34113
34114        // Turns off iScroll for the leaving section
34115        beforeLeave: function(){
34116            iscrollHandler.onLeave()
34117        },
34118
34119        // Turns on iScroll on section load
34120        afterLoad: function(){
34121            iscrollHandler.toggleWheel(true);
34122        },
34123
34124        /**
34125         * Called when overflow scrolling is needed for a section.
34126         *
34127         * @param  {Object} element      jQuery object containing current section
34128         * @param  {Number} scrollHeight Current window height in pixels
34129         */
34130        create: function(element, scrollHeight) {
34131            var scrollable = element.find(SCROLLABLE_SEL);
34132
34133            scrollable.height(scrollHeight);
34134            scrollable.each(function() {
34135                var $this = $(this);
34136                var iScrollInstance = $this.data('iscrollInstance');
34137                if (iScrollInstance) {
34138                    $.each(iscrollHandler.iScrollInstances, function(){
34139                        $(this).destroy();
34140                    });
34141                }
34142
34143                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
34144                iscrollHandler.iScrollInstances.push(iScrollInstance);
34145
34146                //off by default until the section gets active
34147                iScrollInstance.wheelOff();
34148
34149                $this.data('iscrollInstance', iScrollInstance);
34150            });
34151        },
34152
34153        /**
34154         * Return a boolean depending on whether the scrollable element is a
34155         * the end or at the start of the scrolling depending on the given type.
34156         *
34157         * @param  {String}  type       Either 'top' or 'bottom'
34158         * @param  {Object}  scrollable jQuery object for the scrollable element
34159         * @return {Boolean}
34160         */
34161        isScrolled: function(type, scrollable) {
34162            var scroller = scrollable.data('iscrollInstance');
34163
34164            //no scroller?
34165            if (!scroller) {
34166                return true;
34167            }
34168
34169            //Uncode addition
34170            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
34171            //End Uncode addition
34172
34173            if (type === 'top') {
34174                return scroller.y >= 0 && !scrollable.scrollTop();
34175            } else if (type === 'bottom') {
34176                //Uncode change
34177                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34178                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34179                //End Uncode change
34180            }
34181        },
34182
34183        /**
34184         * Returns the scrollable element for the given section.
34185         * If there are landscape slides, will only return a scrollable element
34186         * if it is in the active slide.
34187         *
34188         * @param  {Object}  activeSection jQuery object containing current section
34189         * @return {Boolean}
34190         */
34191        scrollable: function(activeSection){
34192            // if there are landscape slides, we check if the scrolling bar is in the current one or not
34193            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
34194                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
34195            }
34196            return activeSection.find(SCROLLABLE_SEL);
34197        },
34198
34199        /**
34200         * Returns the scroll height of the wrapped content.
34201         * If this is larger than the window height minus section padding,
34202         * overflow scrolling is needed.
34203         *
34204         * @param  {Object} element jQuery object containing current section
34205         * @return {Number}
34206         */
34207        scrollHeight: function(element) {
34208            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
34209        },
34210
34211        /**
34212         * Called when overflow scrolling is no longer needed for a section.
34213         *
34214         * @param  {Object}
34214 element      jQuery object containing current section
34215         */
34216        remove: function(element) {
34217            var scrollable = element.find(SCROLLABLE_SEL);
34218            if (scrollable.length) {
34219                var iScrollInstance = scrollable.data('iscrollInstance');
34220                iScrollInstance.destroy();
34221
34222                scrollable.data('iscrollInstance', null);
34223            }
34224            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
34225        },
34226
34227        /**
34228         * Called when overflow scrolling has already been setup but the
34229         * window height has potentially changed.
34230         *
34231         * @param  {Object} element      jQuery object containing current section
34232         * @param  {Number} scrollHeight Current window height in pixels
34233         */
34234        update: function(element, scrollHeight) {
34235            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
34236            //short period of time.
34237            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
34238            clearTimeout(iscrollHandler.refreshId);
34239            iscrollHandler.refreshId = setTimeout(function(){
34240                $.each(iscrollHandler.iScrollInstances, function(){
34241                    $(this).get(0).refresh();
34242                });
34243            }, 150);
34244
34245            //updating the wrappers height
34246            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
34247        },
34248
34249        /**
34250         * Called to get any additional elements needed to wrap the section
34251         * content in order to facilitate overflow scrolling.
34252         *
34253         * @return {String|Object} Can be a string containing HTML,
34254         *                         a DOM element, or jQuery object.
34255         */
34256        wrapContent: function() {
34257            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
34258        }
34259    };
34260});
34261
34262(function (global, factory) {
34263	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
34264	typeof define === 'function' && define.amd ? define(['exports'], factory) :
34265	(global = global || self, factory(global.window = global.window || {}));
34266}(this, (function (exports) { 'use strict';
34267
34268	/*!
34269	 * ScrollTrigger 3.8.0
34270	 * https://greensock.com
34271	 *
34272	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
34273	 * Subject to the terms at https://greensock.com/standard-license or for
34274	 * Club GreenSock members, the agreement issued with that membership.
34275	 * @author: Jack Doyle, [email protected]
34276	*/
34277	var gsap,
34278	    _coreInitted,
34279	    _win,
34280	    _doc,
34281	    _docEl,
34282	    _body,
34283	    _root,
34284	    _resizeDelay,
34285	    _raf,
34286	    _request,
34287	    _toArray,
34288	    _clamp,
34289	    _time2,
34290	    _syncInterval,
34291	    _refreshing,
34292	    _pointerIsDown,
34293	    _transformProp,
34294	    _i,
34295	    _prevWidth,
34296	    _prevHeight,
34297	    _autoRefresh,
34298	    _sort,
34299	    _suppressOverwrites,
34300	    _ignoreResize,
34301	    _limitCallbacks,
34302	    _startup = 1,
34303	    _proxies = [],
34304	    _scrollers = [],
34305	    _getTime = Date.now,
34306	    _time1 = _getTime(),
34307	    _lastScrollTime = 0,
34308	    _enabled = 1,
34309	    _passThrough = function _passThrough(v) {
34310	  return v;
34311	},
34312	    _getTarget = function _getTarget(t) {
34313	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
34314	},
34315	    _round = function _round(value) {
34316	  return Math.round(value * 100000) / 100000 || 0;
34317	},
34318	    _windowExists = function _windowExists() {
34319	  return typeof window !== "undefined";
34320	},
34321	    _getGSAP = function _getGSAP() {
34322	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
34323	},
34324	    _isViewport = function _isViewport(e) {
34325	  return !!~_root.indexOf(e);
34326	},
34327	    _getProxyProp = function _getProxyProp(element, property) {
34328	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
34329	},
34330	    _getScrollFunc = function _getScrollFunc(element, _ref) {
34331	  var s = _ref.s,
34332	      sc = _ref.sc;
34333
34334	  var i = _scrollers.indexOf(element),
34335	      offset = sc === _vertical.sc ? 1 : 2;
34336
34337	  !~i && (i = _scrollers.push(element) - 1);
34338	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
34339	    return arguments.length ? element[s] = value : element[s];
34340	  }));
34341	},
34342	    _getBoundsFunc = function _getBoundsFunc(element) {
34343	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
34344	    _winOffsets.width = _win.innerWidth;
34345	    _winOffsets.height = _win.innerHeight;
34346	    return _winOffsets;
34347	  } : function () {
34348	    return _getBounds(element);
34349	  });
34350	},
34351	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
34352	  var d = _ref2.d,
34353	      d2 = _ref2.d2,
34354	      a = _ref2.a;
34355	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
34356	    return a()[d];
34357	  } : function () {
34358	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
34359	  };
34360	},
34361	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
34362	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
34363	    return _winOffsets;
34364	  };
34365	},
34366	    _maxScroll = function _maxScroll(element, _ref3) {
34367	  var s = _ref3.s,
34368	      d2 = _ref3.d2,
34369	      d = _ref3.d,
34370	      a = _ref3.a;
34371	  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];
34372	},
34373	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
34374	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 34375-34579
34375	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
34376	  }
34377	},
34378	    _isString = function _isString(value) {
34379	  return typeof value === "string";
34380	},
34381	    _isFunction = function _isFunction(value) {
34382	  return typeof value === "function";
34383	},
34384	    _isNumber = function _isNumber(value) {
34385	  return typeof value === "number";
34386	},
34387	    _isObject = function _isObject(value) {
34388	  return typeof value === "object";
34389	},
34390	    _callIfFunc = function _callIfFunc(value) {
34391	  return _isFunction(value) && value();
34392	},
34393	    _combineFunc = function _combineFunc(f1, f2) {
34394	  return function () {
34395	    var result1 = _callIfFunc(f1),
34396	        result2 = _callIfFunc(f2);
34397
34398	    return function () {
34399	      _callIfFunc(result1);
34400
34401	      _callIfFunc(result2);
34402	    };
34403	  };
34404	},
34405	    _endAnimation = function _endAnimation(animation, reversed, pause) {
34406	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
34407	},
34408	    _callback = function _callback(self, func) {
34409	  var result = func(self);
34410	  result && result.totalTime && (self.callbackAnimation = result);
34411	},
34412	    _abs = Math.abs,
34413	    _scrollLeft = "scrollLeft",
34414	    _scrollTop = "scrollTop",
34415	    _left = "left",
34416	    _top = "top",
34417	    _right = "right",
34418	    _bottom = "bottom",
34419	    _width = "width",
34420	    _height = "height",
34421	    _Right = "Right",
34422	    _Left = "Left",
34423	    _Top = "Top",
34424	    _Bottom = "Bottom",
34425	    _padding = "padding",
34426	    _margin = "margin",
34427	    _Width = "Width",
34428	    _Height = "Height",
34429	    _px = "px",
34430	    _horizontal = {
34431	  s: _scrollLeft,
34432	  p: _left,
34433	  p2: _Left,
34434	  os: _right,
34435	  os2: _Right,
34436	  d: _width,
34437	  d2: _Width,
34438	  a: "x",
34439	  sc: function sc(value) {
34440	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
34441	  }
34442	},
34443	    _vertical = {
34444	  s: _scrollTop,
34445	  p: _top,
34446	  p2: _Top,
34447	  os: _bottom,
34448	  os2: _Bottom,
34449	  d: _height,
34450	  d2: _Height,
34451	  a: "y",
34452	  op: _horizontal,
34453	  sc: function sc(value) {
34454	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
34455	  }
34456	},
34457	    _getComputedStyle = function _getComputedStyle(element) {
34458	  return _win.getComputedStyle(element);
34459	},
34460	    _makePositionable = function _makePositionable(element) {
34461	  var position = _getComputedStyle(element).position;
34462
34463	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
34464	},
34465	    _setDefaults = function _setDefaults(obj, defaults) {
34466	  for (var p in defaults) {
34467	    p in obj || (obj[p] = defaults[p]);
34468	  }
34469
34470	  return obj;
34471	},
34472	    _getBounds = function _getBounds(element, withoutTransforms) {
34473	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
34474	    x: 0,
34475	    y: 0,
34476	    xPercent: 0,
34477	    yPercent: 0,
34478	    rotation: 0,
34479	    rotationX: 0,
34480	    rotationY: 0,
34481	    scale: 1,
34482	    skewX: 0,
34483	    skewY: 0
34484	  }).progress(1),
34485	      bounds = element.getBoundingClientRect();
34486	  tween && tween.progress(0).kill();
34487	  return bounds;
34488	},
34489	    _getSize = function _getSize(element, _ref4) {
34490	  var d2 = _ref4.d2;
34491	  return element["offset" + d2] || element["client" + d2] || 0;
34492	},
34493	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
34494	  var a = [],
34495	      labels = timeline.labels,
34496	      duration = timeline.duration(),
34497	      p;
34498
34499	  for (p in labels) {
34500	    a.push(labels[p] / duration);
34501	  }
34502
34503	  return a;
34504	},
34505	    _getClosestLabel = function _getClosestLabel(animation) {
34506	  return function (value) {
34507	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
34508	  };
34509	},
34510	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
34511	  var snap = gsap.utils.snap(snapIncrementOrArray),
34512	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
34513	    return a - b;
34514	  });
34515	  return a ? function (value, direction) {
34516	    var i;
34517
34518	    if (!direction) {
34519	      return snap(value);
34520	    }
34521
34522	    if (direction > 0) {
34523	      value -= 1e-4;
34524
34525	      for (i = 0; i < a.length; i++) {
34526	        if (a[i] >= value) {
34527	          return a[i];
34528	        }
34529	      }
34530
34531	      return a[i - 1];
34532	    } else {
34533	      i = a.length;
34534	      value += 1e-4;
34535
34536	      while (i--) {
34537	        if (a[i] <= value) {
34538	          return a[i];
34539	        }
34540	      }
34541	    }
34542
34543	    return a[0];
34544	  } : function (value, direction) {
34545	    var snapped = snap(value);
34546	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
34547	  };
34548	},
34549	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
34550	  return function (value, st) {
34551	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
34552	  };
34553	},
34554	    _multiListener = function _multiListener(func, element, types, callback) {
34555	  return types.split(",").forEach(function (type) {
34556	    return func(element, type, callback);
34557	  });
34558	},
34559	    _addListener = function _addListener(element, type, func) {
34560	  return element.addEventListener(type, func, {
34561	    passive: true
34562	  });
34563	},
34564	    _removeListener = function _removeListener(element, type, func) {
34565	  return element.removeEventListener(type, func);
34566	},
34567	    _markerDefaults = {
34568	  startColor: "green",
34569	  endColor: "red",
34570	  indent: 0,
34571	  fontSize: "16px",
34572	  fontWeight: "normal"
34573	},
34574	    _defaults = {
34575	  toggleActions: "play",
34576	  anticipatePin: 0
34577	},
34578	    _keywords = {
34579	  top: 0,
34580	  left: 0,
34581	  center: 0.5,
34582	  bottom: 1,
34583	  right: 1
34584	},
34585	    _offsetToPx = function _offsetToPx(value, size) {
34586	  if (_isString(value)) {
34587	    var eqIndex = value.indexOf("="),
34588	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
34589
34590	    if (~eqIndex) {
34591	      value.indexOf("%") > eqIndex && (relative *= size / 100);
34592	      value = value.substr(0, eqIndex - 1);
34593	    }
34594
34595	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
34596	  }
34597
34598	  return value;
34599	},
34600	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
34601	  var startColor = _ref5.startColor,
34602	      endColor = _ref5.endColor,
34603	      fontSize = _ref5.fontSize,
34604	      indent = _ref5.indent,
34605	      fontWeight = _ref5.fontWeight;
34606
34607	  var e = _doc.createElement("div"),
34608	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
34609	      isScroller = type.indexOf("scroller") !== -1,
34610	      parent = useFixedPosition ? _body : container,
34611	      isStart = type.indexOf("start") !== -1,
34612	      color = isStart ? startColor : endColor,
34613	      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;";
34614
34615	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
34616	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
34617	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
34618	  e._isStart = isStart;
34619	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
34620	  e.style.cssText = css;
34621	  e.innerText = name || name === 0 ? type + "-" + name : type;
34622	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
34623	  e._offset = e["offset" + direction.op.d2];
34624
34625	  _positionMarker(e, 0, direction, isStart);
34626
34627	  return e;
34628	},
34629	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
34630	  var vars = {
34631	    display: "block"
34632	  },
34633	      side = direction[flipped ? "os2" : "p2"],
34634	      oppositeSide = direction[flipped ? "p2" : "os2"];
34635	  marker._isFlipped = flipped;
34636	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
34637	  vars[direction.a] = flipped ? "1px" : 0;
34638	  vars["border" + side + _Width] = 1;
34639	  vars["border" + oppositeSide + _Width] = 0;
34640	  vars[direction.p] = start + "px";
34641	  gsap.set(marker, vars);
34642	},
34643	    _triggers = [],
34644	    _ids = {},
34645	    _sync = function _sync() {
34646	  return _getTime() - _lastScrollTime > 20 && _updateAll();
34647	},
34648	    _onScroll = function _onScroll() {
34649	  var time = _getTime();
34650
34651	  if (_lastScrollTime !== time) {
34652	    _updateAll();
34653
34654	    _lastScrollTime || _dispatch("scrollStart");
34655	    _lastScrollTime = time;
34656	  } else if (!_request) {
34657	    _request = _raf(_updateAll);
34658	  }
34659	},
34660	    _onResize = function _onResize() {
34661	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
34662	},
34663	    _listeners = {},
34664	    _emptyArray = [],
34665	    _media = [],
34666	    _creatingMedia,
34667	    _lastMediaTick,
34668	    _onMediaChange = function _onMediaChange(e) {
34669	  var tick = gsap.ticker.frame,
34670	      matches = [],
34671	      i = 0,
34672	      index;
34673
34674	  if (_lastMediaTick !== tick || _startup) {
34675	    _revertAll();
34676
34677	    for (; i < _media.length; i += 4) {
34678	      index = _win.matchMedia(_media[i]).matches;
34679
34680	      if (index !== _media[i + 3]) {
34681	        _media[i + 3] = index;
34682	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
34683	      }
34684	    }
34685
34686	    _revertRecorded();
34687
34688	    for (i = 0; i < matches.length; i++) {
34689	      index = matches[i];
34690	      _creatingMedia = _media[index];
34691	      _media[index + 2] = _media[index + 1](e);
34692	    }
34693
34694	    _creatingMedia = 0;
34695	    _coreInitted && _refreshAll(0, 1);
34696	    _lastMediaTick = tick;
34697
34698	    _dispatch("matchMedia");
34699	  }
34700	},
34701	    _softRefresh = function _softRefresh() {
34702	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
34703	},
34704	    _dispatch = function _dispatch(type) {
34705	  return _listeners[type] && _listeners[type].map(function (f) {
34706	    return f();
34707	  }) || _emptyArray;
34708	},
34709	    _savedStyles = [],
34710	    _revertRecorded = function _revertRecorded(media) {
34711	  for (var i = 0; i < _savedStyles.length; i += 5) {
34712	    if (!media || _savedStyles[i + 4] === media) {
34713	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
34714	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
34715	      _savedStyles[i + 3].uncache = 1;
34716	    }
34717	  }
34718	},
34719	    _revertAll = function _revertAll(kill, media) {
34720	  var trigger;
34721
34722	  for (_i = 0; _i < _triggers.length; _i++) {
34723	    trigger = _triggers[_i];
34724
34725	    if (!media || trigger.media === media) {
34726	      if (kill) {
34727	        trigger.kill(1);
34728	      } else {
34729	        trigger.revert();
34730	      }
34731	    }
34732	  }
34733
34734	  media && _revertRecorded(media);
34735	  media || _dispatch("revert");
34736	},
34737	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 34738-35072
34738	  return _scrollers.forEach(function (obj) {
34739	    return typeof obj === "function" && (obj.rec = 0);
34740	  });
34741	},
34742	    _refreshingAll,
34743	    _refreshAll = function _refreshAll(force, skipRevert) {
34744	  if (_lastScrollTime && !force) {
34745	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34746
34747	    return;
34748	  }
34749
34750	  _refreshingAll = true;
34751
34752	  var refreshInits = _dispatch("refreshInit");
34753
34754	  _sort && ScrollTrigger.sort();
34755	  skipRevert || _revertAll();
34756
34757	  _triggers.forEach(function (t) {
34758	    return t.refresh();
34759	  });
34760
34761	  refreshInits.forEach(function (result) {
34762	    return result && result.render && result.render(-1);
34763	  });
34764
34765	  _clearScrollMemory();
34766
34767	  _resizeDelay.pause();
34768
34769	  _refreshingAll = false;
34770
34771	  _dispatch("refresh");
34772	},
34773	    _lastScroll = 0,
34774	    _direction = 1,
34775	    _updateAll = function _updateAll() {
34776	  if (!_refreshingAll) {
34777	    var l = _triggers.length,
34778	        time = _getTime(),
34779	        recordVelocity = time - _time1 >= 50,
34780	        scroll = l && _triggers[0].scroll();
34781
34782	    _direction = _lastScroll > scroll ? -1 : 1;
34783	    _lastScroll = scroll;
34784
34785	    if (recordVelocity) {
34786	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34787	        _lastScrollTime = 0;
34788
34789	        _dispatch("scrollEnd");
34790	      }
34791
34792	      _time2 = _time1;
34793	      _time1 = time;
34794	    }
34795
34796	    if (_direction < 0) {
34797	      _i = l;
34798
34799	      while (_i-- > 0) {
34800	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34801	      }
34802
34803	      _direction = 1;
34804	    } else {
34805	      for (_i = 0; _i < l; _i++) {
34806	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34807	      }
34808	    }
34809
34810	    _request = 0;
34811	  }
34812	},
34813	    _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"],
34814	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34815	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34816	  _setState(state);
34817
34818	  var cache = pin._gsap;
34819
34820	  if (cache.spacerIsNative) {
34821	    _setState(cache.spacerState);
34822	  } else if (pin.parentNode === spacer) {
34823	    var parent = spacer.parentNode;
34824
34825	    if (parent) {
34826	      parent.insertBefore(pin, spacer);
34827	      parent.removeChild(spacer);
34828	    }
34829	  }
34830	},
34831	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34832	  if (pin.parentNode !== spacer) {
34833	    var i = _propNamesToCopy.length,
34834	        spacerStyle = spacer.style,
34835	        pinStyle = pin.style,
34836	        p;
34837
34838	    while (i--) {
34839	      p = _propNamesToCopy[i];
34840	      spacerStyle[p] = cs[p];
34841	    }
34842
34843	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34844	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34845	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34846	    spacerStyle.overflow = "visible";
34847	    spacerStyle.boxSizing = "border-box";
34848	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34849	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34850	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34851
34852	    _setState(spacerState);
34853
34854	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34855	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34856	    pinStyle[_padding] = cs[_padding];
34857	    pin.parentNode.insertBefore(spacer, pin);
34858	    spacer.appendChild(pin);
34859	  }
34860	},
34861	    _capsExp = /([A-Z])/g,
34862	    _setState = function _setState(state) {
34863	  if (state) {
34864	    var style = state.t.style,
34865	        l = state.length,
34866	        i = 0,
34867	        p,
34868	        value;
34869	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34870
34871	    for (; i < l; i += 2) {
34872	      value = state[i + 1];
34873	      p = state[i];
34874
34875	      if (value) {
34876	        style[p] = value;
34877	      } else if (style[p]) {
34878	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34879	      }
34880	    }
34881	  }
34882	},
34883	    _getState = function _getState(element) {
34884	  var l = _stateProps.length,
34885	      style = element.style,
34886	      state = [],
34887	      i = 0;
34888
34889	  for (; i < l; i++) {
34890	    state.push(_stateProps[i], style[_stateProps[i]]);
34891	  }
34892
34893	  state.t = element;
34894	  return state;
34895	},
34896	    _copyState = function _copyState(state, override, omitOffsets) {
34897	  var result = [],
34898	      l = state.length,
34899	      i = omitOffsets ? 8 : 0,
34900	      p;
34901
34902	  for (; i < l; i += 2) {
34903	    p = state[i];
34904	    result.push(p, p in override ? override[p] : state[i + 1]);
34905	  }
34906
34907	  result.t = state.t;
34908	  return result;
34909	},
34910	    _winOffsets = {
34911	  left: 0,
34912	  top: 0
34913	},
34914	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34915	  _isFunction(value) && (value = value(self));
34916
34917	  if (_isString(value) && value.substr(0, 3) === "max") {
34918	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34919	  }
34920
34921	  var time = containerAnimation ? containerAnimation.time() : 0,
34922	      p1,
34923	      p2,
34924	      element;
34925	  containerAnimation && containerAnimation.seek(0);
34926
34927	  if (!_isNumber(value)) {
34928	    _isFunction(trigger) && (trigger = trigger(self));
34929	    var offsets = value.split(" "),
34930	        bounds,
34931	        localOffset,
34932	        globalOffset,
34933	        display;
34934	    element = _getTarget(trigger) || _body;
34935	    bounds = _getBounds(element) || {};
34936
34937	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34938	      display = element.style.display;
34939	      element.style.display = "block";
34940	      bounds = _getBounds(element);
34941	      display ? element.style.display = display : element.style.removeProperty("display");
34942	    }
34943
34944	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
34945	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
34946	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
34947	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
34948	    scrollerSize -= scrollerSize - globalOffset;
34949	  } else if (markerScroller) {
34950	    _positionMarker(markerScroller, scrollerSize, direction, true);
34951	  }
34952
34953	  if (marker) {
34954	    var position = value + scrollerSize,
34955	        isStart = marker._isStart;
34956	    p1 = "scroll" + direction.d2;
34957
34958	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
34959
34960	    if (useFixedPosition) {
34961	      scrollerBounds = _getBounds(markerScroller);
34962	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
34963	    }
34964	  }
34965
34966	  if (containerAnimation && element) {
34967	    p1 = _getBounds(element);
34968	    containerAnimation.seek(scrollerMax);
34969	    p2 = _getBounds(element);
34970	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
34971	    value = value / containerAnimation._caScrollDist * scrollerMax;
34972	  }
34973
34974	  containerAnimation && containerAnimation.seek(time);
34975	  return containerAnimation ? value : Math.round(value);
34976	},
34977	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
34978	    _reparent = function _reparent(element, parent, top, left) {
34979	  if (element.parentNode !== parent) {
34980	    var style = element.style,
34981	        p,
34982	        cs;
34983
34984	    if (parent === _body) {
34985	      element._stOrig = style.cssText;
34986	      cs = _getComputedStyle(element);
34987
34988	      for (p in cs) {
34989	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
34990	          style[p] = cs[p];
34991	        }
34992	      }
34993
34994	      style.top = top;
34995	      style.left = left;
34996	    } else {
34997	      style.cssText = element._stOrig;
34998	    }
34999
35000	    gsap.core.getCache(element).uncache = 1;
35001	    parent.appendChild(element);
35002	  }
35003	},
35004	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
35005	  var getScroll = _getScrollFunc(scroller, direction),
35006	      prop = "_scroll" + direction.p2,
35007	      lastScroll1,
35008	      lastScroll2,
35009	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
35010	    var tween = getTween.tween,
35011	        onComplete = vars.onComplete,
35012	        modifiers = {};
35013	    tween && tween.kill();
35014	    lastScroll1 = Math.round(initialValue);
35015	    vars[prop] = scrollTo;
35016	    vars.modifiers = modifiers;
35017
35018	    modifiers[prop] = function (value) {
35019	      value = _round(getScroll());
35020
35021	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
35022	        tween.kill();
35023	        getTween.tween = 0;
35024	      } else {
35025	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
35026	      }
35027
35028	      lastScroll2 = lastScroll1;
35029	      return lastScroll1 = _round(value);
35030	    };
35031
35032	    vars.onComplete = function () {
35033	      getTween.tween = 0;
35034	      onComplete && onComplete.call(tween);
35035	    };
35036
35037	    tween = getTween.tween = gsap.to(scroller, vars);
35038	    return tween;
35039	  };
35040
35041	  scroller[prop] = getScroll;
35042	  scroller.addEventListener("wheel", function () {
35043	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
35044	  }, {
35045	    passive: true
35046	  });
35047	  return getTween;
35048	};
35049
35050	_horizontal.op = _vertical;
35051	var ScrollTrigger = function () {
35052	  function ScrollTrigger(vars, animation) {
35053	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
35054	    this.init(vars, animation);
35055	  }
35056
35057	  var _proto = ScrollTrigger.prototype;
35058
35059	  _proto.init = function init(vars, animation) {
35060	    this.progress = this.start = 0;
35061	    this.vars && this.kill(1);
35062
35063	    if (!_enabled) {
35064	      this.update = this.refresh = this.kill = _passThrough;
35065	      return;
35066	    }
35067
35068	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
35069	      trigger: vars
35070	    } : vars, _defaults);
35071
35072	    var _vars = vars,
35073	        onUpdate = _vars.onUpdate,
35074	        toggleClass = _vars.toggleClass,
35075	        id = _vars.id,
35076	        onToggle = _vars.onToggle,
35077	        onRefresh = _vars.onRefresh,
35078	        scrub = _vars.scrub,
35079	        trigger = _vars.trigger,
35080	        pin = _vars.pin,
35081	        pinSpacing = _vars.pinSpacing,
35082	        invalidateOnRefresh = _vars.invalidateOnRefresh,
35083	        anticipatePin = _vars.anticipatePin,
35084	        onScrubComplete = _vars.onScrubComplete,
35085	        onSnapComplete = _vars.onSnapComplete,
35086	        once = _vars.once,
35087	        snap = _vars.snap,
35088	        pinReparent = _vars.pinReparent,
35089	        pinSpacer = _vars.pinSpacer,
35090	        containerAnimation = _vars.containerAnimation,
35091	        fastScrollEnd = _vars.fastScrollEnd,
35092	        preventOverlaps = _vars.preventOverlaps,
35093	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
35094	        isToggle = !scrub && scrub !== 0,
35095	        scroller = _getTarget(vars.scroller || _win),
35096	        scrollerCache = gsap.core.getCache(scroller),
35097	        isViewport = _isViewport(scroller),
35098	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
35099	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
35100	        toggleActions = isToggle && vars.toggleActions.split(" "),
35101	        markers = "markers" in vars ? vars.markers : _defaults.markers,
35102	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
35103	        self = this,
35104	        onRefreshInit = vars.onRefreshInit && function () {
35105	      return vars.onRefreshInit(self);
35106	    },
35107	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
35108	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
35109	        lastSnap = 0,
35110	        scrollFunc = _getScrollFunc(scroller, direction),
35111	        tweenTo,
35112	        pinCache,
35113	        snapFunc,
35114	        scroll1,
35115	        scroll2,
35116	        start,
35117	        end,
35118	        markerStart,
35119	        markerEnd,
35120	        markerStartTrigger,
35121	        markerEndTrigger,
35122	        markerVars,
35123	        change,
35124	        pinOriginalState,
35125	        pinActiveState,
35126	        pinState,
35127	        spacer,
35128	        offset,
35129	        pinGetter,
35130	        pinSetter,
35131	        pinStart,
35132	        pinChange,
35133	        spacingStart,
35134	        spacerState,
35135	        markerStartSetter,
35136	        markerEndSetter,
35137	        cs,
35138	        snap1,
35139	        snap2,
35140	        scrubTween,
35141	        scrubSmooth,
35142	        snapDurClamp,
35143	        snapDelayedCall,
35144	        prevProgress,
35145	        prevScroll,
35146	        prevAnimProgress,
35147	        caMarkerSetter;
35148
35149	    self.media = _creatingMedia;
35150	    anticipatePin *= 45;
35151	    self.scroller = scroller;
35152	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
35153	    scroll1 = scrollFunc();
35154	    self.vars = vars;
35155	    animation = animation || vars.animation;
35156	    "refreshPriority" in vars && (_sort = 1);
35157	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
35158	      top: _getTweenCreator(scroller, _vertical),
35159	      left: _getTweenCreator(scroller, _horizontal)
35160	    };
35161	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
35162
35163	    if (animation) {
35164	      animation.vars.lazy = false;
35165	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
35166	      self.animation = animation.pause();
35167	      animation.scrollTrigger = self;
35168	      scrubSmooth = _isNumber(scrub) && scrub;
35169	      scrubSmooth && (scrubTween = gsap.to(animation, {
35170	        ease: "power3",
35171	        duration: scrubSmooth,
35172	        onComplete: function onComplete() {
35173	          return onScrubComplete && onScrubComplete(self);
35174	        }
35175	      }));
35176	      snap1 = 0;
35177	      id || (id = animation.vars.id);
35178	    }
35179
35180	    _triggers.push(self);
35181
35182	    if (snap) {
35183	      if (!_isObject(snap) || snap.push) {
35184	        snap = {
35185	          snapTo: snap
35186	        };
35187	      }
35188
35189	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
35190	        scrollBehavior: "auto"
35191	      });
35192	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
35193	        return _snapDirectional(snap.snapTo)(value, st.direction);
35194	      } : gsap.utils.snap(snap.snapTo);
35195	      snapDurClamp = snap.duration || {
35196	        min: 0.1,
35197	        max: 2
35198	      };
35199	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
35200	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
35201	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
35202	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
35203	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
35204	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
35205	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
35206	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
35207	              scroll = scrollFunc(),
35208	              endScroll = Math.round(start + endValue * change),
35209	              _snap = snap,
35210	              onStart = _snap.onStart,
35211	              _onInterrupt = _snap.onInterrupt,
35212	              _onComplete = _snap.onComplete,
35213	              tween = tweenTo.tween;
35214
35215	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
35216	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
35217	              return;
35218	            }
35219
35220	            if (snap.inertia === false) {
35221	              change1 = endValue - self.progress;
35222	            }
35223
35224	            tweenTo(endScroll, {
35225	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
35226	              ease: snap.ease || "power3",
35227	              data: _abs(endScroll - scroll),
35228	              onInterrupt: function onInterrupt() {
35229	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
35230	              },
35231	              onComplete: function onComplete() {
35232	                lastSnap = scrollFunc();
35233	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
35234	                onSnapComplete && onSnapComplete(self);
35235	                _onComplete && _onComplete(self);
35236	              }
35237	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
35238	            onStart && onStart(self, tweenTo.tween);
35239	          }
35240	        } else if (self.isActive) {
35241	          snapDelayedCall.restart(true);
35242	        }
35243	      }).pause();
35244	    }
35245
35246	    id && (_ids[id] = self);
35247	    trigger = self.trigger = _getTarget(trigger || pin);
35248	    pin = pin === true ? trigger : _getTarget(pin);
35249	    _isString(toggleClass) && (toggleClass = {
35250	      targets: trigger,
35251	      className: toggleClass
35252	    });
35253
35254	    if (pin) {
35255	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
35256	      self.pin = pin;
35257	      vars.force3D !== false && gsap.set(pin, {
35258	        force3D: true
35259	      });
35260	      pinCache = gsap.core.getCache(pin);
35261
35262	      if (!pinCache.spacer) {
35263	        if (pinSpacer) {
35264	          pinSpacer = _getTarget(pinSpacer);
35265	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
35266	          pinCache.spacerIsNative = !!pinSpacer;
35267	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
35268	        }
35269
35270	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
35271	        spacer.classList.add("pin-spacer");
35272	        id && spacer.classList.add("pin-spacer-" + id);
35273	        pinCache.pinState = pinOriginalState = _getState(pin);
35274	      } else {
35275	        pinOriginalState = pinCache.pinState;
35276	      }
35277
35278	      self.spacer = spacer = pinCache.spacer;
35279	      cs = _getComputedStyle(pin);
35280	      spacingStart = cs[pinSpacing + direction.os2];
35281	      pinGetter = gsap.getProperty(pin);
35282	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
35283
35284	      _swapPinIn(pin, spacer, cs);
35285
35286	      pinState = _getState(pin);
35287	    }
35288
35289	    if (markers) {
35290	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
35291	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
35292	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
35293	      offset = markerStartTrigger["offset" + direction.op.d2];
35294	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35295	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35296	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
35297
35298	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
35299	        _makePositionable(isViewport ? _body : scroller);
35300
35301	        gsap.set([markerStartTrigger, markerEndTrigger], {
35302	          force3D: true
35303	        });
35304	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
35305	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
35306	      }
35307	    }
35308
35309	    if (containerAnimation) {
35310	      var oldOnUpdate = containerAnimation.vars.onUpdate,
35311	          oldParams = containerAnimation.vars.onUpdateParams;
35312	      containerAnimation.eventCallback("onUpdate", function () {
35313	        self.update(0, 0, 1);
35314	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
35315	      });
35316	    }
35317
35318	    self.previous = function () {
35319	      return _triggers[_triggers.indexOf(self) - 1];
35320	    };
35321
35322	    self.next = function () {
35323	      return _triggers[_triggers.indexOf(self) + 1];
35324	    };
35325
35326	    self.revert = function (revert) {
35327	      var r = revert !== false || !self.enabled,
35328	          prevRefreshing = _refreshing;
35329
35330	      if (r !== self.isReverted) {
35331	        if (r) {
35332	          self.scroll.rec || (self.scroll.rec = scrollFunc());
35333	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
35334	          prevProgress = self.progress;
35335	          prevAnimProgress = animation && animation.progress();
35336	        }
35337
35338	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35339	          return m.style.display = r ? "none" : "block";
35340	        });
35341	        r && (_refreshing = 1);
35342	        self.update(r);
35343	        _refreshing = prevRefreshing;
35344	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
35345	        self.isReverted = r;
35346	      }
35347	    };
35348
35349	    self.refresh = function (soft, force) {
35350	      if ((_refreshing || !self.enabled) && !force) {
35351	        return;
35352	      }
35353
35354	      if (pin && soft && _lastScrollTime) {
35355	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
35356
35357	        return;
35358	      }
35359
35360	      _refreshing = 1;
35361	      scrubTween && scrubTween.pause();
35362	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
35363	      self.isReverted || self.revert();
35364
35365	      var size = getScrollerSize(),
35366	          scrollerBounds = getScrollerOffsets(),
35367	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
35368	          offset = 0,
35369	          otherPinOffset = 0,
35370	          parsedEnd = vars.end,
35371	          parsedEndTrigger = vars.endTrigger || trigger,
35372	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
35373	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
35374	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
35375	          i = triggerIndex,
35376	          cs,
35377	          bounds,
35378	          scroll,
35379	          isVertical,
35380	          override,
35381	          curTrigger,
35382	          curPin,
35383	          oppositeScroll,
35384	          initted,
35385	          revertedPins;
35386
35387	      while (i--) {
35388	        curTrigger = _triggers[i];
35389	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
35390	        curPin = curTrigger.pin;
35391
35392	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
35393	          revertedPins || (revertedPins = []);
35394	          revertedPins.unshift(curTrigger);
35395	          curTrigger.revert();
35396	        }
35397	      }
35398
35399	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
35400	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
35401	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
35402
35403	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
35404	        if (~parsedEnd.indexOf(" ")) {
35405	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
35406	        } else {
35407	          offset = _offsetToPx(parsedEnd.substr(2), size);
35408	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
35409	          parsedEndTrigger = trigger;
35410	        }
35411	      }
35412
35413	      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;
35414	      change = end - start || (start -= 0.01) && 0.001;
35415	      offset = 0;
35416	      i = triggerIndex;
35417
35418	      while (i--) {
35419	        curTrigger = _triggers[i];
35420	        curPin = curTrigger.pin;
35421
35422	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
35423	          cs = curTrigger.end - curTrigger.start;
35424	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
35425	          curPin === pin && (otherPinOffset += cs);
35426	        }
35427	      }
35428
35429	      start += offset;
35430	      end += offset;
35431	      self._pinPush = otherPinOffset;
35432
35433	      if (markerStart && offset) {
35434	        cs = {};
35435	        cs[direction.a] = "+=" + offset;
35436	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
35437	        gsap.set([markerStart, markerEnd], cs);
35438	      }
35439
35440	      if (pin) {
35441	        cs = _getComputedStyle(pin);
35442	        isVertical = direction === _vertical;
35443	        scroll = scrollFunc();
35444	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
35445	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
35446
35447	        _swapPinIn(pin, spacer, cs);
35448
35449	        pinState = _getState(pin);
35450	        bounds = _getBounds(pin, true);
35451	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
35452
35453	        if (pinSpacing) {
35454	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
35455	          spacerState.t = spacer;
35456	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
35457	          i && spacerState.push(direction.d, i + _px);
35458
35459	          _setState(spacerState);
35460
35461	          useFixedPosition && scrollFunc(prevScroll);
35462	        }
35463
35464	        if (useFixedPosition) {
35465	          override = {
35466	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
35467	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
35468	            boxSizing: "border-box",
35469	            position: "fixed"
35470	          };
35471	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
35472	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
35473	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
35474	          override[_padding] = cs[_padding];
35475	          override[_padding + _Top] = cs[_padding + _Top];
35476	          override[_padding + _Right] = cs[_padding + _Right];
35477	          override[_padding + _Bottom] = cs[_padding + _Bottom];
35478	          override[_padding + _Left] = cs[_padding + _Left];
35479	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
35480	        }
35481
35482	        if (animation) {
35483	          initted = animation._initted;
35484
35485	          _suppressOverwrites(1);
35486
35487	          animation.render(animation.duration(), true, true);
35488	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
35489	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
35490	          animation.render(0, true, true);
35491	          initted || animation.invalidate();
35492
35493	          _suppressOverwrites(0);
35494	        } else {
35495	          pinChange = change;
35496	        }
35497	      } else if (trigger && scrollFunc() && !containerAnimation) {
35498	        bounds = trigger.parentNode;
35499
35500	        while (bounds && bounds !== _body) {
35501	          if (bounds._pinOffset) {
35502	            start -= bounds._pinOffset;
35503	            end -= bounds._pinOffset;
35504	          }
35505
35506	          bounds = bounds.parentNode;
35507	        }
35508	      }
35509
35510	      revertedPins && revertedPins.forEach(function (t) {
35511	        return t.revert(false);
35512	      });
35513	      self.start = start;
35514	      self.end = end;
35515	      scroll1 = scroll2 = scrollFunc();
35516
35517	      if (!containerAnimation) {
35518	        scroll1 < prevScroll && scrollFunc(prevScroll);
35519	        self.scroll.rec = 0;
35520	      }
35521
35522	      self.revert(false);
35523	      _refreshing = 0;
35524	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
35525
35526	      if (prevProgress !== self.progress) {
35527	        animation && !isToggle && animation.totalProgress(prevProgress, true);
35528	        self.progress = prevProgress;
35529	        self.update(0, 0, 1);
35530	      }
35531
35532	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
35533	      onRefresh && onRefresh(self);
35534	    };
35535
35536	    self.getVelocity = function () {
35537	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
35538	    };
35539
35540	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 35541-35779
35541	      _endAnimation(self.callbackAnimation);
35542
35543	      if (animation) {
35544	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
35545	      }
35546	    };
35547
35548	    self.getTrailing = function (name) {
35549	      var i = _triggers.indexOf(self),
35550	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
35551
35552	      return _isString(name) ? a.filter(function (t) {
35553	        return t.vars.preventOverlaps === name;
35554	      }) : a;
35555	    };
35556
35557	    self.update = function (reset, recordVelocity, forceFake) {
35558	      if (containerAnimation && !forceFake && !reset) {
35559	        return;
35560	      }
35561
35562	      var scroll = self.scroll(),
35563	          p = reset ? 0 : (scroll - start) / change,
35564	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
35565	          prevProgress = self.progress,
35566	          isActive,
35567	          wasActive,
35568	          toggleState,
35569	          action,
35570	          stateChanged,
35571	          toggled,
35572	          isAtMax,
35573	          isTakingAction;
35574
35575	      if (recordVelocity) {
35576	        scroll2 = scroll1;
35577	        scroll1 = containerAnimation ? scrollFunc() : scroll;
35578
35579	        if (snap) {
35580	          snap2 = snap1;
35581	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
35582	        }
35583	      }
35584
35585	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
35586
35587	      if (clipped !== prevProgress && self.enabled) {
35588	        isActive = self.isActive = !!clipped && clipped < 1;
35589	        wasActive = !!prevProgress && prevProgress < 1;
35590	        toggled = isActive !== wasActive;
35591	        stateChanged = toggled || !!clipped !== !!prevProgress;
35592	        self.direction = clipped > prevProgress ? 1 : -1;
35593	        self.progress = clipped;
35594
35595	        if (stateChanged && !_refreshing) {
35596	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
35597
35598	          if (isToggle) {
35599	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
35600	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
35601	          }
35602	        }
35603
35604	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
35605	          return t.endAnimation();
35606	        }));
35607
35608	        if (!isToggle) {
35609	          if (scrubTween && !_refreshing && !_startup) {
35610	            scrubTween.vars.totalProgress = clipped;
35611	            scrubTween.invalidate().restart();
35612	          } else if (animation) {
35613	            animation.totalProgress(clipped, !!_refreshing);
35614	          }
35615	        }
35616
35617	        if (pin) {
35618	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
35619
35620	          if (!useFixedPosition) {
35621	            pinSetter(pinStart + pinChange * clipped);
35622	          } else if (stateChanged) {
35623	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
35624
35625	            if (pinReparent) {
35626	              if (!reset && (isActive || isAtMax)) {
35627	                var bounds = _getBounds(pin, true),
35628	                    _offset = scroll - start;
35629
35630	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
35631	              } else {
35632	                _reparent(pin, spacer);
35633	              }
35634	            }
35635
35636	            _setState(isActive || isAtMax ? pinActiveState : pinState);
35637
35638	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
35639	          }
35640	        }
35641
35642	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
35643	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
35644	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
35645	        });
35646	        onUpdate && !isToggle && !reset && onUpdate(self);
35647
35648	        if (stateChanged && !_refreshing) {
35649	          if (isToggle) {
35650	            if (isTakingAction) {
35651	              if (action === "complete") {
35652	                animation.pause().totalProgress(1);
35653	              } else if (action === "reset") {
35654	                animation.restart(true).pause();
35655	              } else if (action === "restart") {
35656	                animation.restart(true);
35657	              } else {
35658	                animation[action]();
35659	              }
35660	            }
35661
35662	            onUpdate && onUpdate(self);
35663	          }
35664
35665	          if (toggled || !_limitCallbacks) {
35666	            onToggle && toggled && _callback(self, onToggle);
35667	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35668	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
35669
35670	            if (!toggled) {
35671	              toggleState = clipped === 1 ? 1 : 3;
35672	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35673	            }
35674	          }
35675
35676	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
35677	            _endAnimation(self.callbackAnimation);
35678
35679	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
35680	          }
35681	        } else if (isToggle && onUpdate && !_refreshing) {
35682	          onUpdate(self);
35683	        }
35684	      }
35685
35686	      if (markerEndSetter) {
35687	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
35688	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
35689	        markerEndSetter(n);
35690	      }
35691
35692	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
35693	    };
35694
35695	    self.enable = function (reset, refresh) {
35696	      if (!self.enabled) {
35697	        self.enabled = true;
35698
35699	        _addListener(scroller, "resize", _onResize);
35700
35701	        _addListener(scroller, "scroll", _onScroll);
35702
35703	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
35704
35705	        if (reset !== false) {
35706	          self.progress = prevProgress = 0;
35707	          scroll1 = scroll2 = lastSnap = scrollFunc();
35708	        }
35709
35710	        refresh !== false && self.refresh();
35711	      }
35712	    };
35713
35714	    self.getTween = function (snap) {
35715	      return snap && tweenTo ? tweenTo.tween : scrubTween;
35716	    };
35717
35718	    self.disable = function (reset, allowAnimation) {
35719	      if (self.enabled) {
35720	        reset !== false && self.revert();
35721	        self.enabled = self.isActive = false;
35722	        allowAnimation || scrubTween && scrubTween.pause();
35723	        prevScroll = 0;
35724	        pinCache && (pinCache.uncache = 1);
35725	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
35726
35727	        if (snapDelayedCall) {
35728	          snapDelayedCall.pause();
35729	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
35730	        }
35731
35732	        if (!isViewport) {
35733	          var i = _triggers.length;
35734
35735	          while (i--) {
35736	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
35737	              return;
35738	            }
35739	          }
35740
35741	          _removeListener(scroller, "resize", _onResize);
35742
35743	          _removeListener(scroller, "scroll", _onScroll);
35744	        }
35745	      }
35746	    };
35747
35748	    self.kill = function (revert, allowAnimation) {
35749	      self.disable(revert, allowAnimation);
35750	      scrubTween && scrubTween.kill();
35751	      id && delete _ids[id];
35752
35753	      var i = _triggers.indexOf(self);
35754
35755	      _triggers.splice(i, 1);
35756
35757	      i === _i && _direction > 0 && _i--;
35758	      i = 0;
35759
35760	      _triggers.forEach(function (t) {
35761	        return t.scroller === self.scroller && (i = 1);
35762	      });
35763
35764	      i || (self.scroll.rec = 0);
35765
35766	      if (animation) {
35767	        animation.scrollTrigger = null;
35768	        revert && animation.render(-1);
35769	        allowAnimation || animation.kill();
35770	      }
35771
35772	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35773	        return m.parentNode && m.parentNode.removeChild(m);
35774	      });
35775
35776	      if (pin) {
35777	        pinCache && (pinCache.uncache = 1);
35778	        i = 0;
35779
35780	        _triggers.forEach(function (t) {
35781	          return t.pin === pin && i++;
35782	        });
35783
35784	        i || (pinCache.spacer = 0);
35785	      }
35786	    };
35787
35788	    self.enable(false, false);
35789	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35790	      return start || end || self.refresh();
35791	    }) && (change = 0.01) && (start = end = 0);
35792	  };
35793
35794	  ScrollTrigger.register = function register(core) {
35795	    if (!_coreInitted) {
35796	      gsap = core || _getGSAP();
35797
35798	      if (_windowExists() && window.document) {
35799	        _win = window;
35800	        _doc = document;
35801	        _docEl = _doc.documentElement;
35802	        _body = _doc.body;
35803	      }
35804
35805	      if (gsap) {
35806	        _toArray = gsap.utils.toArray;
35807	        _clamp = gsap.utils.clamp;
35808	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35809	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35810
35811	        if (_body) {
35812	          _raf = _win.requestAnimationFrame || function (f) {
35813	            return setTimeout(f, 16);
35814	          };
35815
35816	          _addListener(_win, "wheel", _onScroll);
35817
35818	          _root = [_win, _doc, _docEl, _body];
35819
35820	          _addListener(_doc, "scroll", _onScroll);
35821
35822	          var bodyStyle = _body.style,
35823	              border = bodyStyle.borderTopStyle,
35824	              bounds;
35825	          bodyStyle.borderTopStyle = "solid";
35826	          bounds = _getBounds(_body);
35827	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35828	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35829	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35830	          _syncInterval = setInterval(_sync, 200);
35831	          gsap.delayedCall(0.5, function () {
35832	            return _startup = 0;
35833	          });
35834
35835	          _addListener(_doc, "touchcancel", _passThrough);
35836
35837	          _addListener(_body, "touchstart", _passThrough);
35838
35839	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35840	            return _pointerIsDown = 1;
35841	          });
35842
35843	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35844	            return _pointerIsDown = 0;
35845	          });
35846
35847	          _transformProp = gsap.utils.checkPrefix("transform");
35848
35849	          _stateProps.push(_transformProp);
35850
35851	          _coreInitted = _getTime();
35852	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35853	          _autoRefresh = [_doc, "visibilitychange", function () {
35854	            var w = _win.innerWidth,
35855	                h = _win.innerHeight;
35856
35857	            if (_doc.hidden) {
35858	              _prevWidth = w;
35859	              _prevHeight = h;
35860	            } else if (_prevWidth !== w || _prevHeight !== h) {
35861	              _onResize();
35862	            }
35863	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35864	            return _lastScrollTime || _refreshAll();
35865	          }, _win, "resize", _onResize];
35866
35867	          _iterateAutoRefresh(_addListener);
35868	        }
35869	      }
35870	    }
35871
35872	    return _coreInitted;
35873	  };
35874
35875	  ScrollTrigger.defaults = function defaults(config) {
35876	    for (var p in config) {
35877	      _defaults[p] = config[p];
35878	    }
35879	  };
35880
35881	  ScrollTrigger.kill = function kill() {
35882	    _enabled = 0;
35883
35884	    _triggers.slice(0).forEach(function (trigger) {
35885	      return trigger.kill(1);
35886	    });
35887	  };
35888
35889	  ScrollTrigger.config = function config(vars) {
35890	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35891	    var ms = vars.syncInterval;
35892	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35893
35894	    if ("autoRefreshEvents" in vars) {
35895	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35896	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35897	    }
35898	  };
35899
35900	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35901	    var t = _getTarget(target),
35902	        i = _scrollers.indexOf(t),
35903	        isViewport = _isViewport(t);
35904
35905	    if (~i) {
35906	      _scrollers.splice(i, isViewport ? 6 : 2);
35907	    }
35908
35909	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35910	  };
35911
35912	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35913	    var mq, p, i, func, result;
35914
35915	    for (p in vars) {
35916	      i = _media.indexOf(p);
35917	      func = vars[p];
35918	      _creatingMedia = p;
35919
35920	      if (p === "all") {
35921	        func();
35922	      } else {
35923	        mq = _win.matchMedia(p);
35924
35925	        if (mq) {
35926	          mq.matches && (result = func());
35927
35928	          if (~i) {
35929	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35930	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35931	          } else {
35932	            i = _media.length;
35933
35934	            _media.push(p, func, result);
35935
35936	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35937	          }
35938
35939	          _media[i + 3] = mq.matches;
35940	        }
35941	      }
35942
35943	      _creatingMedia = 0;
35944	    }
35945
35946	    return _media;
35947	  };
35948
35949	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
35950	    query || (_media.length = 0);
35951	    query = _media.indexOf(query);
35952	    query >= 0 && _media.splice(query, 4);
35953	  };
35954
35955	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
35956	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
35957	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
35958	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
35959	  };
35960
35961	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
35962	    _isString(element) && (element = _getTarget(element));
35963	    var bounds = element.getBoundingClientRect(),
35964	        size = bounds[horizontal ? _width : _height],
35965	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
35966	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
35967	  };
35968
35969	  return ScrollTrigger;
35970	}();
35971	ScrollTrigger.version = "3.8.0";
35972
35973	ScrollTrigger.saveStyles = function (targets) {
35974	  return targets ? _toArray(targets).forEach(function (target) {
35975	    if (target && target.style) {
35976	      var i = _savedStyles.indexOf(target);
35977
35978	      i >= 0 && _savedStyles.splice(i, 5);
35979
35980	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
35981	    }
35982	  }) : _savedStyles;
35983	};
35984
35985	ScrollTrigger.revert = function (soft, media) {
35986	  return _revertAll(!soft, media);
35987	};
35988
35989	ScrollTrigger.create = function (vars, animation) {
35990	  return new ScrollTrigger(vars, animation);
35991	};
35992
35993	ScrollTrigger.refresh = function (safe) {
35994	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
35995	};
35996
35997	ScrollTrigger.update = _updateAll;
35998	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
35999
36000	ScrollTrigger.maxScroll = function (element, horizontal) {
36001	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
36002	};
36003
36004	ScrollTrigger.getScrollFunc = function (element, horizontal) {
36005	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
36006	};
36007
36008	ScrollTrigger.getById = function (id) {
36009	  return _ids[id];
36010	};
36011
36012	ScrollTrigger.getAll = function () {
36013	  return _triggers.slice(0);
36014	};
36015
36016	ScrollTrigger.isScrolling = function () {
36017	  return !!_lastScrollTime;
36018	};
36019
36020	ScrollTrigger.snapDirectional = _snapDirectional;
36021
36022	ScrollTrigger.addEventListener = function (type, callback) {
36023	  var a = _listeners[type] || (_listeners[type] = []);
36024	  ~a.indexOf(callback) || a.push(callback);
36025	};
36026
36027	ScrollTrigger.removeEventListener = function (type, callback) {
36028	  var a = _listeners[type],
36029	      i = a && a.indexOf(callback);
36030	  i >= 0 && a.splice(i, 1);
36031	};
36032
36033	ScrollTrigger.batch = function (targets, vars) {
36034	  var result = [],
36035	      varsCopy = {},
36036	      interval = vars.interval || 0.016,
36037	      batchMax = vars.batchMax || 1e9,
36038	      proxyCallback = function proxyCallback(type, callback) {
36039	    var elements = [],
36040	        triggers = [],
36041	        delay = gsap.delayedCall(interval, function () {
36042	      callback(elements, triggers);
36043	      elements = [];
36044	      triggers = [];
36045	    }).pause();
36046	    return function (self) {
36047	      elements.length || delay.restart(true);
36048	      elements.push(self.trigger);
36049	      triggers.push(self);
36050	      batchMax <= elements.length && delay.progress(1);
36051	    };
36052	  },
36053	      p;
36054
36055	  for (p in vars) {
36056	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
36057	  }
36058
36059	  if (_isFunction(batchMax)) {
36060	    batchMax = batchMax();
36061
36062	    _addListener(ScrollTrigger, "refresh", function () {
36063	      return batchMax = vars.batchMax();
36064	    });
36065	  }
36066
36067	  _toArray(targets).forEach(function (target) {
36068	    var config = {};
36069
36070	    for (p in varsCopy) {
36071	      config[p] = varsCopy[p];
36072	    }
36073
36074	    config.trigger = target;
36075	    result.push(ScrollTrigger.create(config));
36076	  });
36077
36078	  return result;
36079	};
36080
36081	ScrollTrigger.sort = function (func) {
36082	  return _triggers.sort(func || function (a, b) {
36083	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
36084	  });
36085	};
36086
36087	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
36088
36089	exports.ScrollTrigger = ScrollTrigger;
36090	exports.default = ScrollTrigger;
36091
36092	Object.defineProperty(exports, '__esModule', { value: true });
36093
36094})));
36095
36096/* ========================================================================
36097 * Bootstrap: collapse.js v3.1.1
36098 * http://getbootstrap.com/javascript/#collapse
36099 * ========================================================================
36100 * Copyright 2011-2014 Twitter, Inc.
36101 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36102 * ======================================================================== */
36103
36104
36105+function ($) {
36106	'use strict';
36107
36108	// COLLAPSE PUBLIC CLASS DEFINITION
36109	// ================================
36110
36111	var Collapse = function (element, options) {
36112		this.$element      = $(element)
36113		this.options       = $.extend({}, Collapse.DEFAULTS, options)
36114		this.transitioning = null
36115
36116		if (this.options.parent) this.$parent = $(this.options.parent)
36117		if (this.options.toggle) this.toggle()
36118	}
36119
36120	Collapse.DEFAULTS = {
36121		toggle: true
36122	}
36123
36124	Collapse.prototype.dimension = function () {
36125		var hasWidth = this.$element.hasClass('width')
36126		return hasWidth ? 'width' : 'height'
36127	}
36128
36129	Collapse.prototype.show = function () {
36130		if (this.transitioning || this.$element.hasClass('in')) return
36131
36132		var startEvent = $.Event('show.bs.collapse')
36133		this.$element.trigger(startEvent)
36134		if (startEvent.isDefaultPrevented()) return
36135
36136		var actives = this.$parent && this.$parent.find('> .panel > .in')
36137
36138		if (actives && actives.length) {
36139			var hasData = actives.data('bs.collapse')
36140			if (hasData && hasData.transitioning) return
36141			//START UNCODE EDIT
36142			var parentNoToggle = this.$parent.data('no-toggle')
36143			if (!parentNoToggle) {
36144				actives.collapse('hide')
36145			}
36146			//END UNCODE EDIT
36147			hasData || actives.data('bs.collapse', null)
36148		}
36149
36150		var dimension = this.dimension()
36151
36152		this.$element
36153			.removeClass('collapse')
36154			.addClass('collapsing')[dimension](0)
36155
36156		this.transitioning = 1
36157
36158		var complete = function (e) {
36159			if (e && e.target != this.$element[0]) return
36160			this.$element
36161				.removeClass('collapsing')
36162				.addClass('collapse in')[dimension]('auto')
36163			this.transitioning = 0
36164			this.$element.trigger('shown.bs.collapse')
36165		}
36166
36167		if (!$.support.transition) return complete.call(this)
36168
36169		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
36170
36171		this.$element
36172			.one($.support.transition.end, $.proxy(complete, this))
36173			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
36174	}
36175
36176	Collapse.prototype.hide = function () {
36177		if (this.transitioning || !this.$element.hasClass('in')) return
36178
36179		var startEvent = $.Event('hide.bs.collapse')
36180		this.$element.trigger(startEvent)
36181		if (startEvent.isDefaultPrevented()) return
36182
36183		var dimension = this.dimension()
36184
36185		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
36186
36187		this.$element
36188			.addClass('collapsing')
36189			.removeClass('collapse')
36190			.removeClass('in')
36191
36192		this.transitioning = 1
36193
36194		var complete = function (e) {
36195			if (e && e.target != this.$element[0]) return
36196			this.transitioning = 0
36197			this.$element
36198				.trigger('hidden.bs.collapse')
36199				.removeClass('collapsing')
36200				.addClass('collapse')
36201		}
36202
36203		if (!$.support.transition) return complete.call(this)
36204
36205		this.$element
36206			[dimension](0)
36207			.one($.support.transition.end, $.proxy(complete, this))
36208			.emulateTransitionEnd(350)
36209	}
36210
36211	Collapse.prototype.toggle = function () {
36212		this[this.$element.hasClass('in') ? 'hide' : 'show']()
36213	}
36214
36215
36216	// COLLAPSE PLUGIN DEFINITION
36217	// ==========================
36218
36219	var old = $.fn.collapse
36220
36221	$.fn.collapse = function (option) {
36222		return this.each(function () {
36223			var $this   = $(this)
36224			var data    = $this.data('bs.collapse')
36225			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
36226
36227			if (!data && options.toggle && option == 'show') option = !option
36228			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
36229			if (typeof option == 'string') data[option]()
36230		})
36231	}
36232
36233	$.fn.collapse.Constructor = Collapse
36234
36235
36236	// COLLAPSE NO CONFLICT
36237	// ====================
36238
36239	$.fn.collapse.noConflict = function () {
36240		$.fn.collapse = old
36241		return this
36242	}
36243
36244
36245	// COLLAPSE DATA-API
36246	// =================
36247
36248	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
36249		var $this   = $(this), href
36250		var target  = $this.attr('data-target')
36251				|| e.preventDefault()
36252				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
36253		//Edited by Uncode to replace ID in panel [START]
36254		var _target = href.replace(/^#/, "");
36255		if ( $('[data-id="' + _target + '"]').length ) {
36256			var $target = $('[data-id="' + _target + '"]')
36257		} else {
36258			var $target = $(target)
36259		}
36260		//Edited by Uncode to replace ID in panel [END]
36261		var data    = $target.data('bs.collapse')
36262		var option  = data ? 'toggle' : $this.data()
36263		var parent  = $this.attr('data-parent')
36264		var $parent = parent && $(parent)
36265
36266		if (!data || !data.transitioning) {
36267			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
36268			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
36269		}
36270
36271		$target.collapse(option)
36272	})
36273
36274}(jQuery);
36275
36276/* ========================================================================
36277 * Bootstrap: tab.js v3.1.1
36278 * http://getbootstrap.com/javascript/#tabs
36279 * ========================================================================
36280 * Copyright 2011-2014 Twitter, Inc.
36281 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36282 * ======================================================================== */
36283
36284
36285+function ($) {
36286  'use strict';
36287
36288  // TAB CLASS DEFINITION
36289  // ====================
36290
36291  var Tab = function (element) {
36292    this.element = $(element)
36293  }
36294
36295  Tab.prototype.show = function () {
36296    var $this    = this.element
36297    var $ul      = $this.closest('ul:not(.dropdown-menu)')
36298    var selector = $this.data('target')
36299
36300    if (!selector) {
36301      selector = $this.attr('href')
36302      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
36303    }
36304
36305    if ($this.parent('li').hasClass('active')) return
36306
36307    var previous = $ul.find('.active:last a')[0]
36308    var e        = $.Event('show.bs.tab', {
36309      relatedTarget: previous
36310    })
36311
36312    $this.trigger(e)
36313
36314    if (e.isDefaultPrevented()) return
36315
36316    //Edited by Uncode to replace ID in panel [START]
36317    var _target = selector.replace(/^#/, "");
36318    if ( $('[data-id="' + _target + '"]').length )
36319      var $target = $('[data-id="' + _target + '"]')
36320    else
36321      var $target = $(selector)
36322    //Edited by Uncode to replace ID in panel [END]
36323
36324    this.activate($this.parent('li'), $ul)
36325    this.activate($target, $target.parent(), function () {
36326      $this.trigger({
36327        type: 'shown.bs.tab',
36328        relatedTarget: previous
36329      })
36330    })
36331  }
36332
36333  Tab.prototype.activate = function (element, container, callback) {
36334    var $active    = container.find('> .active').add(container.find('> .active > .active'))
36335    var transition = callback
36336      && $.support.transition
36337      && $active.hasClass('fade')
36338
36339    function next() {
36340      $active
36341        .removeClass('active')
36342        .find('> .dropdown-menu > .active')
36343        .removeClass('active')
36344
36345      $active
36346        .find('.tab-excerpt').slideUp();
36347
36348      element.addClass('active')
36349      $('.tab-excerpt', element).slideDown();
36350
36351      //if (transition) {
36352        element[0].offsetWidth // reflow for transition
36353        element.add($active).addClass('in')
36354      /*} else {
36355        element.removeClass('fade')
36356      }*/
36357
36358      if (element.parent('.dropdown-menu')) {
36359        element.closest('li.dropdown').addClass('active')
36360      }
36361
36362      callback && callback()
36363    }
36364
36365    transition ?
36366      $active
36367        .one($.support.transition.end, next)
36368        .emulateTransitionEnd(150) :
36369      next()
36370
36371    $active.removeClass('in')
36372  }
36373
36374
36375  // TAB PLUGIN DEFINITION
36376  // =====================
36377
36378  var old = $.fn.tab
36379
36380  $.fn.tab = function ( option ) {
36381    return this.each(function () {
36382      var $this = $(this)
36383      var data  = $this.data('bs.tab')
36384
36385      if (!data) $this.data('bs.tab', (data = new Tab(this)))
36386      if (typeof option == 'string') data[option]()
36387    })
36388  }
36389
36390  $.fn.tab.Constructor = Tab
36391
36392
36393  // TAB NO CONFLICT
36394  // ===============
36395
36396  $.fn.tab.noConflict = function () {
36397    $.fn.tab = old
36398    return this
36399  }
36400
36401
36402  // TAB DATA-API
36403  // ============
36404
36405  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
36406    e.preventDefault()
36407    $(this).tab('show')
36408  })
36409
36410}(jQuery);
36411
36412/* ========================================================================
36413 * Bootstrap: tooltip.js v3.1.1
36414 * http://getbootstrap.com/javascript/#tooltip
36415 * Inspired by the original jQuery.tipsy by Jason Frame
36416 * ========================================================================
36417 * Copyright 2011-2014 Twitter, Inc.
36418 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36419 * ======================================================================== */
36420
36421
36422+function ($) {
36423  'use strict';
36424
36425  // TOOLTIP PUBLIC CLASS DEFINITION
36426  // ===============================
36427
36428  var Tooltip = function (element, options) {
36429    this.type       =
36430    this.options    =
36431    this.enabled    =
36432    this.timeout    =
36433    this.hoverState =
36434    this.$element   = null
36435
36436    this.init('tooltip', element, options)
36437  }
36438
36439  Tooltip.DEFAULTS = {
36440    animation: true,
36441    placement: 'top',
36442    selector: false,
36443    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
36444    trigger: 'hover focus',
36445    title: '',
36446    delay: 0,
36447    html: false,
36448    container: false,
36449    viewport: {
36450      selector: 'body',
36451      padding: 0
36452    }
36453  }
36454
36455  Tooltip.prototype.init = function (type, element, options) {
36456    this.enabled   = true
36457    this.type      = type
36458    this.$element  = $(element)
36459    this.options   = this.getOptions(options)
36460    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
36461
36462    var triggers = this.options.trigger.split(' ')
36463
36464    for (var i = triggers.length; i--;) {
36465      var trigger = triggers[i]
36466
36467      if (trigger == 'click') {
36468        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
36469      } else if (trigger != 'manual') {
36470        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
36471        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
36472
36473        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
36474        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
36475      }
36476    }
36477
36478    this.options.selector ?
36479      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
36480      this.fixTitle()
36481  }
36482
36483  Tooltip.prototype.getDefaults = function () {
36484    return Tooltip.DEFAULTS
36485  }
36486
36487  Tooltip.prototype.getOptions = function (options) {
36488    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
36489
36490    if (options.delay && typeof options.delay == 'number') {
36491      options.delay = {
36492        show: options.delay,
36493        hide: options.delay
36494      }
36495    }
36496
36497    return options
36498  }
36499
36500  Tooltip.prototype.getDelegateOptions = function () {
36501    var options  = {}
36502    var defaults = this.getDefaults()
36503
36504    this._options && $.each(this._options, function (key, value) {
36505      if (defaults[key] != value) options[key] = value
36506    })
36507
36508    return options
36509  }
36510
36511  Tooltip.prototype.enter = function (obj) {
36512    var self = obj instanceof this.constructor ?
36513      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36514
36515    clearTimeout(self.timeout)
36516
36517    self.hoverState = 'in'
36518
36519    if (!self.options.delay || !self.options.delay.show) return self.show()
36520
36521    self.timeout = setTimeout(function () {
36522      if (self.hoverState == 'in') self.show()
36523    }, self.options.delay.show)
36524  }
36525
36526  Tooltip.prototype.leave = function (obj) {
36527    var self = obj instanceof this.constructor ?
36528      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36529
36530    clearTimeout(self.timeout)
36531
36532    self.hoverState = 'out'
36533
36534    if (!self.options.delay || !self.options.delay.hide) return self.hide()
36535
36536    self.timeout = setTimeout(function () {
36537      if (self.hoverState == 'out') self.hide()
36538    }, self.options.delay.hide)
36539  }
36540
36541  Tooltip.prototype.show = function () {
36542    var e = $.Event('show.bs.' + this.type)
36543
36544    if (this.hasContent() && this.enabled) {
36545      this.$element.trigger(e)
36546
36547      if (e.isDefaultPrevented()) return
36548      var that = this;
36549
36550      var $tip = this.tip()
36551
36552      this.setContent()
36553
36554      if (this.options.animation) $tip.addClass('fade')
36555
36556      var placement = typeof this.options.placement == 'function' ?
36557        this.options.placement.call(this, $tip[0], this.$element[0]) :
36558        this.options.placement
36559
36560      var autoToken = /\s?auto?\s?/i
36561      var autoPlace = autoToken.test(placement)
36562      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
36563
36564      $tip
36565        .detach()
36566        .cs
36566s({ top: 0, left: 0, display: 'block' })
36567        .addClass(placement)
36568
36569      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
36570
36571      var pos          = this.getPosition()
36572      var actualWidth  = $tip[0].offsetWidth
36573      var actualHeight = $tip[0].offsetHeight
36574
36575      if (autoPlace) {
36576        var orgPlacement = placement
36577        var $parent      = this.$element.parent()
36578        var parentDim    = this.getPosition($parent)
36579
36580        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
36581                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
36582                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
36583                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
36584                    placement
36585
36586        $tip
36587          .removeClass(orgPlacement)
36588          .addClass(placement)
36589      }
36590
36591      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
36592
36593      this.applyPlacement(calculatedOffset, placement)
36594      this.hoverState = null
36595
36596      var complete = function() {
36597        that.$element.trigger('shown.bs.' + that.type)
36598      }
36599
36600      $.support.transition && this.$tip.hasClass('fade') ?
36601        $tip
36602          .one($.support.transition.end, complete)
36603          .emulateTransitionEnd(150) :
36604        complete()
36605    }
36606  }
36607
36608  Tooltip.prototype.applyPlacement = function (offset, placement) {
36609    var $tip   = this.tip()
36610    var width  = $tip[0].offsetWidth
36611    var height = $tip[0].offsetHeight
36612
36613    // manually read margins because getBoundingClientRect includes difference
36614    var marginTop = parseInt($tip.css('margin-top'), 10)
36615    var marginLeft = parseInt($tip.css('margin-left'), 10)
36616
36617    // we must check for NaN for ie 8/9
36618    if (isNaN(marginTop))  marginTop  = 0
36619    if (isNaN(marginLeft)) marginLeft = 0
36620
36621    offset.top  = offset.top  + marginTop
36622    offset.left = offset.left + marginLeft
36623
36624    // $.fn.offset doesn't round pixel values
36625    // so we use setOffset directly with our own function B-0
36626    $.offset.setOffset($tip[0], $.extend({
36627      using: function (props) {
36628        $tip.css({
36629          top: Math.round(props.top),
36630          left: Math.round(props.left)
36631        })
36632      }
36633    }, offset), 0)
36634
36635    $tip.addClass('in')
36636
36637    // check to see if placing tip in new offset caused the tip to resize itself
36638    var actualWidth  = $tip[0].offsetWidth
36639    var actualHeight = $tip[0].offsetHeight
36640
36641    if (placement == 'top' && actualHeight != height) {
36642      offset.top = offset.top + height - actualHeight
36643    }
36644
36645    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
36646
36647    if (delta.left) offset.left += delta.left
36648    else offset.top += delta.top
36649
36650    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
36651    var arrowPosition       = delta.left ? 'left'        : 'top'
36652    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
36653
36654    $tip.offset(offset)
36655    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
36656  }
36657
36658  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
36659    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
36660  }
36661
36662  Tooltip.prototype.setContent = function () {
36663    var $tip  = this.tip()
36664    var title = this.getTitle()
36665
36666    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
36667    $tip.removeClass('fade in top bottom left right')
36668  }
36669
36670  Tooltip.prototype.hide = function () {
36671    var that = this
36672    var $tip = this.tip()
36673    var e    = $.Event('hide.bs.' + this.type)
36674
36675    function complete() {
36676      if (that.hoverState != 'in') $tip.detach()
36677      that.$element.trigger('hidden.bs.' + that.type)
36678    }
36679
36680    this.$element.trigger(e)
36681
36682    if (e.isDefaultPrevented()) return
36683
36684    $tip.removeClass('in')
36685
36686    $.support.transition && this.$tip.hasClass('fade') ?
36687      $tip
36688        .one($.support.transition.end, complete)
36689        .emulateTransitionEnd(150) :
36690      complete()
36691
36692    this.hoverState = null
36693
36694    return this
36695  }
36696
36697  Tooltip.prototype.fixTitle = function () {
36698    var $e = this.$element
36699    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
36700      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
36701    }
36702  }
36703
36704  Tooltip.prototype.hasContent = function () {
36705    return this.getTitle()
36706  }
36707
36708  Tooltip.prototype.getPosition = function ($element) {
36709    $element   = $element || this.$element
36710    var el     = $element[0]
36711    var isBody = el.tagName == 'BODY'
36712    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
36713      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
36714      width:  isBody ? $(window).width()  : $element.outerWidth(),
36715      height: isBody ? $(window).height() : $element.outerHeight()
36716    }, isBody ? {top: 0, left: 0} : $element.offset())
36717  }
36718
36719  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
36720    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
36721           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
36722           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
36723        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
36724
36725  }
36726
36727  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
36728    var delta = { top: 0, left: 0 }
36729    if (!this.$viewport) return delta
36730
36731    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
36732    var viewportDimensions = this.getPosition(this.$viewport)
36733
36734    if (/right|left/.test(placement)) {
36735      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
36736      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
36737      if (topEdgeOffset < viewportDimensions.top) { // top overflow
36738        delta.top = viewportDimensions.top - topEdgeOffset
36739      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
36740        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
36740EdgeOffset
36741      }
36742    } else {
36743      var leftEdgeOffset  = pos.left - viewportPadding
36744      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
36745      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
36746        delta.left = viewportDimensions.left - leftEdgeOffset
36747      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
36748        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
36749      }
36750    }
36751
36752    return delta
36753  }
36754
36755  Tooltip.prototype.getTitle = function () {
36756    var title
36757    var $e = this.$element
36758    var o  = this.options
36759
36760    title = $e.attr('data-original-title')
36761      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
36762
36763    return title
36764  }
36765
36766  Tooltip.prototype.tip = function () {
36767    return this.$tip = this.$tip || $(this.options.template)
36768  }
36769
36770  Tooltip.prototype.arrow = function () {
36771    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
36772  }
36773
36774  Tooltip.prototype.validate = function () {
36775    if (!this.$element[0].parentNode) {
36776      this.hide()
36777      this.$element = null
36778      this.options  = null
36779    }
36780  }
36781
36782  Tooltip.prototype.enable = function () {
36783    this.enabled = true
36784  }
36785
36786  Tooltip.prototype.disable = function () {
36787    this.enabled = false
36788  }
36789
36790  Tooltip.prototype.toggleEnabled = function () {
36791    this.enabled = !this.enabled
36792  }
36793
36794  Tooltip.prototype.toggle = function (e) {
36795    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36796    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36797  }
36798
36799  Tooltip.prototype.destroy = function () {
36800    clearTimeout(this.timeout)
36801    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36802  }
36803
36804
36805  // TOOLTIP PLUGIN DEFINITION
36806  // =========================
36807
36808  var old = $.fn.tooltip
36809
36810  $.fn.tooltip = function (option) {
36811    return this.each(function () {
36812      var $this   = $(this)
36813      var data    = $this.data('bs.tooltip')
36814      var options = typeof option == 'object' && option
36815
36816      if (!data && option == 'destroy') return
36817      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36818      if (typeof option == 'string') data[option]()
36819    })
36820  }
36821
36822  $.fn.tooltip.Constructor = Tooltip
36823
36824
36825  // TOOLTIP NO CONFLICT
36826  // ===================
36827
36828  $.fn.tooltip.noConflict = function () {
36829    $.fn.tooltip = old
36830    return this
36831  }
36832
36833}(jQuery);
36834
36835/* ========================================================================
36836 * Bootstrap: transition.js v3.1.1
36837 * http://getbootstrap.com/javascript/#transitions
36838 * ========================================================================
36839 * Copyright 2011-2014 Twitter, Inc.
36840 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36841 * ======================================================================== */
36842
36843
36844+function ($) {
36845  'use strict';
36846
36847  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36848  // ============================================================
36849
36850  function transitionEnd() {
36851    var el = document.createElement('bootstrap')
36852
36853    var transEndEventNames = {
36854      WebkitTransition : 'webkitTransitionEnd',
36855      MozTransition    : 'transitionend',
36856      OTransition      : 'oTransitionEnd otransitionend',
36857      transition       : 'transitionend'
36858    }
36859
36860    for (var name in transEndEventNames) {
36861      if (el.style[name] !== undefined) {
36862        return { end: transEndEventNames[name] }
36863      }
36864    }
36865
36866    return false // explicit for ie8 (  ._.)
36867  }
36868
36869  // http://blog.alexmaccaw.com/css-transitions
36870  $.fn.emulateTransitionEnd = function (duration) {
36871    var called = false, $el = this
36872    $(this).one($.support.transition.end, function () { called = true })
36873    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36874    setTimeout(callback, duration)
36875    return this
36876  }
36877
36878  $(function () {
36879    $.support.transition = transitionEnd()
36880  })
36881
36882}(jQuery);
36883
36884
36885// ------------------------------------------
36886// Rellax.js
36887// Buttery smooth parallax library
36888// Copyright (c) 2016 Moe Amaya (@moeamaya)
36889// MIT license
36890//
36891// Thanks to Paraxify.js and Jaime Cabllero
36892// for parallax concepts
36893// ------------------------------------------
36894
36895(function (root, factory) {
36896	if (typeof define === 'function' && define.amd) {
36897		// AMD. Register as an anonymous module.
36898		define([], factory);
36899	} else if (typeof module === 'object' && module.exports) {
36900		// Node. Does not work with strict CommonJS, but
36901		// only CommonJS-like environments that support module.exports,
36902		// like Node.
36903		module.exports = factory();
36904	} else {
36905		// Browser globals (root is window)
36906		root.Rellax = factory();
36907	}
36908}(typeof window !== "undefined" ? window : global, function () {
36909	var Rellax = function(el, options){
36910		"use strict";
36911
36912		var self = Object.create(Rellax.prototype);
36913
36914		var posY = 0;
36915		var screenY = 0;
36916		var posX = 0;
36917		var screenX = 0;
36918		var blocks = [];
36919		var pause = true;
36920
36921		// check what requestAnimationFrame to use, and if
36922		// it's not supported, use the onscroll event
36923		var loop = window.requestAnimationFrame ||
36924			window.webkitRequestAnimationFrame ||
36925			window.mozRequestAnimationFrame ||
36926			window.msRequestAnimationFrame ||
36927			window.oRequestAnimationFrame ||
36928			function(callback){ return setTimeout(callback, 1000 / 60); };
36929
36930		// store the id for later use
36931		var loopId = null;
36932
36933		// Test via a getter in the options object to see if the passive property is accessed
36934		var supportsPassive = false;
vendor: 10,724 bytes, lines 36935-37236
36935		try {
36936			var opts = Object.defineProperty({}, 'passive', {
36937				get: function() {
36938					supportsPassive = true;
36939				}
36940			});
36941			window.addEventListener("testPassive", null, opts);
36942			window.removeEventListener("testPassive", null, opts);
36943		} catch (e) {}
36944
36945		// check what cancelAnimation method to use
36946		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
36947
36948		// check which transform property to use
36949		var transformProp = window.transformProp || (function(){
36950				var testEl = document.createElement('div');
36951				if (testEl.style.transform === null) {
36952					var vendors = ['Webkit', 'Moz', 'ms'];
36953					for (var vendor in vendors) {
36954						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
36955							return vendors[vendor] + 'Transform';
36956						}
36957					}
36958				}
36959				return 'transform';
36960			})();
36961
36962		// Default Settings
36963		self.options = {
36964			speed: -2,
36965			verticalSpeed: null,
36966			horizontalSpeed: null,
36967			breakpoints: [576, 768, 1201],
36968			center: false,
36969			wrapper: null,
36970			relativeToWrapper: false,
36971			round: true,
36972			vertical: true,
36973			horizontal: false,
36974			verticalScrollAxis: "y",
36975			horizontalScrollAxis: "x",
36976			callback: function() {},
36977		};
36978
36979		// User defined options (might have more in the future)
36980		if (options){
36981			Object.keys(options).forEach(function(key){
36982				self.options[key] = options[key];
36983			});
36984		}
36985
36986		function validateCustomBreakpoints () {
36987			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
36988				var isAscending = true;
36989				var isNumerical = true;
36990				var lastVal;
36991				self.options.breakpoints.forEach(function (i) {
36992					if (typeof i !== 'number') isNumerical = false;
36993					if (lastVal !== null) {
36994						if (i < lastVal) isAscending = false;
36995					}
36996					lastVal = i;
36997				});
36998				if (isAscending && isNumerical) return;
36999			}
37000			// revert defaults if set incorrectly
37001			self.options.breakpoints = [576, 768, 1201];
37002			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
37003		}
37004
37005		if (options && options.breakpoints) {
37006			validateCustomBreakpoints();
37007		}
37008
37009		// By default, rellax class
37010		if (!el) {
37011			el = '.rellax';
37012		}
37013
37014		// check if el is a className or a node
37015		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
37016
37017		// Now query selector
37018		if (elements.length > 0) {
37019			self.elems = elements;
37020		}
37021
37022		// The elements don't exist
37023		else {
37024			console.warn("Rellax: The elements you're trying to select don't exist.");
37025			return;
37026		}
37027
37028		// Has a wrapper and it exists
37029		if (self.options.wrapper) {
37030			if (!self.options.wrapper.nodeType) {
37031				var wrapper = document.querySelector(self.options.wrapper);
37032
37033				if (wrapper) {
37034					self.options.wrapper = wrapper;
37035				} else {
37036					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
37037					return;
37038				}
37039			}
37040		}
37041
37042		// set a placeholder for the current breakpoint
37043		var currentBreakpoint;
37044
37045		// helper to determine current breakpoint
37046		var getCurrentBreakpoint = function (w) {
37047			var bp = self.options.breakpoints;
37048			if (w < bp[0]) return 'xs';
37049			if (w >= bp[0] && w < bp[1]) return 'sm';
37050			if (w >= bp[1] && w < bp[2]) return 'md';
37051			return 'lg';
37052		};
37053
37054		// Get and cache initial position of all elements
37055		var cacheBlocks = function() {
37056			for (var i = 0; i < self.elems.length; i++){
37057				var block = createBlock(self.elems[i]);
37058				blocks.push(block);
37059			}
37060		};
37061
37062
37063		// Let's kick this script off
37064		// Build array for cached element values
37065		var init = function() {
37066			for (var i = 0; i < blocks.length; i++){
37067				self.elems[i].style.cssText = blocks[i].style;
37068			}
37069
37070			blocks = [];
37071
37072			screenY = window.innerHeight;
37073			screenX = window.innerWidth;
37074			currentBreakpoint = getCurrentBreakpoint(screenX);
37075
37076			setPosition();
37077
37078			cacheBlocks();
37079
37080			animate();
37081
37082			// If paused, unpause and set listener for window resizing events
37083			if (pause) {
37084				window.addEventListener('resize', init);
37085				pause = false;
37086				// Start the loop
37087				update();
37088			}
37089		};
37090
37091		// We want to cache the parallax blocks'
37092		// values: base, top, height, speed
37093		// el: is dom object, return: el cache values
37094		var createBlock = function(el) {
37095			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
37096			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
37097			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
37098			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
37099			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
37100			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
37101			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
37102			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
37103			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
37104			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
37105			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
37106			var dataMin = el.getAttribute( 'data-rellax-min' );
37107			var dataMax = el.getAttribute( 'data-rellax-max' );
37108			var dataMinX = el.getAttribute('data-rellax-min-x');
37109			var dataMaxX = el.getAttribute('data-rellax-max-x');
37110			var dataMinY = el.getAttribute('data-rellax-min-y');
37111			var dataMaxY = el.getAttribute('data-rellax-max-y');
37112			var mapBreakpoints;
37113			var breakpoints = true;
37114
37115			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
37116				breakpoints = false;
37117			} else {
37118				mapBreakpoints = {
37119					'xs': dataXsSpeed,
37120					'sm': dataMobileSpeed,
37121					'md': dataTabletSpeed,
37122					'lg': dataDesktopSpeed
37123				};
37124			}
37125
37126			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
37127			// ensures elements are positioned based on HTML layout.
37128			//
37129			// If the element has the percentage attribute, the posY and posX needs to be
37130			// the current scroll position's value, so that the elements are still positioned based on HTML layout
37131			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37132			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
37133			if (self.options.relativeToWrapper) {
37134				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37135				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
37136			}
37137			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
37138			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;
37139
37140			var blockTop = posY + el.getBoundingClientRect().top;
37141			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
37142
37143			var blockLeft = posX + el.getBoundingClientRect().left;
37144			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
37145
37146			// apparently parallax equation everyone uses
37147			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
37148			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
37149			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
37150
37151			// Optional individual block speed as data attr, otherwise global speed
37152			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
37153			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
37154			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
37155
37156			// Optional individual block movement axis direction as data attr, otherwise global movement direction
37157			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
37158			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
37159
37160			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
37161
37162			// ~~Store non-translate3d transforms~~
37163			// Store inline styles and extract transforms
37164			var style = el.style.cssText;
37165			var transform = '';
37166
37167			// Check if there's an inline styled transform
37168			var searchResult = /transform\s*:/i.exec(style);
37169			if (searchResult) {
37170				// Get the index of the transform
37171				var index = searchResult.index;
37172
37173				// Trim the style to the transform point and get the following semi-colon index
37174				var trimmedStyle = style.slice(index);
37175				var delimiter = trimmedStyle.indexOf(';');
37176
37177				// Remove "transform" string and save the attribute
37178				if (delimiter) {
37179					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
37180				} else {
37181					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
37182				}
37183			}
37184
37185			return {
37186				baseX: bases.x,
37187				baseY: bases.y,
37188				top: blockTop,
37189				left: blockLeft,
37190				height: blockHeight,
37191				width: blockWidth,
37192				speed: speed,
37193				verticalSpeed: verticalSpeed,
37194				horizontalSpeed: horizontalSpeed,
37195				verticalScrollAxis: verticalScrollAxis,
37196				horizontalScrollAxis: horizontalScrollAxis,
37197				style: style,
37198				transform: transform,
37199				zindex: dataZindex,
37200				min: dataMin,
37201				max: dataMax,
37202				minX: dataMinX,
37203				maxX: dataMaxX,
37204				minY: dataMinY,
37205				maxY: dataMaxY
37206			};
37207		};
37208
37209		// set scroll position (posY, posX)
37210		// side effect method is not ideal, but okay for now
37211		// returns true if the scroll changed, false if nothing happened
37212		var setPosition = function() {
37213			var oldY = posY;
37214			var oldX = posX;
37215
37216			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37217			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
37218			// If option relativeToWrapper is true, use relative wrapper value instead.
37219			if (self.options.relativeToWrapper) {
37220				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37221				posY = scrollPosY - self.options.wrapper.offsetTop;
37222			}
37223
37224
37225			if (oldY != posY && self.options.vertical) {
37226				// scroll changed, return true
37227				return true;
37228			}
37229
37230			if (oldX != posX && self.options.horizontal) {
37231				// scroll changed, return true
37232				return true;
37233			}
37234
37235			// scroll did not change
37236			return false;
37237		};
37238
37239		// Ahh a pure function, gets new transform value
37240		// based on scrollPosition and speed
37241		// Allow for decimal pixel values
37242		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
37243			var result = {};
37244			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
37245			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
37246
37247			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
37248			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
37249
37250			return result;
37251		};
37252
37253		// Remove event listeners and loop again
37254		var deferredUpdate = function() {
37255			window.removeEventListener('resize', deferredUpdate);
37256			window.removeEventListener('orientationchange', deferredUpdate);
37257			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
37258			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
37259
37260			// loop again
37261			loopId = loop(update);
37262		};
37263
37264		// Loop
37265		var update = function() {
37266			if (setPosition() && pause === false) {
37267				animate();
37268
37269				// loop again
37270				loopId = loop(update);
37271			} else {
37272				loopId = null;
37273
37274				// Don't animate until we get a position updating event
37275				window.addEventListener('resize', deferredUpdate);
37276				window.addEventListener('orientationchange', deferredUpdate);
37277				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
37278				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
37279			}
37280		};
37281
37282		// Transform3d on parallax element
37283		var animate = function() {
37284			var positions;
37285			for (var i = 0; i < self.elems.length; i++){
37286				// Determine relevant movement directions
37287				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
37288				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
37289				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
37290				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
37291				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
37292				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
37293
37294				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
37295				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
37296
37297				// Subtracting initialize value, so element stays in same spot as HTML
37298				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
37299				var positionY = positions.y - blocks[i].baseY;
37300				var positionX = positions.x - blocks[i].baseX;
37301
37302				// The next two "if" blocks go like this:
37303				// Check if a limit is defined (first "min", then "max");
37304				// Check if we need to change the Y or the X
37305				// (Currently working only if just one of the axes is enabled)
37306				// Then, check if the new position is inside the allowed limit
37307				// If so, use new position. If not, set position to limit.
37308
37309				// Check if a min limit is defined
37310				if (blocks[i].min !== null) {
37311					if (self.options.vertical && !self.options.horizontal) {
37312						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
37313					}
37314					if (self.options.horizontal && !self.options.vertical) {
37315						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
37316					}
37317				}
37318
37319				// Check if directional min limits are defined
37320				if (blocks[i].minY != null) {
37321						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
37322				}
37323				if (blocks[i].minX != null) {
37324						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
37325				}
37326
37327				// Check if a max limit is defined
37328				if (blocks[i].max !== null) {
37329					if (self.options.vertical && !self.options.horizontal) {
37330						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
37331					}
37332					if (self.options.horizontal && !self.options.vertical) {
37333						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
37334					}
37335				}
37336
37337				// Check if directional max limits are defined
37338				if (blocks[i].maxY != null) {
37339						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
37340				}
37341				if (blocks[i].maxX != null) {
37342						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
37343				}
37344
37345				var zindex = blocks[i].zindex;
37346
37347				// Move that element
37348				// (Set the new translation and append initial inline transforms.)
37349				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
37350				self.elems[i].style[transformProp] = translate;
37351			}
37352			self.options.callback(positions);
37353		};
37354
37355		self.destroy = function() {
37356			for (var i = 0; i < self.elems.length; i++){
37357				self.elems[i].style.cssText = blocks[i].style;
37358			}
37359
37360			// Remove resize event listener if not pause, and pause
37361			if (!pause) {
37362				window.removeEventListener('resize', init);
37363				pause = true;
37364			}
37365
37366			// Clear the animation loop to prevent possible memory leak
37367			clearLoop(loopId);
37368			loopId = null;
37369		};
37370
37371		// Init
37372		init();
37373
37374		// Allow to recalculate the initial values whenever we want
37375		self.refresh = init;
37376
37377		return self;
37378	};
37379	return Rellax;
37380}));
37381
37382/*
37383 * OKVideo by OKFocus v2.3.2
37384 * http://okfoc.us
37385 *
37386 * Copyright 2014, OKFocus
37387 * Licensed under the MIT license.
37388 *
37389 */
37390var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
37391// youtube player ready
37392function onYouTubeIframeAPIReady() {
37393	YTplayers = new Array();
37394	jQuery('.uncode-video-container.video').each(function() {
37395		var playerY;
37396		if (jQuery(this).attr('data-provider') == 'youtube') {
37397			var id = jQuery(this).attr('data-id'),
37398				start = jQuery(this).attr('data-start'),
37399				end = jQuery(this).attr('data-end');
37400			start = typeof start && start !== null ? start : 0;
37401			end = typeof end && end !== null ? end : 0;
37402			options = jQuery(window).data('okoptions-' + id);
37403			if ( typeof options === 'undefined' ) {
37404				return true;
37405			}
37406			options.time = jQuery(this).attr('data-t');
37407			playerY = new YT.Player('okplayer-' + id, {
37408				videoId: options.video ? options.video.id : null,
37409				playerVars: {
37410					'autohide': 1,
37411					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
37412					'disablekb': 1,
37413					'cc_load_policy': options.captions,
37414					'controls': 0,
37415					'enablejsapi': 1,
37416					'fs': 0,
37417					'modestbranding': 1,
37418					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
37419					'iv_load_policy': options.annotations,
37420					'loop': options.loop,
37421					'showinfo': 0,
37422					'rel': 0,
37423					'wmode': 'opaque',
37424					'hd': options.hd,
37425					'mute': 1,
37426					'start': start,
37427					'end': end
37428				},
37429				events: {
37430					'onReady': OKEvents.yt.ready,
37431					'onStateChange': OKEvents.yt.onStateChange,
37432					'onError': OKEvents.yt.error
37433				}
37434			});
37435			YTplayers[id] = playerY;
37436			playerY.videoId = id;
37437		}
37438
37439	});
37440}
37441// vimeo player ready
37442function vimeoPlayerReady(id) {
37443	options = jQuery(window).data('okoptions-' + id);
37444	if ( typeof options === 'undefined' ) {
37445		return true;
37446	}
37447	var jIframe = options.jobject,
37448		iframe = jIframe[0];
37449
37450	jIframe.attr('src', jIframe.data('src'));
37451	var playerV = new Vimeo.Player(iframe);
37452	// hide player until Vimeo hides controls...
37453	playerV.on('loaded', function(e) {
37454		OKEvents.v.onReady(iframe);
37455		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
37456		if (carouselContainer.length) {
37457			UNCODE.owlPlayVideo(carouselContainer);
37458		}
37459		// "Do not try to add listeners or call functions before receiving this event."
37460		if (OKEvents.utils.isMobile()) {
37461			// mobile devices cannot listen for play event
37462			OKEvents.v.onPlay(playerV);
37463		} else {
37464			playerV.on('play', function(){
37465				OKEvents.v.onPlay(playerV);
37466				jQuery(window).trigger('okevents.v.play', [playerV]);
37467			});
37468			playerV.on('pause', function(){
37469				OKEvents.v.onPause;
37470				jQuery(window).trigger('okevents.v.pause', [playerV]);
37471			});
37472			playerV.on('ended', function(){
37473				OKEvents.v.onFinish
37474				jQuery(window).trigger('okevents.v.ended', [playerV]);
37475			});
37476		}
37477		if (options.time != null) {
37478			var optsTimeStr = (options.time).replace('t=', ''),
37479				timeV = '';
37480
37481			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
37482				var timeArr = optsTimeStr.split(/([^\d.-])/);
37483				for ( var i = 0; i < timeArr.length; i++ ) {
37484					if ( timeArr[i] === 'h' ) {
37485						timeV += parseFloat(timeArr[i-1]) * 3600;
37486					} else if ( timeArr[i] === 'm' ) {
37487						timeV += parseFloat(timeArr[i-1]) * 60;
37488					} else if ( timeArr[i] === 's' ) {
37489						timeV += parseFloat(timeArr[i-1]);
37490					}
37491				}
37492			} else {
37493				timeV = optsTimeStr;
37494			}
37495
37496			playerV.setCurrentTime(timeV);
37497		}
37498
37499		playerV.setVolume(0);
37500		playerV.play();
37501		jQuery(iframe).css({
37502			visibility: 'visible',
37503			opacity: 1
37504		});
37505		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37506		jQuery(iframe).closest('#page-header').addClass('video-started');
37507		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37508
37509		jQuery(window).trigger('okevents.v.loaded', [playerV]);
37510	});
37511}
37512OKEvents = {
37513	yt: {
37514		ready: function(event) {
37515			var id = event.target.videoId,
37516				$video = jQuery('#okplayer-' + id),
37517				options = jQuery(window).data('okoptions-' + id);
37518			if ( typeof options === 'undefined' ) {
37519				return true;
37520			}
37521			youtubePlayers[id] = event.target;
37522			event.target.setVolume(options.volume);
37523			if (options.autoplay === 1) {
37524				if (options.playlist.list) {
37525					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
37526				} else {
37527					var inCarousel = $video.closest('.owl-item');
37528					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
37529						if (options.time != null) {
37530							event.target.seekTo(parseInt(options.time));
37531						}
37532						event.target.playVideo();
37533					} else {
37534						event.target.pauseVideo();
37535					}
37536				}
37537			}
37538			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
37539
37540			$video.closest('[data-provider]').on('uncode-resume', function(){
37541				if (options.time != null) {
37542					event.target.seekTo(parseInt(options.time)).playVideo();
37543				} else {
37544					event.target.seekTo(0).playVideo();
37545				}
37546			});
37547
37548			$video.closest('[data-provider]').on('uncode-pause', function(){
37549				if (options.time != null) {
37550					event.target.seekTo(parseInt(options.time)).pauseVideo();
37551				} else {
37552					event.target.seekTo(0).pauseVideo();
37553				}
37554			});
37555			jQuery(window).trigger('okevents.y.loaded', [event]);
37556		},
37557		onStateChange: function(event) {
37558			var id = event.target.videoId,
37559				$video = jQuery('#okplayer-' + id),
37560				options = jQuery(window).data('okoptions-' + id);
37561			if ( typeof options === 'undefined' ) {
37562				return true;
37563			}
37564			youtubePlayers[id] = event.target;
37565			event.target.setVolume(options.volume);
37566			var $fluid = $video.closest('.fluid-object'),
37567				$tmb = $video.closest('.tmb'),
37568				setTime;
37569			switch (event.data) {
37570				case -1:
37571					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
37572					break;
37573				case 0:
37574					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
37575					options.loop && event.target.playVideo();
37576					break;
37577				case 1:
37578					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37579					setTimeout(function() {
37580						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
37581						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37582						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
37583						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37584					}, 300);
37585				break;
37586				case 2:
37587					OKEvents.utils.isFunction(options.onPause) && options.onPause();
37588					break;
37589				case 3:
37590					OKEvents.utils.isFunction(options.buffering) && options.buffering();
37591					break;
37592				case 5:
37593					OKEvents.utils.isFunction(options.cued) && options.cued();
37594					break;
37595				default:
37596					throw "OKVideo: received invalid data from YT player.";
37597			}
37598
37599			jQuery(window).trigger('okevents.y.change', [event]);
37600		},
37601		error: function(event) {
37602			throw event;
37603		}
37604	},
37605	v: {
37606		onReady: function(target) {
37607			if ( typeof options === 'undefined' ) {
37608				return true;
37609			}
37610			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
37611		},
37612		onPlay: function(player) {
37613			if ( typeof options === 'undefined' ) {
37614				return true;
37615			}
37616			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
37617			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37618			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37619			jQuery(player.element).closest('#page-header').addClass('video-started');
37620			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37621		},
37622		onPause: function() {
37623			if ( typeof options === 'undefined' ) {
37624				return true;
37625			}
37626			OKEvents.utils.isFunction(options.onPause) && options.onPause();
37627		},
37628		onFinish: function() {
37629			if ( typeof options === 'undefined' ) {
37630				return true;
37631			}
37632			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
37633		}
37634	},
37635	utils: {
37636		isFunction: function(func) {
37637			if (typeof func === 'function') {
37638				return true;
37639			} else {
37640				return false;
37641			}
37642		},
37643		isMobile: function() {
37644			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
37645				return true;
37646			} else {
37647				return false;
37648			}
37649		}
37650	}
37651};
37652
37653/**
37654 * vivus - JavaScript library to make drawing animation on SVG
37655 * @version v0.4.4
37656 * @link https://github.com/maxwellito/vivus
37657 * @license MIT
37658 */
37659
37660'use strict';
37661
37662(function () {
37663
37664  'use strict';
37665
37666/**
37667 * Pathformer
37668 * Beta version
37669 *
37670 * Take any SVG version 1.1 and transform
37671 * child elements to 'path' elements
37672 *
37673 * This code is purely forked from
37674 * https://github.com/Waest/SVGPathConverter
37675 */
37676
37677/**
37678 * Class constructor
37679 *
37680 * @param {DOM|String} element Dom element of the SVG or id of it
37681 */
37682function Pathformer(element) {
37683  // Test params
37684  if (typeof element === 'undefined') {
37685	throw new Error('Pathformer [constructor]: "element" parameter is required');
37686  }
37687
37688  // Set the element
37689  if (element.constructor === String) {
37690	element = document.getElementById(element);
37691	if (!element) {
37692	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
37693	}
37694  }
37695  if (element instanceof window.SVGElement ||
37696	  element instanceof window.SVGGElement ||
37697	  /^svg$/i.test(element.nodeName)) {
37698	this.el = element;
37699  } else {
37700	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
37701  }
37702
37703  // Start
37704  this.scan(element);
37705}
37706
37707/**
37708 * List of tags which can be transformed
37709 * to path elements
37710 *
37711 * @type {Array}
37712 */
37713Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
37714
37715/**
37716 * List of attribute names which contain
37717 * data. This array list them to check if
37718 * they contain bad values, like percentage.
37719 *
37720 * @type {Array}
37721 */
37722Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 37722-38520
37722y1', 'y2'];
37723
37724/**
37725 * Finds the elements compatible for transform
37726 * and apply the liked method
37727 *
37728 * @param  {object} options Object from the constructor
37729 */
37730Pathformer.prototype.scan = function (svg) {
37731  var fn, element, pathData, pathDom,
37732	  elements = svg.querySelectorAll(this.TYPES.join(','));
37733
37734  for (var i = 0; i < elements.length; i++) {
37735	element = elements[i];
37736	fn = this[element.tagName.toLowerCase() + 'ToPath'];
37737	pathData = fn(this.parseAttr(element.attributes));
37738	pathDom = this.pathMaker(element, pathData);
37739	element.parentNode.replaceChild(pathDom, element);
37740  }
37741};
37742
37743
37744/**
37745 * Read `line` element to extract and transform
37746 * data, to make it ready for a `path` object.
37747 *
37748 * @param  {DOMelement} element Line element to transform
37749 * @return {object}			 Data for a `path` element
37750 */
37751Pathformer.prototype.lineToPath = function (element) {
37752  var newElement = {},
37753	  x1 = element.x1 || 0,
37754	  y1 = element.y1 || 0,
37755	  x2 = element.x2 || 0,
37756	  y2 = element.y2 || 0;
37757
37758  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
37759  return newElement;
37760};
37761
37762/**
37763 * Read `rect` element to extract and transform
37764 * data, to make it ready for a `path` object.
37765 * The radius-border is not taken in charge yet.
37766 * (your help is more than welcomed)
37767 *
37768 * @param  {DOMelement} element Rect element to transform
37769 * @return {object}             Data for a `path` element
37770 */
37771Pathformer.prototype.rectToPath = function (element) {
37772  var newElement = {},
37773      x      = parseFloat(element.x)      || 0,
37774      y      = parseFloat(element.y)      || 0,
37775      width  = parseFloat(element.width)  || 0,
37776      height = parseFloat(element.height) || 0;
37777
37778  if (element.rx || element.ry) {
37779    var rx = parseInt(element.rx, 10) || -1,
37780        ry = parseInt(element.ry, 10) || -1;
37781    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
37782    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
37783
37784    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
37785                   'L ' + (x + width - rx) + ',' + y + ' ' +
37786                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
37787                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
37788                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
37789                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
37790                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
37791                   'L ' + x + ',' + (y + ry) + ' ' +
37792                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
37793  }
37794  else {
37795    newElement.d = 'M' + x + ' ' + y + ' ' +
37796                   'L' + (x + width) + ' ' + y + ' ' +
37797                   'L' + (x + width) + ' ' + (y + height) + ' ' +
37798                   'L' + x + ' ' + (y + height) + ' Z';
37799  }
37800  return newElement;
37801};
37802
37803/**
37804 * Read `polyline` element to extract and transform
37805 * data, to make it ready for a `path` object.
37806 *
37807 * @param  {DOMelement} element Polyline element to transform
37808 * @return {object}             Data for a `path` element
37809 */
37810Pathformer.prototype.polylineToPath = function (element) {
37811  var newElement = {},
37812      points = element.points.trim().split(' '),
37813      i, path;
37814
37815  // Reformatting if points are defined without commas
37816  if (element.points.indexOf(',') === -1) {
37817    var formattedPoints = [];
37818    for (i = 0; i < points.length; i+=2) {
37819      formattedPoints.push(points[i] + ',' + points[i+1]);
37820    }
37821    points = formattedPoints;
37822  }
37823
37824  // Generate the path.d value
37825  path = 'M' + points[0];
37826  for(i = 1; i < points.length; i++) {
37827    if (points[i].indexOf(',') !== -1) {
37828      path += 'L' + points[i];
37829    }
37830  }
37831  newElement.d = path;
37832  return newElement;
37833};
37834
37835/**
37836 * Read `polygon` element to extract and transform
37837 * data, to make it ready for a `path` object.
37838 * This method rely on polylineToPath, because the
37839 * logic is similar. The path created is just closed,
37840 * so it needs an 'Z' at the end.
37841 *
37842 * @param  {DOMelement} element Polygon element to transform
37843 * @return {object}             Data for a `path` element
37844 */
37845Pathformer.prototype.polygonToPath = function (element) {
37846  var newElement = Pathformer.prototype.polylineToPath(element);
37847
37848  newElement.d += 'Z';
37849  return newElement;
37850};
37851
37852/**
37853 * Read `ellipse` element to extract and transform
37854 * data, to make it ready for a `path` object.
37855 *
37856 * @param  {DOMelement} element ellipse element to transform
37857 * @return {object}             Data for a `path` element
37858 */
37859Pathformer.prototype.ellipseToPath = function (element) {
37860  var newElement = {},
37861      rx = parseFloat(element.rx) || 0,
37862      ry = parseFloat(element.ry) || 0,
37863      cx = parseFloat(element.cx) || 0,
37864      cy = parseFloat(element.cy) || 0,
37865      startX = cx - rx,
37866      startY = cy,
37867      endX = parseFloat(cx) + parseFloat(rx),
37868      endY = cy;
37869
37870  newElement.d = 'M' + startX + ',' + startY +
37871                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37872                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37873  return newElement;
37874};
37875
37876/**
37877 * Read `circle` element to extract and transform
37878 * data, to make it ready for a `path` object.
37879 *
37880 * @param  {DOMelement} element Circle element to transform
37881 * @return {object}             Data for a `path` element
37882 */
37883Pathformer.prototype.circleToPath = function (element) {
37884  var newElement = {},
37885      r  = parseFloat(element.r)  || 0,
37886      cx = parseFloat(element.cx) || 0,
37887      cy = parseFloat(element.cy) || 0,
37888      startX = cx - r,
37889      startY = cy,
37890      endX = parseFloat(cx) + parseFloat(r),
37891      endY = cy;
37892
37893  newElement.d =  'M' + startX + ',' + startY +
37894                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37895                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37896  return newElement;
37897};
37898
37899/**
37900 * Create `path` elements form original element
37901 * and prepared objects
37902 *
37903 * @param  {DOMelement} element  Original element to transform
37904 * @param  {object} pathData     Path data (from `toPath` methods)
37905 * @return {DOMelement}          Path element
37906 */
37907Pathformer.prototype.pathMaker = function (element, pathData) {
37908  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37909  for(i = 0; i < element.attributes.length; i++) {
37910    attr = element.attributes[i];
37911    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37912      pathTag.setAttribute(attr.name, attr.value);
37913    }
37914  }
37915  for(i in pathData) {
37916    pathTag.setAttribute(i, pathData[i]);
37917  }
37918  return pathTag;
37919};
37920
37921/**
37922 * Parse attributes of a DOM element to
37923 * get an object of attribute => value
37924 *
37925 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37926 * @return {object}                  Object of attributes
37927 */
37928Pathformer.prototype.parseAttr = function (element) {
37929  var attr, output = {};
37930  for (var i = 0; i < element.length; i++) {
37931    attr = element[i];
37932    // Check if no data attribute contains '%', or the transformation is impossible
37933    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37934      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37935    }
37936    output[attr.name] = attr.value;
37937  }
37938  return output;
37939};
37940
37941  'use strict';
37942
37943var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
37944
37945/**
37946 * Vivus
37947 * Beta version
37948 *
37949 * Take any SVG and make the animation
37950 * to give give the impression of live drawing
37951 *
37952 * This in more than just inspired from codrops
37953 * At that point, it's a pure fork.
37954 */
37955
37956/**
37957 * Class constructor
37958 * option structure
37959 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
37960 *   duration: <int> (in frames)
37961 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
37962 *   delay: <int> (delay between the drawing of first and last path)
37963 *   dashGap <integer> whitespace extra margin between dashes
37964 *   pathTimingFunction <function> timing animation function for each path element of the SVG
37965 *   animTimingFunction <function> timing animation function for the complete SVG
37966 *   forceRender <boolean> force the browser to re-render all updated path items
37967 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
37968 *
37969 * The attribute 'type' is by default on 'delayed'.
37970 *  - 'delayed'
37971 *    all paths are draw at the same time but with a
37972 *    little delay between them before start
37973 *  - 'sync'
37974 *    all path are start and finish at the same time
37975 *  - 'oneByOne'
37976 *    only one path is draw at the time
37977 *    the end of the first one will trigger the draw
37978 *    of the next one
37979 *
37980 * All these values can be overwritten individually
37981 * for each path item in the SVG
37982 * The value of frames will always take the advantage of
37983 * the duration value.
37984 * If you fail somewhere, an error will be thrown.
37985 * Good luck.
37986 *
37987 * @constructor
37988 * @this {Vivus}
37989 * @param {DOM|String}   element  Dom element of the SVG or id of it
37990 * @param {Object}       options  Options about the animation
37991 * @param {Function}     callback Callback for the end of the animation
37992 */
37993function Vivus (element, options, callback) {
37994
37995  setupEnv();
37996
37997  // Setup
37998  this.isReady = false;
37999  this.setElement(element, options);
38000  this.setOptions(options);
38001  this.setCallback(callback);
38002
38003  if (this.isReady) {
38004    this.init();
38005  }
38006}
38007
38008/**
38009 * Timing functions
38010 **************************************
38011 *
38012 * Default functions to help developers.
38013 * It always take a number as parameter (between 0 to 1) then
38014 * return a number (between 0 and 1)
38015 */
38016Vivus.LINEAR          = function (x) {return x;};
38017Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
38018Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
38019Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
38020Vivus.EASE_OUT_BOUNCE = function (x) {
38021  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
38022    rate = Math.pow(base,1.5),
38023    rateR = Math.pow(1 - x, 2),
38024    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
38025  return (1- rateR) + (progress * rateR);
38026};
38027
38028
38029/**
38030 * Setters
38031 **************************************
38032 */
38033
38034/**
38035 * Check and set the element in the instance
38036 * The method will not return anything, but will throw an
38037 * error if the parameter is invalid
38038 *
38039 * @param {DOM|String}   element  SVG Dom element or id of it
38040 */
38041Vivus.prototype.setElement = function (element, options) {
38042  var onLoad, self;
38043
38044  // Basic check
38045  if (typeof element === 'undefined') {
38046    throw new Error('Vivus [constructor]: "element" parameter is required');
38047  }
38048
38049  // Set the element
38050  if (element.constructor === String) {
38051    element = document.getElementById(element);
38052    if (!element) {
38053      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
38054    }
38055  }
38056  this.parentEl = element;
38057
38058  // Load the SVG with XMLHttpRequest and extract the SVG
38059  if (options && options.file) {
38060    var self = this;
38061    onLoad = function (e) {
38062      var domSandbox = document.createElement('div');
38063      domSandbox.innerHTML = this.responseText;
38064
38065      var svgTag = domSandbox.querySelector('svg');
38066      if (!svgTag) {
38067        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
38068      }
38069
38070      self.el = svgTag
38071      self.el.setAttribute('width', '100%');
38072      self.el.setAttribute('height', '100%');
38073      self.parentEl.appendChild(self.el)
38074      self.isReady = true;
38075      self.init();
38076      self = null;
38077    }
38078
38079    var oReq = new window.XMLHttpRequest();
38080    oReq.addEventListener('load', onLoad);
38081    oReq.open('GET', options.file);
38082    oReq.send();
38083    return;
38084  }
38085
38086  switch (element.constructor) {
38087  case window.SVGSVGElement:
38088  case window.SVGElement:
38089  case window.SVGGElement:
38090    this.el = element;
38091    this.isReady = true;
38092    break;
38093
38094  case window.HTMLObjectElement:
38095    self = this;
38096    onLoad = function (e) {
38097      if (self.isReady) {
38098        return;
38099      }
38100      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
38101      if (!self.el && e) {
38102        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
38103      }
38104      else if (self.el) {
38105        if (element.getAttribute('built-by-vivus')) {
38106          self.parentEl.insertBefore(self.el, element);
38107          self.parentEl.removeChild(element);
38108          self.el.setAttribute('width', '100%');
38109          self.el.setAttribute('height', '100%');
38110        }
38111        self.isReady = true;
38112        self.init();
38113        self = null;
38114      }
38115    };
38116
38117    if (!onLoad()) {
38118      element.addEventListener('load', onLoad);
38119    }
38120    break;
38121
38122  default:
38123    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
38124  }
38125};
38126
38127/**
38128 * Set up user option to the instance
38129 * The method will not return anything, but will throw an
38130 * error if the parameter is invalid
38131 *
38132 * @param  {object} options Object from the constructor
38133 */
38134Vivus.prototype.setOptions = function (options) {
38135  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
38136  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
38137
38138  // Basic check
38139  if (options !== undefined && options.constructor !== Object) {
38140    throw new Error('Vivus [constructor]: "options" parameter must be an object');
38141  }
38142  else {
38143    options = options || {};
38144  }
38145
38146  // Set the animation type
38147  if (options.type && allowedTypes.indexOf(options.type) === -1) {
38148    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
38149  }
38150  else {
38151    this.type = options.type || allowedTypes[0];
38152  }
38153
38154  // Set the start type
38155  if (options.start && allowedStarts.indexOf(options.start) === -1) {
38156    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
38157  }
38158  else {
38159    this.start = options.start || allowedStarts[0];
38160  }
38161
38162  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
38163  this.duration     = parsePositiveInt(options.duration, 120);
38164  this.delay        = parsePositiveInt(options.delay, null);
38165  //Uncode addition
38166  this.delayStart   = parsePositiveInt(options.delayStart, null);
38167  //#END
38168  this.dashGap      = parsePositiveInt(options.dashGap, 1);
38169  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
38170  this.reverseStack = !!options.reverseStack;
38171  this.selfDestroy  = !!options.selfDestroy;
38172  this.onReady      = options.onReady;
38173  this.map          = [];
38174  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
38175
38176  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
38177
38178  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
38179  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
38180
38181  if (this.delay >= this.duration) {
38182    throw new Error('Vivus [constructor]: delay must be shorter than duration');
38183  }
38184};
38185
38186/**
38187 * Set up callback to the instance
38188 * The method will not return enything, but will throw an
38189 * error if the parameter is invalid
38190 *
38191 * @param  {Function} callback Callback for the animation end
38192 */
38193Vivus.prototype.setCallback = function (callback) {
38194  // Basic check
38195  if (!!callback && callback.constructor !== Function) {
38196    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
38197  }
38198  this.callback = callback || function () {};
38199};
38200
38201
38202/**
38203 * Core
38204 **************************************
38205 */
38206
38207/**
38208 * Map the svg, path by path.
38209 * The method return nothing, it just fill the
38210 * `map` array. Each item in this array represent
38211 * a path element from the SVG, with informations for
38212 * the animation.
38213 *
38214 * ```
38215 * [
38216 *   {
38217 *     el: <DOMobj> the path element
38218 *     length: <number> length of the path line
38219 *     startAt: <number> time start of the path animation (in frames)
38220 *     duration: <number> path animation duration (in frames)
38221 *   },
38222 *   ...
38223 * ]
38224 * ```
38225 *
38226 */
38227Vivus.prototype.mapping = function () {
38228  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
38229  timePoint = totalLength = lengthMeter = 0;
38230  paths = this.el.querySelectorAll('path');
38231
38232  for (i = 0; i < paths.length; i++) {
38233    path = paths[i];
38234    if (this.isInvisible(path)) {
38235      continue;
38236    }
38237    pathObj = {
38238      el: path,
38239      length: Math.ceil(path.getTotalLength())
38240    };
38241    // Test if the path length is correct
38242    if (isNaN(pathObj.length)) {
38243      if (window.console && console.warn) {
38244        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
38245      }
38246      continue;
38247    }
38248    this.map.push(pathObj);
38249    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
38250    path.style.strokeDashoffset = pathObj.length + this.dashGap;
38251    pathObj.length += this.dashGap;
38252    totalLength += pathObj.length;
38253
38254    this.renderPath(i);
38255  }
38256
38257  totalLength = totalLength === 0 ? 1 : totalLength;
38258  this.delay = this.delay === null ? this.duration / 3 : this.delay;
38259  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
38260
38261  // Reverse stack if asked
38262  if (this.reverseStack) {
38263    this.map.reverse();
38264  }
38265
38266  for (i = 0; i < this.map.length; i++) {
38267    pathObj = this.map[i];
38268
38269    switch (this.type) {
38270    case 'delayed':
38271      pathObj.startAt = this.delayUnit * i;
38272      pathObj.duration = this.duration - this.delay;
38273      break;
38274
38275    case 'oneByOne':
38276      pathObj.startAt = lengthMeter / totalLength * this.duration;
38277      pathObj.duration = pathObj.length / totalLength * this.duration;
38278      break;
38279
38280    case 'sync':
38281    case 'async':
38282    case 'nsync':
38283      pathObj.startAt = 0;
38284      pathObj.duration = this.duration;
38285      break;
38286
38287    case 'scenario-sync':
38288      path = pathObj.el;
38289      pAttrs = this.parseAttr(path);
38290      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
38291      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38292      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
38293      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38294      break;
38295
38296    case 'scenario':
38297      path = pathObj.el;
38298      pAttrs = this.parseAttr(path);
38299      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
38300      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38301      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38302      break;
38303    }
38304    lengthMeter += pathObj.length;
38305    this.frameLength = this.frameLength || this.duration;
38306  }
38307};
38308
38309/**
38310 * Interval method to draw the SVG from current
38311 * position of the animation. It update the value of
38312 * `currentFrame` and re-trace the SVG.
38313 *
38314 * It use this.handle to store the requestAnimationFrame
38315 * and clear it one the animation is stopped. So this
38316 * attribute can be used to know if the animation is
38317 * playing.
38318 *
38319 * Once the animation at the end, this method will
38320 * trigger the Vivus callback.
38321 *
38322 */
38323Vivus.prototype.drawer = function () {
38324  var self = this;
38325  this.currentFrame += this.speed;
38326
38327  if (this.currentFrame <= 0) {
38328    this.stop();
38329    this.reset();
38330  } else if (this.currentFrame >= this.frameLength) {
38331    this.stop();
38332    this.currentFrame = this.frameLength;
38333    this.trace();
38334    if (this.selfDestroy) {
38335      this.destroy();
38336    }
38337  } else {
38338    this.trace();
38339    this.handle = requestAnimFrame(function () {
38340      self.drawer();
38341    });
38342    return;
38343  }
38344
38345  this.callback(this);
38346  if (this.instanceCallback) {
38347    this.instanceCallback(this);
38348    this.instanceCallback = null;
38349  }
38350};
38351
38352/**
38353 * Draw the SVG at the current instant from the
38354 * `currentFrame` value. Here is where most of the magic is.
38355 * The trick is to use the `strokeDashoffset` style property.
38356 *
38357 * For optimisation reasons, a new property called `progress`
38358 * is added in each item of `map`. This one contain the current
38359 * progress of the path element. Only if the new value is different
38360 * the new value will be applied to the DOM element. This
38361 * method save a lot of resources to re-render the SVG. And could
38362 * be improved if the animation couldn't be played forward.
38363 *
38364 */
38365Vivus.prototype.trace = function () {
38366  var i, progress, path, currentFrame;
38367  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
38368  for (i = 0; i < this.map.length; i++) {
38369    path = this.map[i];
38370    progress = (currentFrame - path.startAt) / path.duration;
38371    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
38372    if (path.progress !== progress) {
38373      path.progress = progress;
38374      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
38375      this.renderPath(i);
38376    }
38377  }
38378};
38379
38380/**
38381 * Method forcing the browser to re-render a path element
38382 * from it's index in the map. Depending on the `forceRender`
38383 * value.
38384 * The trick is to replace the path element by it's clone.
38385 * This practice is not recommended because it's asking more
38386 * ressources, too much DOM manupulation..
38387 * but it's the only way to let the magic happen on IE.
38388 * By default, this fallback is only applied on IE.
38389 *
38390 * @param  {Number} index Path index
38391 */
38392Vivus.prototype.renderPath = function (index) {
38393  if (this.forceRender && this.map && this.map[index]) {
38394    var pathObj = this.map[index],
38395        newPath = pathObj.el.cloneNode(true);
38396    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
38397    pathObj.el = newPath;
38398  }
38399};
38400
38401/**
38402 * When the SVG object is loaded and ready,
38403 * this method will continue the initialisation.
38404 *
38405 * This this mainly due to the case of passing an
38406 * object tag in the constructor. It will wait
38407 * the end of the loading to initialise.
38408 *
38409 */
38410Vivus.prototype.init = function () {
38411  // Set object variables
38412  this.frameLength = 0;
38413  this.currentFrame = 0;
38414  this.map = [];
38415
38416  // Start
38417  new Pathformer(this.el);
38418  this.mapping();
38419  this.starter();
38420
38421  if (this.onReady) {
38422    this.onReady(this);
38423  }
38424};
38425
38426/**
38427 * Trigger to start of the animation.
38428 * Depending on the `start` value, a different script
38429 * will be applied.
38430 *
38431 * If the `start` value is not valid, an error will be thrown.
38432 * Even if technically, this is impossible.
38433 *
38434 */
38435Vivus.prototype.starter = function () {
38436  switch (this.start) {
38437  case 'manual':
38438    return;
38439
38440  case 'autostart':
38441    this.play();
38442    break;
38443
38444  case 'inViewport':
38445    var self = this,
38446    listener = function () {
38447      if (self.isInViewport(self.parentEl, 1)) {
38448        self.play();
38449        window.removeEventListener('scroll', listener);
38450        //Uncode addition
38451        window.removeEventListener('fp-slide-changed', listener);
38452        window.removeEventListener('fp-slide-scroll', listener);
38453        //#END
38454      }
38455    };
38456    window.addEventListener('scroll', listener);
38457    //Uncode addition
38458    window.addEventListener('fp-slide-changed', listener);
38459    window.addEventListener('fp-slide-scroll', listener);
38460    //#END
38461    listener();
38462    break;
38463  }
38464};
38465
38466
38467/**
38468 * Controls
38469 **************************************
38470 */
38471
38472/**
38473 * Get the current status of the animation between
38474 * three different states: 'start', 'progress', 'end'.
38475 * @return {string} Instance status
38476 */
38477Vivus.prototype.getStatus = function () {
38478  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
38479};
38480
38481/**
38482 * Reset the instance to the initial state : undraw
38483 * Be careful, it just reset the animation, if you're
38484 * playing the animation, this won't stop it. But just
38485 * make it start from start.
38486 *
38487 */
38488Vivus.prototype.reset = function () {
38489  return this.setFrameProgress(0);
38490};
38491
38492/**
38493 * Set the instance to the final state : drawn
38494 * Be careful, it just set the animation, if you're
38495 * playing the animation on rewind, this won't stop it.
38496 * But just make it start from the end.
38497 *
38498 */
38499Vivus.prototype.finish = function () {
38500  return this.setFrameProgress(1);
38501};
38502
38503/**
38504 * Set the level of progress of the drawing.
38505 *
38506 * @param {number} progress Level of progress to set
38507 */
38508Vivus.prototype.setFrameProgress = function (progress) {
38509  progress = Math.min(1, Math.max(0, progress));
38510  this.currentFrame = Math.round(this.frameLength * progress);
38511  this.trace();
38512  return this;
38513};
38514
38515/**
38516 * Play the animation at the desired speed.
38517 * Speed must be a valid number (no zero).
38518 * By default, the speed value is 1.
38519 * But a negative value is accepted to go forward.
38520 *
38521 * And works with float too.
38522 * But don't forget we are in JavaScript, se be nice
38523 * with him and give him a 1/2^x value.
38524 *
38525 * @param  {number} speed Animation speed [optional]
38526 */
38527Vivus.prototype.play = function (speed, callback) {
38528  this.instanceCallback = null;
38529
38530  if (speed && typeof speed === 'function') {
38531    this.instanceCallback = speed; // first parameter is actually the callback function
38532    speed = null;
38533  }
38534  else if (speed && typeof speed !== 'number') {
38535    throw new Error('Vivus [play]: invalid speed');
38536  }
38537  // if the first parameter wasn't the callback, check if the seconds was
38538  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
38539    this.instanceCallback = callback;
38540  }
38541
38542
38543  this.speed = speed || 1;
38544  //Uncode addition
38545  if (!this.handle) {
38546    var $this = this,
38547    delay = (this.delayStart != null) ? this.delayStart : 0;
38548    setTimeout(function() {
38549      $this.drawer();
38550    }, delay);
38551  }
38552  //#END
38553  return this;
38554};
38555
38556/**
38557 * Stop the current animation, if on progress.
38558 * Should not trigger any error.
38559 *
38560 */
38561Vivus.prototype.stop = function () {
38562  if (this.handle) {
38563    cancelAnimFrame(this.handle);
38564    this.handle = null;
38565  }
38566  return this;
38567};
38568
38569/**
38570 * Destroy the instance.
38571 * Remove all bad styling attributes on all
38572 * path tags
38573 *
38574 */
38575Vivus.prototype.destroy = function () {
38576  this.stop();
38577  var i, path;
38578  for (i = 0; i < this.map.length; i++) {
38579    path = this.map[i];
38580    path.el.style.strokeDashoffset = null;
38581    path.el.style.strokeDasharray = null;
38582    this.renderPath(i);
38583  }
38584};
38585
38586
38587/**
38588 * Utils methods
38589 * include methods from Codrops
38590 **************************************
38591 */
38592
38593/**
38594 * Method to best guess if a path should added into
38595 * the animation or not.
38596 *
38597 * 1. Use the `data-vivus-ignore` attribute if set
38598 * 2. Check if the instance must ignore invisible paths
38599 * 3. Check if the path is visible
38600 *
38601 * For now the visibility checking is unstable.
38602 * It will be used for a beta phase.
38603 *
38604 * Other improvments are planned. Like detecting
38605 * is the path got a stroke or a valid opacity.
38606 */
38607Vivus.prototype.isInvisible = function (el) {
38608  var rect,
38609    ignoreAttr = el.getAttribute('data-ignore');
38610
38611  if (ignoreAttr !== null) {
38612    return ignoreAttr !== 'false';
38613  }
38614
38615  if (this.ignoreInvisible) {
38616    rect = el.getBoundingClientRect();
38617    return !rect.width && !rect.height;
38618  }
38619  else {
38620    return false;
38621  }
38622};
38623
38624/**
38625 * Parse attributes of a DOM element to
38626 * get an object of {attributeName => attributeValue}
38627 *
38628 * @param  {object} element DOM element to parse
38629 * @return {object}         Object of attributes
38630 */
38631Vivus.prototype.parseAttr = function (element) {
38632  var attr, output = {};
38633  if (element && element.attributes) {
38634    for (var i = 0; i < element.attributes.length; i++) {
38635      attr = element.attributes[i];
38636      output[attr.name] = attr.value;
38637    }
38638  }
38639  return output;
38640};
38641
38642/**
38643 * Reply if an element is in the page viewport
38644 *
38645 * @param  {object} el Element to observe
38646 * @param  {number} h  Percentage of height
38647 * @return {boolean}
38648 */
38649Vivus.prototype.isInViewport = function (el, h) {
38650  var scrolled   = this.scrollY(),
38651    viewed       = scrolled + this.getViewportH(),
38652    elBCR        = el.getBoundingClientRect(),
38653    elHeight     = elBCR.height,
38654    elTop        = scrolled + elBCR.top,
38655    elBottom     = elTop + elHeight;
38656
38657  // if 0, the element is considered in the viewport as soon as it enters.
38658  // if 1, the element is considered in the viewport only when it's fully inside
38659  // value in percentage (1 >= h >= 0)
38660  h = h || 0;
38661
38662  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
38663};
38664
38665
38666/**
38667 * Get the viewport height in pixels
38668 *
38669 * @return {integer} Viewport height
38670 */
38671Vivus.prototype.getViewportH = function () {
38672  var client = this.docElem.clientHeight,
38673    inner = window.innerHeight;
38674
38675  if (client < inner) {
38676    return inner;
38677  }
38678  else {
38679    return client;
38680  }
38681};
38682
38683/**
38684 * Get the page Y offset
38685 *
38686 * @return {integer} Page Y offset
38687 */
38688Vivus.prototype.scrollY = function () {
38689  return window.pageYOffset || this.docElem.scrollTop;
38690};
38691
38692setupEnv = function () {
38693
38694  if (Vivus.prototype.docElem) {
38695    return;
38696  }
38697
38698  /**
38699   * Alias for document element
38700   *
38701   * @type {DOMelement}
38702   */
38703  Vivus.prototype.docElem = window.document.documentElement;
38704
38705  /**
38706   * Alias for `requestAnimationFrame` or
38707   * `setTimeout` function for deprecated browsers.
38708   *
38709   */
38710  requestAnimFrame = (function () {
38711    return (
38712      window.requestAnimationFrame       ||
38713      window.webkitRequestAnimationFrame ||
38714      window.mozRequestAnimationFrame    ||
38715      window.oRequestAnimationFrame      ||
38716      window.msRequestAnimationFrame     ||
38717      function(/* function */ callback){
38718        return window.setTimeout(callback, 1000 / 60);
38719      }
38720    );
38721  })();
38722
38723  /**
38724   * Alias for `cancelAnimationFrame` or
38725   * `cancelTimeout` function for deprecated browsers.
38726   *
38727   */
38728  cancelAnimFrame = (function () {
38729    return (
38730      window.cancelAnimationFrame       ||
38731      window.webkitCancelAnimationFrame ||
38732      window.mozCancelAnimationFrame    ||
38733      window.oCancelAnimationFrame      ||
38734      window.msCancelAnimationFrame     ||
38735      function(id){
38736        return window.clearTimeout(id);
38737      }
38738    );
38739  })();
38740};
38741
38742/**
38743 * Parse string to integer.
38744 * If the number is not positive or null
38745 * the method will return the default value
38746 * or 0 if undefined
38747 *
38748 * @param {string} value String to parse
38749 * @param {*}
38749 defaultValue Value to return if the result parsed is invalid
38750 * @return {number}
38751 *
38752 */
38753parsePositiveInt = function (value, defaultValue) {
38754  var output = parseInt(value, 10);
38755  return (output >= 0) ? output : defaultValue;
38756};
38757
38758
38759  if (typeof define === 'function' && define.amd) {
38760    // AMD. Register as an anonymous module.
38761    define([], function() {
38762      return Vivus;
38763    });
38764  } else if (typeof exports === 'object') {
38765    // Node. Does not work with strict CommonJS, but
38766    // only CommonJS-like environments that support module.exports,
38767    // like Node.
38768    module.exports = Vivus;
38769  } else {
38770    // Browser globals
38771    window.Vivus = Vivus;
38772  }
38773
38774}());

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.