PageSourceSearch

https://chemitec.it/wp-content/themes/uncode/library/js/plugins.js?ver=1555932951

js chemitec.it collected 2026-10-06 00:26:50 UTC 1,294,029 bytes, 38,838 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
5564  var counter = 0,
5565    $headCache = $('head'),
5566    oldBigText = window.BigText,
5567    oldjQueryMethod = $.fn.bigtext,
5568    BigText = {
5569      DEBUG_MODE: false,
5570      DEFAULT_MIN_FONT_SIZE_PX: null,
5571      DEFAULT_MAX_FONT_SIZE_PX: 528,
5572      GLOBAL_STYLE_ID: 'bigtext-style',
5573      STYLE_ID: 'bigtext-id',
5574      LINE_CLASS_PREFIX: 'bigtext-line',
5575      EXEMPT_CLASS: 'bigtext-exempt',
5576      noConflict: function(restore)
5577      {
5578        if(restore) {
5579          $.fn.bigtext = oldjQueryMethod;
5580          window.BigText = oldBigText;
5581        }
5582        return BigText;
5583      },
5584      supports: {
5585        wholeNumberFontSizeOnly: (function() {
5586          if( !( 'getComputedStyle' in window ) ) {
5587            return true;
5588          }
5589          var test = $('<div/>').css({
5590              position: 'absolute',
5591              'font-size': '14.1px'
5592            }).insertBefore( $('script').eq(0) ),
5593            computedStyle = window.getComputedStyle( test[0], null );
5594
5595          var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px';
5596          test.remove();
5597          return ret;
5598        })()
5599      },
5600      init: function() {
5601        if(!$('#'+BigText.GLOBAL_STYLE_ID).length) {
5602          $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }',
5603                                          '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }']));
5604        }
5605      },
5606      bindResize: function(eventName, resizeFunction) {
5607        var timeoutId;
5608        $(window).off(eventName).on(eventName, function() {
5609          if( timeoutId ) {
5610            clearTimeout( timeoutId );
5611          }
5612          timeoutId = setTimeout( resizeFunction, 100 );
5613        });
5614      },
5615      getStyleId: function(id)
5616      {
5617        return BigText.STYLE_ID + '-' + id;
5618      },
5619      generateStyleTag: function(id, css)
5620      {
5621        return $('<style>' + css.join('\n') + '</style>').attr('id', id);
5622      },
5623      clearCss: function(id)
5624      {
5625        var styleId = BigText.getStyleId(id);
5626        $('#' + styleId).remove();
5627      },
5628      generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes)
5629      {
5630        var css = [];
5631
5632        BigText.clearCss(id);
5633
5634        for(var j=0, k=linesFontSizes.length; j<k; j++) {
5635          css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' +
5636            (minFontSizes[j] ? ' white-space: normal;' : '') +
5637            (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') +
5638            (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') +
5639            '}');
5640        }
5641
5642        return BigText.generateStyleTag(BigText.getStyleId(id), css);
5643      },
5644      jQueryMethod: function(options)
5645      {
5646        BigText.init();
5647
5648        options = $.extend({
5649          minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX,
5650          maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX,
5651          childSelector: '',
5652          resize: true
5653        }, options || {});
5654
5655        this.each(function()
5656        {
5657          var $t = $(this).addClass('bigtext'),
5658            maxWidth = $t.width(),
5659            id = $t.attr('id'),
5660            $children = options.childSelector ? $t.find( options.childSelector ) : $t.children();
5661
5662          if(!id) {
5663            id = 'bigtext-id' + (counter++);
5664            $t.attr('id', id);
5665          }
5666
5667          if(options.resize) {
5668            BigText.bindResize('resize.bigtext-event-' + id, function()
5669            {
5670              // TODO only call this if the width has changed.
5671              BigText.jQueryMethod.call($('#' + id), options);
5672            });
5673          }
5674
5675          BigText.clearCss(id);
5676
5677          $children.addClass(function(lineNumber, className)
5678          {
5679            // remove existing line classes.
5680            return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''),
5681                BigText.LINE_CLASS_PREFIX + lineNumber].join(' ');
5682          });
5683
5684          var sizes = BigText.calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize);
5685          $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes));
5686        });
5687
5688        return this.trigger('bigtext:complete');
5689      },
5690      testLineDimensions: function($line, maxWidth, property, size, interval, units, previousWidth)
5691      {
5692        var width;
5693        previousWidth = typeof previousWidth === 'number' ? previousWidth : 0;
5694        $line.css(property, size + units);
5695
5696        width = $line.width();
5697
5698        if(width >= maxWidth) {
5699    // console.log(width, ' previous: ' + previousWidth, property + ' at ' + interval, 'prior: ' + (parseFloat(size) - interval), 'new:' + parseFloat(size));
5700          $line.css(property, '');
5701
5702          if(width === maxWidth) {
5703            return {
5704              match: 'exact',
5705              size: parseFloat((parseFloat(size) - 0.1).toFixed(3))
5706            };
5707          }
5708
5709          // Since this is an estimate, we calculate how far over the width we went with the new value.
5710          // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value.
5711          // Otherwise, we revert to the underestimate.
5712          var under = maxWidth - previousWidth,
5713            over = width - maxWidth;
5714
5715          return {
5716            match: 'estimate',
5717            size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3))
5718          };
5719        }
5720
5721        return width;
5722      },
5723      calculateSizes: function($t, $children, maxWidth, maxFontSize, minFontSize)
5724      {
5725        var $c = $t.clone(true)
5726          .addClass('bigtext-cloned')
5727          .css({
5728            fontFamily: $t.css('font-family'),
5729            textTransform: $t.css('text-transform'),
5730            wordSpacing: $t.css('word-spacing'),
5731            letterSpacing: $t.css('letter-spacing'),
5732            position: 'absolute',
5733            left: BigText.DEBUG_MODE ? 0 : -9999,
5734            top: BigText.DEBUG_MODE ? 0 : -9999
5735          })
5736          .appendTo(document.body);
5737
5738        // font-size isn't the only thing we can modify, we can also mess with:
5739        // word-spacing and letter-spacing. WebKit does not respect subpixel
5740        // letter-spacing, word-spacing, or font-size.
5741        // TODO try -webkit-transform: scale() as a workaround.
5742        var fontSizes = [],
5743          wordSpacings = [],
5744          minFontSizes = [],
5745          ratios = [];
5746
5747        $children.css('float', 'left').each(function() {
5748          var $line = $(this),
5749            // TODO replace 8, 4 with a proportional size to the calculated font-size.
5750            intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1],
5751            lineMax,
5752            newFontSize;
5753
5754          if($line.hasClass(BigText.EXEMPT_CLASS)) {
5755            fontSizes.push(null);
5756            ratios.push(null);
5757            minFontSizes.push(false);
5758            return;
5759          }
5760
5761          // TODO we can cache this ratio?
5762          var autoGuessSubtraction = 32, // font size in px
5763            currentFontSize = parseFloat($line.css('font-size')),
5764            ratio = ( $line.width() / currentFontSize ).toFixed(6);
5765
5766          newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction;
5767
5768          outer: for(var m=0, n=intervals.length; m<n; m++) {
5769            inner: for(var j=1, k=10; j<=k; j++) {
5770              if(newFontSize + j*intervals[m] > maxFontSize) {
5771                newFontSize = maxFontSize;
5772                break outer;
5773              }
5774
5775              lineMax = BigText.testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax);
5776              if(typeof lineMax !== 'number') {
5777                newFontSize = lineMax.size;
5778
5779                if(lineMax.match === 'exact') {
5780                  break outer;
5781                }
5782                break inner;
5783              }
5784            }
5785          }
5786
5787          ratios.push(maxWidth / newFontSize);
5788
5789          if(newFontSize > maxFontSize) {
5790            fontSizes.push(maxFontSize);
5791            minFontSizes.push(false);
5792          } else if(!!minFontSize && newFontSize < minFontSize) {
5793            fontSizes.push(minFontSize);
5794            minFontSizes.push(true);
5795          } else {
5796            fontSizes.push(newFontSize);
5797            minFontSizes.push(false);
5798          }
5799        }).each(function(lineNumber) {
5800          var $line = $(this),
5801            wordSpacing = 0,
5802            interval = 1,
5803            maxWordSpacing;
5804
5805          if($line.hasClass(BigText.EXEMPT_CLASS)) {
5806            wordSpacings.push(null);
5807            return;
5808          }
5809
5810          // must re-use font-size, even though it was removed above.
5811          $line.css('font-size', fontSizes[lineNumber] + 'px');
5812
5813          for(var m=1, n=3; m<n; m+=interval) {
5814            maxWordSpacing = BigText.testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing);
5815            if(typeof maxWordSpacing !== 'number') {
5816              wordSpacing = maxWordSpacing.size;
5817              break;
5818            }
5819          }
5820
5821          $line.css('font-size', '');
5822          wordSpacings.push(wordSpacing);
5823        }).removeAttr('style');
5824
5825        if( !BigText.DEBUG_MODE ) {
5826          $c.remove();
5827        } else {
5828          $c.css({
5829            'background-color': 'rgba(255,255,255,.4)'
5830          });
5831        }
5832
5833        return {
5834          fontSizes: fontSizes,
5835          wordSpacings: wordSpacings,
5836          ratios: ratios,
5837          minFontSizes: minFontSizes
5838        };
5839      }
5840    };
5841
5842  $.fn.bigtext = BigText.jQueryMethod;
5843  window.BigText = BigText;
5844
5845})(this, jQuery);
5846/*!
5847 * Isotope PACKAGED v3.0.6
5848 *
5849 * Licensed GPLv3 for open source use
5850 * or Isotope Commercial License for commercial use
5851 *
5852 * https://isotope.metafizzy.co
5853 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 5853-6503
5853
5854 */
5855
5856/**
5857 * Bridget makes jQuery widgets
5858 * v2.0.1
5859 * MIT license
5860 */
5861
5862/* jshint browser: true, strict: true, undef: true, unused: true */
5863
5864( function( window, factory ) {
5865  // universal module definition
5866  /*jshint strict: false */ /* globals define, module, require */
5867  if ( typeof define == 'function' && define.amd ) {
5868    // AMD
5869    define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) {
5870      return factory( window, jQuery );
5871    });
5872  } else if ( typeof module == 'object' && module.exports ) {
5873    // CommonJS
5874    module.exports = factory(
5875      window,
5876      require('jquery')
5877    );
5878  } else {
5879    // browser global
5880    window.jQueryBridget = factory(
5881      window,
5882      window.jQuery
5883    );
5884  }
5885
5886}( window, function factory( window, jQuery ) {
5887'use strict';
5888
5889// ----- utils ----- //
5890
5891var arraySlice = Array.prototype.slice;
5892
5893// helper function for logging errors
5894// $.error breaks jQuery chaining
5895var console = window.console;
5896var logError = typeof console == 'undefined' ? function() {} :
5897  function( message ) {
5898    console.error( message );
5899  };
5900
5901// ----- jQueryBridget ----- //
5902
5903function jQueryBridget( namespace, PluginClass, $ ) {
5904  $ = $ || jQuery || window.jQuery;
5905  if ( !$ ) {
5906    return;
5907  }
5908
5909  // add option method -> $().plugin('option', {...})
5910  if ( !PluginClass.prototype.option ) {
5911    // option setter
5912    PluginClass.prototype.option = function( opts ) {
5913      // bail out if not an object
5914      if ( !$.isPlainObject( opts ) ){
5915        return;
5916      }
5917      this.options = $.extend( true, this.options, opts );
5918    };
5919  }
5920
5921  // make jQuery plugin
5922  $.fn[ namespace ] = function( arg0 /*, arg1 */ ) {
5923    if ( typeof arg0 == 'string' ) {
5924      // method call $().plugin( 'methodName', { options } )
5925      // shift arguments by 1
5926      var args = arraySlice.call( arguments, 1 );
5927      return methodCall( this, arg0, args );
5928    }
5929    // just $().plugin({ options })
5930    plainCall( this, arg0 );
5931    return this;
5932  };
5933
5934  // $().plugin('methodName')
5935  function methodCall( $elems, methodName, args ) {
5936    var returnValue;
5937    var pluginMethodStr = '$().' + namespace + '("' + methodName + '")';
5938
5939    $elems.each( function( i, elem ) {
5940      // get instance
5941      var instance = $.data( elem, namespace );
5942      if ( !instance ) {
5943        logError( namespace + ' not initialized. Cannot call methods, i.e. ' +
5944          pluginMethodStr );
5945        return;
5946      }
5947
5948      var method = instance[ methodName ];
5949      if ( !method || methodName.charAt(0) == '_' ) {
5950        logError( pluginMethodStr + ' is not a valid method' );
5951        return;
5952      }
5953
5954      // apply method, get return value
5955      var value = method.apply( instance, args );
5956      // set return value if value is returned, use only first value
5957      returnValue = returnValue === undefined ? value : returnValue;
5958    });
5959
5960    return returnValue !== undefined ? returnValue : $elems;
5961  }
5962
5963  function plainCall( $elems, options ) {
5964    $elems.each( function( i, elem ) {
5965      var instance = $.data( elem, namespace );
5966      if ( instance ) {
5967        // set options & init
5968        instance.option( options );
5969        instance._init();
5970      } else {
5971        // initialize new instance
5972        instance = new PluginClass( elem, options );
5973        $.data( elem, namespace, instance );
5974      }
5975    });
5976  }
5977
5978  updateJQuery( $ );
5979
5980}
5981
5982// ----- updateJQuery ----- //
5983
5984// set $.bridget for v1 backwards compatibility
5985function updateJQuery( $ ) {
5986  if ( !$ || ( $ && $.bridget ) ) {
5987    return;
5988  }
5989  $.bridget = jQueryBridget;
5990}
5991
5992updateJQuery( jQuery || window.jQuery );
5993
5994// -----  ----- //
5995
5996return jQueryBridget;
5997
5998}));
5999
6000/**
6001 * EvEmitter v1.1.0
6002 * Lil' event emitter
6003 * MIT License
6004 */
6005
6006/* jshint unused: true, undef: true, strict: true */
6007
6008( function( global, factory ) {
6009  // universal module definition
6010  /* jshint strict: false */ /* globals define, module, window */
6011  if ( typeof define == 'function' && define.amd ) {
6012    // AMD - RequireJS
6013    define( 'ev-emitter/ev-emitter',factory );
6014  } else if ( typeof module == 'object' && module.exports ) {
6015    // CommonJS - Browserify, Webpack
6016    module.exports = factory();
6017  } else {
6018    // Browser globals
6019    global.EvEmitter = factory();
6020  }
6021
6022}( typeof window != 'undefined' ? window : this, function() {
6023
6024
6025
6026function EvEmitter() {}
6027
6028var proto = EvEmitter.prototype;
6029
6030proto.on = function( eventName, listener ) {
6031  if ( !eventName || !listener ) {
6032    return;
6033  }
6034  // set events hash
6035  var events = this._events = this._events || {};
6036  // set listeners array
6037  var listeners = events[ eventName ] = events[ eventName ] || [];
6038  // only add once
6039  if ( listeners.indexOf( listener ) == -1 ) {
6040    listeners.push( listener );
6041  }
6042
6043  return this;
6044};
6045
6046proto.once = function( eventName, listener ) {
6047  if ( !eventName || !listener ) {
6048    return;
6049  }
6050  // add event
6051  this.on( eventName, listener );
6052  // set once flag
6053  // set onceEvents hash
6054  var onceEvents = this._onceEvents = this._onceEvents || {};
6055  // set onceListeners object
6056  var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
6057  // set flag
6058  onceListeners[ listener ] = true;
6059
6060  return this;
6061};
6062
6063proto.off = function( eventName, listener ) {
6064  var listeners = this._events && this._events[ eventName ];
6065  if ( !listeners || !listeners.length ) {
6066    return;
6067  }
6068  var index = listeners.indexOf( listener );
6069  if ( index != -1 ) {
6070    listeners.splice( index, 1 );
6071  }
6072
6073  return this;
6074};
6075
6076proto.emitEvent = function( eventName, args ) {
6077  var listeners = this._events && this._events[ eventName ];
6078  if ( !listeners || !listeners.length ) {
6079    return;
6080  }
6081  // copy over to avoid interference if .off() in listener
6082  listeners = listeners.slice(0);
6083  args = args || [];
6084  // once stuff
6085  var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
6086
6087  for ( var i=0; i < listeners.length; i++ ) {
6088    var listener = listeners[i]
6089    var isOnce = onceListeners && onceListeners[ listener ];
6090    if ( isOnce ) {
6091      // remove listener
6092      // remove before trigger to prevent recursion
6093      this.off( eventName, listener );
6094      // unset once flag
6095      delete onceListeners[ listener ];
6096    }
6097    // trigger listener
6098    listener.apply( this, args );
6099  }
6100
6101  return this;
6102};
6103
6104proto.allOff = function() {
6105  delete this._events;
6106  delete this._onceEvents;
6107};
6108
6109return EvEmitter;
6110
6111}));
6112
6113/*!
6114 * getSize v2.0.3
6115 * measure size of elements
6116 * MIT license
6117 */
6118
6119/* jshint browser: true, strict: true, undef: true, unused: true */
6120/* globals console: false */
6121
6122( function( window, factory ) {
6123  /* jshint strict: false */ /* globals define, module */
6124  if ( typeof define == 'function' && define.amd ) {
6125    // AMD
6126    define( 'get-size/get-size',factory );
6127  } else if ( typeof module == 'object' && module.exports ) {
6128    // CommonJS
6129    module.exports = factory();
6130  } else {
6131    // browser global
6132    window.getSize = factory();
6133  }
6134
6135})( window, function factory() {
6136'use strict';
6137
6138// -------------------------- helpers -------------------------- //
6139
6140// get a number from a string, not a percentage
6141function getStyleSize( value ) {
6142  var num = parseFloat( value );
6143  // not a percent like '100%', and a number
6144  var isValid = value.indexOf('%') == -1 && !isNaN( num );
6145  return isValid && num;
6146}
6147
6148function noop() {}
6149
6150var logError = typeof console == 'undefined' ? noop :
6151  function( message ) {
6152    console.error( message );
6153  };
6154
6155// -------------------------- measurements -------------------------- //
6156
6157var measurements = [
6158  'paddingLeft',
6159  'paddingRight',
6160  'paddingTop',
6161  'paddingBottom',
6162  'marginLeft',
6163  'marginRight',
6164  'marginTop',
6165  'marginBottom',
6166  'borderLeftWidth',
6167  'borderRightWidth',
6168  'borderTopWidth',
6169  'borderBottomWidth'
6170];
6171
6172var measurementsLength = measurements.length;
6173
6174function getZeroSize() {
6175  var size = {
6176    width: 0,
6177    height: 0,
6178    innerWidth: 0,
6179    innerHeight: 0,
6180    outerWidth: 0,
6181    outerHeight: 0
6182  };
6183  for ( var i=0; i < measurementsLength; i++ ) {
6184    var measurement = measurements[i];
6185    size[ measurement ] = 0;
6186  }
6187  return size;
6188}
6189
6190// -------------------------- getStyle -------------------------- //
6191
6192/**
6193 * getStyle, get style of element, check for Firefox bug
6194 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
6195 */
6196function getStyle( elem ) {
6197  var style = getComputedStyle( elem );
6198  if ( !style ) {
6199    logError( 'Style returned ' + style +
6200      '. Are you running this code in a hidden iframe on Firefox? ' +
6201      'See https://bit.ly/getsizebug1' );
6202  }
6203  return style;
6204}
6205
6206// -------------------------- setup -------------------------- //
6207
6208var isSetup = false;
6209
6210var isBoxSizeOuter;
6211
6212/**
6213 * setup
6214 * check isBoxSizerOuter
6215 * do on first getSize() rather than on page load for Firefox bug
6216 */
6217function setup() {
6218  // setup once
6219  if ( isSetup ) {
6220    return;
6221  }
6222  isSetup = true;
6223
6224  // -------------------------- box sizing -------------------------- //
6225
6226  /**
6227   * Chrome & Safari measure the outer-width on style.width on border-box elems
6228   * IE11 & Firefox<29 measures the inner-width
6229   */
6230  var div = document.createElement('div');
6231  div.style.width = '200px';
6232  div.style.padding = '1px 2px 3px 4px';
6233  div.style.borderStyle = 'solid';
6234  div.style.borderWidth = '1px 2px 3px 4px';
6235  div.style.boxSizing = 'border-box';
6236
6237  var body = document.body || document.documentElement;
6238  body.appendChild( div );
6239  var style = getStyle( div );
6240  // round value for browser zoom. desandro/masonry#928
6241  isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200;
6242  getSize.isBoxSizeOuter = isBoxSizeOuter;
6243
6244  body.removeChild( div );
6245}
6246
6247// -------------------------- getSize -------------------------- //
6248
6249function getSize( elem ) {
6250  setup();
6251
6252  // use querySeletor if elem is string
6253  if ( typeof elem == 'string' ) {
6254    elem = document.querySelector( elem );
6255  }
6256
6257  // do not proceed on non-objects
6258  if ( !elem || typeof elem != 'object' || !elem.nodeType ) {
6259    return;
6260  }
6261
6262  var style = getStyle( elem );
6263
6264  // if hidden, everything is 0
6265  if ( style.display == 'none' ) {
6266    return getZeroSize();
6267  }
6268
6269  var size = {};
6270  size.width = elem.offsetWidth;
6271  size.height = elem.offsetHeight;
6272
6273  var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box';
6274
6275  // get all measurements
6276  for ( var i=0; i < measurementsLength; i++ ) {
6277    var measurement = measurements[i];
6278    var value = style[ measurement ];
6279    var num = parseFloat( value );
6280    // any 'auto', 'medium' value will be 0
6281    size[ measurement ] = !isNaN( num ) ? num : 0;
6282  }
6283
6284  var paddingWidth = size.paddingLeft + size.paddingRight;
6285  var paddingHeight = size.paddingTop + size.paddingBottom;
6286  var marginWidth = size.marginLeft + size.marginRight;
6287  var marginHeight = size.marginTop + size.marginBottom;
6288  var borderWidth = size.borderLeftWidth + size.borderRightWidth;
6289  var borderHeight = size.borderTopWidth + size.borderBottomWidth;
6290
6291  var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;
6292
6293  // overwrite width and height if we can get it from style
6294  var styleWidth = getStyleSize( style.width );
6295  if ( styleWidth !== false ) {
6296    size.width = styleWidth +
6297      // add padding and border unless it's already including it
6298      ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth );
6299  }
6300
6301  var styleHeight = getStyleSize( style.height );
6302  if ( styleHeight !== false ) {
6303    size.height = styleHeight +
6304      // add padding and border unless it's already including it
6305      ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight );
6306  }
6307
6308  size.innerWidth = size.width - ( paddingWidth + borderWidth );
6309  size.innerHeight = size.height - ( paddingHeight + borderHeight );
6310
6311  size.outerWidth = size.width + marginWidth;
6312  size.outerHeight = size.height + marginHeight;
6313
6314  return size;
6315}
6316
6317return getSize;
6318
6319});
6320
6321/**
6322 * matchesSelector v2.0.2
6323 * matchesSelector( element, '.selector' )
6324 * MIT license
6325 */
6326
6327/*jshint browser: true, strict: true, undef: true, unused: true */
6328
6329( function( window, factory ) {
6330  /*global define: false, module: false */
6331  'use strict';
6332  // universal module definition
6333  if ( typeof define == 'function' && define.amd ) {
6334    // AMD
6335    define( 'desandro-matches-selector/matches-selector',factory );
6336  } else if ( typeof module == 'object' && module.exports ) {
6337    // CommonJS
6338    module.exports = factory();
6339  } else {
6340    // browser global
6341    window.matchesSelector = factory();
6342  }
6343
6344}( window, function factory() {
6345  'use strict';
6346
6347  var matchesMethod = ( function() {
6348    var ElemProto = window.Element.prototype;
6349    // check for the standard method name first
6350    if ( ElemProto.matches ) {
6351      return 'matches';
6352    }
6353    // check un-prefixed
6354    if ( ElemProto.matchesSelector ) {
6355      return 'matchesSelector';
6356    }
6357    // check vendor prefixes
6358    var prefixes = [ 'webkit', 'moz', 'ms', 'o' ];
6359
6360    for ( var i=0; i < prefixes.length; i++ ) {
6361      var prefix = prefixes[i];
6362      var method = prefix + 'MatchesSelector';
6363      if ( ElemProto[ method ] ) {
6364        return method;
6365      }
6366    }
6367  })();
6368
6369  return function matchesSelector( elem, selector ) {
6370    return elem[ matchesMethod ]( selector );
6371  };
6372
6373}));
6374
6375/**
6376 * Fizzy UI utils v2.0.7
6377 * MIT license
6378 */
6379
6380/*jshint browser: true, undef: true, unused: true, strict: true */
6381
6382( function( window, factory ) {
6383  // universal module definition
6384  /*jshint strict: false */ /*globals define, module, require */
6385
6386  if ( typeof define == 'function' && define.amd ) {
6387    // AMD
6388    define( 'fizzy-ui-utils/utils',[
6389      'desandro-matches-selector/matches-selector'
6390    ], function( matchesSelector ) {
6391      return factory( window, matchesSelector );
6392    });
6393  } else if ( typeof module == 'object' && module.exports ) {
6394    // CommonJS
6395    module.exports = factory(
6396      window,
6397      require('desandro-matches-selector')
6398    );
6399  } else {
6400    // browser global
6401    window.fizzyUIUtils = factory(
6402      window,
6403      window.matchesSelector
6404    );
6405  }
6406
6407}( window, function factory( window, matchesSelector ) {
6408
6409
6410
6411var utils = {};
6412
6413// ----- extend ----- //
6414
6415// extends objects
6416utils.extend = function( a, b ) {
6417  for ( var prop in b ) {
6418    a[ prop ] = b[ prop ];
6419  }
6420  return a;
6421};
6422
6423// ----- modulo ----- //
6424
6425utils.modulo = function( num, div ) {
6426  return ( ( num % div ) + div ) % div;
6427};
6428
6429// ----- makeArray ----- //
6430
6431var arraySlice = Array.prototype.slice;
6432
6433// turn element or nodeList into an array
6434utils.makeArray = function( obj ) {
6435  if ( Array.isArray( obj ) ) {
6436    // use object if already an array
6437    return obj;
6438  }
6439  // return empty array if undefined or null. #6
6440  if ( obj === null || obj === undefined ) {
6441    return [];
6442  }
6443
6444  var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
6445  if ( isArrayLike ) {
6446    // convert nodeList to array
6447    return arraySlice.call( obj );
6448  }
6449
6450  // array of single index
6451  return [ obj ];
6452};
6453
6454// ----- removeFrom ----- //
6455
6456utils.removeFrom = function( ary, obj ) {
6457  var index = ary.indexOf( obj );
6458  if ( index != -1 ) {
6459    ary.splice( index, 1 );
6460  }
6461};
6462
6463// ----- getParent ----- //
6464
6465utils.getParent = function( elem, selector ) {
6466  while ( elem.parentNode && elem != document.body ) {
6467    elem = elem.parentNode;
6468    if ( matchesSelector( elem, selector ) ) {
6469      return elem;
6470    }
6471  }
6472};
6473
6474// ----- getQueryElement ----- //
6475
6476// use element as selector string
6477utils.getQueryElement = function( elem ) {
6478  if ( typeof elem == 'string' ) {
6479    return document.querySelector( elem );
6480  }
6481  return elem;
6482};
6483
6484// ----- handleEvent ----- //
6485
6486// enable .ontype to trigger from .addEventListener( elem, 'type' )
6487utils.handleEvent = function( event ) {
6488  var method = 'on' + event.type;
6489  if ( this[ method ] ) {
6490    this[ method ]( event );
6491  }
6492};
6493
6494// ----- filterFindElements ----- //
6495
6496utils.filterFindElements = function( elems, selector ) {
6497  // make array of elems
6498  elems = utils.makeArray( elems );
6499  var ffElems = [];
6500
6501  elems.forEach( function( elem ) {
6502    // check that elem is an actual element
6503    
6503// START UNCODE EDIT
6504    // if ( !( elem instanceof HTMLElement ) ) {
6505    if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) {
6506    // END UNCODE EDIT
vendor: 23,480 bytes, lines 6506-7418
6506
6507      return;
6508    }
6509    // add elem if no selector
6510    if ( !selector ) {
6511      ffElems.push( elem );
6512      return;
6513    }
6514    // filter & find items if we have a selector
6515    // filter
6516    if ( matchesSelector( elem, selector ) ) {
6517      ffElems.push( elem );
6518    }
6519    // find children
6520    var childElems = elem.querySelectorAll( selector );
6521    // concat childElems to filterFound array
6522    for ( var i=0; i < childElems.length; i++ ) {
6523      ffElems.push( childElems[i] );
6524    }
6525  });
6526
6527  return ffElems;
6528};
6529
6530// ----- debounceMethod ----- //
6531
6532utils.debounceMethod = function( _class, methodName, threshold ) {
6533  threshold = threshold || 100;
6534  // original method
6535  var method = _class.prototype[ methodName ];
6536  var timeoutName = methodName + 'Timeout';
6537
6538  _class.prototype[ methodName ] = function() {
6539    var timeout = this[ timeoutName ];
6540    clearTimeout( timeout );
6541
6542    var args = arguments;
6543    var _this = this;
6544    this[ timeoutName ] = setTimeout( function() {
6545      method.apply( _this, args );
6546      delete _this[ timeoutName ];
6547    }, threshold );
6548  };
6549};
6550
6551// ----- docReady ----- //
6552
6553utils.docReady = function( callback ) {
6554  var readyState = document.readyState;
6555  if ( readyState == 'complete' || readyState == 'interactive' ) {
6556    // do async to allow for other scripts to run. metafizzy/flickity#441
6557    setTimeout( callback );
6558  } else {
6559    document.addEventListener( 'DOMContentLoaded', callback );
6560  }
6561};
6562
6563// ----- htmlInit ----- //
6564
6565// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/
6566utils.toDashed = function( str ) {
6567  return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) {
6568    return $1 + '-' + $2;
6569  }).toLowerCase();
6570};
6571
6572var console = window.console;
6573/**
6574 * allow user to initialize classes via [data-namespace] or .js-namespace class
6575 * htmlInit( Widget, 'widgetName' )
6576 * options are parsed from data-namespace-options
6577 */
6578utils.htmlInit = function( WidgetClass, namespace ) {
6579  utils.docReady( function() {
6580    var dashedNamespace = utils.toDashed( namespace );
6581    var dataAttr = 'data-' + dashedNamespace;
6582    var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' );
6583    var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace );
6584    var elems = utils.makeArray( dataAttrElems )
6585      .concat( utils.makeArray( jsDashElems ) );
6586    var dataOptionsAttr = dataAttr + '-options';
6587    var jQuery = window.jQuery;
6588
6589    elems.forEach( function( elem ) {
6590      var attr = elem.getAttribute( dataAttr ) ||
6591        elem.getAttribute( dataOptionsAttr );
6592      var options;
6593      try {
6594        options = attr && JSON.parse( attr );
6595      } catch ( error ) {
6596        // log error, do not initialize
6597        if ( console ) {
6598          console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className +
6599          ': ' + error );
6600        }
6601        return;
6602      }
6603      // initialize
6604      var instance = new WidgetClass( elem, options );
6605      // make available via $().data('namespace')
6606      if ( jQuery ) {
6607        jQuery.data( elem, namespace, instance );
6608      }
6609    });
6610
6611  });
6612};
6613
6614// -----  ----- //
6615
6616return utils;
6617
6618}));
6619
6620/**
6621 * Outlayer Item
6622 */
6623
6624( function( window, factory ) {
6625  // universal module definition
6626  /* jshint strict: false */ /* globals define, module, require */
6627  if ( typeof define == 'function' && define.amd ) {
6628    // AMD - RequireJS
6629    define( 'outlayer/item',[
6630        'ev-emitter/ev-emitter',
6631        'get-size/get-size'
6632      ],
6633      factory
6634    );
6635  } else if ( typeof module == 'object' && module.exports ) {
6636    // CommonJS - Browserify, Webpack
6637    module.exports = factory(
6638      require('ev-emitter'),
6639      require('get-size')
6640    );
6641  } else {
6642    // browser global
6643    window.Outlayer = {};
6644    window.Outlayer.Item = factory(
6645      window.EvEmitter,
6646      window.getSize
6647    );
6648  }
6649
6650}( window, function factory( EvEmitter, getSize ) {
6651'use strict';
6652
6653// ----- helpers ----- //
6654
6655function isEmptyObj( obj ) {
6656  for ( var prop in obj ) {
6657    return false;
6658  }
6659  prop = null;
6660  return true;
6661}
6662
6663// -------------------------- CSS3 support -------------------------- //
6664
6665
6666var docElemStyle = document.documentElement.style;
6667
6668var transitionProperty = typeof docElemStyle.transition == 'string' ?
6669  'transition' : 'WebkitTransition';
6670var transformProperty = typeof docElemStyle.transform == 'string' ?
6671  'transform' : 'WebkitTransform';
6672
6673var transitionEndEvent = {
6674  WebkitTransition: 'webkitTransitionEnd',
6675  transition: 'transitionend'
6676}[ transitionProperty ];
6677
6678// cache all vendor properties that could have vendor prefix
6679var vendorProperties = {
6680  transform: transformProperty,
6681  transition: transitionProperty,
6682  transitionDuration: transitionProperty + 'Duration',
6683  transitionProperty: transitionProperty + 'Property',
6684  transitionDelay: transitionProperty + 'Delay'
6685};
6686
6687// -------------------------- Item -------------------------- //
6688
6689function Item( element, layout ) {
6690  if ( !element ) {
6691    return;
6692  }
6693
6694  this.element = element;
6695  // parent layout class, i.e. Masonry, Isotope, or Packery
6696  this.layout = layout;
6697  this.position = {
6698    x: 0,
6699    y: 0
6700  };
6701
6702  this._create();
6703}
6704
6705// inherit EvEmitter
6706var proto = Item.prototype = Object.create( EvEmitter.prototype );
6707proto.constructor = Item;
6708
6709proto._create = function() {
6710  // transition objects
6711  this._transn = {
6712    ingProperties: {},
6713    clean: {},
6714    onEnd: {}
6715  };
6716
6717  this.css({
6718    position: 'absolute'
6719  });
6720};
6721
6722// trigger specified handler for event type
6723proto.handleEvent = function( event ) {
6724  var method = 'on' + event.type;
6725  if ( this[ method ] ) {
6726    this[ method ]( event );
6727  }
6728};
6729
6730proto.getSize = function() {
6731  this.size = getSize( this.element );
6732};
6733
6734/**
6735 * apply CSS styles to element
6736 * @param {Object} style
6737 */
6738proto.css = function( style ) {
6739  var elemStyle = this.element.style;
6740
6741  for ( var prop in style ) {
6742    // use vendor property if available
6743    var supportedProp = vendorProperties[ prop ] || prop;
6744    elemStyle[ supportedProp ] = style[ prop ];
6745  }
6746};
6747
6748 // measure position, and sets it
6749proto.getPosition = function() {
6750  var style = getComputedStyle( this.element );
6751  var isOriginLeft = this.layout._getOption('originLeft');
6752  var isOriginTop = this.layout._getOption('originTop');
6753  var xValue = style[ isOriginLeft ? 'left' : 'right' ];
6754  var yValue = style[ isOriginTop ? 'top' : 'bottom' ];
6755  var x = parseFloat( xValue );
6756  var y = parseFloat( yValue );
6757  // convert percent to pixels
6758  var layoutSize = this.layout.size;
6759  if ( xValue.indexOf('%') != -1 ) {
6760    x = ( x / 100 ) * layoutSize.width;
6761  }
6762  if ( yValue.indexOf('%') != -1 ) {
6763    y = ( y / 100 ) * layoutSize.height;
6764  }
6765  // clean up 'auto' or other non-integer values
6766  x = isNaN( x ) ? 0 : x;
6767  y = isNaN( y ) ? 0 : y;
6768  // remove padding from measurement
6769  x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight;
6770  y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom;
6771
6772  this.position.x = x;
6773  this.position.y = y;
6774};
6775
6776// set settled position, apply padding
6777proto.layoutPosition = function() {
6778  var layoutSize = this.layout.size;
6779  var style = {};
6780  var isOriginLeft = this.layout._getOption('originLeft');
6781  var isOriginTop = this.layout._getOption('originTop');
6782
6783  // x
6784  var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight';
6785  var xProperty = isOriginLeft ? 'left' : 'right';
6786  var xResetProperty = isOriginLeft ? 'right' : 'left';
6787
6788  var x = this.position.x + layoutSize[ xPadding ];
6789  // set in percentage or pixels
6790  style[ xProperty ] = this.getXValue( x );
6791  // reset other property
6792  style[ xResetProperty ] = '';
6793
6794  // y
6795  var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom';
6796  var yProperty = isOriginTop ? 'top' : 'bottom';
6797  var yResetProperty = isOriginTop ? 'bottom' : 'top';
6798
6799  var y = this.position.y + layoutSize[ yPadding ];
6800  // set in percentage or pixels
6801  style[ yProperty ] = this.getYValue( y );
6802  // reset other property
6803  style[ yResetProperty ] = '';
6804
6805  this.css( style );
6806  this.emitEvent( 'layout', [ this ] );
6807};
6808
6809proto.getXValue = function( x ) {
6810  var isHorizontal = this.layout._getOption('horizontal');
6811  return this.layout.options.percentPosition && !isHorizontal ?
6812    ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px';
6813};
6814
6815proto.getYValue = function( y ) {
6816  var isHorizontal = this.layout._getOption('horizontal');
6817  return this.layout.options.percentPosition && isHorizontal ?
6818    ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px';
6819};
6820
6821proto._transitionTo = function( x, y ) {
6822  this.getPosition();
6823  // get current x & y from top/left
6824  var curX = this.position.x;
6825  var curY = this.position.y;
6826
6827  var didNotMove = x == this.position.x && y == this.position.y;
6828
6829  // save end position
6830  this.setPosition( x, y );
6831
6832  // if did not move and not transitioning, just go to layout
6833  if ( didNotMove && !this.isTransitioning ) {
6834    this.layoutPosition();
6835    return;
6836  }
6837
6838  var transX = x - curX;
6839  var transY = y - curY;
6840  var transitionStyle = {};
6841  transitionStyle.transform = this.getTranslate( transX, transY );
6842
6843  this.transition({
6844    to: transitionStyle,
6845    onTransitionEnd: {
6846      transform: this.layoutPosition
6847    },
6848    isCleaning: true
6849  });
6850};
6851
6852proto.getTranslate = function( x, y ) {
6853  // flip cooridinates if origin on right or bottom
6854  var isOriginLeft = this.layout._getOption('originLeft');
6855  var isOriginTop = this.layout._getOption('originTop');
6856  x = isOriginLeft ? x : -x;
6857  y = isOriginTop ? y : -y;
6858  return 'translate3d(' + x + 'px, ' + y + 'px, 0)';
6859};
6860
6861// non transition + transform support
6862proto.goTo = function( x, y ) {
6863  this.setPosition( x, y );
6864  this.layoutPosition();
6865};
6866
6867proto.moveTo = proto._transitionTo;
6868
6869proto.setPosition = function( x, y ) {
6870  this.position.x = parseFloat( x );
6871  this.position.y = parseFloat( y );
6872};
6873
6874// ----- transition ----- //
6875
6876/**
6877 * @param {Object} style - CSS
6878 * @param {Function} onTransitionEnd
6879 */
6880
6881// non transition, just trigger callback
6882proto._nonTransition = function( args ) {
6883  this.css( args.to );
6884  if ( args.isCleaning ) {
6885    this._removeStyles( args.to );
6886  }
6887  for ( var prop in args.onTransitionEnd ) {
6888    args.onTransitionEnd[ prop ].call( this );
6889  }
6890};
6891
6892/**
6893 * proper transition
6894 * @param {Object} args - arguments
6895 *   @param {Object} to - style to transition to
6896 *   @param {Object} from - style to start transition from
6897 *   @param {Boolean} isCleaning - removes transition styles after transition
6898 *   @param {Function} onTransitionEnd - callback
6899 */
6900proto.transition = function( args ) {
6901  // redirect to nonTransition if no transition duration
6902  if ( !parseFloat( this.layout.options.transitionDuration ) ) {
6903    this._nonTransition( args );
6904    return;
6905  }
6906
6907  var _transition = this._transn;
6908  // keep track of onTransitionEnd callback by css property
6909  for ( var prop in args.onTransitionEnd ) {
6910    _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ];
6911  }
6912  // keep track of properties that are transitioning
6913  for ( prop in args.to ) {
6914    _transition.ingProperties[ prop ] = true;
6915    // keep track of properties to clean up when transition is done
6916    if ( args.isCleaning ) {
6917      _transition.clean[ prop ] = true;
6918    }
6919  }
6920
6921  // set from styles
6922  if ( args.from ) {
6923    this.css( args.from );
6924    // force redraw. http://blog.alexmaccaw.com/css-transitions
6925    var h = this.element.offsetHeight;
6926    // hack for JSHint to hush about unused var
6927    h = null;
6928  }
6929  // enable transition
6930  this.enableTransition( args.to );
6931  // set styles that are transitioning
6932  this.css( args.to );
6933
6934  this.isTransitioning = true;
6935
6936};
6937
6938// dash before all cap letters, including first for
6939// WebkitTransform => -webkit-transform
6940function toDashedAll( str ) {
6941  return str.replace( /([A-Z])/g, function( $1 ) {
6942    return '-' + $1.toLowerCase();
6943  });
6944}
6945
6946var transitionProps = 'opacity,' + toDashedAll( transformProperty );
6947
6948proto.enableTransition = function(/* style */) {
6949  // HACK changing transitionProperty during a transition
6950  // will cause transition to jump
6951  if ( this.isTransitioning ) {
6952    return;
6953  }
6954
6955  // make `transition: foo, bar, baz` from style object
6956  // HACK un-comment this when enableTransition can work
6957  // while a transition is happening
6958  // var transitionValues = [];
6959  // for ( var prop in style ) {
6960  //   // dash-ify camelCased properties like WebkitTransition
6961  //   prop = vendorProperties[ prop ] || prop;
6962  //   transitionValues.push( toDashedAll( prop ) );
6963  // }
6964  // munge number to millisecond, to match stagger
6965  var duration = this.layout.options.transitionDuration;
6966  duration = typeof duration == 'number' ? duration + 'ms' : duration;
6967  // enable transition styles
6968  this.css({
6969    transitionProperty: transitionProps,
6970    transitionDuration: duration,
6971    transitionDelay: this.staggerDelay || 0
6972  });
6973  // listen for transition end event
6974  this.element.addEventListener( transitionEndEvent, this, false );
6975};
6976
6977// ----- events ----- //
6978
6979proto.onwebkitTransitionEnd = function( event ) {
6980  this.ontransitionend( event );
6981};
6982
6983proto.onotransitionend = function( event ) {
6984  this.ontransitionend( event );
6985};
6986
6987// properties that I munge to make my life easier
6988var dashedVendorProperties = {
6989  '-webkit-transform': 'transform'
6990};
6991
6992proto.ontransitionend = function( event ) {
6993  // disregard bubbled events from children
6994  if ( event.target !== this.element ) {
6995    return;
6996  }
6997  var _transition = this._transn;
6998  // get property name of transitioned property, convert to prefix-free
6999  var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName;
7000
7001  // remove property that has completed transitioning
7002  delete _transition.ingProperties[ propertyName ];
7003  // check if any properties are still transitioning
7004  if ( isEmptyObj( _transition.ingProperties ) ) {
7005    // all properties have completed transitioning
7006    this.disableTransition();
7007  }
7008  // clean style
7009  if ( propertyName in _transition.clean ) {
7010    // clean up style
7011    this.element.style[ event.propertyName ] = '';
7012    delete _transition.clean[ propertyName ];
7013  }
7014  // trigger onTransitionEnd callback
7015  if ( propertyName in _transition.onEnd ) {
7016    var onTransitionEnd = _transition.onEnd[ propertyName ];
7017    onTransitionEnd.call( this );
7018    delete _transition.onEnd[ propertyName ];
7019  }
7020
7021  this.emitEvent( 'transitionEnd', [ this ] );
7022};
7023
7024proto.disableTransition = function() {
7025  this.removeTransitionStyles();
7026  this.element.removeEventListener( transitionEndEvent, this, false );
7027  this.isTransitioning = false;
7028};
7029
7030/**
7031 * removes style property from element
7032 * @param {Object} style
7033**/
7034proto._removeStyles = function( style ) {
7035  // clean up transition styles
7036  var cleanStyle = {};
7037  for ( var prop in style ) {
7038    cleanStyle[ prop ] = '';
7039  }
7040  this.css( cleanStyle );
7041};
7042
7043var cleanTransitionStyle = {
7044  transitionProperty: '',
7045  transitionDuration: '',
7046  transitionDelay: ''
7047};
7048
7049proto.removeTransitionStyles = function() {
7050  // remove transition
7051  this.css( cleanTransitionStyle );
7052};
7053
7054// ----- stagger ----- //
7055
7056proto.stagger = function( delay ) {
7057  delay = isNaN( delay ) ? 0 : delay;
7058  this.staggerDelay = delay + 'ms';
7059};
7060
7061// ----- show/hide/remove ----- //
7062
7063// remove element from DOM
7064proto.removeElem = function() {
7065  this.element.parentNode.removeChild( this.element );
7066  // remove display: none
7067  this.css({ display: '' });
7068  this.emitEvent( 'remove', [ this ] );
7069};
7070
7071proto.remove = function() {
7072  // just remove element if no transition support or no transition
7073  if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) {
7074    this.removeElem();
7075    return;
7076  }
7077
7078  // start transition
7079  this.once( 'transitionEnd', function() {
7080    this.removeElem();
7081  });
7082  this.hide();
7083};
7084
7085proto.reveal = function() {
7086  delete this.isHidden;
7087  // remove display: none
7088  this.css({ display: '' });
7089
7090  var options = this.layout.options;
7091
7092  var onTransitionEnd = {};
7093  var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle');
7094  onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd;
7095
7096  this.transition({
7097    from: options.hiddenStyle,
7098    to: options.visibleStyle,
7099    isCleaning: true,
7100    onTransitionEnd: onTransitionEnd
7101  });
7102};
7103
7104proto.onRevealTransitionEnd = function() {
7105  // check if still visible
7106  // during transition, item may have been hidden
7107  if ( !this.isHidden ) {
7108    this.emitEvent('reveal');
7109  }
7110};
7111
7112/**
7113 * get style property use for hide/reveal transition end
7114 * @param {String} styleProperty - hiddenStyle/visibleStyle
7115 * @returns {String}
7116 */
7117proto.getHideRevealTransitionEndProperty = function( styleProperty ) {
7118  var optionStyle = this.layout.options[ styleProperty ];
7119  // use opacity
7120  if ( optionStyle.opacity ) {
7121    return 'opacity';
7122  }
7123  // get first property
7124  for ( var prop in optionStyle ) {
7125    return prop;
7126  }
7127};
7128
7129proto.hide = function() {
7130  // set flag
7131  this.isHidden = true;
7132  // remove display: none
7133  this.css({ display: '' });
7134
7135  var options = this.layout.options;
7136
7137  var onTransitionEnd = {};
7138  var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle');
7139  onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd;
7140
7141  this.transition({
7142    from: options.visibleStyle,
7143    to: options.hiddenStyle,
7144    // keep hidden stuff hidden
7145    isCleaning: true,
7146    onTransitionEnd: onTransitionEnd
7147  });
7148};
7149
7150proto.onHideTransitionEnd = function() {
7151  // check if still hidden
7152  // during transition, item may have been un-hidden
7153  if ( this.isHidden ) {
7154    this.css({ display: 'none' });
7155    this.emitEvent('hide');
7156  }
7157};
7158
7159proto.destroy = function() {
7160  this.css({
7161    position: '',
7162    left: '',
7163    right: '',
7164    top: '',
7165    bottom: '',
7166    transition: '',
7167    transform: ''
7168  });
7169};
7170
7171return Item;
7172
7173}));
7174
7175/*!
7176 * Outlayer v2.1.1
7177 * the brains and guts of a layout library
7178 * MIT license
7179 */
7180
7181( function( window, factory ) {
7182  'use strict';
7183  // universal module definition
7184  /* jshint strict: false */ /* globals define, module, require */
7185  if ( typeof define == 'function' && define.amd ) {
7186    // AMD - RequireJS
7187    define( 'outlayer/outlayer',[
7188        'ev-emitter/ev-emitter',
7189        'get-size/get-size',
7190        'fizzy-ui-utils/utils',
7191        './item'
7192      ],
7193      function( EvEmitter, getSize, utils, Item ) {
7194        return factory( window, EvEmitter, getSize, utils, Item);
7195      }
7196    );
7197  } else if ( typeof module == 'object' && module.exports ) {
7198    // CommonJS - Browserify, Webpack
7199    module.exports = factory(
7200      window,
7201      require('ev-emitter'),
7202      require('get-size'),
7203      require('fizzy-ui-utils'),
7204      require('./item')
7205    );
7206  } else {
7207    // browser global
7208    window.Outlayer = factory(
7209      window,
7210      window.EvEmitter,
7211      window.getSize,
7212      window.fizzyUIUtils,
7213      window.Outlayer.Item
7214    );
7215  }
7216
7217}( window, function factory( window, EvEmitter, getSize, utils, Item ) {
7218'use strict';
7219
7220// ----- vars ----- //
7221
7222var console = window.console;
7223var jQuery = window.jQuery;
7224var noop = function() {};
7225
7226// -------------------------- Outlayer -------------------------- //
7227
7228// globally unique identifiers
7229var GUID = 0;
7230// internal store of all Outlayer intances
7231var instances = {};
7232
7233
7234/**
7235 * @param {Element, String} element
7236 * @param {Object} options
7237 * @constructor
7238 */
7239function Outlayer( element, options ) {
7240  var queryElement = utils.getQueryElement( element );
7241  if ( !queryElement ) {
7242    if ( console ) {
7243      console.error( 'Bad element for ' + this.constructor.namespace +
7244        ': ' + ( queryElement || element ) );
7245    }
7246    return;
7247  }
7248  this.element = queryElement;
7249  // add jQuery
7250  if ( jQuery ) {
7251    this.$element = jQuery( this.element );
7252  }
7253
7254  // options
7255  this.options = utils.extend( {}, this.constructor.defaults );
7256  this.option( options );
7257
7258  // add id for Outlayer.getFromElement
7259  var id = ++GUID;
7260  this.element.outlayerGUID = id; // expando
7261  instances[ id ] = this; // associate via id
7262
7263  // kick it off
7264  this._create();
7265
7266  var isInitLayout = this._getOption('initLayout');
7267  if ( isInitLayout ) {
7268    this.layout();
7269  }
7270}
7271
7272// settings are for internal use only
7273Outlayer.namespace = 'outlayer';
7274Outlayer.Item = Item;
7275
7276// default options
7277Outlayer.defaults = {
7278  containerStyle: {
7279    position: 'relative'
7280  },
7281  initLayout: true,
7282  originLeft: true,
7283  originTop: true,
7284  resize: true,
7285  resizeContainer: true,
7286  // item options
7287  transitionDuration: '0.4s',
7288  hiddenStyle: {
7289    opacity: 0,
7290    transform: 'scale(0.001)'
7291  },
7292  visibleStyle: {
7293    opacity: 1,
7294    transform: 'scale(1)'
7295  }
7296};
7297
7298var proto = Outlayer.prototype;
7299// inherit EvEmitter
7300utils.extend( proto, EvEmitter.prototype );
7301
7302/**
7303 * set options
7304 * @param {Object} opts
7305 */
7306proto.option = function( opts ) {
7307  utils.extend( this.options, opts );
7308};
7309
7310/**
7311 * get backwards compatible option value, check old name
7312 */
7313proto._getOption = function( option ) {
7314  var oldOption = this.constructor.compatOptions[ option ];
7315  return oldOption && this.options[ oldOption ] !== undefined ?
7316    this.options[ oldOption ] : this.options[ option ];
7317};
7318
7319Outlayer.compatOptions = {
7320  // currentName: oldName
7321  initLayout: 'isInitLayout',
7322  horizontal: 'isHorizontal',
7323  layoutInstant: 'isLayoutInstant',
7324  originLeft: 'isOriginLeft',
7325  originTop: 'isOriginTop',
7326  resize: 'isResizeBound',
7327  resizeContainer: 'isResizingContainer'
7328};
7329
7330proto._create = function() {
7331  // get items from children
7332  this.reloadItems();
7333  // elements that affect layout, but are not laid out
7334  this.stamps = [];
7335  this.stamp( this.options.stamp );
7336  // set container style
7337  utils.extend( this.element.style, this.options.containerStyle );
7338
7339  // bind resize method
7340  var canBindResize = this._getOption('resize');
7341  if ( canBindResize ) {
7342    this.bindResize();
7343  }
7344};
7345
7346// goes through all children again and gets bricks in proper order
7347proto.reloadItems = function() {
7348  // collection of item elements
7349  this.items = this._itemize( this.element.children );
7350};
7351
7352
7353/**
7354 * turn elements into Outlayer.Items to be used in layout
7355 * @param {Array or NodeList or HTMLElement} elems
7356 * @returns {Array} items - collection of new Outlayer Items
7357 */
7358proto._itemize = function( elems ) {
7359
7360  var itemElems = this._filterFindItemElements( elems );
7361  var Item = this.constructor.Item;
7362
7363  // create new Outlayer Items for collection
7364  var items = [];
7365  for ( var i=0; i < itemElems.length; i++ ) {
7366    var elem = itemElems[i];
7367    var item = new Item( elem, this );
7368    items.push( item );
7369  }
7370
7371  return items;
7372};
7373
7374/**
7375 * get item elements to be used in layout
7376 * @param {Array or NodeList or HTMLElement} elems
7377 * @returns {Array} items - item elements
7378 */
7379proto._filterFindItemElements = function( elems ) {
7380  return utils.filterFindElements( elems, this.options.itemSelector );
7381};
7382
7383/**
7384 * getter method for getting item elements
7385 * @returns {Array} elems - collection of item elements
7386 */
7387proto.getItemElements = function() {
7388  return this.items.map( function( item ) {
7389    return item.element;
7390  });
7391};
7392
7393// ----- init & layout ----- //
7394
7395/**
7396 * lays out all items
7397 */
7398proto.layout = function() {
7399  this._resetLayout();
7400  this._manageStamps();
7401
7402  // don't animate first layout
7403  var layoutInstant = this._getOption('layoutInstant');
7404  var isInstant = layoutInstant !== undefined ?
7405    layoutInstant : !this._isLayoutInited;
7406  this.layoutItems( this.items, isInstant );
7407
7408  // flag for initalized
7409  this._isLayoutInited = true;
7410};
7411
7412// _init is alias for layout
7413proto._init = proto.layout;
7414
7415/**
7416 * logic before any new layout
7417 */
7418proto._resetLayout = function() {
vendor: 13,499 bytes, lines 7419-7987
7419  this.getSize();
7420};
7421
7422
7423proto.getSize = function() {
7424  this.size = getSize( this.element );
7425};
7426
7427/**
7428 * get measurement from option, for columnWidth, rowHeight, gutter
7429 * if option is String -> get element from selector string, & get size of element
7430 * if option is Element -> get size of element
7431 * else use option as a number
7432 *
7433 * @param {String} measurement
7434 * @param {String} size - width or height
7435 * @private
7436 */
7437proto._getMeasurement = function( measurement, size ) {
7438  var option = this.options[ measurement ];
7439  var elem;
7440  if ( !option ) {
7441    // default to 0
7442    this[ measurement ] = 0;
7443  } else {
7444    // use option as an element
7445    if ( typeof option == 'string' ) {
7446      elem = this.element.querySelector( option );
7447    } else if ( option instanceof HTMLElement ) {
7448      elem = option;
7449    }
7450    // use size of element, if element
7451    this[ measurement ] = elem ? getSize( elem )[ size ] : option;
7452  }
7453};
7454
7455/**
7456 * layout a collection of item elements
7457 * @api public
7458 */
7459proto.layoutItems = function( items, isInstant ) {
7460  items = this._getItemsForLayout( items );
7461
7462  this._layoutItems( items, isInstant );
7463
7464  this._postLayout();
7465};
7466
7467/**
7468 * get the items to be laid out
7469 * you may want to skip over some items
7470 * @param {Array} items
7471 * @returns {Array} items
7472 */
7473proto._getItemsForLayout = function( items ) {
7474  return items.filter( function( item ) {
7475    return !item.isIgnored;
7476  });
7477};
7478
7479/**
7480 * layout items
7481 * @param {Array} items
7482 * @param {Boolean} isInstant
7483 */
7484proto._layoutItems = function( items, isInstant ) {
7485  this._emitCompleteOnItems( 'layout', items );
7486
7487  if ( !items || !items.length ) {
7488    // no items, emit event with empty array
7489    return;
7490  }
7491
7492  var queue = [];
7493
7494  items.forEach( function( item ) {
7495    // get x/y object from method
7496    var position = this._getItemLayoutPosition( item );
7497    // enqueue
7498    position.item = item;
7499    position.isInstant = isInstant || item.isLayoutInstant;
7500    queue.push( position );
7501  }, this );
7502
7503  this._processLayoutQueue( queue );
7504};
7505
7506/**
7507 * get item layout position
7508 * @param {Outlayer.Item} item
7509 * @returns {Object} x and y position
7510 */
7511proto._getItemLayoutPosition = function( /* item */ ) {
7512  return {
7513    x: 0,
7514    y: 0
7515  };
7516};
7517
7518/**
7519 * iterate over array and position each item
7520 * Reason being - separating this logic prevents 'layout invalidation'
7521 * thx @paul_irish
7522 * @param {Array} queue
7523 */
7524proto._processLayoutQueue = function( queue ) {
7525  this.updateStagger();
7526  queue.forEach( function( obj, i ) {
7527    this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i );
7528  }, this );
7529};
7530
7531// set stagger from option in milliseconds number
7532proto.updateStagger = function() {
7533  var stagger = this.options.stagger;
7534  if ( stagger === null || stagger === undefined ) {
7535    this.stagger = 0;
7536    return;
7537  }
7538  this.stagger = getMilliseconds( stagger );
7539  return this.stagger;
7540};
7541
7542/**
7543 * Sets position of item in DOM
7544 * @param {Outlayer.Item} item
7545 * @param {Number} x - horizontal position
7546 * @param {Number} y - vertical position
7547 * @param {Boolean} isInstant - disables transitions
7548 */
7549proto._positionItem = function( item, x, y, isInstant, i ) {
7550  if ( isInstant ) {
7551    // if not transition, just set CSS
7552    item.goTo( x, y );
7553  } else {
7554    item.stagger( i * this.stagger );
7555    item.moveTo( x, y );
7556  }
7557};
7558
7559/**
7560 * Any logic you want to do after each layout,
7561 * i.e. size the container
7562 */
7563proto._postLayout = function() {
7564  this.resizeContainer();
7565};
7566
7567proto.resizeContainer = function() {
7568  var isResizingContainer = this._getOption('resizeContainer');
7569  if ( !isResizingContainer ) {
7570    return;
7571  }
7572  var size = this._getContainerSize();
7573  if ( size ) {
7574    this._setContainerMeasure( size.width, true );
7575    this._setContainerMeasure( size.height, false );
7576  }
7577};
7578
7579/**
7580 * Sets width or height of container if returned
7581 * @returns {Object} size
7582 *   @param {Number} width
7583 *   @param {Number} height
7584 */
7585proto._getContainerSize = noop;
7586
7587/**
7588 * @param {Number} measure - size of width or height
7589 * @param {Boolean} isWidth
7590 */
7591proto._setContainerMeasure = function( measure, isWidth ) {
7592  if ( measure === undefined ) {
7593    return;
7594  }
7595
7596  var elemSize = this.size;
7597  // add padding and border width if border box
7598  if ( elemSize.isBorderBox ) {
7599    measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight +
7600      elemSize.borderLeftWidth + elemSize.borderRightWidth :
7601      elemSize.paddingBottom + elemSize.paddingTop +
7602      elemSize.borderTopWidth + elemSize.borderBottomWidth;
7603  }
7604
7605  measure = Math.max( measure, 0 );
7606  this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px';
7607};
7608
7609/**
7610 * emit eventComplete on a collection of items events
7611 * @param {String} eventName
7612 * @param {Array} items - Outlayer.Items
7613 */
7614proto._emitCompleteOnItems = function( eventName, items ) {
7615  var _this = this;
7616  function onComplete() {
7617    _this.dispatchEvent( eventName + 'Complete', null, [ items ] );
7618  }
7619
7620  var count = items.length;
7621  if ( !items || !count ) {
7622    onComplete();
7623    return;
7624  }
7625
7626  var doneCount = 0;
7627  function tick() {
7628    doneCount++;
7629    if ( doneCount == count ) {
7630      onComplete();
7631    }
7632  }
7633
7634  // bind callback
7635  items.forEach( function( item ) {
7636    item.once( eventName, tick );
7637  });
7638};
7639
7640/**
7641 * emits events via EvEmitter and jQuery events
7642 * @param {String} type - name of event
7643 * @param {Event} event - original event
7644 * @param {Array} args - extra arguments
7645 */
7646proto.dispatchEvent = function( type, event, args ) {
7647  // add original event to arguments
7648  var emitArgs = event ? [ event ].concat( args ) : args;
7649  this.emitEvent( type, emitArgs );
7650
7651  if ( jQuery ) {
7652    // set this.$element
7653    this.$element = this.$element || jQuery( this.element );
7654    if ( event ) {
7655      // create jQuery event
7656      var $event = jQuery.Event( event );
7657      $event.type = type;
7658      this.$element.trigger( $event, args );
7659    } else {
7660      // just trigger with type if no event available
7661      this.$element.trigger( type, args );
7662    }
7663  }
7664};
7665
7666// -------------------------- ignore & stamps -------------------------- //
7667
7668
7669/**
7670 * keep item in collection, but do not lay it out
7671 * ignored items do not get skipped in layout
7672 * @param {Element} elem
7673 */
7674proto.ignore = function( elem ) {
7675  var item = this.getItem( elem );
7676  if ( item ) {
7677    item.isIgnored = true;
7678  }
7679};
7680
7681/**
7682 * return item to layout collection
7683 * @param {Element} elem
7684 */
7685proto.unignore = function( elem ) {
7686  var item = this.getItem( elem );
7687  if ( item ) {
7688    delete item.isIgnored;
7689  }
7690};
7691
7692/**
7693 * adds elements to stamps
7694 * @param {NodeList, Array, Element, or String} elems
7695 */
7696proto.stamp = function( elems ) {
7697  elems = this._find( elems );
7698  if ( !elems ) {
7699    return;
7700  }
7701
7702  this.stamps = this.stamps.concat( elems );
7703  // ignore
7704  elems.forEach( this.ignore, this );
7705};
7706
7707/**
7708 * removes elements to stamps
7709 * @param {NodeList, Array, or Element} elems
7710 */
7711proto.unstamp = function( elems ) {
7712  elems = this._find( elems );
7713  if ( !elems ){
7714    return;
7715  }
7716
7717  elems.forEach( function( elem ) {
7718    // filter out removed stamp elements
7719    utils.removeFrom( this.stamps, elem );
7720    this.unignore( elem );
7721  }, this );
7722};
7723
7724/**
7725 * finds child elements
7726 * @param {NodeList, Array, Element, or String} elems
7727 * @returns {Array} elems
7728 */
7729proto._find = function( elems ) {
7730  if ( !elems ) {
7731    return;
7732  }
7733  // if string, use argument as selector string
7734  if ( typeof elems == 'string' ) {
7735    elems = this.element.querySelectorAll( elems );
7736  }
7737  elems = utils.makeArray( elems );
7738  return elems;
7739};
7740
7741proto._manageStamps = function() {
7742  if ( !this.stamps || !this.stamps.length ) {
7743    return;
7744  }
7745
7746  this._getBoundingRect();
7747
7748  this.stamps.forEach( this._manageStamp, this );
7749};
7750
7751// update boundingLeft / Top
7752proto._getBoundingRect = function() {
7753  // get bounding rect for container element
7754  var boundingRect = this.element.getBoundingClientRect();
7755  var size = this.size;
7756  this._boundingRect = {
7757    left: boundingRect.left + size.paddingLeft + size.borderLeftWidth,
7758    top: boundingRect.top + size.paddingTop + size.borderTopWidth,
7759    right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ),
7760    bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth )
7761  };
7762};
7763
7764/**
7765 * @param {Element} stamp
7766**/
7767proto._manageStamp = noop;
7768
7769/**
7770 * get x/y position of element relative to container element
7771 * @param {Element} elem
7772 * @returns {Object} offset - has left, top, right, bottom
7773 */
7774proto._getElementOffset = function( elem ) {
7775  var boundingRect = elem.getBoundingClientRect();
7776  var thisRect = this._boundingRect;
7777  var size = getSize( elem );
7778  var offset = {
7779    left: boundingRect.left - thisRect.left - size.marginLeft,
7780    top: boundingRect.top - thisRect.top - size.marginTop,
7781    right: thisRect.right - boundingRect.right - size.marginRight,
7782    bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom
7783  };
7784  return offset;
7785};
7786
7787// -------------------------- resize -------------------------- //
7788
7789// enable event handlers for listeners
7790// i.e. resize -> onresize
7791proto.handleEvent = utils.handleEvent;
7792
7793/**
7794 * Bind layout to window resizing
7795 */
7796proto.bindResize = function() {
7797  window.addEventListener( 'resize', this );
7798  this.isResizeBound = true;
7799};
7800
7801/**
7802 * Unbind layout to window resizing
7803 */
7804proto.unbindResize = function() {
7805  window.removeEventListener( 'resize', this );
7806  this.isResizeBound = false;
7807};
7808
7809proto.onresize = function() {
7810  this.resize();
7811};
7812
7813utils.debounceMethod( Outlayer, 'onresize', 100 );
7814
7815proto.resize = function() {
7816  // don't trigger if size did not change
7817  // or if resize was unbound. See #9
7818  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
7819    return;
7820  }
7821
7822  this.layout();
7823};
7824
7825/**
7826 * check if layout is needed post layout
7827 * @returns Boolean
7828 */
7829proto.needsResizeLayout = function() {
7830  var size = getSize( this.element );
7831  // check that this.size and size are there
7832  // IE8 triggers resize on body size change, so they might not be
7833  var hasSizes = this.size && size;
7834  return hasSizes && size.innerWidth !== this.size.innerWidth;
7835};
7836
7837// -------------------------- methods -------------------------- //
7838
7839/**
7840 * add items to Outlayer instance
7841 * @param {Array or NodeList or Element} elems
7842 * @returns {Array} items - Outlayer.Items
7843**/
7844proto.addItems = function( elems ) {
7845  var items = this._itemize( elems );
7846  // add items to collection
7847  if ( items.length ) {
7848    this.items = this.items.concat( items );
7849  }
7850  return items;
7851};
7852
7853/**
7854 * Layout newly-appended item elements
7855 * @param {Array or NodeList or Element} elems
7856 */
7857proto.appended = function( elems ) {
7858  var items = this.addItems( elems );
7859  if ( !items.length ) {
7860    return;
7861  }
7862  // layout and reveal just the new items
7863  this.layoutItems( items, true );
7864  this.reveal( items );
7865};
7866
7867/**
7868 * Layout prepended elements
7869 * @param {Array or NodeList or Element} elems
7870 */
7871proto.prepended = function( elems ) {
7872  var items = this._itemize( elems );
7873  if ( !items.length ) {
7874    return;
7875  }
7876  // add items to beginning of collection
7877  var previousItems = this.items.slice(0);
7878  this.items = items.concat( previousItems );
7879  // start new layout
7880  this._resetLayout();
7881  this._manageStamps();
7882  // layout new stuff without transition
7883  this.layoutItems( items, true );
7884  this.reveal( items );
7885  // layout previous items
7886  this.layoutItems( previousItems );
7887};
7888
7889/**
7890 * reveal a collection of items
7891 * @param {Array of Outlayer.Items} items
7892 */
7893proto.reveal = function( items ) {
7894  this._emitCompleteOnItems( 'reveal', items );
7895  if ( !items || !items.length ) {
7896    return;
7897  }
7898  var stagger = this.updateStagger();
7899  items.forEach( function( item, i ) {
7900    item.stagger( i * stagger );
7901    item.reveal();
7902  });
7903};
7904
7905/**
7906 * hide a collection of items
7907 * @param {Array of Outlayer.Items} items
7908 */
7909proto.hide = function( items ) {
7910  this._emitCompleteOnItems( 'hide', items );
7911  if ( !items || !items.length ) {
7912    return;
7913  }
7914  var stagger = this.updateStagger();
7915  items.forEach( function( item, i ) {
7916    item.stagger( i * stagger );
7917    item.hide();
7918  });
7919};
7920
7921/**
7922 * reveal item elements
7923 * @param {Array}, {Element}, {NodeList} items
7924 */
7925proto.revealItemElements = function( elems ) {
7926  var items = this.getItems( elems );
7927  this.reveal( items );
7928};
7929
7930/**
7931 * hide item elements
7932 * @param {Array}, {Element}, {NodeList} items
7933 */
7934proto.hideItemElements = function( elems ) {
7935  var items = this.getItems( elems );
7936  this.hide( items );
7937};
7938
7939/**
7940 * get Outlayer.Item, given an Element
7941 * @param {Element} elem
7942 * @param {Function} callback
7943 * @returns {Outlayer.Item} item
7944 */
7945proto.getItem = function( elem ) {
7946  // loop through items to get the one that matches
7947  for ( var i=0; i < this.items.length; i++ ) {
7948    var item = this.items[i];
7949    if ( item.element == elem ) {
7950      // return item
7951      return item;
7952    }
7953  }
7954};
7955
7956/**
7957 * get collection of Outlayer.Items, given Elements
7958 * @param {Array} elems
7959 * @returns {Array} items - Outlayer.Items
7960 */
7961proto.getItems = function( elems ) {
7962  elems = utils.makeArray( elems );
7963  var items = [];
7964  elems.forEach( function( elem ) {
7965    var item = this.getItem( elem );
7966    if ( item ) {
7967      items.push( item );
7968    }
7969  }, this );
7970
7971  return items;
7972};
7973
7974/**
7975 * remove element(s) from instance and DOM
7976 * @param {Array or NodeList or Element} elems
7977 */
7978proto.remove = function( elems ) {
7979  var removeItems = this.getItems( elems );
7980
7981  this._emitCompleteOnItems( 'remove', removeItems );
7982
7983  // bail if no items to remove
7984  if ( !removeItems || !removeItems.length ) {
7985    return;
7986  }
7987
vendor: 38,285 bytes, lines 7988-9411
7988  removeItems.forEach( function( item ) {
7989    item.remove();
7990    // remove item from collection
7991    utils.removeFrom( this.items, item );
7992  }, this );
7993};
7994
7995// ----- destroy ----- //
7996
7997// remove and disable Outlayer instance
7998proto.destroy = function() {
7999  // clean up dynamic styles
8000  var style = this.element.style;
8001  style.height = '';
8002  style.position = '';
8003  style.width = '';
8004  // destroy items
8005  this.items.forEach( function( item ) {
8006    item.destroy();
8007  });
8008
8009  this.unbindResize();
8010
8011  var id = this.element.outlayerGUID;
8012  delete instances[ id ]; // remove reference to instance by id
8013  delete this.element.outlayerGUID;
8014  // remove data for jQuery
8015  if ( jQuery ) {
8016    jQuery.removeData( this.element, this.constructor.namespace );
8017  }
8018
8019};
8020
8021// -------------------------- data -------------------------- //
8022
8023/**
8024 * get Outlayer instance from element
8025 * @param {Element} elem
8026 * @returns {Outlayer}
8027 */
8028Outlayer.data = function( elem ) {
8029  elem = utils.getQueryElement( elem );
8030  var id = elem && elem.outlayerGUID;
8031  return id && instances[ id ];
8032};
8033
8034
8035// -------------------------- create Outlayer class -------------------------- //
8036
8037/**
8038 * create a layout class
8039 * @param {String} namespace
8040 */
8041Outlayer.create = function( namespace, options ) {
8042  // sub-class Outlayer
8043  var Layout = subclass( Outlayer );
8044  // apply new options and compatOptions
8045  Layout.defaults = utils.extend( {}, Outlayer.defaults );
8046  utils.extend( Layout.defaults, options );
8047  Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions  );
8048
8049  Layout.namespace = namespace;
8050
8051  Layout.data = Outlayer.data;
8052
8053  // sub-class Item
8054  Layout.Item = subclass( Item );
8055
8056  // -------------------------- declarative -------------------------- //
8057
8058  utils.htmlInit( Layout, namespace );
8059
8060  // -------------------------- jQuery bridge -------------------------- //
8061
8062  // make into jQuery plugin
8063  if ( jQuery && jQuery.bridget ) {
8064    jQuery.bridget( namespace, Layout );
8065  }
8066
8067  return Layout;
8068};
8069
8070function subclass( Parent ) {
8071  function SubClass() {
8072    Parent.apply( this, arguments );
8073  }
8074
8075  SubClass.prototype = Object.create( Parent.prototype );
8076  SubClass.prototype.constructor = SubClass;
8077
8078  return SubClass;
8079}
8080
8081// ----- helpers ----- //
8082
8083// how many milliseconds are in each unit
8084var msUnits = {
8085  ms: 1,
8086  s: 1000
8087};
8088
8089// munge time-like parameter into millisecond number
8090// '0.4s' -> 40
8091function getMilliseconds( time ) {
8092  if ( typeof time == 'number' ) {
8093    return time;
8094  }
8095  var matches = time.match( /(^\d*\.?\d*)(\w*)/ );
8096  var num = matches && matches[1];
8097  var unit = matches && matches[2];
8098  if ( !num.length ) {
8099    return 0;
8100  }
8101  num = parseFloat( num );
8102  var mult = msUnits[ unit ] || 1;
8103  return num * mult;
8104}
8105
8106// ----- fin ----- //
8107
8108// back in global
8109Outlayer.Item = Item;
8110
8111return Outlayer;
8112
8113}));
8114
8115/**
8116 * Isotope Item
8117**/
8118
8119( function( window, factory ) {
8120  // universal module definition
8121  /* jshint strict: false */ /*globals define, module, require */
8122  if ( typeof define == 'function' && define.amd ) {
8123    // AMD
8124    define( 'isotope-layout/js/item',[
8125        'outlayer/outlayer'
8126      ],
8127      factory );
8128  } else if ( typeof module == 'object' && module.exports ) {
8129    // CommonJS
8130    module.exports = factory(
8131      require('outlayer')
8132    );
8133  } else {
8134    // browser global
8135    window.Isotope = window.Isotope || {};
8136    window.Isotope.Item = factory(
8137      window.Outlayer
8138    );
8139  }
8140
8141}( window, function factory( Outlayer ) {
8142'use strict';
8143
8144// -------------------------- Item -------------------------- //
8145
8146// sub-class Outlayer Item
8147function Item() {
8148  Outlayer.Item.apply( this, arguments );
8149}
8150
8151var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
8152
8153var _create = proto._create;
8154proto._create = function() {
8155  // assign id, used for original-order sorting
8156  this.id = this.layout.itemGUID++;
8157  _create.call( this );
8158  this.sortData = {};
8159};
8160
8161proto.updateSortData = function() {
8162  if ( this.isIgnored ) {
8163    return;
8164  }
8165  // default sorters
8166  this.sortData.id = this.id;
8167  // for backward compatibility
8168  this.sortData['original-order'] = this.id;
8169  this.sortData.random = Math.random();
8170  // go thru getSortData obj and apply the sorters
8171  var getSortData = this.layout.options.getSortData;
8172  var sorters = this.layout._sorters;
8173  for ( var key in getSortData ) {
8174    var sorter = sorters[ key ];
8175    this.sortData[ key ] = sorter( this.element, this );
8176  }
8177};
8178
8179var _destroy = proto.destroy;
8180proto.destroy = function() {
8181  // call super
8182  _destroy.apply( this, arguments );
8183  // reset display, #741
8184  this.css({
8185    display: ''
8186  });
8187};
8188
8189return Item;
8190
8191}));
8192
8193/**
8194 * Isotope LayoutMode
8195 */
8196
8197( function( window, factory ) {
8198  // universal module definition
8199  /* jshint strict: false */ /*globals define, module, require */
8200  if ( typeof define == 'function' && define.amd ) {
8201    // AMD
8202    define( 'isotope-layout/js/layout-mode',[
8203        'get-size/get-size',
8204        'outlayer/outlayer'
8205      ],
8206      factory );
8207  } else if ( typeof module == 'object' && module.exports ) {
8208    // CommonJS
8209    module.exports = factory(
8210      require('get-size'),
8211      require('outlayer')
8212    );
8213  } else {
8214    // browser global
8215    window.Isotope = window.Isotope || {};
8216    window.Isotope.LayoutMode = factory(
8217      window.getSize,
8218      window.Outlayer
8219    );
8220  }
8221
8222}( window, function factory( getSize, Outlayer ) {
8223  'use strict';
8224
8225  // layout mode class
8226  function LayoutMode( isotope ) {
8227    this.isotope = isotope;
8228    // link properties
8229    if ( isotope ) {
8230      this.options = isotope.options[ this.namespace ];
8231      this.element = isotope.element;
8232      this.items = isotope.filteredItems;
8233      this.size = isotope.size;
8234    }
8235  }
8236
8237  var proto = LayoutMode.prototype;
8238
8239  /**
8240   * some methods should just defer to default Outlayer method
8241   * and reference the Isotope instance as `this`
8242  **/
8243  var facadeMethods = [
8244    '_resetLayout',
8245    '_getItemLayoutPosition',
8246    '_manageStamp',
8247    '_getContainerSize',
8248    '_getElementOffset',
8249    'needsResizeLayout',
8250    '_getOption'
8251  ];
8252
8253  facadeMethods.forEach( function( methodName ) {
8254    proto[ methodName ] = function() {
8255      return Outlayer.prototype[ methodName ].apply( this.isotope, arguments );
8256    };
8257  });
8258
8259  // -----  ----- //
8260
8261  // for horizontal layout modes, check vertical size
8262  proto.needsVerticalResizeLayout = function() {
8263    // don't trigger if size did not change
8264    var size = getSize( this.isotope.element );
8265    // check that this.size and size are there
8266    // IE8 triggers resize on body size change, so they might not be
8267    var hasSizes = this.isotope.size && size;
8268    return hasSizes && size.innerHeight != this.isotope.size.innerHeight;
8269  };
8270
8271  // ----- measurements ----- //
8272
8273  proto._getMeasurement = function() {
8274    this.isotope._getMeasurement.apply( this, arguments );
8275  };
8276
8277  proto.getColumnWidth = function() {
8278    this.getSegmentSize( 'column', 'Width' );
8279  };
8280
8281  proto.getRowHeight = function() {
8282    this.getSegmentSize( 'row', 'Height' );
8283  };
8284
8285  /**
8286   * get columnWidth or rowHeight
8287   * segment: 'column' or 'row'
8288   * size 'Width' or 'Height'
8289  **/
8290  proto.getSegmentSize = function( segment, size ) {
8291    var segmentName = segment + size;
8292    var outerSize = 'outer' + size;
8293    // columnWidth / outerWidth // rowHeight / outerHeight
8294    this._getMeasurement( segmentName, outerSize );
8295    // got rowHeight or columnWidth, we can chill
8296    if ( this[ segmentName ] ) {
8297      return;
8298    }
8299    // fall back to item of first element
8300    var firstItemSize = this.getFirstItemSize();
8301    this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] ||
8302      // or size of container
8303      this.isotope.size[ 'inner' + size ];
8304  };
8305
8306  proto.getFirstItemSize = function() {
8307    var firstItem = this.isotope.filteredItems[0];
8308    return firstItem && firstItem.element && getSize( firstItem.element );
8309  };
8310
8311  // ----- methods that should reference isotope ----- //
8312
8313  proto.layout = function() {
8314    this.isotope.layout.apply( this.isotope, arguments );
8315  };
8316
8317  proto.getSize = function() {
8318    this.isotope.getSize();
8319    this.size = this.isotope.size;
8320  };
8321
8322  // -------------------------- create -------------------------- //
8323
8324  LayoutMode.modes = {};
8325
8326  LayoutMode.create = function( namespace, options ) {
8327
8328    function Mode() {
8329      LayoutMode.apply( this, arguments );
8330    }
8331
8332    Mode.prototype = Object.create( proto );
8333    Mode.prototype.constructor = Mode;
8334
8335    // default options
8336    if ( options ) {
8337      Mode.options = options;
8338    }
8339
8340    Mode.prototype.namespace = namespace;
8341    // register in Isotope
8342    LayoutMode.modes[ namespace ] = Mode;
8343
8344    return Mode;
8345  };
8346
8347  return LayoutMode;
8348
8349}));
8350
8351/*!
8352 * Masonry v4.2.1
8353 * Cascading grid layout library
8354 * https://masonry.desandro.com
8355 * MIT License
8356 * by David DeSandro
8357 */
8358
8359( function( window, factory ) {
8360  // universal module definition
8361  /* jshint strict: false */ /*globals define, module, require */
8362  if ( typeof define == 'function' && define.amd ) {
8363    // AMD
8364    define( 'masonry-layout/masonry',[
8365        'outlayer/outlayer',
8366        'get-size/get-size'
8367      ],
8368      factory );
8369  } else if ( typeof module == 'object' && module.exports ) {
8370    // CommonJS
8371    module.exports = factory(
8372      require('outlayer'),
8373      require('get-size')
8374    );
8375  } else {
8376    // browser global
8377    window.Masonry = factory(
8378      window.Outlayer,
8379      window.getSize
8380    );
8381  }
8382
8383}( window, function factory( Outlayer, getSize ) {
8384
8385
8386
8387// -------------------------- masonryDefinition -------------------------- //
8388
8389  // create an Outlayer layout class
8390  var Masonry = Outlayer.create('masonry');
8391  // isFitWidth -> fitWidth
8392  Masonry.compatOptions.fitWidth = 'isFitWidth';
8393
8394  var proto = Masonry.prototype;
8395
8396  proto._resetLayout = function() {
8397    this.getSize();
8398    this._getMeasurement( 'columnWidth', 'outerWidth' );
8399    this._getMeasurement( 'gutter', 'outerWidth' );
8400    this.measureColumns();
8401
8402    // reset column Y
8403    this.colYs = [];
8404    for ( var i=0; i < this.cols; i++ ) {
8405      this.colYs.push( 0 );
8406    }
8407
8408    this.maxY = 0;
8409    this.horizontalColIndex = 0;
8410  };
8411
8412  proto.measureColumns = function() {
8413    this.getContainerWidth();
8414    // if columnWidth is 0, default to outerWidth of first item
8415    if ( !this.columnWidth ) {
8416      var firstItem = this.items[0];
8417      var firstItemElem = firstItem && firstItem.element;
8418      // columnWidth fall back to item of first element
8419      this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth ||
8420        // if first elem has no width, default to size of container
8421        this.containerWidth;
8422    }
8423
8424    var columnWidth = this.columnWidth += this.gutter;
8425
8426    // calculate columns
8427    var containerWidth = this.containerWidth + this.gutter;
8428    var cols = containerWidth / columnWidth;
8429    // fix rounding errors, typically with gutters
8430    var excess = columnWidth - containerWidth % columnWidth;
8431    // if overshoot is less than a pixel, round up, otherwise floor it
8432    var mathMethod = excess && excess < 1 ? 'round' : 'floor';
8433    cols = Math[ mathMethod ]( cols );
8434    this.cols = Math.max( cols, 1 );
8435  };
8436
8437  proto.getContainerWidth = function() {
8438    // container is parent if fit width
8439    var isFitWidth = this._getOption('fitWidth');
8440    var container = isFitWidth ? this.element.parentNode : this.element;
8441    // check that this.size and size are there
8442    // IE8 triggers resize on body size change, so they might not be
8443    var size = getSize( container );
8444    this.containerWidth = size && size.innerWidth;
8445  };
8446
8447  proto._getItemLayoutPosition = function( item ) {
8448    item.getSize();
8449    // how many columns does this brick span
8450    var remainder = item.size.outerWidth % this.columnWidth;
8451    var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
8452    // round if off by 1 pixel, otherwise use ceil
8453    var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth );
8454    colSpan = Math.min( colSpan, this.cols );
8455    // use horizontal or top column position
8456    var colPosMethod = this.options.horizontalOrder ?
8457      '_getHorizontalColPosition' : '_getTopColPosition';
8458    var colPosition = this[ colPosMethod ]( colSpan, item );
8459    // position the brick
8460    var position = {
8461      x: this.columnWidth * colPosition.col,
8462      y: colPosition.y
8463    };
8464    // apply setHeight to necessary columns
8465    var setHeight = colPosition.y + item.size.outerHeight;
8466    var setMax = colSpan + colPosition.col;
8467    for ( var i = colPosition.col; i < setMax; i++ ) {
8468      this.colYs[i] = setHeight;
8469    }
8470
8471    return position;
8472  };
8473
8474  proto._getTopColPosition = function( colSpan ) {
8475    var colGroup = this._getTopColGroup( colSpan );
8476    // get the minimum Y value from the columns
8477    var minimumY = Math.min.apply( Math, colGroup );
8478
8479    return {
8480      col: colGroup.indexOf( minimumY ),
8481      y: minimumY,
8482    };
8483  };
8484
8485  /**
8486   * @param {Number} colSpan - number of columns the element spans
8487   * @returns {Array} colGroup
8488   */
8489  proto._getTopColGroup = function( colSpan ) {
8490    if ( colSpan < 2 ) {
8491      // if brick spans only one column, use all the column Ys
8492      return this.colYs;
8493    }
8494
8495    var colGroup = [];
8496    // how many different places could this brick fit horizontally
8497    var groupCount = this.cols + 1 - colSpan;
8498    // for each group potential horizontal position
8499    for ( var i = 0; i < groupCount; i++ ) {
8500      colGroup[i] = this._getColGroupY( i, colSpan );
8501    }
8502    return colGroup;
8503  };
8504
8505  proto._getColGroupY = function( col, colSpan ) {
8506    if ( colSpan < 2 ) {
8507      return this.colYs[ col ];
8508    }
8509    // make an array of colY values for that one group
8510    var groupColYs = this.colYs.slice( col, col + colSpan );
8511    // and get the max value of the array
8512    return Math.max.apply( Math, groupColYs );
8513  };
8514
8515  // get column position based on horizontal index. #873
8516  proto._getHorizontalColPosition = function( colSpan, item ) {
8517    var col = this.horizontalColIndex % this.cols;
8518    var isOver = colSpan > 1 && col + colSpan > this.cols;
8519    // shift to next row if item can't fit on current row
8520    col = isOver ? 0 : col;
8521    // don't let zero-size items take up space
8522    var hasSize = item.size.outerWidth && item.size.outerHeight;
8523    this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex;
8524
8525    return {
8526      col: col,
8527      y: this._getColGroupY( col, colSpan ),
8528    };
8529  };
8530
8531  proto._manageStamp = function( stamp ) {
8532    var stampSize = getSize( stamp );
8533    var offset = this._getElementOffset( stamp );
8534    // get the columns that this stamp affects
8535    var isOriginLeft = this._getOption('originLeft');
8536    var firstX = isOriginLeft ? offset.left : offset.right;
8537    var lastX = firstX + stampSize.outerWidth;
8538    var firstCol = Math.floor( firstX / this.columnWidth );
8539    firstCol = Math.max( 0, firstCol );
8540    var lastCol = Math.floor( lastX / this.columnWidth );
8541    // lastCol should not go over if multiple of columnWidth #425
8542    lastCol -= lastX % this.columnWidth ? 0 : 1;
8543    lastCol = Math.min( this.cols - 1, lastCol );
8544    // set colYs to bottom of the stamp
8545
8546    var isOriginTop = this._getOption('originTop');
8547    var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) +
8548      stampSize.outerHeight;
8549    for ( var i = firstCol; i <= lastCol; i++ ) {
8550      this.colYs[i] = Math.max( stampMaxY, this.colYs[i] );
8551    }
8552  };
8553
8554  proto._getContainerSize = function() {
8555    this.maxY = Math.max.apply( Math, this.colYs );
8556    var size = {
8557      height: this.maxY
8558    };
8559
8560    if ( this._getOption('fitWidth') ) {
8561      size.width = this._getContainerFitWidth();
8562    }
8563
8564    return size;
8565  };
8566
8567  proto._getContainerFitWidth = function() {
8568    var unusedCols = 0;
8569    // count unused columns
8570    var i = this.cols;
8571    while ( --i ) {
8572      if ( this.colYs[i] !== 0 ) {
8573        break;
8574      }
8575      unusedCols++;
8576    }
8577    // fit container to columns that have been used
8578    return ( this.cols - unusedCols ) * this.columnWidth - this.gutter;
8579  };
8580
8581  proto.needsResizeLayout = function() {
8582    var previousWidth = this.containerWidth;
8583    this.getContainerWidth();
8584    return previousWidth != this.containerWidth;
8585  };
8586
8587  return Masonry;
8588
8589}));
8590
8591/*!
8592 * Masonry layout mode
8593 * sub-classes Masonry
8594 * https://masonry.desandro.com
8595 */
8596
8597( function( window, factory ) {
8598  // universal module definition
8599  /* jshint strict: false */ /*globals define, module, require */
8600  if ( typeof define == 'function' && define.amd ) {
8601    // AMD
8602    define( 'isotope-layout/js/layout-modes/masonry',[
8603        '../layout-mode',
8604        'masonry-layout/masonry'
8605      ],
8606      factory );
8607  } else if ( typeof module == 'object' && module.exports ) {
8608    // CommonJS
8609    module.exports = factory(
8610      require('../layout-mode'),
8611      require('masonry-layout')
8612    );
8613  } else {
8614    // browser global
8615    factory(
8616      window.Isotope.LayoutMode,
8617      window.Masonry
8618    );
8619  }
8620
8621}( window, function factory( LayoutMode, Masonry ) {
8622'use strict';
8623
8624// -------------------------- masonryDefinition -------------------------- //
8625
8626  // create an Outlayer layout class
8627  var MasonryMode = LayoutMode.create('masonry');
8628
8629  var proto = MasonryMode.prototype;
8630
8631  var keepModeMethods = {
8632    _getElementOffset: true,
8633    layout: true,
8634    _getMeasurement: true
8635  };
8636
8637  // inherit Masonry prototype
8638  for ( var method in Masonry.prototype ) {
8639    // do not inherit mode methods
8640    if ( !keepModeMethods[ method ] ) {
8641      proto[ method ] = Masonry.prototype[ method ];
8642    }
8643  }
8644
8645  var measureColumns = proto.measureColumns;
8646  proto.measureColumns = function() {
8647    // set items, used if measuring first item
8648    this.items = this.isotope.filteredItems;
8649    measureColumns.call( this );
8650  };
8651
8652  // point to mode options for fitWidth
8653  var _getOption = proto._getOption;
8654  proto._getOption = function( option ) {
8655    if ( option == 'fitWidth' ) {
8656      return this.options.isFitWidth !== undefined ?
8657        this.options.isFitWidth : this.options.fitWidth;
8658    }
8659    return _getOption.apply( this.isotope, arguments );
8660  };
8661
8662  return MasonryMode;
8663
8664}));
8665
8666/**
8667 * fitRows layout mode
8668 */
8669
8670( function( window, factory ) {
8671  // universal module definition
8672  /* jshint strict: false */ /*globals define, module, require */
8673  if ( typeof define == 'function' && define.amd ) {
8674    // AMD
8675    define( 'isotope-layout/js/layout-modes/fit-rows',[
8676        '../layout-mode'
8677      ],
8678      factory );
8679  } else if ( typeof exports == 'object' ) {
8680    // CommonJS
8681    module.exports = factory(
8682      require('../layout-mode')
8683    );
8684  } else {
8685    // browser global
8686    factory(
8687      window.Isotope.LayoutMode
8688    );
8689  }
8690
8691}( window, function factory( LayoutMode ) {
8692'use strict';
8693
8694var FitRows = LayoutMode.create('fitRows');
8695
8696var proto = FitRows.prototype;
8697
8698proto._resetLayout = function() {
8699  this.x = 0;
8700  this.y = 0;
8701  this.maxY = 0;
8702  this._getMeasurement( 'gutter', 'outerWidth' );
8703};
8704
8705proto._getItemLayoutPosition = function( item ) {
8706  item.getSize();
8707
8708  var itemWidth = item.size.outerWidth + this.gutter;
8709  // if this element cannot fit in the current row
8710  var containerWidth = this.isotope.size.innerWidth + this.gutter;
8711  if ( this.x !== 0 && itemWidth + this.x > containerWidth ) {
8712    this.x = 0;
8713    this.y = this.maxY;
8714  }
8715
8716  var position = {
8717    x: this.x,
8718    y: this.y
8719  };
8720
8721  this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight );
8722  this.x += itemWidth;
8723
8724  return position;
8725};
8726
8727proto._getContainerSize = function() {
8728  return { height: this.maxY };
8729};
8730
8731return FitRows;
8732
8733}));
8734
8735/**
8736 * vertical layout mode
8737 */
8738
8739( function( window, factory ) {
8740  // universal module definition
8741  /* jshint strict: false */ /*globals define, module, require */
8742  if ( typeof define == 'function' && define.amd ) {
8743    // AMD
8744    define( 'isotope-layout/js/layout-modes/vertical',[
8745        '../layout-mode'
8746      ],
8747      factory );
8748  } else if ( typeof module == 'object' && module.exports ) {
8749    // CommonJS
8750    module.exports = factory(
8751      require('../layout-mode')
8752    );
8753  } else {
8754    // browser global
8755    factory(
8756      window.Isotope.LayoutMode
8757    );
8758  }
8759
8760}( window, function factory( LayoutMode ) {
8761'use strict';
8762
8763var Vertical = LayoutMode.create( 'vertical', {
8764  horizontalAlignment: 0
8765});
8766
8767var proto = Vertical.prototype;
8768
8769proto._resetLayout = function() {
8770  this.y = 0;
8771};
8772
8773proto._getItemLayoutPosition = function( item ) {
8774  item.getSize();
8775  var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) *
8776    this.options.horizontalAlignment;
8777  var y = this.y;
8778  this.y += item.size.outerHeight;
8779  return { x: x, y: y };
8780};
8781
8782proto._getContainerSize = function() {
8783  return { height: this.y };
8784};
8785
8786return Vertical;
8787
8788}));
8789
8790/*!
8791 * Isotope v3.0.6
8792 *
8793 * Licensed GPLv3 for open source use
8794 * or Isotope Commercial License for commercial use
8795 *
8796 * https://isotope.metafizzy.co
8797 * Copyright 2010-2018 Metafizzy
8798 */
8799
8800( function( window, factory ) {
8801  // universal module definition
8802  /* jshint strict: false */ /*globals define, module, require */
8803  if ( typeof define == 'function' && define.amd ) {
8804    // AMD
8805    define( [
8806        'outlayer/outlayer',
8807        'get-size/get-size',
8808        'desandro-matches-selector/matches-selector',
8809        'fizzy-ui-utils/utils',
8810        'isotope-layout/js/item',
8811        'isotope-layout/js/layout-mode',
8812        // include default layout modes
8813        'isotope-layout/js/layout-modes/masonry',
8814        'isotope-layout/js/layout-modes/fit-rows',
8815        'isotope-layout/js/layout-modes/vertical'
8816      ],
8817      function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) {
8818        return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode );
8819      });
8820  } else if ( typeof module == 'object' && module.exports ) {
8821    // CommonJS
8822    module.exports = factory(
8823      window,
8824      require('outlayer'),
8825      require('get-size'),
8826      require('desandro-matches-selector'),
8827      require('fizzy-ui-utils'),
8828      require('isotope-layout/js/item'),
8829      require('isotope-layout/js/layout-mode'),
8830      // include default layout modes
8831      require('isotope-layout/js/layout-modes/masonry'),
8832      require('isotope-layout/js/layout-modes/fit-rows'),
8833      require('isotope-layout/js/layout-modes/vertical')
8834    );
8835  } else {
8836    // browser global
8837    window.Isotope = factory(
8838      window,
8839      window.Outlayer,
8840      window.getSize,
8841      window.matchesSelector,
8842      window.fizzyUIUtils,
8843      window.Isotope.Item,
8844      window.Isotope.LayoutMode
8845    );
8846  }
8847
8848}( window, function factory( window, Outlayer, getSize, matchesSelector, utils,
8849  Item, LayoutMode ) {
8850
8851
8852
8853// -------------------------- vars -------------------------- //
8854
8855var jQuery = window.jQuery;
8856
8857// -------------------------- helpers -------------------------- //
8858
8859var trim = String.prototype.trim ?
8860  function( str ) {
8861    return str.trim();
8862  } :
8863  function( str ) {
8864    return str.replace( /^\s+|\s+$/g, '' );
8865  };
8866
8867// -------------------------- isotopeDefinition -------------------------- //
8868
8869  // create an Outlayer layout class
8870  var Isotope = Outlayer.create( 'isotope', {
8871    layoutMode: 'masonry',
8872    isJQueryFiltering: true,
8873    sortAscending: true
8874  });
8875
8876  Isotope.Item = Item;
8877  Isotope.LayoutMode = LayoutMode;
8878
8879  var proto = Isotope.prototype;
8880
8881  proto._create = function() {
8882    this.itemGUID = 0;
8883    // functions that sort items
8884    this._sorters = {};
8885    this._getSorters();
8886    // call super
8887    Outlayer.prototype._create.call( this );
8888
8889    // create layout modes
8890    this.modes = {};
8891    // start filteredItems with all items
8892    this.filteredItems = this.items;
8893    // keep of track of sortBys
8894    this.sortHistory = [ 'original-order' ];
8895    // create from registered layout modes
8896    for ( var name in LayoutMode.modes ) {
8897      this._initLayoutMode( name );
8898    }
8899  };
8900
8901  proto.reloadItems = function() {
8902    // reset item ID counter
8903    this.itemGUID = 0;
8904    // call super
8905    Outlayer.prototype.reloadItems.call( this );
8906  };
8907
8908  proto._itemize = function() {
8909    var items = Outlayer.prototype._itemize.apply( this, arguments );
8910    // assign ID for original-order
8911    for ( var i=0; i < items.length; i++ ) {
8912      var item = items[i];
8913      item.id = this.itemGUID++;
8914    }
8915    this._updateItemsSortData( items );
8916    return items;
8917  };
8918
8919
8920  // -------------------------- layout -------------------------- //
8921
8922  proto._initLayoutMode = function( name ) {
8923    var Mode = LayoutMode.modes[ name ];
8924    // set mode options
8925    // HACK extend initial options, back-fill in default options
8926    var initialOpts = this.options[ name ] || {};
8927    this.options[ name ] = Mode.options ?
8928      utils.extend( Mode.options, initialOpts ) : initialOpts;
8929    // init layout mode instance
8930    this.modes[ name ] = new Mode( this );
8931  };
8932
8933
8934  proto.layout = function() {
8935    // if first time doing layout, do all magic
8936    if ( !this._isLayoutInited && this._getOption('initLayout') ) {
8937      this.arrange();
8938      return;
8939    }
8940    this._layout();
8941  };
8942
8943  // private method to be used in layout() & magic()
8944  proto._layout = function() {
8945    // don't animate first layout
8946    var isInstant = this._getIsInstant();
8947    // layout flow
8948    this._resetLayout();
8949    this._manageStamps();
8950    this.layoutItems( this.filteredItems, isInstant );
8951
8952    // flag for initalized
8953    this._isLayoutInited = true;
8954  };
8955
8956  // filter + sort + layout
8957  proto.arrange = function( opts ) {
8958    // set any options pass
8959    this.option( opts );
8960    this._getIsInstant();
8961    // filter, sort, and layout
8962
8963    // filter
8964    var filtered = this._filter( this.items );
8965    this.filteredItems = filtered.matches;
8966
8967    this._bindArrangeComplete();
8968
8969    if ( this._isInstant ) {
8970      this._noTransition( this._hideReveal, [ filtered ] );
8971    } else {
8972      this._hideReveal( filtered );
8973    }
8974
8975    this._sort();
8976    this._layout();
8977  };
8978  // alias to _init for main plugin method
8979  proto._init = proto.arrange;
8980
8981  proto._hideReveal = function( filtered ) {
8982    this.reveal( filtered.needReveal );
8983    this.hide( filtered.needHide );
8984  };
8985
8986  // HACK
8987  // Don't animate/transition first layout
8988  // Or don't animate/transition other layouts
8989  proto._getIsInstant = function() {
8990    var isLayoutInstant = this._getOption('layoutInstant');
8991    var isInstant = isLayoutInstant !== undefined ? isLayoutInstant :
8992      !this._isLayoutInited;
8993    this._isInstant = isInstant;
8994    return isInstant;
8995  };
8996
8997  // listen for layoutComplete, hideComplete and revealComplete
8998  // to trigger arrangeComplete
8999  proto._bindArrangeComplete = function() {
9000    // listen for 3 events to trigger arrangeComplete
9001    var isLayoutComplete, isHideComplete, isRevealComplete;
9002    var _this = this;
9003    function arrangeParallelCallback() {
9004      if ( isLayoutComplete && isHideComplete && isRevealComplete ) {
9005        _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] );
9006      }
9007    }
9008    this.once( 'layoutComplete', function() {
9009      isLayoutComplete = true;
9010      arrangeParallelCallback();
9011    });
9012    this.once( 'hideComplete', function() {
9013      isHideComplete = true;
9014      arrangeParallelCallback();
9015    });
9016    this.once( 'revealComplete', function() {
9017      isRevealComplete = true;
9018      arrangeParallelCallback();
9019    });
9020  };
9021
9022  // -------------------------- filter -------------------------- //
9023
9024  proto._filter = function( items ) {
9025    var filter = this.options.filter;
9026    filter = filter || '*';
9027    var matches = [];
9028    var hiddenMatched = [];
9029    var visibleUnmatched = [];
9030
9031    var test = this._getFilterTest( filter );
9032
9033    // test each item
9034    for ( var i=0; i < items.length; i++ ) {
9035      var item = items[i];
9036      if ( item.isIgnored ) {
9037        continue;
9038      }
9039      // add item to either matched or unmatched group
9040      var isMatched = test( item );
9041      // item.isFilterMatched = isMatched;
9042      // add to matches if its a match
9043      if ( isMatched ) {
9044        matches.push( item );
9045      }
9046      // add to additional group if item needs to be hidden or revealed
9047      if ( isMatched && item.isHidden ) {
9048        hiddenMatched.push( item );
9049      } else if ( !isMatched && !item.isHidden ) {
9050        visibleUnmatched.push( item );
9051      }
9052    }
9053
9054    // return collections of items to be manipulated
9055    return {
9056      matches: matches,
9057      needReveal: hiddenMatched,
9058      needHide: visibleUnmatched
9059    };
9060  };
9061
9062  // get a jQuery, function, or a matchesSelector test given the filter
9063  proto._getFilterTest = function( filter ) {
9064    if ( jQuery && this.options.isJQueryFiltering ) {
9065      // use jQuery
9066      return function( item ) {
9067        return jQuery( item.element ).is( filter );
9068      };
9069    }
9070    if ( typeof filter == 'function' ) {
9071      // use filter as function
9072      return function( item ) {
9073        return filter( item.element );
9074      };
9075    }
9076    // default, use filter as selector string
9077    return function( item ) {
9078      return matchesSelector( item.element, filter );
9079    };
9080  };
9081
9082  // -------------------------- sorting -------------------------- //
9083
9084  /**
9085   * @params {Array} elems
9086   * @public
9087   */
9088  proto.updateSortData = function( elems ) {
9089    // get items
9090    var items;
9091    if ( elems ) {
9092      elems = utils.makeArray( elems );
9093      items = this.getItems( elems );
9094    } else {
9095      // update all items if no elems provided
9096      items = this.items;
9097    }
9098
9099    this._getSorters();
9100    this._updateItemsSortData( items );
9101  };
9102
9103  proto._getSorters = function() {
9104    var getSortData = this.options.getSortData;
9105    for ( var key in getSortData ) {
9106      var sorter = getSortData[ key ];
9107      this._sorters[ key ] = mungeSorter( sorter );
9108    }
9109  };
9110
9111  /**
9112   * @params {Array} items - of Isotope.Items
9113   * @private
9114   */
9115  proto._updateItemsSortData = function( items ) {
9116    // do not update if no items
9117    var len = items && items.length;
9118
9119    for ( var i=0; len && i < len; i++ ) {
9120      var item = items[i];
9121      item.updateSortData();
9122    }
9123  };
9124
9125  // ----- munge sorter ----- //
9126
9127  // encapsulate this, as we just need mungeSorter
9128  // other functions in here are just for munging
9129  var mungeSorter = ( function() {
9130    // add a magic layer to sorters for convienent shorthands
9131    // `.foo-bar` will use the text of .foo-bar querySelector
9132    // `[foo-bar]` will use attribute
9133    // you can also add parser
9134    // `.foo-bar parseInt` will parse that as a number
9135    function mungeSorter( sorter ) {
9136      // if not a string, return function or whatever it is
9137      if ( typeof sorter != 'string' ) {
9138        return sorter;
9139      }
9140      // parse the sorter string
9141      var args = trim( sorter ).split(' ');
9142      var query = args[0];
9143      // check if query looks like [an-attribute]
9144      var attrMatch = query.match( /^\[(.+)\]$/ );
9145      var attr = attrMatch && attrMatch[1];
9146      var getValue = getValueGetter( attr, query );
9147      // use second argument as a parser
9148      var parser = Isotope.sortDataParsers[ args[1] ];
9149      // parse the value, if there was a parser
9150      sorter = parser ? function( elem ) {
9151        return elem && parser( getValue( elem ) );
9152      } :
9153      // otherwise just return value
9154      function( elem ) {
9155        return elem && getValue( elem );
9156      };
9157
9158      return sorter;
9159    }
9160
9161    // get an attribute getter, or get text of the querySelector
9162    function getValueGetter( attr, query ) {
9163      // if query looks like [foo-bar], get attribute
9164      if ( attr ) {
9165        return function getAttribute( elem ) {
9166          return elem.getAttribute( attr );
9167        };
9168      }
9169
9170      // otherwise, assume its a querySelector, and get its text
9171      return function getChildText( elem ) {
9172        var child = elem.querySelector( query );
9173        return child && child.textContent;
9174      };
9175    }
9176
9177    return mungeSorter;
9178  })();
9179
9180  // parsers used in getSortData shortcut strings
9181  Isotope.sortDataParsers = {
9182    'parseInt': function( val ) {
9183      return parseInt( val, 10 );
9184    },
9185    'parseFloat': function( val ) {
9186      return parseFloat( val );
9187    }
9188  };
9189
9190  // ----- sort method ----- //
9191
9192  // sort filteredItem order
9193  proto._sort = function() {
9194    if ( !this.options.sortBy ) {
9195      return;
9196    }
9197    // keep track of sortBy History
9198    var sortBys = utils.makeArray( this.options.sortBy );
9199    if ( !this._getIsSameSortBy( sortBys ) ) {
9200      // concat all sortBy and sortHistory, add to front, oldest goes in last
9201      this.sortHistory = sortBys.concat( this.sortHistory );
9202    }
9203    // sort magic
9204    var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending );
9205    this.filteredItems.sort( itemSorter );
9206  };
9207
9208  // check if sortBys is same as start of sortHistory
9209  proto._getIsSameSortBy = function( sortBys ) {
9210    for ( var i=0; i < sortBys.length; i++ ) {
9211      if ( sortBys[i] != this.sortHistory[i] ) {
9212        return false;
9213      }
9214    }
9215    return true;
9216  };
9217
9218  // returns a function used for sorting
9219  function getItemSorter( sortBys, sortAsc ) {
9220    return function sorter( itemA, itemB ) {
9221      // cycle through all sortKeys
9222      for ( var i = 0; i < sortBys.length; i++ ) {
9223        var sortBy = sortBys[i];
9224        var a = itemA.sortData[ sortBy ];
9225        var b = itemB.sortData[ sortBy ];
9226        if ( a > b || a < b ) {
9227          // if sortAsc is an object, use the value given the sortBy key
9228          var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc;
9229          var direction = isAscending ? 1 : -1;
9230          return ( a > b ? 1 : -1 ) * direction;
9231        }
9232      }
9233      return 0;
9234    };
9235  }
9236
9237  // -------------------------- methods -------------------------- //
9238
9239  // get layout mode
9240  proto._mode = function() {
9241    var layoutMode = this.options.layoutMode;
9242    var mode = this.modes[ layoutMode ];
9243    if ( !mode ) {
9244      // TODO console.error
9245      throw new Error( 'No layout mode: ' + layoutMode );
9246    }
9247    // HACK sync mode's options
9248    // any options set after init for layout mode need to be synced
9249    mode.options = this.options[ layoutMode ];
9250    return mode;
9251  };
9252
9253  proto._resetLayout = function() {
9254    // trigger original reset layout
9255    Outlayer.prototype._resetLayout.call( this );
9256    this._mode()._resetLayout();
9257  };
9258
9259  proto._getItemLayoutPosition = function( item  ) {
9260    return this._mode()._getItemLayoutPosition( item );
9261  };
9262
9263  proto._manageStamp = function( stamp ) {
9264    this._mode()._manageStamp( stamp );
9265  };
9266
9267  proto._getContainerSize = function() {
9268    return this._mode()._getContainerSize();
9269  };
9270
9271  proto.needsResizeLayout = function() {
9272    return this._mode().needsResizeLayout();
9273  };
9274
9275  // -------------------------- adding & removing -------------------------- //
9276
9277  // HEADS UP overwrites default Outlayer appended
9278  proto.appended = function( elems ) {
9279    var items = this.addItems( elems );
9280    if ( !items.length ) {
9281      return;
9282    }
9283    // filter, layout, reveal new items
9284    var filteredItems = this._filterRevealAdded( items );
9285    // add to filteredItems
9286    this.filteredItems = this.filteredItems.concat( filteredItems );
9287  };
9288
9289  // HEADS UP overwrites default Outlayer prepended
9290  proto.prepended = function( elems ) {
9291    var items = this._itemize( elems );
9292    if ( !items.length ) {
9293      return;
9294    }
9295    // start new layout
9296    this._resetLayout();
9297    this._manageStamps();
9298    // filter, layout, reveal new items
9299    var filteredItems = this._filterRevealAdded( items );
9300    // layout previous items
9301    this.layoutItems( this.filteredItems );
9302    // add to items and filteredItems
9303    this.filteredItems = filteredItems.concat( this.filteredItems );
9304    this.items = items.concat( this.items );
9305  };
9306
9307  proto._filterRevealAdded = function( items ) {
9308    var filtered = this._filter( items );
9309    this.hide( filtered.needHide );
9310    // reveal all new items
9311    this.reveal( filtered.matches );
9312    // layout new items, no transition
9313    this.layoutItems( filtered.matches, true );
9314    return filtered.matches;
9315  };
9316
9317  /**
9318   * Filter, sort, and layout newly-appended item elements
9319   * @param {Array or NodeList or Element} elems
9320   */
9321  proto.insert = function( elems ) {
9322    var items = this.addItems( elems );
9323    if ( !items.length ) {
9324      return;
9325    }
9326    // append item elements
9327    var i, item;
9328    var len = items.length;
9329    for ( i=0; i < len; i++ ) {
9330      item = items[i];
9331      this.element.appendChild( item.element );
9332    }
9333    // filter new stuff
9334    var filteredInsertItems = this._filter( items ).matches;
9335    // set flag
9336    for ( i=0; i < len; i++ ) {
9337      items[i].isLayoutInstant = true;
9338    }
9339    this.arrange();
9340    // reset flag
9341    for ( i=0; i < len; i++ ) {
9342      delete items[i].isLayoutInstant;
9343    }
9344    this.reveal( filteredInsertItems );
9345  };
9346
9347  var _remove = proto.remove;
9348  proto.remove = function( elems ) {
9349    elems = utils.makeArray( elems );
9350    var removeItems = this.getItems( elems );
9351    // do regular thing
9352    _remove.call( this, elems );
9353    // bail if no items to remove
9354    var len = removeItems && removeItems.length;
9355    // remove elems from filteredItems
9356    for ( var i=0; len && i < len; i++ ) {
9357      var item = removeItems[i];
9358      // remove item from collection
9359      utils.removeFrom( this.filteredItems, item );
9360    }
9361  };
9362
9363  proto.shuffle = function() {
9364    // update random sortData
9365    for ( var i=0; i < this.items.length; i++ ) {
9366      var item = this.items[i];
9367      item.sortData.random = Math.random();
9368    }
9369    this.options.sortBy = 'random';
9370    this._sort();
9371    this._layout();
9372  };
9373
9374  /**
9375   * trigger fn without transition
9376   * kind of hacky to have this in the first place
9377   * @param {Function} fn
9378   * @param {Array} args
9379   * @returns ret
9380   * @private
9381   */
9382  proto._noTransition = function( fn, args ) {
9383    // save transitionDuration before disabling
9384    var transitionDuration = this.options.transitionDuration;
9385    // disable transition
9386    this.options.transitionDuration = 0;
9387    // do it
9388    var returnValue = fn.apply( this, args );
9389    // re-enable transition for reveal
9390    this.options.transitionDuration = transitionDuration;
9391    return returnValue;
9392  };
9393
9394  // ----- helper methods ----- //
9395
9396  /**
9397   * getter method for getting filtered item elements
9398   * @returns {Array} elems - collection of item elements
9399   */
9400  proto.getFilteredItemElements = function() {
9401    return this.filteredItems.map( function( item ) {
9402      return item.element;
9403    });
9404  };
9405
9406  // -----  ----- //
9407
9408  return Isotope;
9409
9410}));
9411
vendor: 29,252 bytes, lines 9412-10568
9412/*!
9413 * Packery layout mode PACKAGED v2.0.1
9414 * sub-classes Packery
9415 */
9416
9417/**
9418 * Rect
9419 * low-level utility class for basic geometry
9420 */
9421
9422( function( window, factory ) {
9423  // universal module definition
9424  /* jshint strict: false */ /* globals define, module */
9425  if ( typeof define == 'function' && define.amd ) {
9426    // AMD
9427    define( 'packery/js/rect',factory );
9428  } else if ( typeof module == 'object' && module.exports ) {
9429    // CommonJS
9430    module.exports = factory();
9431  } else {
9432    // browser global
9433    window.Packery = window.Packery || {};
9434    window.Packery.Rect = factory();
9435  }
9436
9437}( window, function factory() {
9438
9439
9440// -------------------------- Rect -------------------------- //
9441
9442function Rect( props ) {
9443  // extend properties from defaults
9444  for ( var prop in Rect.defaults ) {
9445    this[ prop ] = Rect.defaults[ prop ];
9446  }
9447
9448  for ( prop in props ) {
9449    this[ prop ] = props[ prop ];
9450  }
9451
9452}
9453
9454Rect.defaults = {
9455  x: 0,
9456  y: 0,
9457  width: 0,
9458  height: 0
9459};
9460
9461var proto = Rect.prototype;
9462
9463/**
9464 * Determines whether or not this rectangle wholly encloses another rectangle or point.
9465 * @param {Rect} rect
9466 * @returns {Boolean}
9467**/
9468proto.contains = function( rect ) {
9469  // points don't have width or height
9470  var otherWidth = rect.width || 0;
9471  var otherHeight = rect.height || 0;
9472  return this.x <= rect.x &&
9473    this.y <= rect.y &&
9474    this.x + this.width >= rect.x + otherWidth &&
9475    this.y + this.height >= rect.y + otherHeight;
9476};
9477
9478/**
9479 * Determines whether or not the rectangle intersects with another.
9480 * @param {Rect} rect
9481 * @returns {Boolean}
9482**/
9483proto.overlaps = function( rect ) {
9484  var thisRight = this.x + this.width;
9485  var thisBottom = this.y + this.height;
9486  var rectRight = rect.x + rect.width;
9487  var rectBottom = rect.y + rect.height;
9488
9489  // http://stackoverflow.com/a/306332
9490  return this.x < rectRight &&
9491    thisRight > rect.x &&
9492    this.y < rectBottom &&
9493    thisBottom > rect.y;
9494};
9495
9496/**
9497 * @param {Rect} rect - the overlapping rect
9498 * @returns {Array} freeRects - rects representing the area around the rect
9499**/
9500proto.getMaximalFreeRects = function( rect ) {
9501
9502  // if no intersection, return false
9503  if ( !this.overlaps( rect ) ) {
9504    return false;
9505  }
9506
9507  var freeRects = [];
9508  var freeRect;
9509
9510  var thisRight = this.x + this.width;
9511  var thisBottom = this.y + this.height;
9512  var rectRight = rect.x + rect.width;
9513  var rectBottom = rect.y + rect.height;
9514
9515  // top
9516  if ( this.y < rect.y ) {
9517    freeRect = new Rect({
9518      x: this.x,
9519      y: this.y,
9520      width: this.width,
9521      height: rect.y - this.y
9522    });
9523    freeRects.push( freeRect );
9524  }
9525
9526  // right
9527  if ( thisRight > rectRight ) {
9528    freeRect = new Rect({
9529      x: rectRight,
9530      y: this.y,
9531      width: thisRight - rectRight,
9532      height: this.height
9533    });
9534    freeRects.push( freeRect );
9535  }
9536
9537  // bottom
9538  if ( thisBottom > rectBottom ) {
9539    freeRect = new Rect({
9540      x: this.x,
9541      y: rectBottom,
9542      width: this.width,
9543      height: thisBottom - rectBottom
9544    });
9545    freeRects.push( freeRect );
9546  }
9547
9548  // left
9549  if ( this.x < rect.x ) {
9550    freeRect = new Rect({
9551      x: this.x,
9552      y: this.y,
9553      width: rect.x - this.x,
9554      height: this.height
9555    });
9556    freeRects.push( freeRect );
9557  }
9558
9559  return freeRects;
9560};
9561
9562proto.canFit = function( rect ) {
9563  return this.width >= rect.width && this.height >= rect.height;
9564};
9565
9566return Rect;
9567
9568}));
9569
9570/**
9571 * Packer
9572 * bin-packing algorithm
9573 */
9574
9575( function( window, factory ) {
9576  // universal module definition
9577  /* jshint strict: false */ /* globals define, module, require */
9578  if ( typeof define == 'function' && define.amd ) {
9579    // AMD
9580    define( 'packery/js/packer',[ './rect' ], factory );
9581  } else if ( typeof module == 'object' && module.exports ) {
9582    // CommonJS
9583    module.exports = factory(
9584      require('./rect')
9585    );
9586  } else {
9587    // browser global
9588    var Packery = window.Packery = window.Packery || {};
9589    Packery.Packer = factory( Packery.Rect );
9590  }
9591
9592}( window, function factory( Rect ) {
9593
9594
9595// -------------------------- Packer -------------------------- //
9596
9597/**
9598 * @param {Number} width
9599 * @param {Number} height
9600 * @param {String} sortDirection
9601 *   topLeft for vertical, leftTop for horizontal
9602 */
9603function Packer( width, height, sortDirection ) {
9604  this.width = width || 0;
9605  this.height = height || 0;
9606  this.sortDirection = sortDirection || 'downwardLeftToRight';
9607
9608  this.reset();
9609}
9610
9611var proto = Packer.prototype;
9612
9613proto.reset = function() {
9614  this.spaces = [];
9615
9616  var initialSpace = new Rect({
9617    x: 0,
9618    y: 0,
9619    width: this.width,
9620    height: this.height
9621  });
9622
9623  this.spaces.push( initialSpace );
9624  // set sorter
9625  this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight;
9626};
9627
9628// change x and y of rect to fit with in Packer's available spaces
9629proto.pack = function( rect ) {
9630  for ( var i=0; i < this.spaces.length; i++ ) {
9631    var space = this.spaces[i];
9632    if ( space.canFit( rect ) ) {
9633      this.placeInSpace( rect, space );
9634      break;
9635    }
9636  }
9637};
9638
9639proto.columnPack = function( rect ) {
9640  for ( var i=0; i < this.spaces.length; i++ ) {
9641    var space = this.spaces[i];
9642    var canFitInSpaceColumn = space.x <= rect.x &&
9643      space.x + space.width >= rect.x + rect.width &&
9644      space.height >= rect.height - 0.01; // fudge number for rounding error
9645    if ( canFitInSpaceColumn ) {
9646      rect.y = space.y;
9647      this.placed( rect );
9648      break;
9649    }
9650  }
9651};
9652
9653proto.rowPack = function( rect ) {
9654  for ( var i=0; i < this.spaces.length; i++ ) {
9655    var space = this.spaces[i];
9656    var canFitInSpaceRow = space.y <= rect.y &&
9657      space.y + space.height >= rect.y + rect.height &&
9658      space.width >= rect.width - 0.01; // fudge number for rounding error
9659    if ( canFitInSpaceRow ) {
9660      rect.x = space.x;
9661      this.placed( rect );
9662      break;
9663    }
9664  }
9665};
9666
9667proto.placeInSpace = function( rect, space ) {
9668  // place rect in space
9669  rect.x = space.x;
9670  rect.y = space.y;
9671
9672  this.placed( rect );
9673};
9674
9675// update spaces with placed rect
9676proto.placed = function( rect ) {
9677  // update spaces
9678  var revisedSpaces = [];
9679  for ( var i=0; i < this.spaces.length; i++ ) {
9680    var space = this.spaces[i];
9681    var newSpaces = space.getMaximalFreeRects( rect );
9682    // add either the original space or the new spaces to the revised spaces
9683    if ( newSpaces ) {
9684      revisedSpaces.push.apply( revisedSpaces, newSpaces );
9685    } else {
9686      revisedSpaces.push( space );
9687    }
9688  }
9689
9690  this.spaces = revisedSpaces;
9691
9692  this.mergeSortSpaces();
9693};
9694
9695proto.mergeSortSpaces = function() {
9696  // remove redundant spaces
9697  Packer.mergeRects( this.spaces );
9698  this.spaces.sort( this.sorter );
9699};
9700
9701// add a space back
9702proto.addSpace = function( rect ) {
9703  this.spaces.push( rect );
9704  this.mergeSortSpaces();
9705};
9706
9707// -------------------------- utility functions -------------------------- //
9708
9709/**
9710 * Remove redundant rectangle from array of rectangles
9711 * @param {Array} rects: an array of Rects
9712 * @returns {Array} rects: an array of Rects
9713**/
9714Packer.mergeRects = function( rects ) {
9715  var i = 0;
9716  var rect = rects[i];
9717
9718  rectLoop:
9719  while ( rect ) {
9720    var j = 0;
9721    var compareRect = rects[ i + j ];
9722
9723    while ( compareRect ) {
9724      if  ( compareRect == rect ) {
9725        j++; // next
9726      } else if ( compareRect.contains( rect ) ) {
9727        // remove rect
9728        rects.splice( i, 1 );
9729        rect = rects[i]; // set next rect
9730        continue rectLoop; // bail on compareLoop
9731      } else if ( rect.contains( compareRect ) ) {
9732        // remove compareRect
9733        rects.splice( i + j, 1 );
9734      } else {
9735        j++;
9736      }
9737      compareRect = rects[ i + j ]; // set next compareRect
9738    }
9739    i++;
9740    rect = rects[i];
9741  }
9742
9743  return rects;
9744};
9745
9746
9747// -------------------------- sorters -------------------------- //
9748
9749// functions for sorting rects in order
9750var sorters = {
9751  // top down, then left to right
9752  downwardLeftToRight: function( a, b ) {
9753    return a.y - b.y || a.x - b.x;
9754  },
9755  // left to right, then top down
9756  rightwardTopToBottom: function( a, b ) {
9757    return a.x - b.x || a.y - b.y;
9758  }
9759};
9760
9761
9762// --------------------------  -------------------------- //
9763
9764return Packer;
9765
9766}));
9767
9768/**
9769 * Packery Item Element
9770**/
9771
9772( function( window, factory ) {
9773  // universal module definition
9774  /* jshint strict: false */ /* globals define, module, require */
9775  if ( typeof define == 'function' && define.amd ) {
9776    // AMD
9777    define( 'packery/js/item',[
9778        'outlayer/outlayer',
9779        './rect'
9780      ],
9781      factory );
9782  } else if ( typeof module == 'object' && module.exports ) {
9783    // CommonJS
9784    module.exports = factory(
9785      require('outlayer'),
9786      require('./rect')
9787    );
9788  } else {
9789    // browser global
9790    window.Packery.Item = factory(
9791      window.Outlayer,
9792      window.Packery.Rect
9793    );
9794  }
9795
9796}( window, function factory( Outlayer, Rect ) {
9797
9798
9799// -------------------------- Item -------------------------- //
9800
9801var docElemStyle = document.documentElement.style;
9802
9803var transformProperty = typeof docElemStyle.transform == 'string' ?
9804  'transform' : 'WebkitTransform';
9805
9806// sub-class Item
9807var Item = function PackeryItem() {
9808  Outlayer.Item.apply( this, arguments );
9809};
9810
9811var proto = Item.prototype = Object.create( Outlayer.Item.prototype );
9812
9813var __create = proto._create;
9814proto._create = function() {
9815  // call default _create logic
9816  __create.call( this );
9817  this.rect = new Rect();
9818};
9819
9820var _moveTo = proto.moveTo;
9821proto.moveTo = function( x, y ) {
9822  // don't shift 1px while dragging
9823  var dx = Math.abs( this.position.x - x );
9824  var dy = Math.abs( this.position.y - y );
9825
9826  var canHackGoTo = this.layout.dragItemCount && !this.isPlacing &&
9827    !this.isTransitioning && dx < 1 && dy < 1;
9828  if ( canHackGoTo ) {
9829    this.goTo( x, y );
9830    return;
9831  }
9832  _moveTo.apply( this, arguments );
9833};
9834
9835// -------------------------- placing -------------------------- //
9836
9837proto.enablePlacing = function() {
9838  this.removeTransitionStyles();
9839  // remove transform property from transition
9840  if ( this.isTransitioning && transformProperty ) {
9841    this.element.style[ transformProperty ] = 'none';
9842  }
9843  this.isTransitioning = false;
9844  this.getSize();
9845  this.layout._setRectSize( this.element, this.rect );
9846  this.isPlacing = true;
9847};
9848
9849proto.disablePlacing = function() {
9850  this.isPlacing = false;
9851};
9852
9853// -----  ----- //
9854
9855// remove element from DOM
9856proto.removeElem = function() {
9857  this.element.parentNode.removeChild( this.element );
9858  // add space back to packer
9859  this.layout.packer.addSpace( this.rect );
9860  this.emitEvent( 'remove', [ this ] );
9861};
9862
9863// ----- dropPlaceholder ----- //
9864
9865proto.showDropPlaceholder = function() {
9866  var dropPlaceholder = this.dropPlaceholder;
9867  if ( !dropPlaceholder ) {
9868    // create dropPlaceholder
9869    dropPlaceholder = this.dropPlaceholder = document.createElement('div');
9870    dropPlaceholder.className = 'packery-drop-placeholder';
9871    dropPlaceholder.style.position = 'absolute';
9872  }
9873
9874  dropPlaceholder.style.width = this.size.width + 'px';
9875  dropPlaceholder.style.height = this.size.height + 'px';
9876  this.positionDropPlaceholder();
9877  this.layout.element.appendChild( dropPlaceholder );
9878};
9879
9880proto.positionDropPlaceholder = function() {
9881  this.dropPlaceholder.style[ transformProperty ] = 'translate(' +
9882    this.rect.x + 'px, ' + this.rect.y + 'px)';
9883};
9884
9885proto.hideDropPlaceholder = function() {
9886  this.layout.element.removeChild( this.dropPlaceholder );
9887};
9888
9889// -----  ----- //
9890
9891return Item;
9892
9893}));
9894
9895/*!
9896 * Packery v2.0.0
9897 * Gapless, draggable grid layouts
9898 *
9899 * Licensed GPLv3 for open source use
9900 * or Packery Commercial License for commercial use
9901 *
9902 * http://packery.metafizzy.co
9903 * Copyright 2016 Metafizzy
9904 */
9905
9906( function( window, factory ) {
9907  // universal module definition
9908  /* jshint strict: false */ /* globals define, module, require */
9909  if ( typeof define == 'function' && define.amd ) {
9910    // AMD
9911    define( 'packery/js/packery',[
9912        'get-size/get-size',
9913        'outlayer/outlayer',
9914        './rect',
9915        './packer',
9916        './item'
9917      ],
9918      factory );
9919  } else if ( typeof module == 'object' && module.exports ) {
9920    // CommonJS
9921    module.exports = factory(
9922      require('get-size'),
9923      require('outlayer'),
9924      require('./rect'),
9925      require('./packer'),
9926      require('./item')
9927    );
9928  } else {
9929    // browser global
9930    window.Packery = factory(
9931      window.getSize,
9932      window.Outlayer,
9933      window.Packery.Rect,
9934      window.Packery.Packer,
9935      window.Packery.Item
9936    );
9937  }
9938
9939}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) {
9940
9941
9942// ----- Rect ----- //
9943
9944// allow for pixel rounding errors IE8-IE11 & Firefox; #227
9945Rect.prototype.canFit = function( rect ) {
9946  return this.width >= rect.width - 1 && this.height >= rect.height - 1;
9947};
9948
9949// -------------------------- Packery -------------------------- //
9950
9951// create an Outlayer layout class
9952var Packery = Outlayer.create('packery');
9953Packery.Item = Item;
9954
9955var proto = Packery.prototype;
9956
9957proto._create = function() {
9958  // call super
9959  Outlayer.prototype._create.call( this );
9960
9961  // initial properties
9962  this.packer = new Packer();
9963  // packer for drop targets
9964  this.shiftPacker = new Packer();
9965  this.isEnabled = true;
9966
9967  this.dragItemCount = 0;
9968
9969  // create drag handlers
9970  var _this = this;
9971  this.handleDraggabilly = {
9972    dragStart: function() {
9973      _this.itemDragStart( this.element );
9974    },
9975    dragMove: function() {
9976      _this.itemDragMove( this.element, this.position.x, this.position.y );
9977    },
9978    dragEnd: function() {
9979      _this.itemDragEnd( this.element );
9980    }
9981  };
9982
9983  this.handleUIDraggable = {
9984    start: function handleUIDraggableStart( event, ui ) {
9985      // HTML5 may trigger dragstart, dismiss HTML5 dragging
9986      if ( !ui ) {
9987        return;
9988      }
9989      _this.itemDragStart( event.currentTarget );
9990    },
9991    drag: function handleUIDraggableDrag( event, ui ) {
9992      if ( !ui ) {
9993        return;
9994      }
9995      _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top );
9996    },
9997    stop: function handleUIDraggableStop( event, ui ) {
9998      if ( !ui ) {
9999        return;
10000      }
10001      _this.itemDragEnd( event.currentTarget );
10002    }
10003  };
10004
10005};
10006
10007
10008// ----- init & layout ----- //
10009
10010/**
10011 * logic before any new layout
10012 */
10013proto._resetLayout = function() {
10014  this.getSize();
10015
10016  this._getMeasurements();
10017
10018  // reset packer
10019  var width, height, sortDirection;
10020  // packer settings, if horizontal or vertical
10021  if ( this._getOption('horizontal') ) {
10022    width = Infinity;
10023    height = this.size.innerHeight + this.gutter;
10024    sortDirection = 'rightwardTopToBottom';
10025  } else {
10026    width = this.size.innerWidth + this.gutter;
10027    height = Infinity;
10028    sortDirection = 'downwardLeftToRight';
10029  }
10030
10031  this.packer.width = this.shiftPacker.width = width;
10032  this.packer.height = this.shiftPacker.height = height;
10033  this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection;
10034
10035  this.packer.reset();
10036
10037  // layout
10038  this.maxY = 0;
10039  this.maxX = 0;
10040};
10041
10042/**
10043 * update columnWidth, rowHeight, & gutter
10044 * @private
10045 */
10046proto._getMeasurements = function() {
10047  this._getMeasurement( 'columnWidth', 'width' );
10048  this._getMeasurement( 'rowHeight', 'height' );
10049  this._getMeasurement( 'gutter', 'width' );
10050};
10051
10052proto._getItemLayoutPosition = function( item ) {
10053  this._setRectSize( item.element, item.rect );
10054  if ( this.isShifting || this.dragItemCount > 0 ) {
10055    var packMethod = this._getPackMethod();
10056    this.packer[ packMethod ]( item.rect );
10057  } else {
10058    this.packer.pack( item.rect );
10059  }
10060
10061  this._setMaxXY( item.rect );
10062  return item.rect;
10063};
10064
10065proto.shiftLayout = function() {
10066  this.isShifting = true;
10067  this.layout();
10068  delete this.isShifting;
10069};
10070
10071proto._getPackMethod = function() {
10072  return this._getOption('horizontal') ? 'rowPack' : 'columnPack';
10073};
10074
10075
10076/**
10077 * set max X and Y value, for size of container
10078 * @param {Packery.Rect} rect
10079 * @private
10080 */
10081proto._setMaxXY = function( rect ) {
10082  this.maxX = Math.max( rect.x + rect.width, this.maxX );
10083  this.maxY = Math.max( rect.y + rect.height, this.maxY );
10084};
10085
10086/**
10087 * set the width and height of a rect, applying columnWidth and rowHeight
10088 * @param {Element} elem
10089 * @param {Packery.Rect} rect
10090 */
10091proto._setRectSize = function( elem, rect ) {
10092  var size = getSize( elem );
10093  var w = size.outerWidth;
10094  var h = size.outerHeight;
10095  // size for columnWidth and rowHeight, if available
10096  // only check if size is non-zero, #177
10097  if ( w || h ) {
10098    w = this._applyGridGutter( w, this.columnWidth );
10099    h = this._applyGridGutter( h, this.rowHeight );
10100  }
10101  // rect must fit in packer
10102  rect.width = Math.min( w, this.packer.width );
10103  rect.height = Math.min( h, this.packer.height );
10104};
10105
10106/**
10107 * fits item to columnWidth/rowHeight and adds gutter
10108 * @param {Number} measurement - item width or height
10109 * @param {Number} gridSize - columnWidth or rowHeight
10110 * @returns measurement
10111 */
10112proto._applyGridGutter = function( measurement, gridSize ) {
10113  // just add gutter if no gridSize
10114  if ( !gridSize ) {
10115    return measurement + this.gutter;
10116  }
10117  gridSize += this.gutter;
10118  // fit item to columnWidth/rowHeight
10119  var remainder = measurement % gridSize;
10120  var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil';
10121  measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize;
10122  return measurement;
10123};
10124
10125proto._getContainerSize = function() {
10126  if ( this._getOption('horizontal') ) {
10127    return {
10128      width: this.maxX - this.gutter
10129    };
10130  } else {
10131    return {
10132      height: this.maxY - this.gutter
10133    };
10134  }
10135};
10136
10137
10138// -------------------------- stamp -------------------------- //
10139
10140/**
10141 * makes space for element
10142 * @param {Element} elem
10143 */
10144proto._manageStamp = function( elem ) {
10145
10146  var item = this.getItem( elem );
10147  var rect;
10148  if ( item && item.isPlacing ) {
10149    rect = item.rect;
10150  } else {
10151    var offset = this._getElementOffset( elem );
10152    rect = new Rect({
10153      x: this._getOption('originLeft') ? offset.left : offset.right,
10154      y: this._getOption('originTop') ? offset.top : offset.bottom
10155    });
10156  }
10157
10158  this._setRectSize( elem, rect );
10159  // save its space in the packer
10160  this.packer.placed( rect );
10161  this._setMaxXY( rect );
10162};
10163
10164// -------------------------- methods -------------------------- //
10165
10166function verticalSorter( a, b ) {
10167  return a.position.y - b.position.y || a.position.x - b.position.x;
10168}
10169
10170function horizontalSorter( a, b ) {
10171  return a.position.x - b.position.x || a.position.y - b.position.y;
10172}
10173
10174proto.sortItemsByPosition = function() {
10175  var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter;
10176  this.items.sort( sorter );
10177};
10178
10179/**
10180 * Fit item element in its current position
10181 * Packery will position elements around it
10182 * useful for expanding elements
10183 *
10184 * @param {Element} elem
10185 * @param {Number} x - horizontal destination position, optional
10186 * @param {Number} y - vertical destination position, optional
10187 */
10188proto.fit = function( elem, x, y ) {
10189  var item = this.getItem( elem );
10190  if ( !item ) {
10191    return;
10192  }
10193
10194  // stamp item to get it out of layout
10195  this.stamp( item.element );
10196  // set placing flag
10197  item.enablePlacing();
10198  this.updateShiftTargets( item );
10199  // fall back to current position for fitting
10200  x = x === undefined ? item.rect.x: x;
10201  y = y === undefined ? item.rect.y: y;
10202  // position it best at its destination
10203  this.shift( item, x, y );
10204  this._bindFitEvents( item );
10205  item.moveTo( item.rect.x, item.rect.y );
10206  // layout everything else
10207  this.shiftLayout();
10208  // return back to regularly scheduled programming
10209  this.unstamp( item.element );
10210  this.sortItemsByPosition();
10211  item.disablePlacing();
10212};
10213
10214/**
10215 * emit event when item is fit and other items are laid out
10216 * @param {Packery.Item} item
10217 * @private
10218 */
10219proto._bindFitEvents = function( item ) {
10220  var _this = this;
10221  var ticks = 0;
10222  function onLayout() {
10223    ticks++;
10224    if ( ticks != 2 ) {
10225      return;
10226    }
10227    _this.dispatchEvent( 'fitComplete', null, [ item ] );
10228  }
10229  // when item is laid out
10230  item.once( 'layout', onLayout );
10231  // when all items are laid out
10232  this.once( 'layoutComplete', onLayout );
10233};
10234
10235// -------------------------- resize -------------------------- //
10236
10237// debounced, layout on resize
10238proto.resize = function() {
10239  // don't trigger if size did not change
10240  // or if resize was unbound. See #285, outlayer#9
10241  if ( !this.isResizeBound || !this.needsResizeLayout() ) {
10242    return;
10243  }
10244
10245  if ( this.options.shiftPercentResize ) {
10246    this.resizeShiftPercentLayout();
10247  } else {
10248    this.layout();
10249  }
10250};
10251
10252/**
10253 * check if layout is needed post layout
10254 * @returns Boolean
10255 */
10256proto.needsResizeLayout = function() {
10257  var size = getSize( this.element );
10258  var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth';
10259  return size[ innerSize ] != this.size[ innerSize ];
10260};
10261
10262proto.resizeShiftPercentLayout = function() {
10263  var items = this._getItemsForLayout( this.items );
10264
10265  var isHorizontal = this._getOption('horizontal');
10266  var coord = isHorizontal ? 'y' : 'x';
10267  var measure = isHorizontal ? 'height' : 'width';
10268  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
10269  var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth';
10270
10271  // proportional re-align items
10272  var previousSegment = this[ segmentName ];
10273  previousSegment = previousSegment && previousSegment + this.gutter;
10274
10275  if ( previousSegment ) {
10276    this._getMeasurements();
10277    var currentSegment = this[ segmentName ] + this.gutter;
10278    items.forEach( function( item ) {
10279      var seg = Math.round( item.rect[ coord ] / previousSegment );
10280      item.rect[ coord ] = seg * currentSegment;
10281    });
10282  } else {
10283    var currentSize = getSize( this.element )[ innerSize ] + this.gutter;
10284    var previousSize = this.packer[ measure ];
10285    items.forEach( function( item ) {
10286      item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize;
10287    });
10288  }
10289
10290  this.shiftLayout();
10291};
10292
10293// -------------------------- drag -------------------------- //
10294
10295/**
10296 * handle an item drag start event
10297 * @param {Element} elem
10298 */
10299proto.itemDragStart = function( elem ) {
10300  if ( !this.isEnabled ) {
10301    return;
10302  }
10303  this.stamp( elem );
10304  // this.ignore( elem );
10305  var item = this.getItem( elem );
10306  if ( !item ) {
10307    return;
10308  }
10309
10310  item.enablePlacing();
10311  item.showDropPlaceholder();
10312  this.dragItemCount++;
10313  this.updateShiftTargets( item );
10314};
10315
10316proto.updateShiftTargets = function( dropItem ) {
10317  this.shiftPacker.reset();
10318
10319  // pack stamps
10320  this._getBoundingRect();
10321  var isOriginLeft = this._getOption('originLeft');
10322  var isOriginTop = this._getOption('originTop');
10323  this.stamps.forEach( function( stamp ) {
10324    // ignore dragged item
10325    var item = this.getItem( stamp );
10326    if ( item && item.isPlacing ) {
10327      return;
10328    }
10329    var offset = this._getElementOffset( stamp );
10330    var rect = new Rect({
10331      x: isOriginLeft ? offset.left : offset.right,
10332      y: isOriginTop ? offset.top : offset.bottom
10333    });
10334    this._setRectSize( stamp, rect );
10335    // save its space in the packer
10336    this.shiftPacker.placed( rect );
10337  }, this );
10338
10339  // reset shiftTargets
10340  var isHorizontal = this._getOption('horizontal');
10341  var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth';
10342  var measure = isHorizontal ? 'height' : 'width';
10343
10344  this.shiftTargetKeys = [];
10345  this.shiftTargets = [];
10346  var boundsSize;
10347  var segment = this[ segmentName ];
10348  segment = segment && segment + this.gutter;
10349
10350  if ( segment ) {
10351    var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment );
10352    var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment );
10353    boundsSize = ( segs - segmentSpan ) * segment;
10354    // add targets on top
10355    for ( var i=0; i < segs; i++ ) {
10356      this._addShiftTarget( i * segment, 0, boundsSize );
10357    }
10358  } else {
10359    boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ];
10360    this._addShiftTarget( 0, 0, boundsSize );
10361  }
10362
10363  // pack each item to measure where shiftTargets are
10364  var items = this._getItemsForLayout( this.items );
10365  var packMethod = this._getPackMethod();
10366  items.forEach( function( item ) {
10367    var rect = item.rect;
10368    this._setRectSize( item.element, rect );
10369    this.shiftPacker[ packMethod ]( rect );
10370
10371    // add top left corner
10372    this._addShiftTarget( rect.x, rect.y, boundsSize );
10373    // add bottom left / top right corner
10374    var cornerX = isHorizontal ? rect.x + rect.width : rect.x;
10375    var cornerY = isHorizontal ? rect.y : rect.y + rect.height;
10376    this._addShiftTarget( cornerX, cornerY, boundsSize );
10377
10378    if ( segment ) {
10379      // add targets for each column on bottom / row on right
10380      var segSpan = Math.round( rect[ measure ] / segment );
10381      for ( var i=1; i < segSpan; i++ ) {
10382        var segX = isHorizontal ? cornerX : rect.x + segment * i;
10383        var segY = isHorizontal ? rect.y + segment * i : cornerY;
10384        this._addShiftTarget( segX, segY, boundsSize );
10385      }
10386    }
10387  }, this );
10388
10389};
10390
10391proto._addShiftTarget = function( x, y, boundsSize ) {
10392  var checkCoord = this._getOption('horizontal') ? y : x;
10393  if ( checkCoord !== 0 && checkCoord > boundsSize ) {
10394    return;
10395  }
10396  // create string for a key, easier to keep track of what targets
10397  var key = x + ',' + y;
10398  var hasKey = this.shiftTargetKeys.indexOf( key ) != -1;
10399  if ( hasKey ) {
10400    return;
10401  }
10402  this.shiftTargetKeys.push( key );
10403  this.shiftTargets.push({ x: x, y: y });
10404};
10405
10406// -------------------------- drop -------------------------- //
10407
10408proto.shift = function( item, x, y ) {
10409  var shiftPosition;
10410  var minDistance = Infinity;
10411  var position = { x: x, y: y };
10412  this.shiftTargets.forEach( function( target ) {
10413    var distance = getDistance( target, position );
10414    if ( distance < minDistance ) {
10415      shiftPosition = target;
10416      minDistance = distance;
10417    }
10418  });
10419  item.rect.x = shiftPosition.x;
10420  item.rect.y = shiftPosition.y;
10421};
10422
10423function getDistance( a, b ) {
10424  var dx = b.x - a.x;
10425  var dy = b.y - a.y;
10426  return Math.sqrt( dx * dx + dy * dy );
10427}
10428
10429// -------------------------- drag move -------------------------- //
10430
10431var DRAG_THROTTLE_TIME = 120;
10432
10433/**
10434 * handle an item drag move event
10435 * @param {Element} elem
10436 * @param {Number} x - horizontal change in position
10437 * @param {Number} y - vertical change in position
10438 */
10439proto.itemDragMove = function( elem, x, y ) {
10440  var item = this.isEnabled && this.getItem( elem );
10441  if ( !item ) {
10442    return;
10443  }
10444
10445  x -= this.size.paddingLeft;
10446  y -= this.size.paddingTop;
10447
10448  var _this = this;
10449  function onDrag() {
10450    _this.shift( item, x, y );
10451    item.positionDropPlaceholder();
10452    _this.layout();
10453  }
10454
10455  // throttle
10456  var now = new Date();
10457  if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) {
10458    clearTimeout( this.dragTimeout );
10459    this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME );
10460  } else {
10461    onDrag();
10462    this._itemDragTime = now;
10463  }
10464};
10465
10466// -------------------------- drag end -------------------------- //
10467
10468/**
10469 * handle an item drag end event
10470 * @param {Element} elem
10471 */
10472proto.itemDragEnd = function( elem ) {
10473  var item = this.isEnabled && this.getItem( elem );
10474  if ( !item ) {
10475    return;
10476  }
10477
10478  clearTimeout( this.dragTimeout );
10479  item.element.classList.add('is-positioning-post-drag');
10480
10481  var completeCount = 0;
10482  var _this = this;
10483  function onDragEndLayoutComplete() {
10484    completeCount++;
10485    if ( completeCount != 2 ) {
10486      return;
10487    }
10488    // reset drag item
10489    item.element.classList.remove('is-positioning-post-drag');
10490    item.hideDropPlaceholder();
10491    _this.dispatchEvent( 'dragItemPositioned', null, [ item ] );
10492  }
10493
10494  item.once( 'layout', onDragEndLayoutComplete );
10495  this.once( 'layoutComplete', onDragEndLayoutComplete );
10496  item.moveTo( item.rect.x, item.rect.y );
10497  this.layout();
10498  this.dragItemCount = Math.max( 0, this.dragItemCount - 1 );
10499  this.sortItemsByPosition();
10500  item.disablePlacing();
10501  this.unstamp( item.element );
10502};
10503
10504/**
10505 * binds Draggabilly events
10506 * @param {Draggabilly} draggie
10507 */
10508proto.bindDraggabillyEvents = function( draggie ) {
10509  this._bindDraggabillyEvents( draggie, 'on' );
10510};
10511
10512proto.unbindDraggabillyEvents = function( draggie ) {
10513  this._bindDraggabillyEvents( draggie, 'off' );
10514};
10515
10516proto._bindDraggabillyEvents = function( draggie, method ) {
10517  var handlers = this.handleDraggabilly;
10518  draggie[ method ]( 'dragStart', handlers.dragStart );
10519  draggie[ method ]( 'dragMove', handlers.dragMove );
10520  draggie[ method ]( 'dragEnd', handlers.dragEnd );
10521};
10522
10523/**
10524 * binds jQuery UI Draggable events
10525 * @param {jQuery} $elems
10526 */
10527proto.bindUIDraggableEvents = function( $elems ) {
10528  this._bindUIDraggableEvents( $elems, 'on' );
10529};
10530
10531proto.unbindUIDraggableEvents = function( $elems ) {
10532  this._bindUIDraggableEvents( $elems, 'off' );
10533};
10534
10535proto._bindUIDraggableEvents = function( $elems, method ) {
10536  var handlers = this.handleUIDraggable;
10537  $elems
10538    [ method ]( 'dragstart', handlers.start )
10539    [ method ]( 'drag', handlers.drag )
10540    [ method ]( 'dragstop', handlers.stop );
10541};
10542
10543// ----- destroy ----- //
10544
10545var _destroy = proto.destroy;
10546proto.destroy = function() {
10547  _destroy.apply( this, arguments );
10548  // disable flag; prevent drag events from triggering. #72
10549  this.isEnabled = false;
10550};
10551
10552// -----  ----- //
10553
10554Packery.Rect = Rect;
10555Packery.Packer = Packer;
10556
10557return Packery;
10558
10559}));
10560
10561/*!
10562 * Packery layout mode v2.0.1
10563 * sub-classes Packery
10564 */
10565
10566/*jshint browser: true, strict: true, undef: true, unused: true */
10567
10568( function( window, factory ) {
10569
10570  // universal module definition
10571  if ( typeof define == 'function' && define.amd ) {
10572    // AMD
10573    define( [
10574        'isotope-layout/js/layout-mode',
10575        'packery/js/packery'
10576      ],
10577      factory );
10578  } else if ( typeof module == 'object' && module.exports ) {
10579    // CommonJS
10580    module.exports = factory(
10581      require('isotope-layout/js/layout-mode'),
10582      require('packery')
10583    );
10584  } else {
10585    // browser global
10586    factory(
10587      window.Isotope.LayoutMode,
10588      window.Packery
10589    );
10590  }
10591
10592}( window, function factor( LayoutMode, Packery ) {
10593
10594
10595  // create an Outlayer layout class
10596  var PackeryMode = LayoutMode.create('packery');
10597  var proto = PackeryMode.prototype;
10598
10599  var keepModeMethods = {
10600    _getElementOffset: true,
10601    _getMeasurement: true
10602  };
10603
10604  // inherit Packery prototype
10605  for ( var method in Packery.prototype ) {
10606    // do not inherit mode methods
10607    if ( !keepModeMethods[ method ] ) {
10608      proto[ method ] = Packery.prototype[ method ];
10609    }
10610  }
10611
10612  // set packer in _resetLayout
10613  var _resetLayout = proto._resetLayout;
10614  proto._resetLayout = function() {
10615    this.packer = this.packer || new Packery.Packer();
10616    this.shiftPacker = this.shiftPacker || new Packery.Packer();
10617    _resetLayout.apply( this, arguments );
10618  };
10619
10620  var _getItemLayoutPosition = proto._getItemLayoutPosition;
10621  proto._getItemLayoutPosition = function( item ) {
10622    // set packery rect
10623    item.rect = item.rect || new Packery.Rect();
10624    return _getItemLayoutPosition.call( this, item );
10625  };
10626
10627  // needsResizeLayout for vertical or horizontal
10628  var _needsResizeLayout = proto.needsResizeLayout;
10629  proto.needsResizeLayout = function() {
10630    if ( this._getOption('horizontal') ) {
10631      return this.needsVerticalResizeLayout();
10632    } else {
10633      return _needsResizeLayout.call( this );
10634    }
10635  };
10636
10637  // point to mode options for horizontal
10638  var _getOption = proto._getOption;
10639  proto._getOption = function( option ) {
10640    if ( option == 'horizontal' ) {
10641      return this.options.isHorizontal !== undefined ?
10642        this.options.isHorizontal : this.options.horizontal;
10643    }
10644    return _getOption.apply( this.isotope, arguments );
10645  };
10646
10647  return PackeryMode;
10648
10649}));
10650
10651/*!
10652 * cellsByRows layout mode for Isotope
10653 * v1.1.3
10654 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html
10655 */
10656
10657/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */
10658
10659( function( window, factory ) {
10660  // universal module definition
10661  /* jshint strict: false */ /*globals define, module, require */
10662  if ( typeof define === 'function' && define.amd ) {
10663    // AMD
10664    define( [
10665        'isotope/js/layout-mode'
10666      ],
10667      factory );
10668  } else if ( typeof exports === 'object' ) {
10669    // CommonJS
10670    module.exports = factory(
10671      require('isotope-layout/js/layout-mode')
10672    );
10673  } else {
10674    // browser global
10675    factory(
10676      window.Isotope.LayoutMode
10677    );
10678  }
10679
10680}( window, function factory( LayoutMode ) {
10681  'use strict';
10682
10683  var CellsByRow = LayoutMode.create( 'cellsByRow' );
10684  var proto = CellsByRow.prototype;
10685
10686  proto._resetLayout = function() {
10687    // reset properties
10688    this.itemIndex = 0;
10689    // measurements
10690    this.getColumnWidth();
10691    this.getRowHeight();
10692    // set cols
10693    this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth );
10694    this.cols = Math.max( this.cols, 1 );
10695  };
10696
10697  proto._getItemLayoutPosition = function( item ) {
10698    item.getSize();
10699    var col = this.itemIndex % this.cols;
10700    var row = Math.floor( this.itemIndex / this.cols );
10701    // center item within cell
10702    var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2;
10703    var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2;
10704    this.itemIndex++;
10705    return { x: x, y: y };
10706  };
10707
10708  proto._getContainerSize = function() {
10709    return {
10710      height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight
10711    };
10712  };
10713
10714  return CellsByRow;
10715
10716}));
10717/*global jQuery: true */
10718
10719/*!
10720   --------------------------------
10721   Infinite Scroll
10722   --------------------------------
10723   + https://github.com/paulirish/infinite-scroll
10724   + version 2.1.0
10725   + Copyright 2011/12 Paul Irish & Luke Shumard
10726   + Licensed under the MIT license
10727
10728   + Documentation: http://infinite-scroll.com/
10729*/
10730
10731// Uses AMD or browser globals to create a jQuery plugin.
10732(function (factory) {
10733	if (typeof define === 'function' && define.amd) {
10734		// AMD. Register as an anonymous module.
10735		define(['jquery'], factory);
10736	} else {
10737		// Browser globals
10738		factory(jQuery);
10739	}
10740}(function ($, undefined) {
10741	'use strict';
10742
10743	$.infinitescroll = function infscr(options, callback, element) {
10744		this.element = $(element);
10745
10746		// Flag the object in the event of a failed creation
10747		if (!this._create(options, callback)) {
10748			this.failed = true;
10749		}
10750	};
10751
10752	$.infinitescroll.defaults = {
10753		loading: {
10754			finished: undefined,
10755			finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>",
10756			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
10756MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
10756iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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',
10757			msg: null,
10758			msgText: '<em>Loading the next set of posts...</em>',
10759			selector: null,
10760			speed: 'fast',
10761			start: undefined
10762		},
10763		state: {
10764			isDuringAjax: false,
10765			isInvalidPage: false,
10766			isDestroyed: false,
10767			isDone: false, // For when it goes all the way through the archive.
10768			isPaused: false,
10769			isBeyondMaxPage: false,
10770			currPage: 1
10771		},
10772		debug: false,
10773		behavior: undefined,
10774		binder: $(window), // used to cache the selector
10775		nextSelector: 'div.navigation a:first',
10776		navSelector: 'div.navigation',
10777		contentSelector: null, // rename to pageFragment
10778		extraScrollPx: 150,
10779		itemSelector: 'div.post',
10780		animate: false,
10781		pathParse: undefined,
10782		dataType: 'html',
10783		appendCallback: true,
10784		bufferPx: 40,
10785		errorCallback: function () { },
10786		infid: 0, //Instance ID
10787		pixelsFromNavToBottom: undefined,
10788		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
10789		prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted
10790		maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work)
10791	};
10792
10793	$.infinitescroll.prototype = {
10794
10795		/*
10796			----------------------------
10797			Private methods
10798			----------------------------
10799			*/
10800
10801		// Bind or unbind from scroll
10802		_binding: function infscr_binding(binding) {
10803
10804			var instance = this,
10805				opts = instance.options;
10806
10807			opts.v = '2.0b2.120520';
10808
10809			// if behavior is defined and this function is extended, call that instead of default
10810			if (!!opts.behavior && this['_binding_' + opts.behavior] !== undefined) {
10811				this['_binding_' + opts.behavior].call(this);
10812				return;
10813			}
10814
10815			if (binding !== 'bind' && binding !== 'unbind') {
10816				this._debug('Binding value  ' + binding + ' not valid');
10817				return false;
10818			}
10819
10820			if (binding === 'unbind') {
10821				(this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid);
10822			} else {
10823				(this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () {
10824					instance.scroll();
10825				});
10826			}
10827
10828			this._debug('Binding', binding);
10829		},
10830
10831		// Fundamental aspects of the plugin are initialized
10832		_create: function infscr_create(options, callback) {
10833
10834			// Add custom options to defaults
10835			var opts = $.extend(true, {}, $.infinitescroll.defaults, options);
10836			this.options = opts;
10837			var $window = $(window);
10838			var instance = this;
10839
10840			// Validate selectors
10841			if (!instance._validate(options)) {
10842				return false;
10843			}
10844
10845			// Validate page fragment path
10846			var path = $(opts.nextSelector).attr('href');
10847			if (!path) {
10848				this._debug('Navigation selector not found');
10849				return false;
10850			}
10851
10852			// Set the path to be a relative URL from root.
10853			opts.path = opts.path || this._determinepath(path);
10854
10855			// contentSelector is 'page fragment' option for .load() / .ajax() calls
10856			opts.contentSelector = opts.contentSelector || this.element;
10857
10858			// loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector
10859			opts.loading.selector = opts.loading.selector || opts.contentSelector;
10860
10861			// Define loading.msg
10862			opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>');
10863
10864			// Preload loading.img
10865			(new Image()).src = opts.loading.img;
10866
10867			// distance from nav links to bottom
10868			// computed as: height of the document + top offset of container - top offset of nav link
10869			if (opts.pixelsFromNavToBottom === undefined) {
10870				opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top;
10871				this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom);
10872			}
10873
10874			var self = this;
10875
10876			// determine loading.start actions
10877			opts.loading.start = opts.loading.start || function () {
10878				$(opts.navSelector).hide();
10879				opts.loading.msg
10880					.appendTo(opts.loading.selector)
10881					.show(opts.loading.speed, $.proxy(function () {
10882						this.beginAjax(opts);
10883					}, self));
10884			};
10885
10886			// determine loading.finished actions
10887			opts.loading.finished = opts.loading.finished || function () {
10888				if (!opts.state.isBeyondMaxPage)
10889					opts.loading.msg.fadeOut(opts.loading.speed);
10890			};
10891
10892			// callback loading
10893			opts.callback = function (instance, data, url) {
10894				if (!!opts.behavior && instance['_callback_' + opts.behavior] !== undefined) {
10895					instance['_callback_' + opts.behavior].call($(opts.contentSelector)[0], data, url);
10896				}
10897
10898				if (callback) {
10899					callback.call($(opts.contentSelector)[0], data, opts, url);
10900				}
10901
10902				if (opts.prefill) {
10903					$window.bind('resize.infinite-scroll', instance._prefill);
10904				}
10905			};
10906
10907			if (options.debug) {
10908				// Tell IE9 to use its built-in console
10909				if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') {
10910					['log', 'info', 'warn', 'error', 'assert', 'dir', 'clear', 'profile', 'profileEnd']
10911						.forEach(function (method) {
10912							console[method] = this.call(console[method], console);
10913						}, Function.prototype.bind);
10914				}
10915			}
10916
10917			this._setup();
10918
10919			// Setups the prefill method for use
10920			if (opts.prefill) {
10921				this._prefill();
10922			}
10923
10924			// Return true to indicate successful creation
10925			return true;
10926		},
10927
10928		_prefill: function infscr_prefill() {
10929			var instance = this;
10930			var $window = $(window);
10931
10932			function needsPrefill() {
10933				return ($(instance.options.contentSelector).height() <= $window.height());
10934			}
10935
10936			this._prefill = function () {
10937				if (needsPrefill()) {
10938					instance.scroll();
10939				}
10940
10941				$window.bind('resize.infinite-scroll', function () {
10942					if (needsPrefill()) {
10943						$window.unbind('resize.infinite-scroll');
10944						instance.scroll();
10945					}
10946				});
10947			};
10948
10949			// Call self after setting up the new function
10950			this._prefill();
10951		},
10952
10953		// Console log wrapper
10954		_debug: function infscr_debug() {
10955			if (true !== this.options.debug) {
10956				return;
10957			}
10958
10959			if (typeof console !== 'undefined' && typeof console.log === 'function') {
10960				// Modern browsers
10961				// Single argument, which is a string
10962				if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') {
10963					console.log((Array.prototype.slice.call(arguments)).toString());
10964				} else {
10965					console.log(Array.prototype.slice.call(arguments));
10966				}
10967			} else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') {
10968				// IE8
10969				Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments));
10970			}
10971		},
10972
10973		// find the number to increment in the path.
10974		_determinepath: function infscr_determinepath(path) {
10975
10976			var opts = this.options;
10977
10978			// if behavior is defined and this function is extended, call that instead of default
10979			if (!!opts.behavior && this['_determinepath_' + opts.behavior] !== undefined) {
10980				return this['_determinepath_' + opts.behavior].call(this, path);
10981			}
10982
10983			var url = new URL(path);
10984			var pathname = url.pathname;
10985			var hasNumber = /\d/.test(pathname);
10986
10987			if (!!opts.pathParse) {
10988				this._debug('pathParse manual');
10989				return opts.pathParse(path, this.options.state.currPage + 1);
10990            } else if (hasNumber && path.match(/(\?|\&)(upage=)(\d+)/)) {
10991				var parts = path.split(/(\?|\&)(upage=)(\d+)/);
10992				return [parts[0] + parts[1] + parts[2], parts[4]];
10993            } else if (path.match(/^(.*?)\b2\b(.*?$)/)) {
10994				path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1);
10995
10996                // if there is any 2 in the url at all.
10997            } else if (path.match(/^(.*?)2(.*?$)/)) {
10998                // page= is used in django:
10999                // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127
11000                if (path.match(/^(.*?page=)2(\/.*|$)/)) {
11001                    path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1);
11002                    return path;
11003                }
11004
11005                path = path.match(/^(.*?)2(.*?$)/).slice(1);
11006
11007            } else {
11008                // page= is used in drupal too but second page is page=1 not page=2:
11009                // thx Jerod Fritz, vladikoff
11010                if (path.match(/^(.*?page=)1(\/.*|$)/)) {
11011                    path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1);
11012                    return path;
11013                } else {
11014                    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.");
11015                    // Get rid of isInvalidPage to allow permalink to state
11016                    opts.state.isInvalidPage = true;  //prevent it from running on this page.
11017                }
11018            }
11019            this._debug('determinePath', path);
11020            return path;
11021
11022        },
11023
11024        // Custom error
11025        _error: function infscr_error(xhr) {
11026
11027            var opts = this.options;
11028
11029            // if behavior is defined and this function is extended, call that instead of default
11030            if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) {
11031                this['_error_'+opts.behavior].call(this,xhr);
11032                return;
11033            }
11034
11035            if (xhr !== 'destroy' && xhr !== 'end') {
11036                xhr = 'unknown';
11037            }
11038
11039            this._debug('Error', xhr);
11040
11041            if (xhr === 'end' || opts.state.isBeyondMaxPage) {
11042                this._showdonemsg();
11043            }
11044
11045            opts.state.isDone = true;
11046            opts.state.currPage = 1; // if you need to go back to this instance
11047            opts.state.isPaused = false;
11048            opts.state.isBeyondMaxPage = false;
11049            this._binding('unbind');
11050
11051        },
11052
11053        // Load Callback
11054        _loadcallback: function infscr_loadcallback(box, data, url) {
11055            var opts = this.options,
11056            callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK
11057            result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append',
11058            frag;
11059
11060            // if behavior is defined and this function is extended, call that instead of default
11061            if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) {
11062                this['_loadcallback_'+opts.behavior].call(this,box,data);
11063                return;
11064            }
11065
11066            switch (result) {
11067                case 'done':
11068                    this._showdonemsg();
11069                    return false;
11070
11071                case 'no-append':
11072                    if (opts.dataType === 'html') {
11073                        data = '<div>' + data + '</div>';
11074                        data = $(data).find(opts.itemSelector);
11075                    }
11076
11077                    // if it didn't return anything
11078                    if (data.length === 0) {
11079                        return this._error('end');
11080                    }
11081
11082                    break;
11083
11084                case 'append':
11085                    var children = box.children();
11086                    // if it didn't return anything
11087                    if (children.length === 0) {
11088                        return this._error('end');
11089                    }
11090
11091                    // use a documentFragment because it works when content is going into a table or UL
11092                    frag = document.createDocumentFragment();
11093                    while (box[0].firstChild) {
11094                        frag.appendChild(box[0].firstChild);
11095                    }
11096
11097                    this._debug('contentSelector', $(opts.contentSelector)[0]);
11098                    $(opts.contentSelector)[0].appendChild(frag);
11099                    // previously, we would pass in the new DOM element as context for the callback
11100                    // however we're now using a documentfragment, which doesn't have parents or children,
11101                    // so the context is the contentContainer guy, and we pass in an array
11102                    // of the elements collected as the first argument.
11103
11104                    data = children.get();
11105                    break;
11106            }
11107
11108            // loadingEnd function
11109            opts.loading.finished.call($(opts.contentSelector)[0],opts);
11110
11111            // smooth scroll to ease in the new content
11112            if (opts.animate) {
11113                var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px';
11114                $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; });
11115            }
11116
11117            if (!opts.animate) {
11118                // once the call is done, we can allow it again.
11119                opts.state.isDuringAjax = false;
11120            }
11121
11122            callback(this, data, url);
11123
11124            if (opts.prefill) {
11125                this._prefill();
11126            }
11127        },
11128
11129        _nearbottom: function infscr_nearbottom() {
11130
11131            var opts = this.options,
11132            pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height();
11133
11134            // if behavior is defined and this function is extended, call that instead of default
11135            if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) {
11136                return this['_nearbottom_'+opts.behavior].call(this);
11137            }
11138
11139            this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom);
11140
11141            // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom....
11142            return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom);
11143
11144        },
11145
11146        // Pause / temporarily disable plugin from firing
11147        _pausing: function infscr_pausing(pause) {
11148
11149            var opts = this.options;
11150
11151            // if behavior is defined and this function is extended, call that instead of default
11152            if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) {
11153                this['_pausing_'+opts.behavior].call(this,pause);
11154                return;
11155            }
11156
11157            // If pause is not 'pause' or 'resume', toggle it's value
11158            if (pause !== 'pause' && pause !== 'resume' && pause !== null) {
11159                this._debug('Invalid argument. Toggling pause value instead');
11160            }
11161
11162            pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle';
11163
11164            switch (pause) {
11165                case 'pause':
11166                    opts.state.isPaused = true;
11167                break;
11168
11169                case 'resume':
11170                    opts.state.isPaused = false;
11171                break;
11172
11173                case 'toggle':
11174                    opts.state.isPaused = !opts.state.isPaused;
11175                break;
11176            }
11177
11178            this._debug('Paused', opts.state.isPaused);
11179            return false;
11180
11181        },
11182
11183        // Behavior is determined
11184        // If the behavior option is undefined, it will set to default and bind to scroll
11185        _setup: function infscr_setup() {
11186
11187            var opts = this.options;
11188
11189            // if behavior is defined and this function is extended, call that instead of default
11190            if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) {
11191                this['_setup_'+opts.behavior].call(this);
11192                return;
11193            }
11194
11195            this._binding('bind');
11196
11197            return false;
11198
11199        },
11200
11201        // Show done message
11202        _showdonemsg: function infscr_showdonemsg() {
11203
11204            var opts = this.options;
11205
11206            // if behavior is defined and this function is extended, call that instead of default
11207            if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) {
11208                this['_showdonemsg_'+opts.behavior].call(this);
11209                return;
11210            }
11211
11212            opts.loading.msg
11213            .find('img')
11214            .hide()
11215            .parent()
11216            .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () {
11217                $(this).parent().fadeOut(opts.loading.speed);
11218            });
11219
11220            // user provided callback when done
11221            opts.errorCallback.call($(opts.contentSelector)[0],'done');
11222        },
11223
11224        // grab each selector option and see if any fail
11225        _validate: function infscr_validate(opts) {
11226            for (var key in opts) {
11227                if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) {
11228                    this._debug('Your ' + key + ' found no elements.');
11229                    return false;
11230                }
11231            }
11232
11233            return true;
11234        },
11235
11236        /*
11237            ----------------------------
11238            Public methods
11239            ----------------------------
11240            */
11241
11242        // Bind to scroll
11243        bind: function infscr_bind() {
11244            this._binding('bind');
11245        },
11246
11247        // Destroy current instance of plugin
11248        destroy: function infscr_destroy() {
11249            this.options.state.isDestroyed = true;
11250            this.options.loading.finished();
11251            return this._error('destroy');
11252        },
11253
11254        // Set pause value to false
11255        pause: function infscr_pause() {
11256            this._pausing('pause');
11257        },
11258
11259        // Set pause value to false
11260        resume: function infscr_resume() {
11261            this._pausing('resume');
11262        },
11263
11264        beginAjax: function infscr_ajax(opts) {
11265            var instance = this,
11266                path = opts.path,
11267                box, desturl, method, condition;
11268
11269			// increment the URL bit. e.g. /page/3/
11270            opts.state.currPage++;
11271
11272            // Manually control maximum page
11273            if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){
11274                opts.state.isBeyondMaxPage = true;
11275                this.destroy();
11276                return;
11277            }
11278
11279            // if we're dealing with a table we can't use DIVs
11280            box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>');
11281
11282			desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage);
11283
11284            instance._debug('heading into ajax', desturl);
11285
11286            method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback';
11287            if (opts.appendCallback && opts.dataType === 'html') {
11288                method += '+callback';
11289            }
11290
11291            switch (method) {
11292                case 'html+callback':
11293                    instance._debug('Using HTML via .load() method');
11294                    box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) {
11295                        instance._loadcallback(box, responseText, desturl);
11296                    });
11297
11298                    break;
11299
11300                case 'html':
11301                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
11302                    $.ajax({
11303                        // params
11304                        url: desturl,
11305                        dataType: opts.dataType,
11306                        complete: function infscr_ajax_callback(jqXHR, textStatus) {
11307                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
11308                            if (condition) {
11309                                instance._loadcallback(box, jqXHR.responseText, desturl);
11310                            } else {
11311                                instance._error('end');
11312                            }
11313                        }
11314                    });
11315
11316                    break;
11317                case 'json':
11318                    instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method');
11319                    $.ajax({
11320                        dataType: 'json',
11321                        type: 'GET',
11322                        url: desturl,
11323                        success: function (data, textStatus, jqXHR) {
11324                            condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified');
11325                            if (opts.appendCallback) {
11326                                // if appendCallback is true, you must defined template in options.
11327                                // note that data passed into _loadcallback is already an html (after processed in opts.template(data)).
11328                                if (opts.template !== undefined) {
11329                                    var theData = opts.template(data);
11330                                    box.append(theData);
11331                                    if (condition) {
11332                                        instance._loadcallback(box, theData);
11333                                    } else {
11334                                        instance._error('end');
11335                                    }
11336                                } else {
11337                                    instance._debug('template must be defined.');
11338                                    instance._error('end');
11339                                }
11340                            } else {
11341                                // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback.
11342                                if (condition) {
11343                                    instance._loadcallback(box, data, desturl);
11344                                } else {
11345                                    instance._error('end');
11346                                }
11347                            }
11348                        },
11349                        error: function() {
11350                            instance._debug('JSON ajax request failed.');
11351                            instance._error('end');
11352                        }
11353                    });
11354
11355                    break;
11356            }
11357        },
11358
11359        // Retrieve next set of content items
11360        retrieve: function infscr_retrieve(pageNum) {
11361            pageNum = pageNum || null;
11362
11363            var instance = this,
11364            opts = instance.options;
11365
11366            // if behavior is defined and this function is extended, call that instead of default
11367            if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) {
11368                this['retrieve_'+opts.behavior].call(this,pageNum);
11369                return;
11370            }
11371
11372            // for manual triggers, if destroyed, get out of here
11373            if (opts.state.isDestroyed) {
11374                this._debug('Instance is destroyed');
11375                return false;
11376            }
11377
11378            // we dont want to fire the ajax multiple times
11379            opts.state.isDuringAjax = true;
11380
11381            opts.loading.start.call($(opts.contentSelector)[0],opts);
11382        },
11383
11384        // Check to see next page is needed
11385        scroll: function infscr_scroll() {
11386
11387            var opts = this.options,
11388            state = opts.state;
11389
11390            // if behavior is defined and this function is extended, call that instead of default
11391            if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) {
11392                this['scroll_'+opts.behavior].call(this);
11393                return;
11394            }
11395
11396            if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) {
11397                return;
11398            }
11399
11400            if (!this._nearbottom()) {
11401                return;
11402            }
11403
11404            this.retrieve();
11405
11406        },
11407
11408        // Toggle pause value
11409        toggle: function infscr_toggle() {
11410            this._pausing();
11411        },
11412
11413        // Unbind from scroll
11414        unbind: function infscr_unbind() {
11415            this._binding('unbind');
11416        },
11417
11418        // update options
11419        update: function infscr_options(key) {
11420            if ($.isPlainObject(key)) {
11421                this.options = $.extend(true,this.options,key);
11422            }
11423        }
11424    };
11425
11426
11427    /*
11428        ----------------------------
11429        Infinite Scroll function
11430        ----------------------------
11431
11432        Borrowed logic from the following...
11433
11434        jQuery UI
11435        - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js
11436
11437        jCarousel
11438        - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js
11439
11440        Masonry
11441        - https://github.com/desandro/masonry/blob/master/jquery.masonry.js
11442
11443*/
11444
11445    $.fn.infinitescroll = function infscr_init(options, callback) {
11446
11447
11448        var thisCall = typeof options;
11449
11450        switch (thisCall) {
11451
11452            // method
11453            case 'string':
11454                var args = Array.prototype.slice.call(arguments, 1);
11455
11456                this.each(function () {
11457                    var instance = $.data(this, 'infinitescroll');
11458
11459                    if (!instance) {
11460                        // not setup yet
11461                        // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup');
11462                        return false;
11463                    }
11464
11465                    if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
11466                        // return $.error('No such method ' + options + ' for Infinite Scroll');
11467                        return false;
11468                    }
11469
11470                    // no errors!
11471                    instance[options].apply(instance, args);
11472                });
11473
11474            break;
11475
11476            // creation
11477            case 'object':
11478
11479                this.each(function () {
11480
11481                var instance = $.data(this, 'infinitescroll');
11482
11483                if (instance) {
11484
11485                    // update options of current instance
11486                    instance.update(options);
11487
11488                } else {
11489
11490                    // initialize new instance
11491                    instance = new $.infinitescroll(options, callback, this);
11492
11493                    // don't attach if instantiation failed
11494                    if (!instance.failed) {
11495                        $.data(this, 'infinitescroll', instance);
11496                    }
11497
11498                }
11499
11500            });
11501
11502            break;
11503
11504        }
11505
11506        return this;
11507    };
11508
11509
11510
11511    /*
11512     * smartscroll: debounced scroll event for jQuery *
11513     * https://github.com/lukeshumard/smartscroll
11514     * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js *
11515     * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. *
11516     */
11517
11518    var event = $.event,
11519    scrollTimeout;
11520
11521    event.special.smartscroll = {
11522        setup: function () {
11523            $(this).bind('scroll', event.special.smartscroll.handler);
11524        },
11525        teardown: function () {
11526            $(this).unbind('scroll', event.special.smartscroll.handler);
11527        },
11528        handler: function (event, execAsap) {
11529            // Save the context
11530            var context = this,
11531            args = arguments;
11532
11533            // set correct event type
11534            event.type = 'smartscroll';
11535
11536            if (scrollTimeout) { clearTimeout(scrollTimeout); }
11537            scrollTimeout = setTimeout(function () {
11538                $(context).trigger('smartscroll', args);
11539            }, execAsap === 'execAsap' ? 0 : 100);
11540        }
11541    };
11542
11543    $.fn.smartscroll = function (fn) {
11544        return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']);
11545    };
11546
11547}));
11548
11549/*!
11550Waypoints - 4.0.1
11551Copyright © 2011-2016 Caleb Troughton
11552Licensed under the MIT license.
11553https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
11554*/
11555(function() {
11556  'use strict'
11557
11558  var keyCounter = 0
11559  var allWaypoints = {}
11560
11561  /* http://imakewebthings.com/waypoints/api/waypoint */
11562  function Waypoint(options) {
11563    if (!options) {
11564      throw new Error('No options passed to Waypoint constructor')
11565    }
11566    if (!options.element) {
11567      throw new Error('No element option passed to Waypoint constructor')
11568    }
11569    if (!options.handler) {
11570      throw new Error('No handler option passed to Waypoint constructor')
11571    }
11572
11573    this.key = 'waypoint-' + keyCounter
11574    this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options)
11575    this.element = this.options.element
11576    this.adapter = new Waypoint.Adapter(this.element)
11577    this.callback = options.handler
11578    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
11579    this.enabled = this.options.enabled
11580    this.triggerPoint = null
11581    this.group = Waypoint.Group.findOrCreate({
11582      name: this.options.group,
11583      axis: this.axis
11584    })
11585    this.context = Waypoint.Context.findOrCreateByElement(this.options.context)
11586
11587    if (Waypoint.offsetAliases[this.options.offset]) {
11588      this.options.offset = Waypoint.offsetAliases[this.options.offset]
11589    }
11590    this.group.add(this)
11591    this.context.add(this)
11592    allWaypoints[this.key] = this
11593    keyCounter += 1
11594  }
11595
11596  /* Private */
11597  Waypoint.prototype.queueTrigger = function(direction) {
11598    this.group.queueTrigger(this, direction)
11599  }
11600
11601  /* Private */
11602  Waypoint.prototype.trigger = function(args) {
11603    if (!this.enabled) {
11604      return
11605    }
11606    if (this.callback) {
11607      this.callback.apply(this, args)
11608    }
11609  }
11610
11611  /* Public */
11612  /* http://imakewebthings.com/waypoints/api/destroy */
11613  Waypoint.prototype.destroy = function() {
11614    this.context.remove(this)
11615    this.group.remove(this)
11616    delete allWaypoints[this.key]
11617  }
11618
11619  /* Public */
11620  /* http://imakewebthings.com/waypoints/api/disable */
11621  Waypoint.prototype.disable = function() {
11622    this.enabled = false
11623    return this
11624  }
11625
11626  /* Public */
11627  /* http://imakewebthings.com/waypoints/api/enable */
11628  Waypoint.prototype.enable = function() {
11629    this.context.refresh()
11630    this.enabled = true
11631    return this
11632  }
11633
11634  /* Public */
11635  /* http://imakewebthings.com/waypoints/api/next */
11636  Waypoint.prototype.next = function() {
11637    return this.group.next(this)
11638  }
11639
11640  /* Public */
11641  /* http://imakewebthings.com/waypoints/api/previous */
11642  Waypoint.prototype.previous = function() {
11643    return this.group.previous(this)
11644  }
11645
11646  /* Private */
11647  Waypoint.invokeAll = function(method) {
11648    var allWaypointsArray = []
11649    for (var waypointKey in allWaypoints) {
11650      allWaypointsArray.push(allWaypoints[waypointKey])
11651    }
11652    for (var i = 0, end = allWaypointsArray.length; i < end; i++) {
11653      allWaypointsArray[i][method]()
11654    }
11655  }
11656
11657  /* Public */
11658  /* http://imakewebthings.com/waypoints/api/destroy-all */
11659  Waypoint.destroyAll = function() {
11660    Waypoint.invokeAll('destroy')
11661  }
11662
11663  /* Public */
11664  /* http://imakewebthings.com/waypoints/api/disable-all */
11665  Waypoint.disableAll = function() {
11666    Waypoint.invokeAll('disable')
11667  }
11668
11669  /* Public */
11670  /* http://imakewebthings.com/waypoints/api/enable-all */
11671  Waypoint.enableAll = function() {
11672    Waypoint.Context.refreshAll()
11673    for (var waypointKey in allWaypoints) {
11674      allWaypoints[waypointKey].enabled = true
11675    }
11676    return this
11677  }
11678
11679  /* Public */
11680  /* http://imakewebthings.com/waypoints/api/refresh-all */
11681  Waypoint.refreshAll = function() {
11682    Waypoint.Context.refreshAll()
11683  }
11684
11685  /* Public */
11686  /* http://imakewebthings.com/waypoints/api/viewport-height */
11687  Waypoint.viewportHeight = function() {
11688    return window.innerHeight || document.documentElement.clientHeight
11689  }
11690
11691  /* Public */
11692  /* http://imakewebthings.com/waypoints/api/viewport-width */
11693  Waypoint.viewportWidth = function() {
11694    return document.documentElement.clientWidth
11695  }
11696
11697  Waypoint.adapters = []
11698
11699  Waypoint.defaults = {
11700    context: window,
11701    continuous: true,
11702    enabled: true,
11703    group: 'default',
11704    horizontal: false,
11705    offset: 0
11706  }
11707
11708  Waypoint.offsetAliases = {
11709    'bottom-in-view': function() {
11710      return this.context.innerHeight() - this.adapter.outerHeight()
11711    },
11712    'right-in-view': function() {
11713      return this.context.innerWidth() - this.adapter.outerWidth()
11714    }
11715  }
11716
11717  window.Waypoint = Waypoint
11718}())
11719;(function() {
11720  'use strict'
11721
11722  function requestAnimationFrameShim(callback) {
11723    window.setTimeout(callback, 1000 / 60)
11724  }
11725
11726  var keyCounter = 0
11727  var contexts = {}
11728  var Waypoint = window.Waypoint
11729  var oldWindowLoad = window.onload
11730
11731  /* http://imakewebthings.com/waypoints/api/context */
11732  function Context(element) {
11733    this.element = element
11734    this.Adapter = Waypoint.Adapter
11735    this.adapter = new this.Adapter(element)
11736    this.key = 'waypoint-context-' + keyCounter
11737    this.didScroll = false
11738    this.didResize = false
11739    this.oldScroll = {
11740      x: this.adapter.scrollLeft(),
11741      y: this.adapter.scrollTop()
11742    }
11743    this.waypoints = {
11744      vertical: {},
11745      horizontal: {}
11746    }
11747
11748    element.waypointContextKey = this.key
11749    contexts[element.waypointContextKey] = this
11750    keyCounter += 1
11751    if (!Waypoint.windowContext) {
11752      Waypoint.windowContext = true
11753      Waypoint.windowContext = new Context(window)
11754    }
11755
11756    this.createThrottledScrollHandler()
11757    this.createThrottledResizeHandler()
11758  }
11759
11760  /* Private */
11761  Context.prototype.add = function(waypoint) {
11762    var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical'
11763    this.waypoints[axis][waypoint.key] = waypoint
11764    this.refresh()
11765  }
11766
11767  /* Private */
11768  Context.prototype.checkEmpty = function() {
11769    var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal)
11770    var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical)
11771    var isWindow = this.element == this.element.window
11772    if (horizontalEmpty && verticalEmpty && !isWindow) {
11773      this.adapter.off('.waypoints')
11774      delete contexts[this.key]
11775    }
11776  }
11777
11778  /* Private */
11779  Context.prototype.createThrottledResizeHandler = function() {
11780    var self = this
11781
11782    function resizeHandler() {
11783      self.handleResize()
11784      self.didResize = false
11785    }
11786
11787    this.adapter.on('resize.waypoints', function() {
11788      if (!self.didResize) {
11789        self.didResize = true
11790        Waypoint.requestAnimationFrame(resizeHandler)
11791      }
11792    })
11793  }
11794
11795  /* Private */
11796  Context.prototype.createThrottledScrollHandler = function() {
11797    var self = this
11798    function scrollHandler() {
11799      self.handleScroll()
11800      self.didScroll = false
11801    }
11802
11803    this.adapter.on('scroll.waypoints', function() {
11804      if (!self.didScroll || Waypoint.isTouch) {
11805        self.didScroll = true
11806        Waypoint.requestAnimationFrame(scrollHandler)
11807      }
11808    })
11809  }
11810
11811  /* Private */
11812  Context.prototype.handleResize = function() {
11813    Waypoint.Context.refreshAll()
11814  }
11815
11816  /* Private */
11817  Context.prototype.handleScroll = function() {
11818    var triggeredGroups = {}
11819    var axes = {
11820      horizontal: {
11821        newScroll: this.adapter.scrollLeft(),
11822        oldScroll: this.oldScroll.x,
11823        forward: 'right',
11824        backward: 'left'
11825      },
11826      vertical: {
11827        newScroll: this.adapter.scrollTop(),
11828        oldScroll: this.oldScroll.y,
11829        forward: 'down',
11830        backward: 'up'
11831      }
11832    }
11833
11834    for (var axisKey in axes) {
11835      var axis = axes[axisKey]
11836      var isForward = axis.newScroll > axis.oldScroll
11837      var direction = isForward ? axis.forward : axis.backward
11838
11839      for (var waypointKey in this.waypoints[axisKey]) {
11840        var waypoint = this.waypoints[axisKey][waypointKey]
11841        if (waypoint.triggerPoint === null) {
11842          continue
11843        }
11844        var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint
11845        var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint
11846        var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint
11847        var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint
11848        if (crossedForward || crossedBackward) {
11849          waypoint.queueTrigger(direction)
11850          triggeredGroups[waypoint.group.id] = waypoint.group
11851        }
11852      }
11853    }
11854
11855    for (var groupKey in triggeredGroups) {
11856      triggeredGroups[groupKey].flushTriggers()
11857    }
11858
11859    this.oldScroll = {
11860      x: axes.horizontal.newScroll,
11861      y: axes.vertical.newScroll
11862    }
11863  }
11864
11865  /* Private */
11866  Context.prototype.innerHeight = function() {
11867    /*eslint-disable eqeqeq */
11868    if (this.element == this.element.window) {
11869      return Waypoint.viewportHeight()
11870    }
11871    /*eslint-enable eqeqeq */
11872    return this.adapter.innerHeight()
11873  }
11874
11875  /* Private */
11876  Context.prototype.remove = function(waypoint) {
11877    delete this.waypoints[waypoint.axis][waypoint.key]
11878    this.checkEmpty()
11879  }
11880
11881  /* Private */
11882  Context.prototype.innerWidth = function() {
11883    /*eslint-disable eqeqeq */
11884    if (this.element == this.element.window) {
11885      return Waypoint.viewportWidth()
11886    }
11887    /*eslint-enable eqeqeq */
11888    return this.adapter.innerWidth()
11889  }
11890
11891  /* Public */
11892  /* http://imakewebthings.com/waypoints/api/context-destroy */
11893  Context.prototype.destroy = function() {
11894    var allWaypoints = []
11895    for (var axis in this.waypoints) {
11896      for (var waypointKey in this.waypoints[axis]) {
11897        allWaypoints.push(this.waypoints[axis][waypointKey])
11898      }
11899    }
11900    for (var i = 0, end = allWaypoints.length; i < end; i++) {
11901      allWaypoints[i].destroy()
11902    }
11903  }
11904
11905  /* Public */
11906  /* http://imakewebthings.com/waypoints/api/context-refresh */
11907  Context.prototype.refresh = function() {
11908    /*eslint-disable eqeqeq */
11909    var isWindow = this.element == this.element.window
11910    /*eslint-enable eqeqeq */
11911    var contextOffset = isWindow ? undefined : this.adapter.offset()
11912    var triggeredGroups = {}
11913    var axes
11914
11915    this.handleScroll()
11916    axes = {
11917      horizontal: {
11918        contextOffset: isWindow ? 0 : contextOffset.left,
11919        contextScroll: isWindow ? 0 : this.oldScroll.x,
11920        contextDimension: this.innerWidth(),
11921        oldScroll: this.oldScroll.x,
11922        forward: 'right',
11923        backward: 'left',
11924        offsetProp: 'left'
11925      },
11926      vertical: {
11927        contextOffset: isWindow ? 0 : contextOffset.top,
11928        contextScroll: isWindow ? 0 : this.oldScroll.y,
11929        contextDimension: this.innerHeight(),
11930        oldScroll: this.oldScroll.y,
11931        forward: 'down',
11932        backward: 'up',
11933        offsetProp: 'top'
11934      }
11935    }
11936
11937    for (var axisKey in axes) {
11938      var axis = axes[axisKey]
11939      for (var waypointKey in this.waypoints[axisKey]) {
11940        var waypoint = this.waypoints[axisKey][waypointKey]
11941        var adjustment = waypoint.options.offset
11942        var oldTriggerPoint = waypoint.triggerPoint
11943        var elementOffset = 0
11944        var freshWaypoint = oldTriggerPoint == null
11945        var contextModifier, wasBeforeScroll, nowAfterScroll
11946        var triggeredBackward, triggeredForward
11947
11948        if (waypoint.element !== waypoint.element.window) {
11949          elementOffset = waypoint.adapter.offset()[axis.offsetProp]
11950        }
11951
11952        if (typeof adjustment === 'function') {
11953          adjustment = adjustment.apply(waypoint)
11954        }
11955        else if (typeof adjustment === 'string') {
11956          adjustment = parseFloat(adjustment)
11957          if (waypoint.options.offset.indexOf('%') > - 1) {
11958            adjustment = Math.ceil(axis.contextDimension * adjustment / 100)
11959          }
11960        }
11961
11962        contextModifier = axis.contextScroll - axis.contextOffset
11963        waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment)
11964        wasBeforeScroll = oldTriggerPoint < axis.oldScroll
11965        nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll
11966        triggeredBackward = wasBeforeScroll && nowAfterScroll
11967        triggeredForward = !wasBeforeScroll && !nowAfterScroll
11968
11969        if (!freshWaypoint && triggeredBackward) {
11970          waypoint.queueTrigger(axis.backward)
11971          triggeredGroups[waypoint.group.id] = waypoint.group
11972        }
11973        else if (!freshWaypoint && triggeredForward) {
11974          waypoint.queueTrigger(axis.forward)
11975          triggeredGroups[waypoint.group.id] = waypoint.group
11976        }
11977        else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) {
11978          waypoint.queueTrigger(axis.forward)
11979          triggeredGroups[waypoint.group.id] = waypoint.group
11980        }
11981      }
11982    }
11983
11984    Waypoint.requestAnimationFrame(function() {
11985      for (var groupKey in triggeredGroups) {
11986        triggeredGroups[groupKey].flushTriggers()
11987      }
11988    })
11989
11990    return this
11991  }
11992
11993  /* Private */
11994  Context.findOrCreateByElement = function(element) {
11995    return Context.findByElement(element) || new Context(element)
11996  }
11997
11998  /* Private */
11999  Context.refreshAll = function() {
12000    for (var contextId in contexts) {
12001      contexts[contextId].refresh()
12002    }
12003  }
12004
12005  /* Public */
12006  /* http://imakewebthings.com/waypoints/api/context-find-by-element */
12007  Context.findByElement = function(element) {
12008    return contexts[element.waypointContextKey]
12009  }
12010
12011  window.onload = function() {
12012    if (oldWindowLoad) {
12013      oldWindowLoad()
12014    }
12015    Context.refreshAll()
12016  }
12017
12018
12019  Waypoint.requestAnimationFrame = function(callback) {
12020    var requestFn = window.requestAnimationFrame ||
12021      window.mozRequestAnimationFrame ||
12022      window.webkitRequestAnimationFrame ||
12023      requestAnimationFrameShim
12024    requestFn.call(window, callback)
12025  }
12026  Waypoint.Context = Context
12027}())
12028;(function() {
12029  'use strict'
12030
12031  function byTriggerPoint(a, b) {
12032    return a.triggerPoint - b.triggerPoint
12033  }
12034
12035  function byReverseTriggerPoint(a, b) {
12036    return b.triggerPoint - a.triggerPoint
12037  }
12038
12039  var groups = {
12040    vertical: {},
12041    horizontal: {}
12042  }
12043  var Waypoint = window.Waypoint
12044
12045  /* http://imakewebthings.com/waypoints/api/group */
12046  function Group(options) {
12047    this.name = options.name
12048    this.axis = options.axis
12049    this.id = this.name + '-' + this.axis
12050    this.waypoints = []
12051    this.clearTriggerQueues()
12052    groups[this.axis][this.name] = this
12053  }
12054
12055  /* Private */
12056  Group.prototype.add = function(waypoint) {
12057    this.waypoints.push(waypoint)
12058  }
12059
12060  /* Private */
12061  Group.prototype.clearTriggerQueues = function() {
12062    this.triggerQueues = {
12063      up: [],
12064      down: [],
12065      left: [],
12066      right: []
12067    }
12068  }
12069
12070  /* Private */
12071  Group.prototype.flushTriggers = function() {
12072    for (var direction in this.triggerQueues) {
12073      var waypoints = this.triggerQueues[direction]
12074      var reverse = direction === 'up' || direction === 'left'
12075      waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint)
12076      for (var i = 0, end = waypoints.length; i < end; i += 1) {
12077        var waypoint = waypoints[i]
12078        if (waypoint.options.continuous || i === waypoints.length - 1) {
12079          waypoint.trigger([direction])
12080        }
12081      }
12082    }
12083    this.clearTriggerQueues()
12084  }
12085
12086  /* Private */
12087  Group.prototype.next = function(waypoint) {
12088    this.waypoints.sort(byTriggerPoint)
12089    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12090    var isLast = index === this.waypoints.length - 1
12091    return isLast ? null : this.waypoints[index + 1]
12092  }
12093
12094  /* Private */
12095  Group.prototype.previous = function(waypoint) {
12096    this.waypoints.sort(byTriggerPoint)
12097    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12098    return index ? this.waypoints[index - 1] : null
12099  }
12100
12101  /* Private */
12102  Group.prototype.queueTrigger = function(waypoint, direction) {
12103    this.triggerQueues[direction].push(waypoint)
12104  }
12105
12106  /* Private */
12107  Group.prototype.remove = function(waypoint) {
12108    var index = Waypoint.Adapter.inArray(waypoint, this.waypoints)
12109    if (index > -1) {
12110      this.waypoints.splice(index, 1)
12111    }
12112  }
12113
12114  /* Public */
12115  /* http://imakewebthings.com/waypoints/api/first */
12116  Group.prototype.first = function() {
12117    return this.waypoints[0]
12118  }
12119
12120  /* Public */
12121  /* http://imakewebthings.com/waypoints/api/last */
12122  Group.prototype.last = function() {
12123    return this.waypoints[this.waypoints.length - 1]
12124  }
12125
12126  /* Private */
12127  Group.findOrCreate = function(options) {
12128    return groups[options.axis][options.name] || new Group(options)
12129  }
12130
12131  Waypoint.Group = Group
12132}())
12133;(function() {
12134  'use strict'
12135
12136  var $ = window.jQuery
12137  var Waypoint = window.Waypoint
12138
12139  function JQueryAdapter(element) {
12140    this.$element = $(element)
12141  }
12142
12143  $.each([
12144    'innerHeight',
12145    'innerWidth',
12146    'off',
12147    'offset',
12148    'on',
12149    'outerHeight',
12150    'outerWidth',
12151    'scrollLeft',
12152    'scrollTop'
12153  ], function(i, method) {
12154    JQueryAdapter.prototype[method] = function() {
12155      var args = Array.prototype.slice.call(arguments)
12156      return this.$element[method].apply(this.$element, args)
12157    }
12158  })
12159
12160  $.each([
12161    'extend',
12162    'inArray',
12163    'isEmptyObject'
12164  ], function(i, method) {
12165    JQueryAdapter[method] = $[method]
12166  })
12167
12168  Waypoint.adapters.push({
12169    name: 'jquery',
12170    Adapter: JQueryAdapter
12171  })
12172  Waypoint.Adapter = JQueryAdapter
12173}())
12174;(function() {
12175  'use strict'
12176
12177  var Waypoint = window.Waypoint
12178
12179  function createExtension(framework) {
12180    return function() {
12181      var waypoints = []
12182      var overrides = arguments[0]
12183
12184      if (framework.isFunction(arguments[0])) {
12185        overrides = framework.extend({}, arguments[1])
12186        overrides.handler = arguments[0]
12187      }
12188
12189      this.each(function() {
12190        var options = framework.extend({}, overrides, {
12191          element: this
12192        })
12193        if (typeof options.context === 'string') {
12194          options.context = framework(this).closest(options.context)[0]
12195        }
12196        waypoints.push(new Waypoint(options))
12197      })
12198
12199      return waypoints
12200    }
12201  }
12202
12203  if (window.jQuery) {
12204    window.jQuery.fn.waypoint = createExtension(window.jQuery)
12205  }
12206  if (window.Zepto) {
12207    window.Zepto.fn.waypoint = createExtension(window.Zepto)
12208  }
12209}())
12210;
12211/*!
12212Waypoints Inview Shortcut - 4.0.1
12213Copyright © 2011-2016 Caleb Troughton
12214Licensed under the MIT license.
12215https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
12216*/
12217(function() {
12218  'use strict'
12219
12220  function noop() {}
12221
12222  var Waypoint = window.Waypoint
12223
12224  /* http://imakewebthings.com/waypoints/shortcuts/inview */
12225  function Inview(options) {
12226    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
12227    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
12228    this.waypoints = []
12229    this.element = this.options.element
12230    this.createWaypoints()
12231  }
12232
12233  /* Private */
12234  Inview.prototype.createWaypoints = function() {
12235    var configs = {
12236      vertical: [{
12237        down: 'enter',
12238        up: 'exited',
12239        offset: '100%'
12240      }, {
12241        down: 'entered',
12242        up: 'exit',
12243        offset: 'bottom-in-view'
12244      }, {
12245        down: 'exit',
12246        up: 'entered',
12247        offset: 0
12248      }, {
12249        down: 'exited',
12250        up: 'enter',
12251        offset: function() {
12252          return -this.adapter.outerHeight()
12253        }
12254      }],
12255      horizontal: [{
12256        right: 'enter',
12257        left: 'exited',
12258        offset: '100%'
12259      }, {
12260        right: 'entered',
12261        left: 'exit',
12262        offset: 'right-in-view'
12263      }, {
12264        right: 'exit',
12265        left: 'entered',
12266        offset: 0
12267      }, {
12268        right: 'exited',
12269        left: 'enter',
12270        offset: function() {
12271          return -this.adapter.outerWidth()
12272        }
12273      }]
12274    }
12275
12276    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
12277      var config = configs[this.axis][i]
12278      this.createWaypoint(config)
12279    }
12280  }
12281
12282  /* Private */
12283  Inview.prototype.createWaypoint = function(config) {
12284    var self = this
12285    this.waypoints.push(new Waypoint({
12286      context: this.options.context,
12287      element: this.options.element,
12288      enabled: this.options.enabled,
12289      handler: (function(config) {
12290        return function(direction) {
12291          self.options[config[direction]].call(self, direction)
12292        }
12293      }(config)),
12294      offset: config.offset,
12295      horizontal: this.options.horizontal
12296    }))
12297  }
12298
12299  /* Public */
12300  Inview.prototype.destroy = function() {
12301    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12302      this.waypoints[i].destroy()
12303    }
12304    this.waypoints = []
12305  }
12306
12307  Inview.prototype.disable = function() {
12308    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12309      this.waypoints[i].disable()
12310    }
12311  }
12312
12313  Inview.prototype.enable = function() {
12314    for (var i = 0, end = this.waypoints.length; i < end; i++) {
12315      this.waypoints[i].enable()
12316    }
12317  }
12318
12319  Inview.defaults = {
12320    context: window,
12321    enabled: true,
12322    enter: noop,
12323    entered: noop,
12324    exit: noop,
12325    exited: noop
12326  }
12327
12328  Waypoint.Inview = Inview
12329}())
12330;
12331
12332/*
12333 * SmartMenus jQuery v0.9.6
12334 * http://www.smartmenus.org/
12335 *
12336 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd.
12337 * http://vadikom.com/
12338 *
12339 * Released under the MIT license:
12340 * http://www.opensource.org/licenses/MIT
12341 */
12342
12343(function($) {
12344
12345	var menuTrees = [],
12346		IE = !!window.createPopup, // we need to detect it, unfortunately
12347		IElt9 = IE && !document.defaultView,
12348		IElt8 = IE && !document.querySelector,
12349		IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined',
12350		mouse = false, // optimize for touch by default - we will detect for mouse input
12351		mouseDetectionEnabled = false;
12352
12353	// Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.)
12354	function initMouseDetection(disable) {
12355		if (!mouseDetectionEnabled && !disable) {
12356			// if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present
12357			// 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)
12358			var firstTime = true,
12359				lastMove = null;
12360			$(document).bind({
12361				'mousemove.smartmenus_mouse': function(e) {
12362					var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() };
12363					if (lastMove) {
12364						var deltaX = Math.abs(lastMove.x - thisMove.x),
12365							deltaY = Math.abs(lastMove.y - thisMove.y);
12366	 					if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) {
12367							mouse = true;
12368							// 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
12369							if (firstTime) {
12370								var $a = $(e.target).closest('a');
12371								if ($a.is('a')) {
12372									$.each(menuTrees, function() {
12373										if ($.contains(this.$root[0], $a[0])) {
12374											this.itemEnter({ currentTarget: $a[0] });
12375											return false;
12376										}
12377									});
12378								}
12379								firstTime = false;
12380							}
12381						}
12382					}
12383					lastMove = thisMove;
12384				},
12385				'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) {
12386					if (!/^(4|mouse|pen)$/.test(e.originalEvent.pointerType)) {
12387						mouse = false;
12388					}
12389				}
12390			});
12391			mouseDetectionEnabled = true;
12392		} else if (mouseDetectionEnabled && disable) {
12393			$(document).unbind('.smartmenus_mouse');
12394			mouseDetectionEnabled = false;
12395		}
12396	};
12397
12398	$.SmartMenus = function(elm, options) {
12399		this.$root = $(elm);
12400		this.opts = options;
12401		this.rootId = ''; // internal
12402		this.$subArrow = null;
12403		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)
12404		this.activatedItems = []; // stores last activated A's for each level
12405		this.visibleSubMenus = []; // stores visible sub menus UL's
12406		this.showTimeout = 0;
12407		this.hideTimeout = 0;
12408		this.scrollTimeout = 0;
12409		this.clickActivated = false;
12410		this.zIndexInc = 0;
12411		this.$firstLink = null; // we'll use these for some tests
12412		this.$firstSub = null; // at runtime so we'll cache them
12413		this.disabled = false;
12414		this.$disableOverlay = null;
12415		this.init();
12416	};
12417
12418	$.extend($.SmartMenus, {
12419		hideAll: function() {
12420			$.each(menuTrees, function() {
12421				this.menuHideAll();
12422			});
12423		},
12424		destroy: function() {
12425			while (menuTrees.length) {
12426				menuTrees[0].destroy();
12427			}
12428			initMouseDetection(true);
12429		},
12430		prototype: {
12431			init: function(refresh) {
12432				var self = this;
12433
12434				if (!refresh) {
12435					menuTrees.push(this);
12436
12437					this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, '');
12438
12439					if (this.$root.hasClass('sm-rtl')) {
12440						this.opts.rightToLeftSubMenus = true;
12441					}
12442
12443					// init root (main menu)
12444					this.$root
12445						.data('smartmenus', this)
12446						.attr('data-smartmenus-id', this.rootId)
12447						.dataSM('level', 1)
12448						.bind({
12449							'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
12450							'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this)
12451						})
12452						.delegate('a, div.logo-container', {
12453							'mouseenter.smartmenus': $.proxy(this.itemEnter, this),
12454							'mouseleave.smartmenus': $.proxy(this.itemLeave, this),
12455							'mousedown.smartmenus': $.proxy(this.itemDown, this),
12456							'focus.smartmenus': $.proxy(this.itemFocus, this),
12457							'blur.smartmenus': $.proxy(this.itemBlur, this),
12458							'click.smartmenus': $.proxy(this.itemClick, this),
12459							'touchend.smartmenus': $.proxy(this.itemTouchEnd, this)
12460						});
12461
12462					var eNamespace = '.smartmenus' + this.rootId;
12463					// hide menus on tap or click outside the root UL
12464					if (this.opts.hideOnClick) {
12465							$(document).on('touchstart' + eNamespace, $.proxy(this.docTouchStart, this))
12466								.on('touchmove' + eNamespace, $.proxy(this.docTouchMove, this))
12467								.on('touchend' + eNamespace, $.proxy(this.docTouchEnd, this))
12468								// for Opera Mobile < 11.5, webOS browser, etc. we'll check click too
12469								.on('click' + eNamespace, $.proxy(this.docClick, this));
12470					}
12471					// hide sub menus on resize
12472					$(window).on('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12473					var $vmenu = $('body.vmenu .vmenu-container');
12474					if ( ! $vmenu.length && UNCODE.wwidth > UNCODE.mediaQuery ) {
12475						$(window).on('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this));
12476					}
12477
12478					if (this.opts.subIndicators) {
12479						this.$subArrow = $('<span/>').addClass('sub-arrow');
12480						if (this.opts.subIndicatorsText) {
12481							this.$subArrow.html(this.opts.subIndicatorsText);
12482						}
12483					}
12484
12485					// make sure mouse detection is enabled
12486					initMouseDetection();
12487				}
12488
12489				// init sub menus
12490				this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0);
12491
12492				this.$firstLink = this.$root.find('a').eq(0);
12493
12494				// find current item
12495				if (this.opts.markCurrentItem) {
12496					var reDefaultDoc = /(index|default)\.[^#\?\/]*/i,
12497						reHash = /#.*/,
12498						locHref = window.location.href.replace(reDefaultDoc, ''),
12499						locHrefNoHash = locHref.replace(reHash, '');
12500					this.$root.find('a').each(function() {
12501						var href = this.href.replace(reDefaultDoc, ''),
12502							$this = $(this);
12503						if (href == locHref || href == locHrefNoHash) {
12504							$this.addClass('current');
12505							if (self.opts.markCurrentTree) {
12506								$this.parents('li').each(function() {
12507									var $this = $(this);
12508									if ($this.dataSM('sub')) {
12509										$this.children('a').addClass('current');
12510									}
12511								});
12512							}
12513						}
12514					});
12515				}
12516			},
12517			destroy: function() {
12518				this.menuHideAll();
12519				this.$root
12520					.removeData('smartmenus')
12521					.removeAttr('data-smartmenus-id')
12522					.removeDataSM('level')
12523					.unbind('.smartmenus')
12524					.undelegate('.smartmenus');
12525				var eNamespace = '.smartmenus' + this.rootId;
12526				$(document).unbind(eNamespace);
12527				$(window).unbind(eNamespace);
12528				if (this.opts.subIndicators) {
12529					this.$subArrow = null;
12530				}
12531				var self = this;
12532				$.each(this.subMenus, function() {
12533					if (this.hasClass('mega-menu')) {
12534						this.find('ul').removeDataSM('in-mega');
12535					}
12536					if (this.dataSM('shown-before')) {
12537						if (IElt8) {
12538							this.children().css({ styleFloat: '', width: '' });
12539						}
12540						if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) {
12541							if (!IE6) {
12542								this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap');
12543							} else {
12544								this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', '');
12545							}
12546						}
12547						if (this.dataSM('scroll-arrows')) {
12548							this.dataSM('scroll-arrows').remove();
12549						}
12550						this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' });
12551					}
12552					if (self.opts.subIndicators) {
12553						this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove();
12554					}
12555					this.removeDataSM('shown-before')
12556						.removeDataSM('ie-shim')
12557						.removeDataSM('scroll-arrows')
12558						.removeDataSM('parent-a')
12559						.removeDataSM('level')
12560						.removeDataSM('beforefirstshowfired')
12561						.parent().removeDataSM('sub');
12562				});
12563				if (this.opts.markCurrentItem) {
12564					this.$root.find('a.current').removeClass('current');
12565				}
12566				this.$root = null;
12567				this.$firstLink = null;
12568				this.$firstSub = null;
12569				if (this.$disableOverlay) {
12570					this.$disableOverlay.remove();
12571					this.$disableOverlay = null;
12572				}
12573				menuTrees.splice($.inArray(this, menuTrees), 1);
12574			},
12575			disable: function(noOverlay) {
12576				if (!this.disabled) {
12577					this.menuHideAll();
12578					// display overlay over the menu to prevent interaction
12579					if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) {
12580						var pos = this.$root.offset();
12581						this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({
12582							position: 'absolute',
12583							top: pos.top,
12584							left: pos.left,
12585							width: this.$root.outerWidth(),
12586							height: this.$root.outerHeight(),
12587							zIndex: this.getStartZIndex() + 1,
12588							opacity: 0
12589						}).appendTo(document.body);
12590					}
12591					this.disabled = true;
12592				}
12593			},
12594			docClick: function(e) {
12595				// hide on any click outside the menu or on a menu link
12596				if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) {
12597					this.menuHideAll($(e.target));
12598				}
12599			},
12600			docTouchEnd: function(e) {
12601				if (!this.lastTouch) {
12602					return;
12603				}
12604				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))) {
12605					if (this.hideTimeout) {
12606						clearTimeout(this.hideTimeout);
12607						this.hideTimeout = 0;
12608					}
12609					// hide with a delay to prevent triggering accidental unwanted click on some page element
12610					var self = this;
12611					this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350);
12612				}
12613				this.lastTouch = null;
12614			},
12615			docTouchMove: function(e) {
12616				if (!this.lastTouch) {
12617					return;
12618				}
12619				var touchPoint = e.originalEvent.touches[0];
12620				this.lastTouch.x2 = touchPoint.pageX;
12621				this.lastTouch.y2 = touchPoint.pageY;
12622			},
12623			docTouchStart: function(e) {
12624				var touchPoint = e.originalEvent.touches[0];
12625				this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target };
12626			},
12627			enable: function() {
12628				if (this.disabled) {
12629					if (this.$disableOverlay) {
12630						this.$disableOverlay.remove();
12631						this.$disableOverlay = null;
12632					}
12633					this.disabled = false;
12634				}
12635			},
12636			getHeight: function($elm) {
12637				return this.getOffset($elm, true);
12638			},
12639			// returns precise width/height float values in IE9+, FF4+, recent WebKit
12640			// http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/
12641			getOffset: function($elm, height) {
12642				var old,
12643					$win = $(window),
12644					winW = $win.width();
12645				if ($elm.css('display') == 'none') {
12646					old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility };
12647					$elm.css({ position: 'absolute', visibility: 'hidden' }).show();
12648					if ( 
12649						($('body').hasClass('menu-mobile-off-canvas') && winW < 960 && $elm.closest('.main-menu-container').length)
12650						||
12651						(( $('body').hasClass('vmenu-offcanvas-overlay') || $('body').hasClass('vmenu') ) && winW >= 960 && $elm.closest('.main-menu-container').length && !$elm.closest('.menu-horizontal-inner').length)
12652					) {
12653						$elm.closest('li').addClass('smartmenu-open-item');
12654					}
12655				}
12656				var defaultView = $elm[0].ownerDocument.defaultView,
12657					compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null),
12658					val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']);
12659				if (val) {
12660					val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft'])
12661	 					+ parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight'])
12662	 					+ parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth'])
12663	 					+ parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']);
12664				} else {
12665					val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth;
12666				}
12667				if (old) {
12668					$elm.hide().css(old);
12669				}
12670				return val;
12671			},
12672			getWidth: function($elm) {
12673				return this.getOffset($elm);
12674			},
12675			getStartZIndex: function() {
12676				var zIndex = parseInt(this.$root.css('z-index'));
12677				return !isNaN(zIndex) ? zIndex : 1;
12678			},
12679			handleEvents: function() {
12680				return !this.disabled && this.isCSSOn();
12681			},
12682			handleItemEvents: function($a) {
12683				return this.handleEvents() && !this.isLinkInMegaMenu($a);
12684			},
12685			isCollapsible: function() {
12686				return this.$firstSub.css('position') == 'static';
12687			},
12688			isCSSOn: function() {
12689				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';
12690			},
12691			isFixed: function() {
12692				return this.$root.css('position') == 'fixed';
12693			},
12694			isLinkInMegaMenu: function($a) {
12695				return !$a.parent().parent().dataSM('level');
12696			},
12697			isTouchMode: function() {
12698				return !mouse || this.isCollapsible();
12699			},
12700			itemActivate: function($a) {
12701				var $li = $a.parent(),
12702					$ul = $li.parent(),
12703					level = $ul.dataSM('level');
12704				// 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
12705				if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) {
12706					var self = this;
12707					$($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() {
12708						self.itemActivate($(this).dataSM('parent-a'));
12709					});
12710				}
12711				// hide any visible deeper level sub menus
12712				if (this.visibleSubMenus.length > level) {
12713					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--) {
12714						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12715							this.menuHide(this.visibleSubMenus[i]);
12716						//}
12717					}
12718				}
12719				// save new active item and sub menu for this level
12720				this.activatedItems[level - 1] = $a;
12721				this.visibleSubMenus[level - 1] = $ul;
12722				if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) {
12723					return;
12724				}
12725				// show the sub menu if this item has one
12726				var $sub = $li.dataSM('sub');
12727				if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) {
12728					this.menuShow($sub);
12729				}
12730			},
12731			itemBlur: function(e) {
12732				var $a = $(e.currentTarget);
12733				if (!this.handleItemEvents($a)) {
12734					return;
12735				}
12736				this.$root.triggerHandler('blur.smapi', $a[0]);
12737			},
12738			itemClick: function(e) {
12739				var $a = $(e.currentTarget);
12740
12741				if (!this.handleItemEvents($a)) {
12742					return;
12743				}
12744				$a.removeDataSM('mousedown');
12745				if (this.$root.triggerHandler('click.smapi', $a[0]) === false) {
12746					return false;
12747				}
12748				var $sub = $a.parent().dataSM('sub');
12749				if (this.isTouchMode()) {
12750					// undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu
12751					if ($a.dataSM('href')) {
12752						$a.attr('href', $a.dataSM('href')).removeDataSM('href');
12753					}
12754					// if the sub is not visible
12755					if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12756						// try to activate the item and show the sub
12757						this.itemActivate($a);
12758						// if "itemActivate" showed the sub, prevent the click so that the link is not loaded
12759						// 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
12760						if ($sub.is(':visible')) {
12761							return false;
12762						}
12763					}
12764				} else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) {
12765					this.clickActivated = true;
12766					this.menuShow($sub);
12767					return false;
12768				}
12769				if ($a.hasClass('disabled')) {
12770					return false;
12771				}
12772				if (this.$root.triggerHandler('select.smapi', $a[0]) === false) {
12773					return false;
12774				}
12775			},
12776			itemDown: function(e) {
12777				var $a = $(e.currentTarget);
12778				if (!this.handleItemEvents($a)) {
12779					return;
12780				}
12781				$a.dataSM('mousedown', true);
12782			},
12783			itemEnter: function(e) {
12784				var $a = $(e.currentTarget);
12785				if (!this.handleItemEvents($a)) {
12786					return;
12787				}
12788				if (!this.isTouchMode()) {
12789					if (this.showTimeout) {
12790						clearTimeout(this.showTimeout);
12791						this.showTimeout = 0;
12792					}
12793					var self = this;
12794					this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout);
12795				}
12796				this.$root.triggerHandler('mouseenter.smapi', $a[0]);
12797			},
12798			itemFocus: function(e) {
12799				var $a = $(e.currentTarget);
12800				if (!this.handleItemEvents($a)) {
12801					return;
12802				}
12803				// 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
12804				if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) {
12805					this.itemActivate($a);
12806				}
12807				this.$root.triggerHandler('focus.smapi', $a[0]);
12808			},
12809			itemLeave: function(e) {
12810				var $a = $(e.currentTarget);
12811				if (!this.handleItemEvents($a)) {
12812					return;
12813				}
12814				if (!this.isTouchMode()) {
12815					if ($a[0].blur) {
12816						$a[0].blur();
12817					}
12818					if (this.showTimeout) {
12819						clearTimeout(this.showTimeout);
12820						this.showTimeout = 0;
12821					}
12822				}
12823				$a.removeDataSM('mousedown');
12824				this.$root.triggerHandler('mouseleave.smapi', $a[0]);
12825			},
12826			itemTouchEnd: function(e) {
12827				var $a = $(e.currentTarget);
12828				if (!this.handleItemEvents($a)) {
12829					return;
12830				}
12831				// prevent the address bar on iPhone from sliding down when expanding a sub menu
12832				var $sub = $a.parent().dataSM('sub');
12833				if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) {
12834					$a.dataSM('href', $a.attr('href'));
12835					$a.attr('href', '#');
12836				}
12837			},
12838			menuFixLayout: function($ul) {
12839				// fixes a menu that is being shown for the first time
12840				if (!$ul.dataSM('shown-before')) {
12841					$ul.hide().dataSM('shown-before', true);
12842					// fix the layout of the items in IE<8
12843					if (IElt8) {
12844						$ul.children().css({ styleFloat: 'left', width: '100%' });
12845					}
12846				}
12847			},
12848			menuHide: function($sub) {
12849				if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) {
12850					return;
12851				}
12852				$sub.stop(true, true);
12853				if ($sub.is(':visible')) {
12854					var complete = function() {
12855						// unset z-index
12856						if (IElt9) {
12857							$sub.parent().css('z-index', '');
12858						} else {
12859							$sub.css('z-index', '');
12860						}
12861					};
12862					// if sub is collapsible (mobile view)
12863					if (this.isCollapsible()) {
12864						if (this.opts.collapsibleHideFunction) {
12865							this.opts.collapsibleHideFunction.call(this, $sub, complete);
12866						} else {
12867							$sub.hide(this.opts.collapsibleHideDuration, complete);
12868						}
12869					} else {
12870						if (this.opts.hideFunction) {
12871							this.opts.hideFunction.call(this, $sub, complete);
12872						} else {
12873							$sub.hide(this.opts.hideDuration, complete);
12874						}
12875					}
12876					// remove IE iframe shim
12877					if ($sub.dataSM('ie-shim')) {
12878						$sub.dataSM('ie-shim').remove();
12879					}
12880					// deactivate scrolling if it is activated for this sub
12881					if ($sub.dataSM('scroll')) {
12882						$sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide();
12883					}
12884					// unhighlight parent item
12885					$sub.dataSM('parent-a').removeClass('highlighted');
12886					var level = $sub.dataSM('level');
12887					this.activatedItems.splice(level - 1, 1);
12888					this.visibleSubMenus.splice(level - 1, 1);
12889					this.$root.triggerHandler('hide.smapi', $sub[0]);
12890				}
12891			},
12892			menuHideAll: function($item) {
12893				if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return;
12894				var $win = $(window),
12895					winW = $win.width();
12896				if (this.showTimeout) {
12897					clearTimeout(this.showTimeout);
12898					this.showTimeout = 0;
12899				}
12900				// hide all subs
12901				for (var i = this.visibleSubMenus.length - 1; i > 0; i--) {
12902					if ( this.visibleSubMenus[i].closest('.smartmenu-open-item').length ) {
12903						if ( $item != undefined && $item.closest('.smartmenu-open-item').length ) {
12904							this.menuHide(this.visibleSubMenus[i]);
12905							$(this.visibleSubMenus[i]).closest('.smartmenu-open-item').removeClass('smartmenu-open-item');
12906						} else {
12907							return;
12908						}
12909					} else {
12910						//if ( !this.visibleSubMenus[i].closest('.menu-accordion').length ) {
12911							this.menuHide(this.visibleSubMenus[i]);
12912						//}
12913					}
12914				}
12915				// hide root if it's popup
12916				if (this.opts.isPopup) {
12917					this.$root.stop(true, true);
12918					if (this.$root.is(':visible')) {
12919						if (this.opts.hideFunction) {
12920							this.opts.hideFunction.call(this, this.$root);
12921						} else {
12922							this.$root.hide(this.opts.hideDuration);
12923						}
12924						// remove IE iframe shim
12925						if (this.$root.dataSM('ie-shim')) {
12926							this.$root.dataSM('ie-shim').remove();
12927						}
12928					}
12929				}
12930				this.activatedItems = [];
12931				this.visibleSubMenus = [];
12932				this.clickActivated = false;
12933				// reset z-index increment
12934				this.zIndexInc = 0;
12935			},
12936			menuIframeShim: function($ul) {
12937				// create iframe shim for the menu
12938				if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) {
12939					$ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 })
12940						.css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' })
12941					);
12942				}
12943			},
12944			menuInit: function($ul) {
12945				if (!$ul.dataSM('in-mega')) {
12946					this.subMenus.push($ul);
12947					// mark UL's in mega drop downs (if any) so we can neglect them
12948					if ($ul.hasClass('mega-menu')) {
12949						$ul.find('ul').dataSM('in-mega', true);
12950					}
12951					// get level (much faster than, for example, using parentsUntil)
12952					var level = 2,
12953						par = $ul[0];
12954					while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) {
12955						level++;
12956					}
12957					// cache stuff
12958					$ul.dataSM('parent-a', $ul.prevAll('a').eq(-1))
12959						.dataSM('level', level)
12960						.parent().dataSM('sub', $ul);
12961					// add sub indicator to parent item
12962					if (this.opts.subIndicators) {
12963						$ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone());
12964					}
12965				}
12966			},
12967			menuPosition: function($sub) {
12968				var fixIE = $('html.ie').length;
12969				// if (fixIE) {
12970				// 	var $rowParent = $($sub).closest('.main-menu-container');
12971				// 	$rowParent.height($rowParent.height());
12972				// }
12973				var $a = $sub.dataSM('parent-a'),
12974					$li = $sub.parent(),
12975					$ul = $sub.parent().parent(),
12976					// $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'),
12977					$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'),
12978					level = $sub.dataSM('level'),
12979					subW = this.getWidth($sub),
12980					subH = this.getHeight($sub),
12981					itemOffset = $a.offset(),
12982					itemX = itemOffset.left,
12983					itemY = itemOffset.top,
12984					itemW = this.getWidth($a),
12985					itemH = this.getHeight($a),
12986					$win = $(window),
12987					winX = $win.scrollLeft(),
12988					winY = $win.scrollTop(),
12989					winW = $win.width(),
12990					winH = $win.height(),
12991					containerW = $container.width(),
12992					containerOffsetX = containerW + ((winW - containerW) / 2),
12993					horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'),
12994					subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX,
12995					subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY,
12996					x, y, leftPos;
12997
12998				if (horizontalParent) {
12999					x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX;
13000					y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY;
13001				} else {
13002					x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX;
13003					y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY;
13004				}
13005				if (this.opts.keepInViewport && !this.isCollapsible()) {
13006					if (this.isFixed()) {
13007						itemX -= winX;
13008						itemY -= winY;
13009						winX = winY = 0;
13010					}
13011					var absX = itemX + x,
13012						absY = itemY + y;
13013					if (this.opts.rightToLeftSubMenus && absX < winX) {
13014						x = horizontalParent ? winX - absX + x : itemW - subOffsetX;
13015					} else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) {
13016						x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW;
13017					}
13018					if (!horizontalParent) {
13019						if (subH < winH && absY + subH > winY + winH) {
13020							y += winY + winH - subH - absY;
13021						} else if (subH >= winH || absY < winY) {
13022							y += winY - absY;
13023						}
13024					}
13025					// do we need scrolling?
13026					// 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH"
13027					if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) {
13028						var self = this;
13029						if (!$sub.dataSM('scroll-arrows')) {
13030							$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]])
13031								.bind({
13032									mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); },
13033									mouseleave: function(e) {
13034										self.menuScrollStop($sub);
13035										self.menuScrollOut($sub, e);
13036									},
13037									'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); }
13038								})
13039								.insertAfter($sub)
13040							);
13041						}
13042						// bind events to show/hide arrows on hover and save scrolling data for this sub
13043						var vportY = winY - (itemY + itemH);
13044						$sub.dataSM('scroll', {
13045								vportY: vportY,
13046								subH: subH,
13047								winH: winH,
13048								step: 1
13049							})
13050							.bind({
13051								'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); },
13052								'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); },
13053								'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); }
13054							})
13055							.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
13055StartZIndex() + this.zIndexInc })
13056							.eq(0).css('margin-top', vportY).end()
13057							.eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end()
13058							.eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show();
13059					}
13060				}
13061				if ( !$sub.closest('.menu-accordion').length ) {
13062					var rightPos = 'auto';
13063					if ( $sub.closest('.grid-filters').length ) {
13064						if ( $sub.closest('.text-right').length ) {
13065							leftPos = '0px';
13066							rightPos = 'auto';
13067						} else {
13068							leftPos = 'auto';
13069							rightPos = '0px';
13070						}
13071						x = 0;
13072					} else {
13073						if ( $sub.hasClass('mega-menu-inner') ) {
13074							$sub.css({ width: containerW});
13075							leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left));
13076							if ( ! $('body').hasClass('megamenu-side-to-side') ) {
13077								leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft'));
13078							}
13079							x = 0;
13080						} else {
13081							leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px';
13082							x = (level > 2 && x >= 0) ? x + 1 : x - 1;
13083						}
13084					}
13085				}
13086
13087				// $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) });
13088				$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) });
13089				// IE iframe shim
13090				this.menuIframeShim($sub);
13091				if ($sub.dataSM('ie-shim')) {
13092					$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) });
13093				}
13094			},
13095			menuScroll: function($sub, up, wheel) {
13096				var y = parseFloat($sub.css('margin-top')),
13097					scroll = $sub.dataSM('scroll'),
13098					navH = $('.navbar-main').outerHeight(),
13099					end = scroll.vportY + (up ? navH + 54 : scroll.winH - scroll.subH),
13100					step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step);
13101				$sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end);
13102				y = parseFloat($sub.css('margin-top'));
13103				// show opposite arrow if appropriate
13104				if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) {
13105					$sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show();
13106				}
13107				// accelerate when not using mousewheel to scroll
13108				if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) {
13109					$sub.dataSM('scroll').step += 0.5;
13110				}
13111				// "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used
13112				if (Math.abs(y - end) < 1) {
13113					$sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide();
13114					$sub.dataSM('scroll').step = 1;
13115				} else if (!wheel) {
13116					var self = this;
13117					this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval);
13118				}
13119			},
13120			menuScrollMousewheel: function($sub, e) {
13121				var $closestSub = $(e.target).closest('ul');
13122				while ($closestSub.dataSM('in-mega')) {
13123					$closestSub = $closestSub.parent().closest('ul');
13124				}
13125				if ($closestSub[0] == $sub[0]) {
13126					var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0;
13127					if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) {
13128						this.menuScroll($sub, up, true);
13129					}
13130				}
13131				if ( ! $sub.hasClass('mega-menu-inner') ) {
13132					e.preventDefault();
13133				}
13134			},
13135			menuScrollOut: function($sub, e) {
13136				var reClass = /^scroll-(up|down)/,
13137					$closestSub = $(e.relatedTarget).closest('ul');
13138				while ($closestSub.dataSM('in-mega')) {
13139					$closestSub = $closestSub.parent().closest('ul');
13140				}
13141				if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) {
13142					$sub.dataSM('scroll-arrows').css('visibility', 'hidden');
13143				}
13144			},
13145			menuScrollOver: function($sub, e) {
13146				var reClass = /^scroll-(up|down)/,
13147					$closestSub = $(e.target).closest('ul');
13148				while ($closestSub.dataSM('in-mega')) {
13149					$closestSub = $closestSub.parent().closest('ul');
13150				}
13151				if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) {
13152					$sub.dataSM('scroll-arrows').css('visibility', 'visible');
13153				}
13154			},
13155			menuScrollStop: function($sub) {
13156				if (this.scrollTimeout) {
13157					clearTimeout(this.scrollTimeout);
13158					this.scrollTimeout = 0;
13159					$sub.dataSM('scroll').step = 1;
13160				}
13161			},
13162			menuShow: function($sub) {
13163				if (!$sub.dataSM('beforefirstshowfired')) {
13164					$sub.dataSM('beforefirstshowfired', true);
13165					if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) {
13166						return;
13167					}
13168				}
13169				if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) {
13170					return;
13171				}
13172				this.menuFixLayout($sub);
13173				$sub.stop(true, true);
13174				if (!$sub.is(':visible')) {
13175					$sub.css({
13176						'visibility': 'visible',
13177						'pointer-events': 'auto',
13178					});
13179					// set z-index - for IE < 9 set it to the parent LI
13180					var zIndex = this.getStartZIndex() + (++this.zIndexInc);
13181					if (IElt9) {
13182						$sub.parent().css('z-index', zIndex);
13183					} else {
13184						$sub.css('z-index', zIndex);
13185					}
13186					// highlight parent item
13187					if (this.opts.keepHighlighted || this.isCollapsible()) {
13188						if ($sub.dataSM('parent-a').attr('data-type') != 'title')
13189							$sub.dataSM('parent-a').addClass('highlighted');
13190					}
13191					// min/max-width fix - no way to rely purely on CSS as all UL's are nested
13192					if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) {
13193						if (!IElt8) {
13194							$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13195							if (this.opts.subMenusMinWidth) {
13196							 	$sub.css('min-width', this.opts.subMenusMinWidth);
13197							}
13198							if (this.opts.subMenusMaxWidth) {
13199							 	var noMaxWidth = this.getWidth($sub);
13200							 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13201								 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13202							 	}
13203								if (noMaxWidth > this.getWidth($sub)) {
13204									$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13205								}
13206							}
13207						// IE6,7
13208 						} else {
13209							$sub.children().css('styleFloat', 'none');
13210							if (IE6) {
13211								$sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1)
13212									.children().children('a').css('white-space', 'nowrap');
13213							} else { // IE7
13214								$sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap');
13215								if (this.opts.subMenusMinWidth) {
13216									$sub.css('min-width', this.opts.subMenusMinWidth);
13217								}
13218							}
13219							if (this.opts.subMenusMaxWidth) {
13220								var noMaxWidth = $sub.width();
13221								if (IE6) {
13222							 		var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width();
13223									if (noMaxWidth > maxWidth) {
13224										$sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', '');
13225									} else {
13226										$sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' });
13227									}
13228								} else { // IE7
13229								 	if ( ! $sub.hasClass('mega-menu-inner') ) {
13230									 	$sub.css('max-width', this.opts.subMenusMaxWidth);
13231								 	}
13232									if (noMaxWidth > $sub.width()) {
13233										$sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth);
13234									} else {
13235										$sub.width(noMaxWidth);
13236									}
13237								}
13238							} else {
13239							 	$sub.width($sub.width());
13240							}
13241							$sub.children().css('styleFloat', 'left');
13242						}
13243					}
13244					if ( $sub.hasClass('mega-menu-inner') && $('body').hasClass('scrollable-megamenu') && UNCODE.wwidth > UNCODE.mediaQuery ) {
13245						var $nav = $('.navbar-main'),
13246							navH = 0,
13247							navTop = 0,
13248							$vmenu = $('body.vmenu .vmenu-container, body.menu-overlay .vmenu-container, body.menu-offcanvas .vmenu-container');
13249						if ( $nav.length && typeof $nav[0] !== 'undefined' ) {
13250							var navRect = $nav[0].getBoundingClientRect();
13251							navH = navRect.height;
13252							navTop = navRect.top;
13253						}
13254						if ( ! $vmenu.length ) {
13255							$sub.css({ maxHeight: UNCODE.wheight - navH });
13256						}
13257					}
13258					this.menuPosition($sub);
13259					// insert IE iframe shim
13260					if ($sub.dataSM('ie-shim')) {
13261						$sub.dataSM('ie-shim').insertBefore($sub);
13262					}
13263					var complete = function() {
13264						// fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used
13265						$sub.css('overflow', '');
13266					};
13267					// if sub is collapsible (mobile view)
13268					if (this.isCollapsible()) {
13269						if (this.opts.collapsibleShowFunction) {
13270							this.opts.collapsibleShowFunction.call(this, $sub, complete);
13271						} else {
13272							$sub.show(this.opts.collapsibleShowDuration, complete);
13273						}
13274					} else {
13275						if (this.opts.showFunction) {
13276							this.opts.showFunction.call(this, $sub, complete);
13277						} else {
13278							$sub.show(this.opts.showDuration, complete);
13279						}
13280					}
13281					// save new sub menu for this level
13282					this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub;
13283					this.$root.triggerHandler('show.smapi', $sub[0]);
13284				}
13285			},
13286			popupHide: function(noHideTimeout) {
13287				if (this.hideTimeout) {
13288					clearTimeout(this.hideTimeout);
13289					this.hideTimeout = 0;
13290				}
13291				var self = this;
13292				this.hideTimeout = setTimeout(function() {
13293					self.menuHideAll();
13294				}, noHideTimeout ? 1 : this.opts.hideTimeout);
13295			},
13296			popupShow: function(left, top) {
13297				if (!this.opts.isPopup) {
13298					alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.');
13299					return;
13300				}
13301				if (this.hideTimeout) {
13302					clearTimeout(this.hideTimeout);
13303					this.hideTimeout = 0;
13304				}
13305				this.menuFixLayout(this.$root);
13306				this.$root.stop(true, true);
13307				if (!this.$root.is(':visible')) {
13308					this.$root.css({ left: left, top: top });
13309					// IE iframe shim
13310					this.menuIframeShim(this.$root);
13311					if (this.$root.dataSM('ie-shim')) {
13312						this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
13312: left, top: top }).insertBefore(this.$root);
13313					}
13314					// show menu
13315					if (this.opts.showFunction) {
13316						this.opts.showFunction.call(this, this.$root);
13317					} else {
13318						this.$root.show(this.opts.showDuration);
13319					}
13320					this.visibleSubMenus[0] = this.$root;
13321				}
13322			},
13323			refresh: function() {
13324				this.menuHideAll();
13325				this.$root.find('ul').each(function() {
13326						var $this = $(this);
13327						if ($this.dataSM('scroll-arrows')) {
13328							$this.dataSM('scroll-arrows').remove();
13329						}
13330					})
13331					.removeDataSM('in-mega')
13332					.removeDataSM('shown-before')
13333					.removeDataSM('ie-shim')
13334					.removeDataSM('scroll-arrows')
13335					.removeDataSM('parent-a')
13336					.removeDataSM('level')
13337					.removeDataSM('beforefirstshowfired');
13338				this.$root.find('a.has-submenu').removeClass('has-submenu')
13339					.parent().removeDataSM('sub');
13340				if (this.opts.subIndicators) {
13341					this.$root.find('span.sub-arrow').remove();
13342				}
13343				if (this.opts.markCurrentItem) {
13344					this.$root.find('a.current').removeClass('current');
13345				}
13346				this.subMenus = [];
13347				this.init(true);
13348			},
13349			rootOut: function(e) {
13350				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13351					return;
13352				}
13353				if (this.hideTimeout) {
13354					clearTimeout(this.hideTimeout);
13355					this.hideTimeout = 0;
13356				}
13357				if (!this.opts.showOnClick || !this.opts.hideOnClick) {
13358					var self = this;
13359					this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout);
13360				}
13361			},
13362			rootOver: function(e) {
13363				if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) {
13364					return;
13365				}
13366				if (this.hideTimeout) {
13367					clearTimeout(this.hideTimeout);
13368					this.hideTimeout = 0;
13369				}
13370			},
13371			winResize: function(e) {
13372				if (!this.handleEvents()) {
13373					// we still need to resize the disable overlay if it's visible
13374					if (this.$disableOverlay) {
13375						var pos = this.$root.offset();
13376	 					this.$disableOverlay.css({
13377							top: pos.top,
13378							left: pos.left,
13379							width: this.$root.outerWidth(),
13380							height: this.$root.outerHeight()
13381						});
13382					}
13383					return;
13384				}
13385				// hide sub menus on resize - on mobile do it only on orientation change
13386				if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) {
13387					if (this.activatedItems.length) {
13388						this.activatedItems[this.activatedItems.length - 1][0].blur();
13389					}
13390					this.menuHideAll();
13391				}
13392			}
13393		}
13394	});
13395
13396	$.fn.dataSM = function(key, val) {
13397		if (val) {
13398			return this.data(key + '_smartmenus', val);
13399		}
13400		return this.data(key + '_smartmenus');
13401	}
13402
13403	$.fn.removeDataSM = function(key) {
13404		return this.removeData(key + '_smartmenus');
13405	}
13406
13407	$.fn.smartmenus = function(options) {
13408		if (typeof options == 'string') {
13409			var args = arguments,
13410				method = options;
13411			Array.prototype.shift.call(args);
13412			return this.each(function() {
13413				var smartmenus = $(this).data('smartmenus');
13414				if (smartmenus && smartmenus[method]) {
13415					smartmenus[method].apply(smartmenus, args);
13416				}
13417			});
13418		}
13419		var opts = $.extend({}, $.fn.smartmenus.defaults, options);
13420		return this.each(function() {
13421			new $.SmartMenus(this, opts);
13422		});
13423	}
13424
13425	// default settings
13426	$.fn.smartmenus.defaults = {
13427		isPopup:		false,		// is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar
13428		mainMenuSubOffsetX:	0,		// pixels offset from default position
13429		mainMenuSubOffsetY:	0,		// pixels offset from default position
13430		subMenusSubOffsetX:	0,		// pixels offset from default position
13431		subMenusSubOffsetY:	0,		// pixels offset from default position
13432		subMenusMinWidth:	false, //'10em',		// min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13433		subMenusMaxWidth:	false, //'20em',		// max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored
13434		subIndicators: 		true,		// create sub menu indicators - creates a SPAN and inserts it in the A
13435		subIndicatorsPos: 	'prepend',	// position of the SPAN relative to the menu item content ('prepend', 'append')
13436		subIndicatorsText:	'+',		// [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too)
13437		scrollStep: 		30,		// pixels step when scrolling long sub menus that do not fit in the viewport height
13438		scrollInterval:		30,		// interval between each scrolling step
13439		scrollAccelerate:	true,		// accelerate scrolling or use a fixed step
13440		showTimeout:		250,		// timeout before showing the sub menus
13441		hideTimeout:		500,		// timeout before hiding the sub menus
13442		showDuration:		0,		// duration for show animation - set to 0 for no animation - matters only if showFunction:null
13443		showFunction:		null,		// custom function to use when showing a sub menu (the default is the jQuery 'show')
13444							// don't forget to call complete() at the end of whatever you do
13445							// e.g.: function($ul, complete) { $ul.fadeIn(250, complete); }
13446		hideDuration:		0,		// duration for hide animation - set to 0 for no animation - matters only if hideFunction:null
13447		hideFunction:		function($ul, complete) { $ul.fadeOut(200, complete); },	// custom function to use when hiding a sub menu (the default is the jQuery 'hide')
13448							// don't forget to call complete() at the end of whatever you do
13449							// e.g.: function($ul, complete) { $ul.fadeOut(250, complete); }
13450		collapsibleShowDuration:0,		// duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null
13451		collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); },	// custom function to use when showing a collapsible sub menu
13452							// (i.e. when mobile styles are used to make the sub menus collapsible)
13453		collapsibleHideDuration:0,		// duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null
13454		collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); },	// custom function to use when hiding a collapsible sub menu
13455							// (i.e. when mobile styles are used to make the sub menus collapsible)
13456		showOnClick:		false,		// show the first-level sub menus onclick instead of onmouseover (matters only for mouse input)
13457		hideOnClick:		true,		// hide the sub menus on click/tap anywhere on the page
13458		keepInViewport:		true,		// reposition the sub menus if needed to make sure they always appear inside the viewport
13459		keepHighlighted:	true,		// keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's)
13460		markCurrentItem:	false,		// automatically add the 'current' class to the A element of the item linking to the current URL
13461		markCurrentTree:	true,		// add the 'current' class also to the A elements of all ancestor items of the current item
13462		rightToLeftSubMenus:	false,		// right to left display of the sub menus (check the CSS for the sub indicators' position)
13463		bottomToTopSubMenus:	false,		// bottom to top display of the sub menus
13464		overlapControlsInIE:	true		// make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.)
13465	};
13466
13467})(jQuery);
13468/*
13469 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
13470 * Open source under the BSD License.
13471 * Copyright © 2008 George McGinley Smith
13472 * All rights reserved.
13473 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE
13474*/
13475
13476/* globals jQuery, define, module, require */
13477(function (factory) {
13478	if (typeof define === "function" && define.amd) {
13479		define(['jquery'], function ($) {
13480			return factory($);
13481		});
13482	} else if (typeof module === "object" && typeof module.exports === "object") {
13483		module.exports = factory(require('jquery'));
13484	} else {
13485		factory(jQuery);
13486	}
13487})(function($){
13488
13489	// Preserve the original jQuery "swing" easing as "jswing"
13490	if (typeof $.easing !== 'undefined') {
13491		$.easing['jswing'] = $.easing['swing'];
13492	}
13493
13494	var pow = Math.pow,
13495		sqrt = Math.sqrt,
13496		sin = Math.sin,
13497		cos = Math.cos,
13498		PI = Math.PI,
13499		c1 = 1.70158,
13500		c2 = c1 * 1.525,
13501		c3 = c1 + 1,
13502		c4 = ( 2 * PI ) / 3,
13503		c5 = ( 2 * PI ) / 4.5;
13504
13505	// x is the fraction of animation progress, in the range 0..1
13506	function bounceOut(x) {
13507		var n1 = 7.5625,
13508			d1 = 2.75;
13509		if ( x < 1/d1 ) {
13510			return n1*x*x;
13511		} else if ( x < 2/d1 ) {
13512			return n1*(x-=(1.5/d1))*x + .75;
13513		} else if ( x < 2.5/d1 ) {
13514			return n1*(x-=(2.25/d1))*x + .9375;
13515		} else {
13516			return n1*(x-=(2.625/d1))*x + .984375;
13517		}
13518	}
13519
13520	$.extend( $.easing, {
13521		def: 'easeOutQuad',
13522		swing: function (x) {
13523			return $.easing[$.easing.def](x);
13524		},
13525		easeInQuad: function (x) {
13526			return x * x;
13527		},
13528		easeOutQuad: function (x) {
13529			return 1 - ( 1 - x ) * ( 1 - x );
13530		},
13531		easeInOutQuad: function (x) {
13532			return x < 0.5 ?
13533				2 * x * x :
13534				1 - pow( -2 * x + 2, 2 ) / 2;
13535		},
13536		easeInCubic: function (x) {
13537			return x * x * x;
13538		},
13539		easeOutCubic: function (x) {
13540			return 1 - pow( 1 - x, 3 );
13541		},
13542		easeInOutCubic: function (x) {
13543			return x < 0.5 ?
13544				4 * x * x * x :
13545				1 - pow( -2 * x + 2, 3 ) / 2;
13546		},
13547		easeInQuart: function (x) {
13548			return x * x * x * x;
13549		},
13550		easeOutQuart: function (x) {
13551			return 1 - pow( 1 - x, 4 );
13552		},
13553		easeInOutQuart: function (x) {
13554			return x < 0.5 ?
13555				8 * x * x * x * x :
13556				1 - pow( -2 * x + 2, 4 ) / 2;
13557		},
13558		easeInQuint: function (x) {
13559			return x * x * x * x * x;
13560		},
13561		easeOutQuint: function (x) {
13562			return 1 - pow( 1 - x, 5 );
13563		},
13564		easeInOutQuint: function (x) {
13565			return x < 0.5 ?
13566				16 * x * x * x * x * x :
13567				1 - pow( -2 * x + 2, 5 ) / 2;
13568		},
13569		easeInSine: function (x) {
13570			return 1 - cos( x * PI/2 );
13571		},
13572		easeOutSine: function (x) {
13573			return sin( x * PI/2 );
13574		},
13575		easeInOutSine: function (x) {
13576			return -( cos( PI * x ) - 1 ) / 2;
13577		},
13578		easeInExpo: function (x) {
13579			return x === 0 ? 0 : pow( 2, 10 * x - 10 );
13580		},
13581		easeOutExpo: function (x) {
13582			return x === 1 ? 1 : 1 - pow( 2, -10 * x );
13583		},
13584		easeInOutExpo: function (x) {
13585			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13586				pow( 2, 20 * x - 10 ) / 2 :
13587				( 2 - pow( 2, -20 * x + 10 ) ) / 2;
13588		},
13589		easeInCirc: function (x) {
13590			return 1 - sqrt( 1 - pow( x, 2 ) );
13591		},
13592		easeOutCirc: function (x) {
13593			return sqrt( 1 - pow( x - 1, 2 ) );
13594		},
13595		easeInOutCirc: function (x) {
13596			return x < 0.5 ?
13597				( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 :
13598				( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2;
13599		},
13600		easeInElastic: function (x) {
13601			return x === 0 ? 0 : x === 1 ? 1 :
13602				-pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 );
13603		},
13604		easeOutElastic: function (x) {
13605			return x === 0 ? 0 : x === 1 ? 1 :
13606				pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1;
13607		},
13608		easeInOutElastic: function (x) {
13609			return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ?
13610				-( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 :
13611				pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1;
13612		},
13613		easeInBack: function (x) {
13614			return c3 * x * x * x - c1 * x * x;
13615		},
13616		easeOutBack: function (x) {
13617			return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 );
13618		},
13619		easeInOutBack: function (x) {
13620			return x < 0.5 ?
13621				( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 :
13622				( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2;
13623		},
13624		easeInBounce: function (x) {
13625			return 1 - bounceOut( 1 - x );
13626		},
13627		easeOutBounce: bounceOut,
13628		easeInOutBounce: function (x) {
13629			return x < 0.5 ?
13630				( 1 - bounceOut( 1 - 2 * x ) ) / 2 :
13631				( 1 + bounceOut( 2 * x - 1 ) ) / 2;
13632		}
13633	});
13634	return $;
13635});
13636
13637/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
13638 * Licensed under the MIT License (LICENSE.txt).
13639 *
13640 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
13641 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
13642 * Thanks to: Seamus Leahy for adding deltaX and deltaY
13643 *
13644 * Version: 3.0.6
13645 *
13646 * Requires: 1.2.2+
13647 */
13648(function($) {
13649    var types = ['DOMMouseScroll', 'mousewheel'];
13650    if ($.event.fixHooks) {
13651        for (var i = types.length; i;) {
13652            $.event.fixHooks[types[--i]] = $.event.mouseHooks;
13653        }
13654    }
13655    $.event.special.mousewheel = {
13656        setup: function() {
13657            if (this.addEventListener) {
13658                for (var i = types.length; i;) {
13659                    this.addEventListener(types[--i], handler, false);
13660                }
13661            } else {
13662                this.onmousewheel = handler;
13663            }
13664        },
13665        teardown: function() {
13666            if (this.removeEventListener) {
13667                for (var i = types.length; i;) {
13668                    this.removeEventListener(types[--i], handler, false);
13669                }
13670            } else {
13671                this.onmousewheel = null;
13672            }
13673        }
13674    };
13675    $.fn.extend({
13676        mousewheel: function(fn) {
13677            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
13678        },
13679        unmousewheel: function(fn) {
13680            return this.unbind("mousewheel", fn);
13681        }
13682    });
13683
13684    function handler(event) {
13685        var orgEvent = event || window.event,
13686            args = [].slice.call(arguments, 1),
13687            delta = 0,
13688            returnValue = true,
13689            deltaX = 0,
13690            deltaY = 0;
13691        event = $.event.fix(orgEvent);
13692        event.type = "mousewheel";
13693        // Old school scrollwheel delta
13694        if (orgEvent.wheelDelta) {
13695            delta = orgEvent.wheelDelta / 120;
13696        }
13697        if (orgEvent.detail) {
13698            delta = -orgEvent.detail / 3;
13699        }
13700        // New school multidimensional scroll (touchpads) deltas
13701        deltaY = delta;
13702        // Gecko
13703        if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
13704            deltaY = 0;
13705            deltaX = -1 * delta;
13706        }
13707        // Webkit
13708        if (orgEvent.wheelDeltaY !== undefined) {
13709            deltaY = orgEvent.wheelDeltaY / 120;
13710        }
13711        if (orgEvent.wheelDeltaX !== undefined) {
13712            deltaX = -1 * orgEvent.wheelDeltaX / 120;
13713        }
13714        // Add event and delta to the front of the arguments
13715        args.unshift(event, delta, deltaX, deltaY);
13716        return ($.event.dispatch || $.event.handle).apply(this, args);
13717    }
13718})(jQuery);
13719/**
13720 * jQuery iLightBox - Revolutionary Lightbox Plugin
13721 * http://www.ilightbox.net/
13722 *
13723 * @version: 2.2.4 - October 14, 2017
13724 *
13725 * @author: iProDev (Hemn Chawroka)
13726 *          http://www.iprodev.com/
13727 *
13728 */
13729(function($, window, undefined) {
13730
13731	var extensions = {
13732			flash: ['swf'],
13733			image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'],
13734			iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'],
13735			video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v']
13736		},
13737
13738		// Global DOM elements
13739		$win = $(window),
13740		$doc = $(document),
13741
13742		// Support indicators
13743		browser,
13744		transform,
13745		gpuAcceleration,
13746		fullScreenApi = '',
13747		userAgent = navigator.userAgent || navigator.vendor || window.opera,
13748        supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1),
13749        ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1,
13750        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)),
13751
13752		// Events
13753		clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox",
13754		touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox",
13755		touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox",
13756		touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox",
13757
13758		// Math shorthands
13759		abs = Math.abs,
13760		sqrt = Math.sqrt,
13761		round = Math.round,
13762		max = Math.max,
13763		min = Math.min,
13764		floor = Math.floor,
13765		random = Math.random,
13766
13767		pluginspages = {
13768			quicktime: 'http://www.apple.com/quicktime/download',
13769			flash: 'http://www.adobe.com/go/getflash'
13770		},
13771
13772		iLightBox = function(el, options, items, instant) {
13773			var iL = this;
13774
13775			iL.options = options,
13776				iL.selector = options.selector || el,
13777				iL.context = document,
13778				iL.instant = instant;
13779
13780			if (items.length < 1) iL.attachItems();
13781			else iL.items = items;
13782
13783			iL.vars = {
13784				total: iL.items.length,
13785				start: 0,
13786				current: null,
13787				next: null,
13788				prev: null,
13789				BODY: $('body'),
13790				loadRequests: 0,
13791				overlay: $('<div class="ilightbox-overlay"></div>'),
13792				loader: $('<div class="ilightbox-loader"><div></div></div>'),
13793				toolbar: $('<div class="ilightbox-toolbar"></div>'),
13794				innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'),
13795				title: $('<div class="ilightbox-title"></div>'),
13796				closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'),
13797				fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'),
13798				innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'),
13799				innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'),
13800				innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'),
13801				holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13802				nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13803				prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'),
13804				nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'),
13805				prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13806				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>'),
13807				thumbs: false,
13808				nextLock: false,
13809				prevLock: false,
13810				hashLock: false,
13811				isMobile: false,
13812				mobileMaxWidth: 980,
13813				isInFullScreen: false,
13814				isSwipe: false,
13815				mouseID: 0,
13816				cycleID: 0,
13817				isPaused: 0,
13818				captionHeight: 39,
13819			};
13820
13821			// Hideable elements with mousemove event
13822			iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton);
13823
13824			iL.normalizeItems();
13825
13826			//Check necessary plugins
13827			iL.availPlugins();
13828
13829			//Set startFrom
13830			iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom;
13831
13832			//If randomStart
13833			iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom;
13834			iL.vars.start = iL.options.startFrom;
13835
13836			if (instant) iL.instantCall();
13837			else iL.patchItemsEvents();
13838
13839			if (iL.options.linkId) {
13840				iL.hashChangeHandler();
13841				$win.iLightBoxHashChange(function() {
13842					iL.hashChangeHandler();
13843				});
13844			}
13845
13846			if (supportTouch) {
13847				var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig,
13848					replace = "itap";
13849				iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace),
13850					iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace),
13851					iL.options.social.show = iL.options.social.show.replace(RegExp, replace),
13852					iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace);
13853			}
13854
13855			if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) {
13856				$.extend(iL.options.styles, {
13857					nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13858					prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4,
13859					nextOpacity: 0,
13860					prevOpacity: 0
13861				});
13862			}
13863		};
13864
13865	//iLightBox helpers
13866	iLightBox.prototype = {
13867		showLoader: function() {
13868			var iL = this;
13869			iL.vars.loadRequests += 1;
13870			if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({
13871				//top: '-30px'
13872				opacity: '1'
13873			}, iL.options.show.speed, 'easeOutCirc');
13874			else iL.vars.loader.addClass('ilightbox-show').stop().animate({
13875				//left: '-30px'
13876				opacity: '1'
13877			}, iL.options.show.speed, 'easeOutCirc');
13878		},
13879
13880		hideLoader: function() {
13881			var iL = this;
13882			iL.vars.loadRequests -= 1;
13883			iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests;
13884			if (iL.options.path.toLowerCase() == "horizontal") {
13885				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13886					//top: '-192px'
13887					opacity: '0'
13888				}, iL.options.show.speed, 'easeInCirc');
13889			} else {
13890				if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({
13891					//left: '-192px'
13892					opacity: '0'
13893				}, iL.options.show.speed, 'easeInCirc');
13894			}
13895		},
13896
13897		createUI: function() {
13898			var iL = this;
13899
13900			iL.ui = {
13901				currentElement: iL.vars.holder,
13902				nextElement: iL.vars.nextPhoto,
13903				prevElement: iL.vars.prevPhoto,
13904				currentItem: iL.vars.current,
13905				nextItem: iL.vars.next,
13906				prevItem: iL.vars.prev,
13907				hide: function() {
13908					iL.closeAction();
13909				},
13910				refresh: function() {
13911					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
13912				},
13913				fullscreen: function() {
13914					iL.fullScreenAction();
13915				}
13916			};
13917		},
13918
13919		attachItems: function() {
13920			var iL = this,
13921				itemsObject = new Array(),
13922				items = new Array();
13923
13924			$(iL.selector, iL.context).each(function() {
13925				var t = $(this),
13926					URL = t.attr(iL.options.attr) || null,
13927					options = t.data("options") && eval("({" + t.data("options") + "})") || {},
13928					caption = t.data('caption'),
13929					title = t.data('title'),
13930					type = t.data('type') || getTypeByExtension(URL),
13931					clone = t.data('lbox-clone') || false;
13932
13933				//Uncode addition ##START##
13934				if (type === false) {
13935					return;
13936				}
13937				//Uncode addition ##END##
13938
13939				if (t.data('lbox-clone') != undefined) return;
13940
13941				//Uncode addition ##START##
13942				if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) {
13943					var ALBUM_URLS = JSON.parse(t.attr('data-album')),
13944						URL_i,
13945						URLS_LENGHT = ALBUM_URLS.length;
13946
13947					for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) {
13948						if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) {
13949							var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\'';
13950							item_opts = item_opts && eval("({" + item_opts + "})") || {},
13951							items.push({
13952								URL: ALBUM_URLS[URL_i].url,
13953								caption: ALBUM_URLS[URL_i].caption,
13954								title: ALBUM_URLS[URL_i].title,
13955								type: getTypeByExtension(ALBUM_URLS[URL_i].url),
13956								options: item_opts,
13957								clone: clone
13958							});
13959							var newT = t;
13960							newT.attr('href',ALBUM_URLS[URL_i].url);
13961							if (!iL.instant) itemsObject.push(newT);
13962						}
13963					}
13964				} else {
13965				//Uncode addition ##END##
13966					items.push({
13967						URL: URL,
13968						caption: caption,
13969						title: title,
13970						type: type,
13971						options: options,
13972						clone: clone
13973					});
13974				}
13975
13976
13977				if (iL.vars != undefined) iL.vars.total = items.length;
13978
13979				if (!iL.instant) itemsObject.push(t);
13980			});
13981
13982			iL.items = items,
13983				iL.itemsObject = itemsObject;
13984
13985		},
13986
13987		normalizeItems: function() {
13988			var iL = this,
13989				newItems = new Array();
13990
13991			$.each(iL.items, function(key, val) {
13992
13993				if (typeof val == "string") val = {
13994					url: val
13995				};
13996
13997				var URL = val.url || val.URL || null,
13998					options = val.options || {},
13999					caption = val.caption || null,
14000					title = val.title || null,
14001					type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL),
14002					ext = (typeof URL != 'object') ? getExtension(URL) : '';
14003
14004				options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
14005				options.videoType = options.videoType || null,
14006				options.skin = options.skin || iL.options.skin,
14007				options.width = options.width || null,
14008				options.height = options.height || null,
14009				options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true,
14010				options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true,
14011				options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons);
14012
14013				if (type == "video") {
14014					options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {};
14015
14016					options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null;
14017					options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls";
14018					options.html5video.preload = options.html5video.preload || "metadata";
14019					options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false;
14020					//UNCODE addition
14021					options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false;
14022				}
14023
14024				if (!options.width || !options.height) {
14025					if (type == "video") options.width = 1280, options.height = 720;
14026					else if (type == "iframe") options.width = '100%', options.height = '90%';
14027					else if (type == "flash") options.width = 1280, options.height = 720;
14028				}
14029
14030				delete val.url;
14031				val.index = key;
14032				val.URL = URL;
14033				val.caption = caption;
14034				val.title = title;
14035				val.type = type;
14036				val.options = options;
14037				val.ext = ext;
14038
14039				newItems.push(val);
14040			});
14041
14042			iL.items = newItems;
14043		},
14044
14045		instantCall: function() {
14046			var iL = this,
14047				key = iL.vars.start;
14048
14049			iL.vars.current = key;
14050			iL.vars.next = (iL.items[key + 1]) ? key + 1 : null;
14051			iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null;
14052
14053			iL.addContents();
14054			iL.patchEvents();
14055		},
14056
14057		addContents: function() {
14058			var iL = this,
14059				vars = iL.vars,
14060				opts = iL.options,
14061				viewport = getViewport(),
14062				path = opts.path.toLowerCase(),
14063				recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) {
14064					return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition);
14065				}),
14066				needRecognition = recognizingItems.length > 0;
14067
14068			if (opts.mobileOptimizer && !opts.innerToolbar)
14069				vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14070
14071			vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity);
14072
14073			if (opts.linkId)
14074				vars.overlay[0].setAttribute('linkid', opts.linkId);
14075
14076			//Add Toolbar Buttons
14077			if (opts.controls.toolbar) {
14078				vars.toolbar.addClass(opts.skin).append(vars.closeButton);
14079				if (opts.controls.fullscreen)
14080					vars.toolbar.append(vars.fullScreenButton);
14081				if (opts.controls.slideshow)
14082					vars.toolbar.append(vars.innerPlayButton);
14083				if (vars.total > 1)
14084					vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton);
14085			}
14086
14087			//Append elements to body
14088			vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto);
14089
14090			if (!opts.innerToolbar)
14091				vars.BODY.append(vars.toolbar);
14092			if (opts.controls.arrows)
14093				vars.BODY.append(vars.nextButton).append(vars.prevButton);
14094
14095			if (opts.controls.thumbnail && vars.total > 1) {
14096				vars.BODY.append(vars.thumbnails);
14097				vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path);
14098				$('div.ilightbox-thumbnails-grid', vars.thumbnails).empty();
14099				vars.thumbs = true;
14100			}
14101
14102			//Configure loader and arrows
14103			var loaderCss = (opts.path.toLowerCase() == "horizontal") ? {
14104				left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2))
14105			} : {
14106				top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2))
14107			};
14108			vars.loader.addClass(opts.skin).css(loaderCss);
14109			vars.nextButton.add(vars.prevButton).addClass(opts.skin);
14110			if (path == "horizontal")
14111				vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal');
14112
14113			// Configure arrow buttons
14114			vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14115
14116			if (!opts.infinite) {
14117				vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
14118
14119				if (vars.current == 0)
14120					vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
14121				if (vars.current >= vars.total - 1)
14122					vars.nextButton.add(vars.innerNextButton).addClass('disabled');
14123			}
14124
14125			if (opts.show.effect) {
14126				vars.overlay.stop().fadeIn(opts.show.speed);
14127				vars.toolbar.stop().fadeIn(opts.show.speed);
14128			} else {
14129				vars.overlay.show();
14130				vars.toolbar.show();
14131			}
14132
14133			var length = recognizingItems.length;
14134			if (needRecognition) {
14135				iL.showLoader();
14136
14137				$.each(recognizingItems, function(key, val) {
14138					var resultFnc = function(result) {
14139							var key = -1,
14140								filter = iL.items.filter(function(e, i, arr) {
14141									if (e.URL == result.url)
14142										key = i;
14143
14144									return e.URL == result.url;
14145								}),
14146								self = iL.items[key];
14147
14148							if (result)
14149								$.extend(true, self, {
14150									URL: result.source,
14151									type: result.type,
14152									recognized: true,
14153									options: {
14154										html5video: result.html5video,
14155										width: (result.type == "image") ? 0 : (result.width || self.width),
14156										height: (result.type == "image") ? 0 : (result.height || self.height),
14157										thumbnail: self.options.thumbnail || result.thumbnail
14158									}
14159								});
14160
14161							length--;
14162
14163							if (length == 0) {
14164								iL.hideLoader();
14165
14166								vars.dontGenerateThumbs = false;
14167								iL.generateThumbnails();
14168
14169								if (opts.show.effect)
14170									setTimeout(function() {
14171										iL.generateBoxes();
14172									}, opts.show.speed);
14173								else
14174									iL.generateBoxes();
14175							}
14176						};
14177
14178					iL.ogpRecognition(this, resultFnc);
14179				});
14180			}
14181			else {
14182				if (opts.show.effect)
14183					setTimeout(function() {
14184						iL.generateBoxes();
14185					}, opts.show.speed);
14186				else
14187					iL.generateBoxes();
14188			}
14189
14190			iL.createUI();
14191
14192			window.iLightBox = {
14193				close: function() {
14194					iL.closeAction();
14195				},
14196				fullscreen: function() {
14197					iL.fullScreenAction();
14198				},
14199				moveNext: function() {
14200					iL.moveTo('next');
14201				},
14202				movePrev: function() {
14203					iL.moveTo('prev');
14204				},
14205				goTo: function(index) {
14206					iL.goTo(index);
14207				},
14208				refresh: function() {
14209					iL.refresh();
14210				},
14211				reposition: function() {
14212					(arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto();
14213				},
14214				setOption: function(options) {
14215					iL.setOption(options);
14216				},
14217				destroy: function() {
14218					iL.closeAction();
14219					iL.dispatchItemsEvents();
14220				}
14221			};
14222
14223			if (opts.linkId) {
14224				vars.hashLock = true;
14225				window.location.hash = opts.linkId + '/' + vars.current;
14226				setTimeout(function() {
14227					vars.hashLock = false;
14228				}, 55);
14229			}
14230
14231			if (!opts.slideshow.startPaused) {
14232				iL.resume();
14233				vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause');
14234			}
14235
14236			//Trigger the onOpen callback
14237			if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL);
14238		},
14239
14240		loadContent: function(obj, opt, speed) {
14241			var iL = this,
14242				holder, item;
14243
14244			iL.createUI();
14245
14246			obj.speed = speed || iL.options.effects.loadedFadeSpeed;
14247
14248			if (opt == 'current') {
14249				if (!obj.options.mousewheel) iL.vars.lockWheel = true;
14250				else iL.vars.lockWheel = false;
14251
14252				if (!obj.options.swipe) iL.vars.lockSwipe = true;
14253				else iL.vars.lockSwipe = false;
14254			}
14255
14256			switch (opt) {
14257				case 'current':
14258					holder = iL.vars.holder, item = iL.vars.current;
14259					break;
14260				case 'next':
14261					holder = iL.vars.nextPhoto, item = iL.vars.next;
14262					break;
14263				case 'prev':
14264					holder = iL.vars.prevPhoto, item = iL.vars.prev;
14265					break;
14266			}
14267
14268			holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin);
14269			$('div.ilightbox-inner-toolbar', holder).remove();
14270
14271			if (obj.title || iL.options.innerToolbar) {
14272				var innerToolbar = iL.vars.innerToolbar.clone();
14273				if (obj.title && iL.options.show.title) {
14274					var title = iL.vars.title.clone();
14275					title.empty().html(obj.title);
14276					innerToolbar.append(title);
14277				}
14278				if (iL.options.innerToolbar) {
14279					innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar);
14280				}
14281				holder.prepend(innerToolbar);
14282			}
14283
14284			//console.warn('loadContent', arguments);
14285
14286			iL.loadSwitcher(obj, holder, item, opt);
14287		},
14288
14289		loadSwitcher: function(obj, holder, item, opt) {
14290			var iL = this,
14291				opts = iL.options,
14292				api = {
14293					element: holder,
14294					position: item
14295				};
14296
14297			switch (obj.type) {
14298				case 'image':
14299					//Trigger the onBeforeLoad callback
14300					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14301					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14302
14303					iL.loadImage(obj.URL, function(img) {
14304						//Trigger the onAfterLoad callback
14305						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14306						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14307
14308						var width = (img) ? img.width : 400,
14309							height = (img) ? img.height : 200;
14310
14311						holder.data({
14312							naturalWidth: width,
14313							naturalHeight: height
14314						});
14315
14316						$('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>');
14317
14318						//Trigger the onRender callback
14319						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14320						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14321
14322						iL.configureHolder(obj, opt, holder);
14323					});
14324
14325					break;
14326
14327				case 'video':
14328					holder.data({
14329						naturalWidth: obj.options.width,
14330						naturalHeight: obj.options.height
14331					});
14332
14333					if (opt === 'current') {
14334						iL.addContent(holder, obj);
14335
14336						//Trigger the onRender callback
14337						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14338						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14339					} else {
14340						$('div.ilightbox-container', holder).empty();
14341					}
14342
14343					iL.configureHolder(obj, opt, holder);
14344
14345					break;
14346
14347				case 'iframe':
14348					//iL.showLoader();
14349					holder.data({
14350						naturalWidth: obj.options.width,
14351						naturalHeight: obj.options.height
14352					});
14353
14354					iL.configureHolder(obj, opt, holder);
14355
14356					if (opt === 'current') {
14357						var el = iL.addContent(holder, obj);
14358
14359						//Trigger the onRender callback
14360						if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14361						if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14362
14363						//Trigger the onBeforeLoad callback
14364						if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14365						if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14366
14367						el.bind('load', function() {
14368							//Trigger the onAfterLoad callback
14369							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14370							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14371
14372							//iL.hideLoader();
14373							el.unbind('load');
14374						});
14375					} else {
14376						$('div.ilightbox-container', holder).empty();
14377					}
14378
14379					break;
14380
14381				case 'inline':
14382					var el = $(obj.URL),
14383						content = iL.addContent(holder, obj),
14384						images = findImageInElement(holder);
14385
14386					holder.data({
14387						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14388						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14389					});
14390					content.children().eq(0).show();
14391
14392					//Trigger the onRender callback
14393					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14394					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14395
14396					//Trigger the onBeforeLoad callback
14397					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14398					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14399
14400					iL.loadImage(images, function() {
14401						//Trigger the onAfterLoad callback
14402						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14403						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14404
14405						iL.configureHolder(obj, opt, holder);
14406					});
14407
14408					break;
14409
14410				case 'flash':
14411					var el = iL.addContent(holder, obj);
14412
14413					holder.data({
14414						naturalWidth: (iL.items[item].options.width || el.outerWidth()),
14415						naturalHeight: (iL.items[item].options.height || el.outerHeight())
14416					});
14417
14418					//Trigger the onRender callback
14419					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14420					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14421
14422					iL.configureHolder(obj, opt, holder);
14423
14424					break;
14425
14426				case 'ajax':
14427					var ajax = obj.options.ajax || {};
14428					//Trigger the onBeforeLoad callback
14429					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14430					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14431
14432					iL.showLoader();
14433					$.ajax({
14434						url: obj.URL || opts.ajaxSetup.url,
14435						data: ajax.data || null,
14436						dataType: ajax.dataType || "html",
14437						type: ajax.type || opts.ajaxSetup.type,
14438						cache: ajax.cache || opts.ajaxSetup.cache,
14439						crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain,
14440						global: ajax.global || opts.ajaxSetup.global,
14441						ifModified: ajax.ifModified || opts.ajaxSetup.ifModified,
14442						username: ajax.username || opts.ajaxSetup.username,
14443						password: ajax.password || opts.ajaxSetup.password,
14444						beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend,
14445						complete: ajax.complete || opts.ajaxSetup.complete,
14446						success: function(data, textStatus, jqXHR) {
14447							iL.hideLoader();
14448
14449							var el = $(data),
14450								container = $('div.ilightbox-container', holder),
14451								elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')),
14452								elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')),
14453								css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? {
14454									'overflow': 'hidden'
14455								} : {};
14456
14457							container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el));
14458							holder.show().data({
14459								naturalWidth: (elWidth || container.outerWidth()),
14460								naturalHeight: (elHeight || container.outerHeight())
14461							}).hide();
14462
14463							//Trigger the onRender callback
14464							if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14465							if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14466
14467							var images = findImageInElement(holder);
14468							iL.loadImage(images, function() {
14469								//Trigger the onAfterLoad callback
14470								if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14471								if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14472
14473								iL.configureHolder(obj, opt, holder);
14474							});
14475
14476							opts.ajaxSetup.success(data, textStatus, jqXHR);
14477							if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR);
14478						},
14479						error: function(jqXHR, textStatus, errorThrown) {
14480							//Trigger the onAfterLoad callback
14481							if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14482							if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14483
14484							iL.hideLoader();
14485							$('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>');
14486							iL.configureHolder(obj, opt, holder);
14487
14488							opts.ajaxSetup.error(jqXHR, textStatus, errorThrown);
14489							if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown);
14490						}
14491					});
14492
14493					break;
14494
14495				case 'html':
14496					var object = obj.URL,
14497						el
14498					container = $('div.ilightbox-container', holder);
14499
14500					if (object[0].nodeName) el = object.clone();
14501					else {
14502						var dom = $(object);
14503						if (dom.selector) el = $('<div>' + dom + '</div>');
14504						else el = dom;
14505					}
14506
14507					var elWidth = iL.items[item].options.width || parseInt(el.attr('width')),
14508						elHeight = iL.items[item].options.height || parseInt(el.attr('height'));
14509
14510					iL.addContent(holder, obj);
14511
14512					el.appendTo(document.documentElement).hide();
14513
14514					//Trigger the onRender callback
14515					if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item);
14516					if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api);
14517
14518					var images = findImageInElement(holder);
14519
14520					//Trigger the onBeforeLoad callback
14521					if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item);
14522					if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api);
14523
14524					iL.loadImage(images, function() {
14525						//Trigger the onAfterLoad callback
14526						if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item);
14527						if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api);
14528
14529						holder.show().data({
14530							naturalWidth: (elWidth || container.outerWidth()),
14531							naturalHeight: (elHeight || container.outerHeight())
14532						}).hide();
14533						el.remove();
14534
14535						iL.configureHolder(obj, opt, holder);
14536					});
14537
14538					break;
14539			}
14540		},
14541
14542		configureHolder: function(obj, opt, holder) {
14543			var iL = this,
14544				vars = iL.vars,
14545				opts = iL.options;
14546
14547			if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev');
14548
14549			if (opt == "current")
14550				var item = vars.current;
14551			else if (opt == "next")
14552				var opacity = opts.styles.nextOpacity,
14553					item = vars.next;
14554			else
14555				var opacity = opts.styles.prevOpacity,
14556					item = vars.prev;
14557
14558			var api = {
14559				element: holder,
14560				position: item
14561			};
14562
14563			iL.items[item].options.width = iL.items[item].options.width || 0,
14564			iL.items[item].options.height = iL.items[item].options.height || 0;
14565
14566			if (opt == "current") {
14567				if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() {
14568					holder.css(transform, '');
14569					if (obj.caption) {
14570						iL.setCaption(obj, holder);
14571						var caption = $('div.ilightbox-caption', holder),
14572							percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100);
14573						if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
14573Speed);
14574					}
14575
14576					var social = obj.options.social;
14577					if (social) {
14578						iL.setSocial(social, obj.URL, holder);
14579						if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed);
14580					}
14581
14582					//Generate thumbnails
14583					iL.generateThumbnails();
14584
14585					//Trigger the onShow callback
14586					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14587					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14588				});
14589				else {
14590					holder.show();
14591
14592					//Generate thumbnails
14593					iL.generateThumbnails();
14594
14595					//Trigger the onShow callback
14596					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14597					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14598				}
14599			} else {
14600				if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() {
14601					if (opt == "next") vars.nextLock = false;
14602					else vars.prevLock = false;
14603
14604					//Generate thumbnails
14605					iL.generateThumbnails();
14606
14607					//Trigger the onShow callback
14608					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14609					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14610				});
14611				else {
14612					holder.css({
14613						opacity: opacity
14614					}).show();
14615					if (opt == "next") vars.nextLock = false;
14616					else vars.prevLock = false;
14617
14618					//Generate thumbnails
14619					iL.generateThumbnails();
14620
14621					//Trigger the onShow callback
14622					if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item);
14623					if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api);
14624				}
14625			}
14626
14627			setTimeout(function() {
14628				iL.repositionPhoto();
14629			}, 0);
14630		},
14631
14632		generateBoxes: function() {
14633			var iL = this,
14634				vars = iL.vars,
14635				opts = iL.options;
14636
14637			if (opts.infinite && vars.total >= 3) {
14638				if (vars.current == vars.total - 1) vars.next = 0;
14639				if (vars.current == 0) vars.prev = vars.total - 1;
14640			} else opts.infinite = false;
14641
14642			//UNCODE addition
14643			if ( typeof iL.items[vars.current] == 'undefined' )
14644				vars.current = 0;
14645
14646			iL.loadContent(iL.items[vars.current], 'current', opts.show.speed);
14647
14648			if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed);
14649			if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed);
14650		},
14651
14652		generateThumbnails: function() {
14653			var iL = this,
14654				vars = iL.vars,
14655				opts = iL.options,
14656				timeOut = null;
14657
14658			if (vars.thumbs && !iL.vars.dontGenerateThumbs) {
14659				var thumbnails = vars.thumbnails,
14660					container = $('div.ilightbox-thumbnails-container', thumbnails),
14661					grid = $('div.ilightbox-thumbnails-grid', container),
14662					i = 0;
14663
14664				grid.removeAttr('style').empty();
14665
14666				$.each(iL.items, function(key, val) {
14667					var isActive = (vars.current == key) ? 'ilightbox-active' : '',
14668						opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity,
14669						thumb = val.options.thumbnail,
14670						thumbnail = $('<div class="ilightbox-thumbnail"></div>'),
14671						icon = $('<div class="ilightbox-thumbnail-icon"></div>');
14672
14673					thumbnail.css({
14674						opacity: 0
14675					}).addClass(isActive);
14676
14677					if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') {
14678						icon.addClass('ilightbox-thumbnail-video');
14679						thumbnail.append(icon);
14680					} else if (val.options.icon) {
14681						icon.addClass('ilightbox-thumbnail-' + val.options.icon);
14682						thumbnail.append(icon);
14683					}
14684
14685					if (thumb) iL.loadImage(thumb, function(img) {
14686						i++;
14687						if (img) thumbnail.data({
14688							naturalWidth: img.width,
14689							naturalHeight: img.height
14690						}).append('<img src="' + thumb + '" border="0" />');
14691						else thumbnail.data({
14692							naturalWidth: opts.thumbnails.maxWidth,
14693							naturalHeight: opts.thumbnails.maxHeight
14694						});
14695
14696						clearTimeout(timeOut);
14697						timeOut = setTimeout(function() {
14698							iL.positionThumbnails(thumbnails, container, grid);
14699						}, 20);
14700						setTimeout(function() {
14701							thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity);
14702						}, i * 20);
14703					});
14704
14705					grid.append(thumbnail);
14706				});
14707				iL.vars.dontGenerateThumbs = true;
14708			}
14709		},
14710
14711		positionThumbnails: function(thumbnails, container, grid) {
14712			var iL = this,
14713				vars = iL.vars,
14714				opts = iL.options,
14715				viewport = getViewport(),
14716				path = opts.path.toLowerCase();
14717
14718			if (!thumbnails) thumbnails = vars.thumbnails;
14719			if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails);
14720			if (!grid) grid = $('div.ilightbox-thumbnails-grid', container);
14721
14722			var thumbs = $('.ilightbox-thumbnail', grid),
14723				widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX,
14724				heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY,
14725				gridWidth = (path == 'horizontal') ? 0 : widthAvail,
14726				gridHeight = (path == 'horizontal') ? heightAvail : 0,
14727				active = $('.ilightbox-active', grid),
14728				gridCss = {},
14729				css = {};
14730
14731			if (arguments.length < 3) {
14732				thumbs.css({
14733					opacity: opts.thumbnails.normalOpacity
14734				});
14735				active.css({
14736					opacity: opts.thumbnails.activeOpacity
14737				});
14738			}
14739
14740			thumbs.each(function(i) {
14741				var t = $(this),
14742					data = t.data(),
14743					width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth;
14744				height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0;
14745				dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true);
14746
14747				t.css({
14748					width: dims.width,
14749					height: dims.height
14750				});
14751				if (path == 'horizontal') t.css({
14752					'float': 'left'
14753				});
14754
14755				(path == 'horizontal') ? (
14756					gridWidth += t.outerWidth()
14757				) : (
14758					gridHeight += t.outerHeight()
14759				);
14760			});
14761
14762			gridCss = {
14763				width: gridWidth,
14764				height: gridHeight
14765			};
14766
14767			grid.css(gridCss);
14768
14769			gridCss = {};
14770
14771			var gridOffset = grid.offset(),
14772				activeOffset = (active.length) ? active.offset() : {
14773					top: parseInt(heightAvail / 2),
14774					left: parseInt(widthAvail / 2)
14775				};
14776
14777			gridOffset.top = (gridOffset.top - $doc.scrollTop()),
14778				gridOffset.left = (gridOffset.left - $doc.scrollLeft()),
14779				activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()),
14780				activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft());
14781
14782			(path == 'horizontal') ? (
14783				gridCss.top = 0,
14784				gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2))
14785			) : (
14786				gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))),
14787				gridCss.left = 0
14788			);
14789
14790			if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc');
14791			else grid.css(gridCss);
14792		},
14793
14794		loadImage: function(image, callback) {
14795			if (!$.isArray(image)) image = [image];
14796
14797			var iL = this,
14798				length = image.length;
14799
14800			if (length > 0) {
14801				iL.showLoader();
14802				$.each(image, function(index, value) {
14803					var img = new Image();
14804					img.onload = function() {
14805						length -= 1;
14806						if (length == 0) {
14807							iL.hideLoader();
14808							callback(img);
14809						}
14810					};
14811					img.onerror = img.onabort = function() {
14812						length -= 1;
14813						if (length == 0) {
14814							iL.hideLoader();
14815							callback(false);
14816						}
14817					};
14818					img.src = image[index];
14819				});
14820			} else callback(false);
14821		},
14822
14823		patchItemsEvents: function() {
14824			var iL = this,
14825				vars = iL.vars,
14826				clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL",
14827				vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL";
14828
14829			if (iL.context && iL.selector) {
14830				var $items = $(iL.selector, iL.context);
14831
14832				$(iL.context).on(clickEvent, iL.selector, function() {
14833					var $this = $(this),
14834						//UNCODE addition
14835						key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this);
14836					if (UNCODE.isMobile) {
14837						var isCarousel = $this.closest('.owl-carousel');
14838						if (isCarousel.length) {
14839							if (isCarousel.hasClass('owl-translating')) return false;
14840						}
14841					}
14842
14843					vars.current = key;
14844					vars.next = iL.items[key + 1] ? key + 1 : null;
14845					vars.prev = iL.items[key - 1] ? key - 1 : null;
14846
14847					//UNCODE addition
14848					if ( vars.BODY.hasClass('fp-slide-scrolling') )
14849						return false;
14850
14851					iL.addContents();
14852					iL.patchEvents();
14853
14854					return false;
14855				}).on(vEvent, iL.selector, function() {
14856					return false;
14857				});
14858			} else
14859				$.each(iL.itemsObject, function(key, val) {
14860					val.on(clickEvent, function() {
14861						vars.current = key;
14862						vars.next = iL.items[key + 1] ? key + 1 : null;
14863						vars.prev = iL.items[key - 1] ? key - 1 : null;
14864
14865						iL.addContents();
14866						iL.patchEvents();
14867
14868						return false;
14869					}).on(vEvent, function() {
14870						return false;
14871					});
14872				});
14873		},
14874
14875		dispatchItemsEvents: function() {
14876			var iL = this,
14877				vars = iL.vars,
14878				opts = iL.options;
14879
14880			if (iL.context && iL.selector)
14881				$(iL.context).off('.iL', iL.selector);
14882			else
14883				$.each(iL.itemsObject, function(key, val) {
14884					val.off('.iL');
14885				});
14886		},
14887
14888		refresh: function() {
14889			var iL = this;
14890
14891			iL.dispatchItemsEvents();
14892			iL.attachItems();
14893			iL.normalizeItems();
14894			iL.patchItemsEvents();
14895		},
14896
14897		patchEvents: function() {
14898			var iL = this,
14899				vars = iL.vars,
14900				opts = iL.options,
14901				path = opts.path.toLowerCase(),
14902				holders = $('.ilightbox-holder'),
14903				fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox',
14904				durationThreshold = 1000,
14905				horizontalDistanceThreshold =
14906				verticalDistanceThreshold = 100,
14907				buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild];
14908
14909			$win.bind('resize.iLightBox', function() {
14910				var viewport = getViewport();
14911
14912				if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth;
14913				vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile');
14914
14915				iL.repositionPhoto(null);
14916				if (supportTouch) {
14917					clearTimeout(vars.setTime);
14918					vars.setTime = setTimeout(function() {
14919						var scrollTop = getScrollXY().y;
14920						window.scrollTo(0, scrollTop - 30);
14921						window.scrollTo(0, scrollTop + 30);
14922						window.scrollTo(0, scrollTop);
14923					}, 2000);
14924				}
14925				if (vars.thumbs) iL.positionThumbnails();
14926			}).bind('keydown.iLightBox', function(event) {
14927				if (opts.controls.keyboard) {
14928					switch (event.keyCode) {
14929						case 13:
14930							if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction();
14931							break;
14932						case 27:
14933							if (opts.keyboard.esc) iL.closeAction();
14934							break;
14935						case 37:
14936							if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev');
14937							break;
14938						case 38:
14939							if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev');
14940							break;
14941						case 39:
14942							if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next');
14943							break;
14944						case 40:
14945							if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next');
14946							break;
14947					}
14948				}
14949			});
14950
14951			if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() {
14952				iL.doFullscreen();
14953			});
14954
14955			var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) {
14956					return arr.lastIndexOf(e) === i;
14957				}),
14958				holderEvents = "";
14959
14960			$.each(holderEventsArr, function(key, val) {
14961				if (key != 0) holderEvents += ' ';
14962				holderEvents += val;
14963			});
14964
14965			$doc.on(clickEvent, '.ilightbox-overlay', function() {
14966				if (opts.overlay.blur) iL.closeAction();
14967			}).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() {
14968				iL.moveTo('next');
14969			}).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() {
14970				iL.moveTo('prev');
14971			}).on(clickEvent, '.ilightbox-thumbnail', function() {
14972				var t = $(this),
14973					thumbs = $('.ilightbox-thumbnail', vars.thumbnails),
14974					index = thumbs.index(t);
14975
14976				if (index != vars.current) iL.goTo(index);
14977			}).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
14978				var caption = $('div.ilightbox-caption', vars.holder),
14979					social = $('div.ilightbox-social', vars.holder),
14980					fadeSpeed = opts.effects.fadeSpeed;
14981
14982				if (vars.nextLock || vars.prevLock) {
14983					if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed);
14984					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed);
14985
14986					if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed);
14987					else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed);
14988				} else {
14989					if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed);
14990					else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed);
14991
14992					if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed);
14993					else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed);
14994				}
14995			}).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) {
14996				if (e.type == 'mouseenter') vars.lockWheel = true;
14997				else vars.lockWheel = false;
14998			}).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() {
14999				var t = $(this);
15000
15001				if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction();
15002				else if (t.hasClass('ilightbox-play')) {
15003					iL.resume();
15004					t.addClass('ilightbox-pause').removeClass('ilightbox-play');
15005				} else if (t.hasClass('ilightbox-pause')) {
15006					iL.pause();
15007					t.addClass('ilightbox-play').removeClass('ilightbox-pause');
15008				} else iL.closeAction();
15009			}).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) {
15010				// prevent scrolling
15011				e.preventDefault();
15012			});
15013
15014			function mouseMoveHandler(e) {
15015				if (!vars.isMobile) {
15016					if (!vars.mouseID) {
15017						vars.hideableElements.show();
15018					}
15019
15020					vars.mouseID = clearTimeout(vars.mouseID);
15021
15022					if (buttonsArray.indexOf(e.target) === -1)
15023						vars.mouseID = setTimeout(function() {
15024							vars.hideableElements.hide();
15025							vars.mouseID = clearTimeout(vars.mouseID);
15026						}, 3000);
15027				}
15028			}
15029
15030			if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler);
15031
15032			if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) {
15033				if (e.type == 'mouseenter' && vars.cycleID) iL.pause();
15034				else if (e.type == 'mouseleave' && vars.isPaused) iL.resume();
15035			});
15036
15037			var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'),
15038				delay = false;
15039
15040			if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) {
15041				event.preventDefault();
15042				if (delay) return;
15043				delay = true;
15044				if (!vars.lockWheel) {
15045					event.preventDefault();
15046					if (delta < 0) {
15047						iL.moveTo('next');
15048					} else if (delta > 0) {
15049						iL.moveTo('prev');
15050					}
15051				}
15052				setTimeout(function(){
15053					delay = false;
15054				}, 2000);
15055			});
15056
15057			if (opts.controls.swipe) holders.on(touchStartEvent, function(event) {
15058				if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return;
15059
15060				vars.BODY.addClass('ilightbox-closedhand');
15061
15062				var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event,
15063					scrollTop = $doc.scrollTop(),
15064					scrollLeft = $doc.scrollLeft(),
15065					offsets = [
15066						holders.eq(0).offset(),
15067						holders.eq(1).offset(),
15068						holders.eq(2).offset()
15069					],
15070					offSet = [{
15071						top: offsets[0].top - scrollTop,
15072						left: offsets[0].left - scrollLeft
15073					}, {
15074						top: offsets[1].top - scrollTop,
15075						left: offsets[1].left - scrollLeft
15076					}, {
15077						top: offsets[2].top - scrollTop,
15078						left: offsets[2].left - scrollLeft
15079					}],
15080					start = {
15081						time: (new Date()).getTime(),
15082						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15083					},
15084					stop;
15085
15086				function moveEachHandler(i) {
15087					var t = $(this),
15088						offset = offSet[i],
15089						scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])];
15090
15091					t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px';
15092				}
15093
15094				function moveHandler(event) {
15095
15096					if (!start) return;
15097
15098					var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event;
15099
15100					stop = {
15101						time: (new Date()).getTime(),
15102						coords: [data.pageX - scrollLeft, data.pageY - scrollTop]
15103					};
15104
15105					holders.each(moveEachHandler);
15106
15107					// prevent scrolling
15108					event.preventDefault();
15109				}
15110
15111				function repositionHolders() {
15112					holders.each(function() {
15113						var t = $(this),
15114							offset = t.data('offset') || {
15115								top: t.offset().top - scrollTop,
15116								left: t.offset().left - scrollLeft
15117							},
15118							top = offset.top,
15119							left = offset.left;
15120
15121						t.css(transform, gpuAcceleration).stop().animate({
15122							top: top,
15123							left: left
15124						}, 500, 'easeOutCirc', function() {
15125							t.css(transform, '');
15126						});
15127					});
15128				}
15129
15130				holders.bind(touchMoveEvent, moveHandler);
15131				$doc.one(touchStopEvent, function(event) {
15132					holders.unbind(touchMoveEvent, moveHandler);
15133
15134					vars.BODY.removeClass('ilightbox-closedhand');
15135
15136					if (start && stop) {
15137						if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) {
15138							if (start.coords[0] > stop.coords[0]) {
15139								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15140								else {
15141									vars.isSwipe = true;
15142									iL.moveTo('next');
15143								}
15144							} else {
15145								if (vars.current == 0 && !opts.infinite) repositionHolders();
15146								else {
15147									vars.isSwipe = true;
15148									iL.moveTo('prev');
15149								}
15150							}
15151						} 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) {
15152							if (start.coords[1] > stop.coords[1]) {
15153								if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders();
15154								else {
15155									vars.isSwipe = true;
15156									iL.moveTo('next');
15157								}
15158							} else {
15159								if (vars.current == 0 && !opts.infinite) repositionHolders();
15160								else {
15161									vars.isSwipe = true;
15162									iL.moveTo('prev');
15163								}
15164							}
15165						} else repositionHolders();
15166					}
15167					start = stop = undefined;
15168				});
15169			});
15170
15171		},
15172
15173		goTo: function(index) {
15174			var iL = this,
15175				vars = iL.vars,
15176				opts = iL.options,
15177				diff = (index - vars.current);
15178
15179			if (opts.infinite) {
15180				if (index == vars.total - 1 && vars.current == 0) diff = -1;
15181				if (vars.current == vars.total - 1 && index == 0) diff = 1;
15182			}
15183
15184			if (diff == 1) iL.moveTo('next');
15185			else if (diff == -1) iL.moveTo('prev');
15186			else {
15187
15188				if (vars.nextLock || vars.prevLock) return false;
15189
15190				//Trigger the onBeforeChange callback
15191				if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui);
15192
15193				if (opts.linkId) {
15194					vars.hashLock = true;
15195					window.location.hash = opts.linkId + '/' + index;
15196				}
15197
15198				if (iL.items[index]) {
15199					if (!iL.items[index].options.mousewheel) vars.lockWheel = true;
15200					else iL.vars.lockWheel = false;
15201
15202					if (!iL.items[index].options.swipe) vars.lockSwipe = true;
15203					else vars.lockSwipe = false;
15204				}
15205
15206				$.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) {
15207					val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed);
15208				});
15209
15210				vars.current = index;
15211				vars.next = index + 1;
15212				vars.prev = index - 1;
15213
15214				iL.createUI();
15215
15216				setTimeout(function() {
15217					iL.generateBoxes();
15218				}, opts.effects.loadedFadeSpeed + 50);
15219
15220				$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active');
15221				iL.positionThumbnails();
15222
15223				if (opts.linkId) setTimeout(function() {
15224					vars.hashLock = false;
15225				}, 55);
15226
15227				// Configure arrow buttons
15228				if (!opts.infinite) {
15229					vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15230
15231					if (vars.current == 0) {
15232						vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15233					}
15234					if (vars.current >= vars.total - 1) {
15235						vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15236					}
15237				}
15238
15239				// Reset next cycle timeout
15240				iL.resetCycle();
15241
15242				//Trigger the onAfterChange callback
15243				if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui);
15244			}
15245		},
15246
15247		moveTo: function(side) {
15248			var iL = this,
15249				vars = iL.vars,
15250				opts = iL.options,
15251				path = opts.path.toLowerCase(),
15252				viewport = getViewport(),
15253				switchSpeed = opts.effects.switchSpeed;
15254
15255			if (vars.nextLock || vars.prevLock) return false;
15256			else {
15257
15258				var item = (side == "next") ? vars.next : vars.prev;
15259
15260				if (opts.linkId) {
15261					vars.hashLock = true;
15262					window.location.hash = opts.linkId + '/' + item;
15263				}
15264
15265				if (side == "next") {
15266					if (!iL.items[item]) return false;
15267					var firstHolder = vars.nextPhoto,
15268						secondHolder = vars.holder,
15269						lastHolder = vars.prevPhoto,
15270						firstClass = 'ilightbox-prev',
15271						secondClass = 'ilightbox-next';
15272				} else if (side == "prev") {
15273					if (!iL.items[item]) return false;
15274					var firstHolder = vars.prevPhoto,
15275						secondHolder = vars.holder,
15276						lastHolder = vars.nextPhoto,
15277						firstClass = 'ilightbox-next',
15278						secondClass = 'ilightbox-prev';
15279				}
15280
15281				//Trigger the onBeforeChange callback
15282				if (typeof opts.callback.onBeforeChange == 'function')
15283					opts.callback.onBeforeChange.call(iL, iL.ui);
15284
15285				(side == "next") ? vars.nextLock = true: vars.prevLock = true;
15286
15287				var captionFirst = $('div.ilightbox-caption', secondHolder),
15288					socialFirst = $('div.ilightbox-social', secondHolder);
15289
15290				if (captionFirst.length)
15291					captionFirst.stop().fadeOut(switchSpeed, function() {
15292						$(this).remove();
15293					});
15294				if (socialFirst.length)
15295					socialFirst.stop().fadeOut(switchSpeed, function() {
15296						$(this).remove();
15297					});
15298
15299				if (iL.items[item].caption) {
15300					iL.setCaption(iL.items[item], firstHolder);
15301					var caption = $('div.ilightbox-caption', firstHolder),
15302						percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100);
15303					if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed);
15304				}
15305
15306				var social = iL.items[item].options.social;
15307				if (social) {
15308					iL.setSocial(social, iL.items[item].URL, firstHolder);
15309					if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed);
15310				}
15311
15312				$.each([firstHolder, secondHolder, lastHolder], function(key, val) {
15313					val.removeClass('ilightbox-next ilightbox-prev');
15314				});
15315
15316				var firstOffset = firstHolder.data('offset'),
15317					winW = (viewport.width - (opts.styles.pageOffsetX)),
15318					winH = (viewport.height - (opts.styles.pageOffsetY)),
15319					width = firstOffset.newDims.width,
15320					height = firstOffset.newDims.height,
15321					thumbsOffset = firstOffset.thumbsOffset,
15322					diff = firstOffset.diff,
15323					top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)),
15324					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15325
15326				var secondOffset = secondHolder.data('offset'),
15327					object = secondOffset.object;
15328
15329				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15330					var objRatio = width / height;
15331					height = height - vars.captionHeight;
15332					width = height * objRatio;
15333					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top,
15334					left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2));
15335				}*/
15336
15337				firstHolder.show().css(transform, gpuAcceleration).animate({
15338					top: top,
15339					left: left,
15340					opacity: 1
15341				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15342					firstHolder.css(transform, '');
15343				});
15344
15345				$('div.ilightbox-container', firstHolder).animate({
15346					width: width,
15347					height: height
15348				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15349
15350				diff = secondOffset.diff;
15351
15352				width = secondOffset.newDims.width,
15353					height = secondOffset.newDims.height;
15354
15355				width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15356					height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']),
15357					top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2));
15358
15359				if (side == 'prev')
15360					left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2));
15361				else {
15362					top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)),
15363					left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2));
15364				}
15365
15366				/*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) {
15367					var objRatio = width / height;
15368					height = height - vars.captionHeight;
15369					width = height * objRatio;
15370					top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top;
15371				}*/
15372
15373				$('div.ilightbox-container', secondHolder).animate({
15374					width: width,
15375					height: height
15376				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc');
15377
15378				secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({
15379					top: top,
15380					left: left,
15381					opacity: opts.styles.prevOpacity,
15382				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15383					secondHolder.css(transform, '');
15384
15385					$('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active');
15386					iL.positionThumbnails();
15387
15388					if (iL.items[item]) {
15389						if (!iL.items[item].options.mousewheel) vars.lockWheel = true;
15390						else vars.lockWheel = false;
15391
15392						if (!iL.items[item].options.swipe) vars.lockSwipe = true;
15393						else vars.lockSwipe = false;
15394					}
15395
15396					vars.isSwipe = false;
15397
15398					// Remove iframe & video from previous slide
15399					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15400						$('div.ilightbox-container', secondHolder).empty();
15401					}
15402
15403					if (side == "next") {
15404						vars.nextPhoto = lastHolder,
15405							vars.prevPhoto = secondHolder,
15406							vars.holder = firstHolder;
15407
15408						vars.nextPhoto.hide();
15409
15410						vars.next = vars.next + 1,
15411							vars.prev = vars.current,
15412							vars.current = vars.current + 1;
15413
15414						if (opts.infinite) {
15415							if (vars.current > vars.total - 1) vars.current = 0;
15416							if (vars.current == vars.total - 1) vars.next = 0;
15417							if (vars.current == 0) vars.prev = vars.total - 1;
15418						}
15419
15420						iL.createUI();
15421
15422						if (!iL.items[vars.next])
15423							vars.nextLock = false;
15424						else
15425							iL.loadContent(iL.items[vars.next], 'next');
15426					} else {
15427						vars.prevPhoto = lastHolder;
15428						vars.nextPhoto = secondHolder;
15429						vars.holder = firstHolder;
15430
15431						vars.prevPhoto.hide();
15432
15433						vars.next = vars.current;
15434						vars.current = vars.prev;
15435						vars.prev = vars.current - 1;
15436
15437						if (opts.infinite) {
15438							if (vars.current == vars.total - 1) vars.next = 0;
15439							if (vars.current == 0) vars.prev = vars.total - 1;
15440						}
15441
15442						iL.createUI();
15443
15444						if (!iL.items[vars.prev])
15445							vars.prevLock = false;
15446						else
15447							iL.loadContent(iL.items[vars.prev], 'prev');
15448					}
15449
15450					// Add iframe & video content for current slide
15451					if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) {
15452						iL.loadContent(iL.items[vars.current], 'current');
15453					}
15454
15455					if (opts.linkId) setTimeout(function() {
15456						vars.hashLock = false;
15457					}, 55);
15458
15459					// Configure arrow buttons
15460					if (!opts.infinite) {
15461						vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15462
15463						if (vars.current == 0)
15464							vars.prevButton.add(vars.innerPrevButton).addClass('disabled');
15465						if (vars.current >= vars.total - 1)
15466							vars.nextButton.add(vars.innerNextButton).addClass('disabled');
15467					}
15468
15469					iL.repositionPhoto();
15470
15471					// Reset next cycle timeout
15472					iL.resetCycle();
15473
15474					//Trigger the onAfterChange callback
15475					if (typeof opts.callback.onAfterChange == 'function')
15476						opts.callback.onAfterChange.call(iL, iL.ui);
15477				});
15478
15479				top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)),
15480					left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left');
15481
15482				lastHolder.css(transform, gpuAcceleration).animate({
15483					top: top,
15484					left: left,
15485					opacity: opts.styles.nextOpacity
15486				}, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() {
15487					lastHolder.css(transform, '');
15488				}).addClass(secondClass);
15489			}
15490		},
15491
15492		setCaption: function(obj, target) {
15493			var iL = this,
15494				caption = $('<div class="ilightbox-caption"></div>');
15495
15496			if (obj.caption) {
15497				caption.html(obj.caption);
15498				$('div.ilightbox-container', target).append(caption);
15499			}
15500		},
15501
15502		normalizeSocial: function(obj, url) {
15503			var iL = this,
15504				vars = iL.vars,
15505				opts = iL.options,
15506				baseURL = window.location.href;
15507
15508			$.each(obj, function(key, value) {
15509				if (!value)
15510					return true;
15511
15512				var item = key.toLowerCase(),
15513					source, text;
15514
15515				switch (item) {
15516					case 'facebook':
15517						source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}",
15518							text = "Share on Facebook";
15519						break;
15520					case 'twitter':
15521						source = "http://twitter.com/home?status={URL}",
15522							text = "Share on Twitter";
15523						break;
15524					case 'digg':
15525						source = "http://digg.com/submit?phase=2&url={URL}",
15526							text = "Share on Digg";
15527						break;
15528					case 'reddit':
15529						source = "http://reddit.com/submit?url={URL}",
15530							text = "Share on reddit";
15531						break;
15532				}
15533
15534				obj[key] = {
15535					URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL,
15536					source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url),
15537					text: value.text || text || "Share on " + key,
15538					width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640,
15539					height: value.height || 360
15540				};
15541
15542			});
15543
15544			return obj;
15545		},
15546
15547		setSocial: function(obj, url, target) {
15548			var iL = this,
15549				socialBar = $('<div class="ilightbox-social"></div>'),
15550				buttons = '<ul>';
15551
15552			obj = iL.normalizeSocial(obj, url);
15553
15554			$.each(obj, function(key, value) {
15555				var item = key.toLowerCase(),
15556					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, '+'));
15557				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>';
15558			});
15559
15560			buttons += '</ul>';
15561
15562			socialBar.html(buttons);
15563			$('div.ilightbox-container', target).append(socialBar);
15564		},
15565
15566		fullScreenAction: function() {
15567			var iL = this,
15568				vars = iL.vars;
15569
15570			if (fullScreenApi.supportsFullScreen) {
15571				if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement);
15572				else fullScreenApi.requestFullScreen(document.documentElement);
15573			} else {
15574				iL.doFullscreen();
15575			}
15576		},
15577
15578		doFullscreen: function() {
15579			var iL = this,
15580				vars = iL.vars,
15581				viewport = getViewport(),
15582				opts = iL.options;
15583
15584			if (opts.fullAlone) {
15585				var currentHolder = vars.holder,
15586					current = iL.items[vars.current],
15587					windowWidth = viewport.width,
15588					windowHeight = viewport.height,
15589					elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader],
15590					hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15591
15592				if (!vars.isInFullScreen) {
15593					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true;
15594					vars.overlay.css({
15595						opacity: 1
15596					});
15597
15598					$.each(hideElements, function(i, element) {
15599						element.hide();
15600					});
15601
15602					vars.fullScreenButton.attr('title', opts.text.exitFullscreen);
15603
15604					if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
15605						naturalWidthOld: currentHolder.data('naturalWidth'),
15606						naturalHeightOld: currentHolder.data('naturalHeight'),
15607						naturalWidth: windowWidth,
15608						naturalHeight: windowHeight
15609					});
15610					else {
15611						var viewport = current.options.fullViewPort || opts.fullViewPort || '',
15612							newWidth = windowWidth,
15613							newHeight = windowHeight,
15614							width = currentHolder.data('naturalWidth'),
15615							height = currentHolder.data('naturalHeight');
15616
15617						if (viewport.toLowerCase() == 'fill') {
15618							newHeight = (newWidth / width) * height;
15619
15620							if (newHeight < windowHeight) {
15621								newWidth = (windowHeight / height) * width,
15622									newHeight = windowHeight;
15623							}
15624						} else if (viewport.toLowerCase() == 'fit') {
15625							var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true);
15626
15627							newWidth = dims.width,
15628								newHeight = dims.height;
15629						} else if (viewport.toLowerCase() == 'stretch') {
15630							newWidth = newWidth,
15631								newHeight = newHeight;
15632						} else {
15633							var scale = (width > newWidth || height > newHeight) ? true : false,
15634								dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale);
15635							newWidth = dims.width,
15636								newHeight = dims.height;
15637						}
15638
15639						currentHolder.data({
15640							naturalWidthOld: currentHolder.data('naturalWidth'),
15641							naturalHeightOld: currentHolder.data('naturalHeight'),
15642							naturalWidth: newWidth,
15643							naturalHeight: newHeight
15644						});
15645					}
15646
15647					$.each(elements, function(key, val) {
15648						val.addClass('ilightbox-fullscreen');
15649					});
15650
15651					//Trigger the onEnterFullScreen callback
15652					if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui);
15653				} else {
15654					vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false;
15655					vars.overlay.css({
15656						opacity: iL.options.overlay.opacity
15657					});
15658
15659					$.each(hideElements, function(i, element) {
15660						element.show();
15661					});
15662
15663					vars.fullScreenButton.attr('title', opts.text.enterFullscreen);
15664
15665					currentHolder.data({
15666						naturalWidth: currentHolder.data('naturalWidthOld'),
15667						naturalHeight: currentHolder.data('naturalHeightOld'),
15668						naturalWidthOld: null,
15669						naturalHeightOld: null
15670					});
15671
15672					$.each(elements, function(key, val) {
15673						val.removeClass('ilightbox-fullscreen');
15674					});
15675
15676					//Trigger the onExitFullScreen callback
15677					if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui);
15678				}
15679			} else {
15680				if (!vars.isInFullScreen) vars.isInFullScreen = true;
15681				else vars.isInFullScreen = false;
15682			}
15683			iL.repositionPhoto(true);
15684		},
15685
15686		closeAction: function() {
15687			var iL = this,
15688				vars = iL.vars,
15689				opts = iL.options;
15690
15691			$win.unbind('.iLightBox');
15692			$doc.off('.iLightBox');
15693
15694			if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement);
15695
15696			$('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox');
15697
15698			if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() {
15699				vars.overlay.remove();
15700				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15701			});
15702			else {
15703				vars.overlay.remove();
15704				vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox');
15705			}
15706
15707			var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails];
15708
15709			$.each(fadeOuts, function(i, element) {
15710				element.removeAttr('style').remove();
15711			});
15712
15713			vars.dontGenerateThumbs = vars.isInFullScreen = false;
15714
15715			window.iLightBox = null;
15716
15717			if (opts.linkId) {
15718				vars.hashLock = true;
15719				removeHash();
15720				setTimeout(function() {
15721					vars.hashLock = false;
15722				}, 55);
15723			}
15724
15725			vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled');
15726
15727			//Trigger the onHide callback
15728			if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui);
15729		},
15730
15731		repositionPhoto: function() {
15732			var iL = this,
15733				vars = iL.vars,
15734				opts = iL.options,
15735				path = opts.path.toLowerCase(),
15736				viewport = getViewport(),
15737				winWidth = viewport.width,
15738				winHeight = viewport.height;
15739
15740			if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0;
15741
15742			var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()),
15743				thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)),
15744				width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)),
15745				height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)),
15746				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,
15747				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)));
15748
15749			var elObject = {
15750				type: 'current',
15751				width: width,
15752				height: height,
15753				item: iL.items[vars.current],
15754				offsetW: offsetW,
15755				offsetH: offsetH,
15756				thumbsOffsetW: thumbsOffsetW,
15757				thumbsOffsetH: thumbsOffsetH,
15758				animate: arguments.length,
15759				holder: vars.holder
15760			};
15761
15762			iL.repositionEl(elObject);
15763
15764			if (iL.items[vars.next]) {
15765				elObject = $.extend(elObject, {
15766					type: 'next',
15767					item: iL.items[vars.next],
15768					offsetX: opts.styles.nextOffsetX,
15769					offsetY: opts.styles.nextOffsetY,
15770					holder: vars.nextPhoto
15771				});
15772
15773				iL.repositionEl(elObject);
15774			}
15775
15776			if (iL.items[vars.prev]) {
15777				elObject = $.extend(elObject, {
15778					type: 'prev',
15779					item: iL.items[vars.prev],
15780					offsetX: opts.styles.nextOffsetX,
15781					offsetY: opts.styles.prevOffsetY,
15782					holder: vars.prevPhoto
15783				});
15784
15785				iL.repositionEl(elObject);
15786			}
15787
15788			var loaderCss = (path == "horizontal") ? {
15789				left: parseInt((width / 2) - (vars.loader.outerWidth() / 2))
15790			} : {
15791				top: parseInt((height / 2) - (vars.loader.outerHeight() / 2))
15792			};
15793			vars.loader.css(loaderCss);
15794		},
15795
15796		repositionEl: function(obj) {
15797			var iL = this,
15798				vars = iL.vars,
15799				opts = iL.options,
15800				path = opts.path.toLowerCase(),
15801				widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW),
15802				heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH),
15803				itemParent = obj.item,
15804				item = obj.item.options,
15805				holder = obj.holder,
15806				offsetX = obj.offsetX || 0,
15807				offsetY = obj.offsetY || 0,
15808				//Uncode change ##START##
15809				toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0,
15810				//Uncode change ##END##
15811				thumbsOffsetW = obj.thumbsOffsetW,
15812				thumbsOffsetH = obj.thumbsOffsetH;
15813
15814			if (obj.type == 'current') {
15815				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);
15816				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);
15817			} else {
15818				if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width;
15819				if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height;
15820			}
15821
15822
15823			//Uncode change ##START##
15824			heightAvail = parseInt(heightAvail - toolbarHeight);
15825			// heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight());
15826			//Uncode change ##END##
15827
15828			var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'),
15829				height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight');
15830
15831			var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? {
15832					width: width,
15833					height: height
15834				} : iL.getNewDimenstions(widthAvail, heightAvail, width, height)),
15835				newDims = $.extend({}, dims, {});
15836
15837			if (obj.type == 'prev' || obj.type == 'next')
15838				width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)),
15839				height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale));
15840			else
15841				width = dims.width,
15842				height = dims.height;
15843
15844			var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2),
15845				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);
15846
15847			switch (obj.type) {
15848				case 'current':
15849					var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)),
15850						left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15851					break;
15852
15853				case 'next':
15854					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)),
15855						left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2));
15856					break;
15857
15858				case 'prev':
15859					var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)),
15860						left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2));
15861					break;
15862			}
15863
15864			holder.data('offset', {
15865				top: top,
15866				left: left,
15867				newDims: newDims,
15868				diff: {
15869					W: widthDiff,
15870					H: heightDiff
15871				},
15872				thumbsOffset: {
15873					W: thumbsOffsetW,
15874					H: thumbsOffsetH
15875				},
15876				object: obj
15877			});
15878
15879			var opacityMobile;
15880			if ( isMobile ) {
15881				opacityMobile = {
15882					opacity: 1,
15883					top: top,
15884					left: left
15885				};
15886			} else {
15887				opacityMobile = {
15888					top: top,
15889					left: left
15890				};
15891			}
15892
15893			if (obj.animate > 0 && opts.effects.reposition) {
15894				holder.css(transform, gpuAcceleration).stop().animate(
15895					opacityMobile,
15896					opts.effects.repositionSpeed, 'easeOutCirc', function() {
15897					holder.css(transform, '');
15898				});
15899				$('div.ilightbox-container', holder).stop().animate({
15900					width: width,
15901					height: height
15902				}, opts.effects.repositionSpeed, 'easeOutCirc');
15903				$('div.ilightbox-inner-toolbar', holder).stop().animate({
15904					width: width
15905				}, opts.effects.repositionSpeed, 'easeOutCirc', function() {
15906					$(this).css('overflow', 'visible');
15907				});
15908			} else {
15909				holder.css(opacityMobile);
15910				$('div.ilightbox-container', holder).css({
15911					width: width,
15912					height: height
15913				});
15914				$('div.ilightbox-inner-toolbar', holder).css({
15915					width: width
15916				});
15917			}
15918		},
15919
15920
15921		resume: function(priority) {
15922			var iL = this,
15923				vars = iL.vars,
15924				opts = iL.options;
15925
15926			if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) {
15927				return;
15928			}
15929
15930			vars.isPaused = 0;
15931
15932			if (vars.cycleID) {
15933				vars.cycleID = clearTimeout(vars.cycleID);
15934			}
15935
15936			vars.cycleID = setTimeout(function() {
15937				if (vars.current == vars.total - 1) iL.goTo(0);
15938				else iL.moveTo('next');
15939			}, opts.slideshow.pauseTime);
15940		},
15941
15942		pause: function(priority) {
15943			var iL = this,
15944				vars = iL.vars,
15945				opts = iL.options;
15946
15947			if (priority < vars.isPaused) {
15948				return;
15949			}
15950
15951			vars.isPaused = priority || 100;
15952
15953			if (vars.cycleID) {
15954				vars.cycleID = clearTimeout(vars.cycleID);
15955			}
15956		},
15957
15958		resetCycle: function() {
15959			var iL = this,
15960				vars = iL.vars,
15961				opts = iL.options;
15962
15963			if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) {
15964				iL.resume();
15965			}
15966		},
15967
15968		getNewDimenstions: function(width, height, width_old, height_old, thumb) {
15969			var iL = this;
15970
15971			if (!width) factor = height / height_old;
15972			else if (!height) factor = width / width_old;
15973			else factor = min(width / width_old, height / height_old);
15974
15975			if (!thumb) {
15976				if (factor > iL.options.maxScale) factor = iL.options.maxScale;
15977				else if (factor < iL.options.minScale) factor = iL.options.minScale;
15978			}
15979
15980			var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width,
15981				final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height;
15982
15983			return {
15984				width: final_width,
15985				height: final_height,
15986				ratio: factor
15987			};
15988		},
15989
15990		setOption: function(options) {
15991			var iL = this;
15992
15993			iL.options = $.extend(true, iL.options, options || {});
15994			iL.refresh();
15995		},
15996
15997		availPlugins: function() {
15998			var iL = this,
15999				testEl = document.createElement("video");
16000
16001			iL.plugins = {
16002				flash: !isMobile,
16003				quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false,
16004				html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')),
16005				html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')),
16006				html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')),
16007				html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, ''))
16008			};
16009		},
16010
16011		addContent: function(element, obj) {
16012			var iL = this,
16013				el;
16014
16015			switch (obj.type) {
16016				case 'video':
16017					var HTML5 = false,
16018						videoType = obj.videoType,
16019						html5video = obj.options.html5video;
16020
16021					if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264)
16022						obj.ext = 'mp4',
16023						obj.URL = html5video.h264 || obj.URL;
16024					else if (html5video.webm && iL.plugins.html5WebM)
16025						obj.ext = 'webm',
16026						obj.URL = html5video.webm || obj.URL;
16027					else if (html5video.ogg && iL.plugins.html5Vorbis)
16028						obj.ext = 'ogv',
16029						obj.URL = html5video.ogg || obj.URL;
16030
16031					if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4";
16032					else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm";
16033					else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg";
16034					else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime";
16035
16036					if (HTML5) {
16037						el = $('<video />
16037', {
16038							"width": "100%",
16039							"height": "100%",
16040							"preload": html5video.preload,
16041							"autoplay": html5video.autoplay,
16042							"loop": html5video.loop,
16043							"poster": html5video.poster,
16044							"controls": html5video.controls,
16045							"controlslist": "nodownload"
16046						}).append($('<source />', {
16047							"src": obj.URL,
16048							"type": videoType
16049						}));
16050					} else {
16051						if (!iL.plugins.quicktime) el = $('<span />', {
16052							"class": "ilightbox-alert",
16053							html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime')
16054						});
16055						else {
16056
16057							el = $('<object />', {
16058								"type": "video/quicktime",
16059								"pluginspage": pluginspages.quicktime
16060							}).attr({
16061								"data": obj.URL,
16062								"width": "100%",
16063								"height": "100%"
16064							}).append($('<param />', {
16065								"name": "src",
16066								"value": obj.URL
16067							})).append($('<param />', {
16068								"name": "autoplay",
16069								"value": "false"
16070							})).append($('<param />', {
16071								"name": "loop",
16072								"value": "false"
16073							})).append($('<param />', {
16074								"name": "scale",
16075								"value": "tofit"
16076							}));
16077
16078							if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false');
16079						}
16080					}
16081
16082					break;
16083
16084				case 'flash':
16085					if (!iL.plugins.flash) el = $('<span />', {
16086						"class": "ilightbox-alert",
16087						html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player')
16088					});
16089					else {
16090						var flashvars = "",
16091							i = 0;
16092
16093						if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) {
16094							if (i != 0) flashvars += "&";
16095							flashvars += k + "=" + encodeURIComponent(v);
16096							i++;
16097						});
16098						else flashvars = null;
16099
16100						el = $('<embed />').attr({
16101							"type": "application/x-shockwave-flash",
16102							"src": obj.URL,
16103							"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16104							"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16105							"quality": "high",
16106							"bgcolor": "#000000",
16107							"play": "true",
16108							"loop": "true",
16109							"menu": "true",
16110							"wmode": "transparent",
16111							"scale": "showall",
16112							"allowScriptAccess": "always",
16113							"allowFullScreen": "true",
16114							"flashvars": flashvars,
16115							"fullscreen": "yes"
16116						});
16117					}
16118
16119					break;
16120
16121				case 'iframe':
16122					el = $('<iframe />').attr({
16123						"width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%",
16124						"height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%",
16125						src: obj.URL,
16126						frameborder: 0,
16127						'hspace': 0,
16128						'vspace': 0,
16129						'scrolling': supportTouch ? 'auto' : 'scroll',
16130						'webkitAllowFullScreen': '',
16131						'mozallowfullscreen': '',
16132						'allowFullScreen': ''
16133					});
16134
16135					break;
16136
16137				case 'inline':
16138					el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true));
16139
16140					break;
16141
16142				case 'html':
16143					var object = obj.URL,
16144						el;
16145
16146					if (object[0].nodeName) {
16147						el = $('<div class="ilightbox-wrapper"></div>').html(object);
16148					} else {
16149						var dom = $(obj.URL),
16150							html = (dom.selector) ? $('<div>' + dom + '</div>') : dom;
16151						el = $('<div class="ilightbox-wrapper"></div>').html(html);
16152					}
16153
16154					break;
16155			}
16156
16157			$('div.ilightbox-container', element).empty().html(el);
16158
16159			// For fixing Chrome about just playing the video for first time
16160			if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() {
16161				var src = el[0].currentSrc + '?' + floor(random() * 30000);
16162				el[0].currentSrc = src;
16163				el[0].src = src;
16164			});
16165
16166			return el;
16167		},
16168
16169		ogpRecognition: function(obj, callback) {
16170			var iL = this,
16171				url = obj.URL;
16172
16173			iL.showLoader();
16174			doAjax(url, function(data) {
16175				iL.hideLoader();
16176				if (data) {
16177					var object = new Object();
16178
16179					object.length = false,
16180					object.url = data.url;
16181
16182					if (data.status == 200) {
16183						var result = data.results,
16184							type = result.type,
16185							source = result.source;
16186
16187						object.source = source.src,
16188						object.width = source.width && parseInt(source.width) || 0,
16189						object.height = source.height && parseInt(source.height) || 0,
16190						object.type = type,
16191						object.thumbnail = source.thumbnail || result.images && result.images[0],
16192						object.html5video = result.html5video || {},
16193						object.length = true;
16194
16195						if (source.type == 'application/x-shockwave-flash') object.type = "flash";
16196						else if (source.type.indexOf("video/") != -1) object.type = "video";
16197						else if (source.type.indexOf("/html") != -1) object.type = "iframe";
16198						else if (source.type.indexOf("image/") != -1) object.type = "image";
16199
16200					} else if (typeof data.response != 'undefined')
16201						throw data.response;
16202
16203					callback.call(this, object.length ? object : false);
16204				}
16205			});
16206		},
16207
16208		hashChangeHandler: function(url) {
16209			var iL = this,
16210				vars = iL.vars,
16211				opts = iL.options,
16212				URL = url || window.location.href,
16213				hash = parseURI(URL).hash,
16214				split = hash.split('/'),
16215				index = split[1];
16216
16217			if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return;
16218
16219			if (index) {
16220				var target = split[1] || 0;
16221				if (iL.items[target]) {
16222					var overlay = $('.ilightbox-overlay');
16223					if (overlay.length && overlay.attr('linkid') == opts.linkId) {
16224						iL.goTo(target);
16225					} else {
16226						iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click');
16227						//iL.goTo(target);
16228					}
16229				} else {
16230					var overlay = $('.ilightbox-overlay');
16231					if (overlay.length) iL.closeAction();
16232				}
16233			} else {
16234				var overlay = $('.ilightbox-overlay');
16235				if (overlay.length) iL.closeAction();
16236			}
16237		}
16238	};
16239
16240	/**
16241	 * Parse style to pixels.
16242	 *
16243	 * @param {Object}   $element   jQuery object with element.
16244	 * @param {Property} property   CSS property to get the pixels from.
16245	 *
16246	 * @return {Int}
16247	 */
16248	function getPixel($element, property) {
16249		return parseInt($element.css(property), 10) || 0;
16250	}
16251
16252	/**
16253	 * Make sure that number is within the limits.
16254	 *
16255	 * @param {Number} number
16256	 * @param {Number} min
16257	 * @param {Number} max
16258	 *
16259	 * @return {Number}
16260	 */
16261	function within(number, min, max) {
16262		return number < min ? min : number > max ? max : number;
16263	}
16264
16265	/**
16266	 * Get viewport/window size (width and height).
16267	 *
16268	 * @return {Object}
16269	 */
16270	function getViewport() {
16271		var e = window,
16272			a = 'inner';
16273		if (!('innerWidth' in window)) {
16274			a = 'client';
16275			e = document.documentElement || document.body;
16276		}
16277		return {
16278			width: e[a + 'Width'],
16279			height: e[a + 'Height']
16280		}
16281	}
16282
16283	/**
16284	 * Remove hash tag from the URL
16285	 *
16286	 * @return {Void}
16287	 */
16288	function removeHash() {
16289		var scroll = getScrollXY();
16290
16291		//UNCODE change
16292		// window.location.hash = "";
16293		// history.pushState("", document.title, window.location.pathname + window.location.search);
16294		history.replaceState({}, document.title, window.location.pathname + window.location.search);
16295
16296		// Restore the scroll offset, should be flicker free
16297		window.scrollTo(scroll.x, scroll.y);
16298	}
16299
16300	/**
16301	 * Do the ajax requests with callback.
16302	 *
16303	 * @param {String}   url
16304	 * @param {Function} callback
16305	 *
16306	 * @return {Void}
16307	 */
16308	function doAjax(url, callback) {
16309		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');
16310		$.ajax({
16311			url: url,
16312			dataType: 'jsonp'
16313		});
16314
16315		iLCallback = function(data) {
16316			callback.call(this, data);
16317		};
16318	}
16319
16320	/**
16321	 * Find image from DOM elements
16322	 *
16323	 * @param {Element} element
16324	 *
16325	 * @return {Void}
16326	 */
16327	function findImageInElement(element) {
16328		var elements = $('*', element),
16329			imagesArr = new Array();
16330
16331		elements.each(function() {
16332			var url = "",
16333				element = this;
16334
16335			if ($(element).css("background-image") != "none") {
16336				url = $(element).css("background-image");
16337			} else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") {
16338				url = $(element).attr("src");
16339			}
16340
16341			if (url.indexOf("gradient") == -1) {
16342				url = url.replace(/url\(\"/g, "");
16343				url = url.replace(/url\(/g, "");
16344				url = url.replace(/\"\)/g, "");
16345				url = url.replace(/\)/g, "");
16346
16347				var urls = url.split(",");
16348
16349				for (var i = 0; i < urls.length; i++) {
16350					if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) {
16351						var extra = "";
16352						if (browser.msie && browser.version < 9) {
16353							extra = "?" + floor(random() * 3000);
16354						}
16355						imagesArr.push(urls[i] + extra);
16356					}
16357				}
16358			}
16359		});
16360
16361		return imagesArr;
16362	}
16363
16364	/**
16365	 * Get file extension.
16366	 *
16367	 * @param {String} URL
16368	 *
16369	 * @return {String}
16370	 */
16371	function getExtension(URL) {
16372		if (URL !== null) {
16373			//UNCODE: fix issue to detect media type with query strings
16374			var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL;
16375			ext = ext.split('.').pop().toLowerCase();
16376
16377			return ext;
16378		}
16379	}
16380
16381	/**
16382	 * Get type via extension.
16383	 *
16384	 * @param {String} URL
16385	 *
16386	 * @return {String}
16387	 */
16388	function getTypeByExtension(URL) {
16389		var type,
16390			ext = getExtension(URL);
16391
16392		//Uncode addition ##START##
16393		if (URL == undefined) {
16394			return false;
16395		}
16396		//Uncode addition ##END##
16397
16398		if (extensions.image.indexOf(ext) !== -1) type = 'image';
16399		else if (extensions.flash.indexOf(ext) !== -1) type = 'flash';
16400		else if (extensions.video.indexOf(ext) !== -1) type = 'video';
16401		else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition
16402		else type = 'iframe';
16403
16404		return type;
16405	}
16406
16407	/**
16408	 * Return value from percent of a number.
16409	 *
16410	 * @param {Number} percent
16411	 * @param {Number} total
16412	 *
16413	 * @return {Number}
16414	 */
16415	function percentToValue(percent, total) {
16416		return parseInt((total / 100) * percent);
16417	}
16418
16419	/**
16420	 * A JavaScript equivalent of PHP’s parse_url.
16421	 *
16422	 * @param {String} url           The URL to parse.
16423	 *
16424	 * @return {Mixed}
16425	 */
16426	function parseURI(url) {
16427		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
16428		// authority = '//' + user + ':' + pass '@' + hostname + ':' port
16429		return (m ? {
16430			href: m[0] || '',
16431			protocol: m[1] || '',
16432			authority: m[2] || '',
16433			host: m[3] || '',
16434			hostname: m[4] || '',
16435			port: m[5] || '',
16436			pathname: m[6] || '',
16437			search: m[7] || '',
16438			hash: m[8] || ''
16439		} : null);
16440	}
16441
16442	/**
16443	 * Gets the absolute URI.
16444	 *
16445	 * @param {String} href     The relative URL.
16446	 * @param {String} base     The base URL.
16447	 *
16448	 * @return {String}         The absolute URL.
16449	 */
16450	function absolutizeURI(base, href) { // RFC 3986
16451		var iL = this;
16452
16453		function removeDotSegments(input) {
16454			var output = [];
16455			input.replace(/^(\.\.?(\/|$))+/, '')
16456				.replace(/\/(\.(\/|$))+/g, '/')
16457				.replace(/\/\.\.$/, '/../')
16458				.replace(/\/?[^\/]*/g, function(p) {
16459					if (p === '/..') {
16460						output.pop();
16461					} else {
16462						output.push(p);
16463					}
16464				});
16465			return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
16466		}
16467
16468		href = parseURI(href || '');
16469		base = parseURI(base || '');
16470
16471		return !href || !base ? null : (href.protocol || base.protocol) +
16472			(href.protocol || href.authority ? href.authority : base.authority) +
16473			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)) +
16474			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
16475			href.hash;
16476	}
16477
16478	/**
16479	 * A JavaScript equivalent of PHP’s version_compare.
16480	 *
16481	 * @param {String} v1
16482	 * @param {String} v2
16483	 * @param {String} operator
16484	 *
16485	 * @return {Boolean}
16486	 */
16487	function version_compare(v1, v2, operator) {
16488		this.php_js = this.php_js || {};
16489		this.php_js.ENV = this.php_js.ENV || {};
16490		var i = 0,
16491			x = 0,
16492			compare = 0,
16493			vm = {
16494				'dev': -6,
16495				'alpha': -5,
16496				'a': -5,
16497				'beta': -4,
16498				'b': -4,
16499				'RC': -3,
16500				'rc': -3,
16501				'#': -2,
16502				'p': 1,
16503				'pl': 1
16504			},
16505			prepVersion = function(v) {
16506				v = ('' + v).replace(/[_\-+]/g, '.');
16507				v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
16508				return (!v.length ? [-8] : v.split('.'));
16509			},
16510			numVersion = function(v) {
16511				return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
16512			};
16513		v1 = prepVersion(v1);
16514		v2 = prepVersion(v2);
16515		x = max(v1.length, v2.length);
16516		for (i = 0; i < x; i++) {
16517			if (v1[i] == v2[i]) {
16518				continue;
16519			}
16520			v1[i] = numVersion(v1[i]);
16521			v2[i] = numVersion(v2[i]);
16522			if (v1[i] < v2[i]) {
16523				compare = -1;
16524				break;
16525			} else if (v1[i] > v2[i]) {
16526				compare = 1;
16527				break;
16528			}
16529		}
16530		if (!operator) {
16531			return compare;
16532		}
16533
16534		switch (operator) {
16535			case '>':
16536			case 'gt':
16537				return (compare > 0);
16538			case '>=':
16539			case 'ge':
16540				return (compare >= 0);
16541			case '<=':
16542			case 'le':
16543				return (compare <= 0);
16544			case '==':
16545			case '=':
16546			case 'eq':
16547				return (compare === 0);
16548			case '<>':
16549			case '!=':
16550			case 'ne':
16551				return (compare !== 0);
16552			case '':
16553			case '<':
16554			case 'lt':
16555				return (compare < 0);
16556			default:
16557				return null;
16558		}
16559	}
16560
16561
16562	// Begin the iLightBox plugin
16563	$.fn.iLightBox = function() {
16564
16565		var args = arguments,
16566			opt = ($.isPlainObject(args[0])) ? args[0] : args[1],
16567			items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1];
16568
16569		if (!opt) opt = {};
16570
16571		// Default options. Play carefully.
16572		var options = $.extend(true, {
16573			attr: 'href',
16574			path: 'vertical',
16575			skin: 'dark',
16576			linkId: false,
16577			infinite: false,
16578			startFrom: 0,
16579			randomStart: false,
16580			keepAspectRatio: true,
16581			maxScale: 1,
16582			minScale: .2,
16583			innerToolbar: false,
16584			smartRecognition: false,
16585			mobileOptimizer: true,
16586			fullAlone: true,
16587			fullViewPort: null,
16588			fullStretchTypes: 'flash, video',
16589			overlay: {
16590				blur: true,
16591				opacity: .85
16592			},
16593			controls: {
16594				arrows: false,
16595				slideshow: false,
16596				toolbar: true,
16597				fullscreen: true,
16598				thumbnail: true,
16599				keyboard: true,
16600				mousewheel: true,
16601				swipe: true
16602			},
16603			keyboard: {
16604				left: true, // previous
16605				right: true, // next
16606				up: true, // previous
16607				down: true, // next
16608				esc: true, // close
16609				shift_enter: true // fullscreen
16610			},
16611			show: {
16612				effect: true,
16613				speed: 300,
16614				title: true
16615			},
16616			hide: {
16617				effect: true,
16618				speed: 300
16619			},
16620			caption: {
16621				start: true,
16622				show: 'mouseenter',
16623				hide: 'mouseleave'
16624			},
16625			social: {
16626				start: true,
16627				show: 'mouseenter',
16628				hide: 'mouseleave',
16629				buttons: false
16630			},
16631			styles: {
16632				pageOffsetX: 0,
16633				pageOffsetY: 0,
16634				nextOffsetX: 45,
16635				nextOffsetY: 0,
16636				nextOpacity: 1,
16637				nextScale: 1,
16638				prevOffsetX: 45,
16639				prevOffsetY: 0,
16640				prevOpacity: 1,
16641				prevScale: 1
16642			},
16643			thumbnails: {
16644				maxWidth: 120,
16645				maxHeight: 80,
16646				normalOpacity: 1,
16647				activeOpacity: .6
16648			},
16649			effects: {
16650				reposition: true,
16651				repositionSpeed: 200,
16652				switchSpeed: 500,
16653				loadedFadeSpeed: 180,
16654				fadeSpeed: 200
16655			},
16656			slideshow: {
16657				pauseTime: 5000,
16658				pauseOnHover: false,
16659				startPaused: true
16660			},
16661			text: {
16662				close: "Press Esc to close",
16663				enterFullscreen: "Enter Fullscreen (Shift+Enter)",
16664				exitFullscreen: "Exit Fullscreen (Shift+Enter)",
16665				slideShow: "Slideshow",
16666				next: "Next",
16667				previous: "Previous"
16668			},
16669			errors: {
16670				loadImage: "An error occurred when trying to load photo.",
16671				loadContents: "An error occurred when trying to load contents.",
16672				missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>."
16673			},
16674			ajaxSetup: {
16675				url: '',
16676				beforeSend: function(jqXHR, settings) {},
16677				cache: false,
16678				complete: function(jqXHR, textStatus) {},
16679				crossDomain: false,
16680				error: function(jqXHR, textStatus, errorThrown) {},
16681				success: function(data, textStatus, jqXHR) {},
16682				global: true,
16683				ifModified: false,
16684				username: null,
16685				password: null,
16686				type: 'GET'
16687			},
16688			callback: {}
16689		}, opt);
16690
16691		var instant = ($.isArray(items) || typeof items == 'string') ? true : false;
16692
16693		items = $.isArray(items) ? items : new Array();
16694
16695		if (typeof args[0] == 'string') items[0] = args[0];
16696
16697		if (version_compare($.fn.jquery, '1.8', '>=')) {
16698			var iLB = new iLightBox($(this), options, items, instant);
16699			return {
16700				close: function() {
16701					iLB.closeAction();
16702				},
16703				fullscreen: function() {
16704					iLB.fullScreenAction();
16705				},
16706				moveNext: function() {
16707					iLB.moveTo('next');
16708				},
16709				movePrev: function() {
16710					iLB.moveTo('prev');
16711				},
16712				goTo: function(index) {
16713					iLB.goTo(index);
16714				},
16715				refresh: function() {
16716					iLB.refresh();
16717				},
16718				reposition: function() {
16719					(arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto();
16720				},
16721				setOption: function(options) {
16722					iLB.setOption(options);
16723				},
16724				destroy: function() {
16725					iLB.closeAction();
16726					iLB.dispatchItemsEvents();
16727				}
16728			};
16729		} else {
16730			throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+";
16731		}
16732
16733	};
16734
16735
16736	$.iLightBox = function() {
16737		return $.fn.iLightBox(arguments[0], arguments[1]);
16738	};
16739
16740	function getScrollXY() {
16741		var scrOfX = 0,
16742			scrOfY = 0;
16743		if (typeof(window.pageYOffset) == 'number') {
16744			//Netscape compliant
16745			scrOfY = window.pageYOffset;
16746			scrOfX = window.pageXOffset;
16747		} else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
16748			//DOM compliant
16749			scrOfY = document.body.scrollTop;
16750			scrOfX = document.body.scrollLeft;
16751		} else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
16752			//IE6 standards compliant mode
16753			scrOfY = document.documentElement.scrollTop;
16754			scrOfX = document.documentElement.scrollLeft;
16755		}
16756		return {
16757			x: scrOfX,
16758			y: scrOfY
16759		};
16760	}
16761
16762	(function() {
16763		// add new event shortcuts
16764		$.each(("touchstart touchmove touchend " +
16765			"tap taphold " +
16766			"swipe swipeleft swiperight " +
16767			"scrollstart scrollstop").split(" "), function(i, name) {
16768
16769			$.fn[name] = function(fn) {
16770				return fn ? this.bind(name, fn) : this.trigger(name);
16771			};
16772
16773			// jQuery < 1.8
16774			// if ($.attrFn) {
16775			// 	$.attrFn[name] = true;
16776			// }
16777		});
16778
16779		var tapSettings = {
16780			startEvent: 'touchstart.iTap',
16781			endEvent: 'touchend.iTap'
16782		};
16783
16784		// tap Event:
16785		$.event.special.itap = {
16786			setup: function() {
16787
16788				var self = this,
16789					$self = $(this),
16790					start, stop;
16791
16792				$self.bind(tapSettings.startEvent, function(event) {
16793					start = getScrollXY();
16794
16795					$self.one(tapSettings.endEvent, function(event) {
16796						stop = getScrollXY();
16797
16798						var orgEvent = event || window.event;
16799						event = $.event.fix(orgEvent);
16800						event.type = "itap";
16801
16802						if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event);
16803
16804						start = stop = undefined;
16805					});
16806				});
16807			},
16808
16809			teardown: function() {
16810				$(this).unbind(tapSettings.startEvent);
16811			}
16812		};
16813	}());
16814
16815
16816	//Fullscreen API
16817	(function() {
16818		fullScreenApi = {
16819				supportsFullScreen: false,
16820				isFullScreen: function() {
16821					return false;
16822				},
16823				requestFullScreen: function() {},
16824				cancelFullScreen: function() {},
16825				fullScreenEventName: '',
16826				prefix: ''
16827			},
16828			browserPrefixes = 'webkit moz o ms khtml'.split(' ');
16829
16830		// check for native support
16831		if (typeof document.cancelFullScreen != 'undefined') {
16832			fullScreenApi.supportsFullScreen = true;
16833		} else {
16834			// check for fullscreen support by vendor prefix
16835			for (var i = 0, il = browserPrefixes.length; i < il; i++) {
16836				fullScreenApi.prefix = browserPrefixes[i];
16837
16838				if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') {
16839					fullScreenApi.supportsFullScreen = true;
16840
16841					break;
16842				}
16843			}
16844		}
16845
16846		// update methods to do something useful
16847		if (fullScreenApi.supportsFullScreen) {
16848			fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange';
16849
16850			fullScreenApi.isFullScreen = function() {
16851				switch (this.prefix) {
16852					case '':
16853						return document.fullScreen;
16854					case 'webkit':
16855						return document.webkitIsFullScreen;
16856					default:
16857						return document[this.prefix + 'FullScreen'];
16858				}
16859			}
16860			fullScreenApi.requestFullScreen = function(el) {
16861				return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen']();
16862			}
16863			fullScreenApi.cancelFullScreen = function(el) {
16864				return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen']();
16865			}
16866		}
16867	}());
16868
16869	// Browser detect
16870	(function() {
16871		function uaMatch(ua) {
16872			ua = ua.toLowerCase();
16873
16874			var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
16875				/(webkit)[ \/]([\w.]+)/.exec(ua) ||
16876				/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
16877				/(msie) ([\w.]+)/.exec(ua) ||
16878				ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
16879
16880			return {
16881				browser: match[1] || "",
16882				version: match[2] || "0"
16883			};
16884		}
16885
16886		var matched = uaMatch(navigator.userAgent);
16887		browser = {};
16888
16889		if (matched.browser) {
16890			browser[matched.browser] = true;
16891			browser.version = matched.version;
16892		}
16893
16894		// Chrome is Webkit, but Webkit is also Safari.
16895		if (browser.chrome) {
16896			browser.webkit = true;
16897		} else if (browser.webkit) {
16898			browser.safari = true;
16899		}
16900	}());
16901
16902	// Feature detects
16903	(function() {
16904		var prefixes = ['', 'webkit', 'moz', 'ms', 'o'];
16905		var el = document.createElement('div');
16906
16907		function testProp(prop) {
16908			for (var p = 0, pl = prefixes.length; p < pl; p++) {
16909				var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop;
16910				if (el.style[prefixedProp] !== undefined) {
16911					return prefixedProp;
16912				}
16913			}
16914		}
16915
16916		// Global support indicators
16917		transform = testProp('transform') || '';
16918		gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : '';
16919	}());
16920
16921
16922	/*
16923		PluginDetect v0.7.9
16924		www.pinlady.net/PluginDetect/license/
16925		[ getVersion onWindowLoaded BetterIE ]
16926		[ Flash QuickTime Shockwave ]
16927	*/
16928	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;
16928d++){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);
16928d.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)}
16928c.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;
16928if(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();
16929
16930	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)};
16931
16932
16933	/*
16934		jQuery hashchange event v1.3
16935		https://github.com/cowboy/jquery-hashchange
16936		Copyright (c) 2010 "Cowboy" Ben Alman
16937		Dual licensed under the MIT and GPL licenses.
16938	*/
16939	(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=
16940	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||
16941	"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;
16941a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})();
16942
16943	if (!Array.prototype.filter) {
16944		Array.prototype.filter = function(fun /*, thisp */ ) {
16945			"use strict";
16946
16947			if (this == null)
16948				throw new TypeError();
16949
16950			var t = Object(this);
16951			var len = t.length >>> 0;
16952			if (typeof fun != "function")
16953				throw new TypeError();
16954
16955			var res = [];
16956			var thisp = arguments[1];
16957			for (var i = 0; i < len; i++) {
16958				if (i in t) {
16959					var val = t[i]; // in case fun mutates this
16960					if (fun.call(thisp, val, i, t))
16961						res.push(val);
16962				}
16963			}
16964
16965			return res;
16966		};
16967	}
16968
16969	if (!Array.prototype.indexOf) {
16970		Array.prototype.indexOf = function(searchElement, fromIndex) {
16971			var k;
16972
16973			if (this == null) {
16974				throw new TypeError('"this" is null or not defined');
16975			}
16976
16977			var O = Object(this);
16978
16979			var len = O.length >>> 0;
16980
16981			if (len === 0) {
16982				return -1;
16983			}
16984
16985			var n = +fromIndex || 0;
16986
16987			if (abs(n) === Infinity) {
16988				n = 0;
16989			}
16990
16991			if (n >= len) {
16992				return -1;
16993			}
16994
16995			k = max(n >= 0 ? n : len - abs(n), 0);
16996
16997			while (k < len) {
16998				var kValue;
16999				if (k in O && O[k] === searchElement) {
17000					return k;
17001				}
17002				k++;
17003			}
17004			return -1;
17005		};
17006	}
17007
17008	if (!Array.prototype.lastIndexOf) {
17009		Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) {
17010			"use strict";
17011
17012			if (this == null)
17013				throw new TypeError();
17014
17015			var t = Object(this);
17016			var len = t.length >>> 0;
17017			if (len === 0)
17018				return -1;
17019
17020			var n = len;
17021			if (arguments.length > 1) {
17022				n = Number(arguments[1]);
17023				if (n != n)
17024					n = 0;
17025				else if (n != 0 && n != (1 / 0) && n != -(1 / 0))
17026					n = (n > 0 || -1) * floor(abs(n));
17027			}
17028
17029			var k = n >= 0 ? min(n, len - 1) : len - abs(n);
17030
17031			for (; k >= 0; k--) {
17032				if (k in t && t[k] === searchElement)
17033					return k;
17034			}
17035			return -1;
17036		};
17037	}
17038})(jQuery, this);
17039
17040/*!
17041 * lightgallery | 2.5.0 | June 13th 2022
17042 * http://www.lightgalleryjs.com/
17043 * Copyright (c) 2020 Sachin Neravath;
17044 * @license GPLv3
17045 */
17046
17047(function (global, factory) {
17048	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
17049	typeof define === 'function' && define.amd ? define(factory) :
17050	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory());
17051}(this, (function () { 'use strict';
17052
17053	/*! *****************************************************************************
17054	Copyright (c) Microsoft Corporation.
17055
17056	Permission to use, copy, modify, and/or distribute this software for any
17057	purpose with or without fee is hereby granted.
17058
17059	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
17060	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
17061	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17062	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
17063	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17064	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17065	PERFORMANCE OF THIS SOFTWARE.
17066	***************************************************************************** */
17067
17068	var __assign = function() {
17069		__assign = Object.assign || function __assign(t) {
17070			for (var s, i = 1, n = arguments.length; i < n; i++) {
17071				s = arguments[i];
17072				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
17073			}
17074			return t;
17075		};
17076		return __assign.apply(this, arguments);
17077	};
17078
17079	function __spreadArrays() {
17080		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
17081		for (var r = Array(s), k = 0, i = 0; i < il; i++)
17082			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
17083				r[k] = a[j];
17084		return r;
17085	}
17086
17087	/**
17088	 * List of lightGallery events
17089	 * All events should be documented here
17090	 * Below interfaces are used to build the website documentations
17091	 * */
17092	var lGEvents = {
17093		afterAppendSlide: 'lgAfterAppendSlide',
17094		init: 'lgInit',
17095		hasVideo: 'lgHasVideo',
17096		containerResize: 'lgContainerResize',
17097		updateSlides: 'lgUpdateSlides',
17098		afterAppendSubHtml: 'lgAfterAppendSubHtml',
17099		beforeOpen: 'lgBeforeOpen',
17100		afterOpen: 'lgAfterOpen',
17101		slideItemLoad: 'lgSlideItemLoad',
17102		beforeSlide: 'lgBeforeSlide',
17103		afterSlide: 'lgAfterSlide',
17104		posterClick: 'lgPosterClick',
17105		dragStart: 'lgDragStart',
17106		dragMove: 'lgDragMove',
17107		dragEnd: 'lgDragEnd',
17108		beforeNextSlide: 'lgBeforeNextSlide',
17109		beforePrevSlide: 'lgBeforePrevSlide',
17110		beforeClose: 'lgBeforeClose',
17111		afterClose: 'lgAfterClose',
17112		rotateLeft: 'lgRotateLeft',
17113		rotateRight: 'lgRotateRight',
17114		flipHorizontal: 'lgFlipHorizontal',
17115		flipVertical: 'lgFlipVertical',
17116		autoplay: 'lgAutoplay',
17117		autoplayStart: 'lgAutoplayStart',
17118		autoplayStop: 'lgAutoplayStop',
17119	};
17120
17121	var lightGalleryCoreSettings = {
17122		mode: 'lg-slide',
17123		easing: 'ease',
17124		speed: 400,
17125		licenseKey: '0000-0000-000-0000',
17126		height: '100%',
17127		width: '100%',
17128		addClass: '',
17129		startClass: 'lg-start-zoom',
17130		backdropDuration: 300,
17131		container: '',
17132		startAnimationDuration: 400,
17133		zoomFromOrigin: true,
17134		hideBarsDelay: 0,
17135		showBarsAfter: 10000,
17136		slideDelay: 0,
17137		supportLegacyBrowser: true,
17138		allowMediaOverlap: false,
17139		videoMaxSize: '1280-720',
17140		loadYouTubePoster: true,
17141		defaultCaptionHeight: 0,
17142		ariaLabelledby: '',
17143		ariaDescribedby: '',
17144		resetScrollPosition: true,
17145		hideScrollbar: false,
17146		closable: true,
17147		swipeToClose: true,
17148		closeOnTap: true,
17149		showCloseIcon: true,
17150		showMaximizeIcon: false,
17151		loop: true,
17152		escKey: true,
17153		keyPress: true,
17154		trapFocus: true,
17155		controls: true,
17156		slideEndAnimation: true,
17157		hideControlOnEnd: false,
vendor: 15,066 bytes, lines 17158-17705
17158		mousewheel: false,
17159		getCaptionFromTitleOrAlt: true,
17160		appendSubHtmlTo: '.lg-sub-html',
17161		subHtmlSelectorRelative: false,
17162		preload: 2,
17163		numberOfSlideItemsInDom: 10,
17164		selector: '',
17165		selectWithin: '',
17166		nextHtml: '',
17167		prevHtml: '',
17168		index: 0,
17169		iframeWidth: '100%',
17170		iframeHeight: '100%',
17171		iframeMaxWidth: '100%',
17172		iframeMaxHeight: '100%',
17173		download: true,
17174		counter: true,
17175		appendCounterTo: '.lg-toolbar',
17176		swipeThreshold: 50,
17177		enableSwipe: true,
17178		enableDrag: true,
17179		dynamic: false,
17180		dynamicEl: [],
17181		extraProps: [],
17182		exThumbImage: '',
17183		isMobile: undefined,
17184		mobileSettings: {
17185			controls: false,
17186			showCloseIcon: false,
17187			download: false,
17188		},
17189		plugins: [],
17190		strings: {
17191			closeGallery: 'Close gallery',
17192			toggleMaximize: 'Toggle maximize',
17193			previousSlide: 'Previous slide',
17194			nextSlide: 'Next slide',
17195			download: 'Download',
17196			playVideo: 'Play video',
17197		},
17198	};
17199
17200	function initLgPolyfills() {
17201		(function () {
17202			if (typeof window.CustomEvent === 'function')
17203				return false;
17204			function CustomEvent(event, params) {
17205				params = params || {
17206					bubbles: false,
17207					cancelable: false,
17208					detail: null,
17209				};
17210				var evt = document.createEvent('CustomEvent');
17211				evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
17212				return evt;
17213			}
17214			window.CustomEvent = CustomEvent;
17215		})();
17216		(function () {
17217			if (!Element.prototype.matches) {
17218				Element.prototype.matches =
17219					Element.prototype.msMatchesSelector ||
17220						Element.prototype.webkitMatchesSelector;
17221			}
17222		})();
17223	}
17224	var lgQuery = /** @class */ (function () {
17225		function lgQuery(selector) {
17226			this.cssVenderPrefixes = [
17227				'TransitionDuration',
17228				'TransitionTimingFunction',
17229				'Transform',
17230				'Transition',
17231			];
17232			this.selector = this._getSelector(selector);
17233			this.firstElement = this._getFirstEl();
17234			return this;
17235		}
17236		lgQuery.generateUUID = function () {
17237			return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
17238				var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;
17239				return v.toString(16);
17240			});
17241		};
17242		lgQuery.prototype._getSelector = function (selector, context) {
17243			if (context === void 0) { context = document; }
17244			if (typeof selector !== 'string') {
17245				return selector;
17246			}
17247			context = context || document;
17248			var fl = selector.substring(0, 1);
17249			if (fl === '#') {
17250				return context.querySelector(selector);
17251			}
17252			else {
17253				return context.querySelectorAll(selector);
17254			}
17255		};
17256		lgQuery.prototype._each = function (func) {
17257			if (!this.selector) {
17258				return this;
17259			}
17260			if (this.selector.length !== undefined) {
17261				[].forEach.call(this.selector, func);
17262			}
17263			else {
17264				func(this.selector, 0);
17265			}
17266			return this;
17267		};
17268		lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) {
17269			// prettier-ignore
17270			var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) {
17271				return group1.toUpperCase();
17272			});
17273			if (this.cssVenderPrefixes.indexOf(property) !== -1) {
17274				el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value;
17275				el.style['webkit' + property] = value;
17276				el.style['moz' + property] = value;
17277				el.style['ms' + property] = value;
17278				el.style['o' + property] = value;
17279			}
17280			else {
17281				el.style[property] = value;
17282			}
17283		};
17284		lgQuery.prototype._getFirstEl = function () {
17285			if (this.selector && this.selector.length !== undefined) {
17286				return this.selector[0];
17287			}
17288			else {
17289				return this.selector;
17290			}
17291		};
17292		lgQuery.prototype.isEventMatched = function (event, eventName) {
17293			var eventNamespace = eventName.split('.');
17294			return event
17295				.split('.')
17296				.filter(function (e) { return e; })
17297				.every(function (e) {
17298				return eventNamespace.indexOf(e) !== -1;
17299			});
17300		};
17301		lgQuery.prototype.attr = function (attr, value) {
17302			if (value === undefined) {
17303				if (!this.firstElement) {
17304					return '';
17305				}
17306				return this.firstElement.getAttribute(attr);
17307			}
17308			this._each(function (el) {
17309				el.setAttribute(attr, value);
17310			});
17311			return this;
17312		};
17313		lgQuery.prototype.find = function (selector) {
17314			return $LG(this._getSelector(selector, this.selector));
17315		};
17316		lgQuery.prototype.first = function () {
17317			if (this.selector && this.selector.length !== undefined) {
17318				return $LG(this.selector[0]);
17319			}
17320			else {
17321				return $LG(this.selector);
17322			}
17323		};
17324		lgQuery.prototype.eq = function (index) {
17325			return $LG(this.selector[index]);
17326		};
17327		lgQuery.prototype.parent = function () {
17328			return $LG(this.selector.parentElement);
17329		};
17330		lgQuery.prototype.get = function () {
17331			return this._getFirstEl();
17332		};
17333		lgQuery.prototype.removeAttr = function (attributes) {
17334			var attrs = attributes.split(' ');
17335			this._each(function (el) {
17336				attrs.forEach(function (attr) { return el.removeAttribute(attr); });
17337			});
17338			return this;
17339		};
17340		lgQuery.prototype.wrap = function (className) {
17341			if (!this.firstElement) {
17342				return this;
17343			}
17344			var wrapper = document.createElement('div');
17345			wrapper.className = className;
17346			this.firstElement.parentNode.insertBefore(wrapper, this.firstElement);
17347			this.firstElement.parentNode.removeChild(this.firstElement);
17348			wrapper.appendChild(this.firstElement);
17349			return this;
17350		};
17351		lgQuery.prototype.addClass = function (classNames) {
17352			if (classNames === void 0) { classNames = ''; }
17353			this._each(function (el) {
17354				// IE doesn't support multiple arguments
17355				classNames.split(' ').forEach(function (className) {
17356					if (className) {
17357						el.classList.add(className);
17358					}
17359				});
17360			});
17361			return this;
17362		};
17363		lgQuery.prototype.removeClass = function (classNames) {
17364			this._each(function (el) {
17365				// IE doesn't support multiple arguments
17366				classNames.split(' ').forEach(function (className) {
17367					if (className) {
17368						el.classList.remove(className);
17369					}
17370				});
17371			});
17372			return this;
17373		};
17374		lgQuery.prototype.hasClass = function (className) {
17375			if (!this.firstElement) {
17376				return false;
17377			}
17378			return this.firstElement.classList.contains(className);
17379		};
17380		lgQuery.prototype.hasAttribute = function (attribute) {
17381			if (!this.firstElement) {
17382				return false;
17383			}
17384			return this.firstElement.hasAttribute(attribute);
17385		};
17386		lgQuery.prototype.toggleClass = function (className) {
17387			if (!this.firstElement) {
17388				return this;
17389			}
17390			if (this.hasClass(className)) {
17391				this.removeClass(className);
17392			}
17393			else {
17394				this.addClass(className);
17395			}
17396			return this;
17397		};
17398		lgQuery.prototype.css = function (property, value) {
17399			var _this = this;
17400			this._each(function (el) {
17401				_this._setCssVendorPrefix(el, property, value);
17402			});
17403			return this;
17404		};
17405		// Need to pass separate namespaces for separate elements
17406		lgQuery.prototype.on = function (events, listener) {
17407			var _this = this;
17408			if (!this.selector) {
17409				return this;
17410			}
17411			events.split(' ').forEach(function (event) {
17412				if (!Array.isArray(lgQuery.eventListeners[event])) {
17413					lgQuery.eventListeners[event] = [];
17414				}
17415				lgQuery.eventListeners[event].push(listener);
17416				_this.selector.addEventListener(event.split('.')[0], listener);
17417			});
17418			return this;
17419		};
17420		// @todo - test this
17421		lgQuery.prototype.once = function (event, listener) {
17422			var _this = this;
17423			this.on(event, function () {
17424				_this.off(event);
17425				listener(event);
17426			});
17427			return this;
17428		};
17429		lgQuery.prototype.off = function (event) {
17430			var _this = this;
17431			if (!this.selector) {
17432				return this;
17433			}
17434			Object.keys(lgQuery.eventListeners).forEach(function (eventName) {
17435				if (_this.isEventMatched(event, eventName)) {
17436					lgQuery.eventListeners[eventName].forEach(function (listener) {
17437						_this.selector.removeEventListener(eventName.split('.')[0], listener);
17438					});
17439					lgQuery.eventListeners[eventName] = [];
17440				}
17441			});
17442			return this;
17443		};
17444		lgQuery.prototype.trigger = function (event, detail) {
17445			if (!this.firstElement) {
17446				return this;
17447			}
17448			var customEvent = new CustomEvent(event.split('.')[0], {
17449				detail: detail || null,
17450			});
17451			this.firstElement.dispatchEvent(customEvent);
17452			return this;
17453		};
17454		// Does not support IE
17455		lgQuery.prototype.load = function (url) {
17456			var _this = this;
17457			fetch(url)
17458				.then(function (res) { return res.text(); })
17459				.then(function (html) {
17460				_this.selector.innerHTML = html;
17461			});
17462			return this;
17463		};
17464		lgQuery.prototype.html = function (html) {
17465			if (html === undefined) {
17466				if (!this.firstElement) {
17467					return '';
17468				}
17469				return this.firstElement.innerHTML;
17470			}
17471			this._each(function (el) {
17472				el.innerHTML = html;
17473			});
17474			return this;
17475		};
17476		lgQuery.prototype.append = function (html) {
17477			this._each(function (el) {
17478				if (typeof html === 'string') {
17479					el.insertAdjacentHTML('beforeend', html);
17480				}
17481				else {
17482					el.appendChild(html);
17483				}
17484			});
17485			return this;
17486		};
17487		lgQuery.prototype.prepend = function (html) {
17488			this._each(function (el) {
17489				el.insertAdjacentHTML('afterbegin', html);
17490			});
17491			return this;
17492		};
17493		lgQuery.prototype.remove = function () {
17494			this._each(function (el) {
17495				el.parentNode.removeChild(el);
17496			});
17497			return this;
17498		};
17499		lgQuery.prototype.empty = function () {
17500			this._each(function (el) {
17501				el.innerHTML = '';
17502			});
17503			return this;
17504		};
17505		lgQuery.prototype.scrollTop = function (scrollTop) {
17506			if (scrollTop !== undefined) {
17507				document.body.scrollTop = scrollTop;
17508				document.documentElement.scrollTop = scrollTop;
17509				return this;
17510			}
17511			else {
17512				return (window.pageYOffset ||
17513					document.documentElement.scrollTop ||
17514					document.body.scrollTop ||
17515					0);
17516			}
17517		};
17518		lgQuery.prototype.scrollLeft = function (scrollLeft) {
17519			if (scrollLeft !== undefined) {
17520				document.body.scrollLeft = scrollLeft;
17521				document.documentElement.scrollLeft = scrollLeft;
17522				return this;
17523			}
17524			else {
17525				return (window.pageXOffset ||
17526					document.documentElement.scrollLeft ||
17527					document.body.scrollLeft ||
17528					0);
17529			}
17530		};
17531		lgQuery.prototype.offset = function () {
17532			if (!this.firstElement) {
17533				return {
17534					left: 0,
17535					top: 0,
17536				};
17537			}
17538			var rect = this.firstElement.getBoundingClientRect();
17539			var bodyMarginLeft = $LG('body').style().marginLeft;
17540			// Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value
17541			return {
17542				left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(),
17543				top: rect.top + this.scrollTop(),
17544			};
17545		};
17546		lgQuery.prototype.style = function () {
17547			if (!this.firstElement) {
17548				return {};
17549			}
17550			return (this.firstElement.currentStyle ||
17551				window.getComputedStyle(this.firstElement));
17552		};
17553		// Width without padding and border even if box-sizing is used.
17554		lgQuery.prototype.width = function () {
17555			var style = this.style();
17556			return (this.firstElement.clientWidth -
17557				parseFloat(style.paddingLeft) -
17558				parseFloat(style.paddingRight));
17559		};
17560		// Height without padding and border even if box-sizing is used.
17561		lgQuery.prototype.height = function () {
17562			var style = this.style();
17563			return (this.firstElement.clientHeight -
17564				parseFloat(style.paddingTop) -
17565				parseFloat(style.paddingBottom));
17566		};
17567		lgQuery.eventListeners = {};
17568		return lgQuery;
17569	}());
17570	function $LG(selector) {
17571		initLgPolyfills();
17572		return new lgQuery(selector);
17573	}
17574
17575	var defaultDynamicOptions = [
17576		'src',
17577		'sources',
17578		'subHtml',
17579		'subHtmlUrl',
17580		'html',
17581		'video',
17582		'poster',
17583		'slideName',
17584		'responsive',
17585		'srcset',
17586		'sizes',
17587		'iframe',
17588		'downloadUrl',
17589		'download',
17590		'width',
17591		'facebookShareUrl',
17592		'tweetText',
17593		'iframeTitle',
17594		'twitterShareUrl',
17595		'pinterestShareUrl',
17596		'pinterestText',
17597		'fbHtml',
17598		'disqusIdentifier',
17599		'disqusUrl',
17600	];
17601	// Convert html data-attribute to camalcase
17602	function convertToData(attr) {
17603		// FInd a way for lgsize
17604		if (attr === 'href') {
17605			return 'src';
17606		}
17607		attr = attr.replace('data-', '');
17608		attr = attr.charAt(0).toLowerCase() + attr.slice(1);
17609		attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
17610		return attr;
17611	}
17612	var utils = {
17613		/**
17614		 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option
17615		 */
17616		//Uncode edit ##START##
17617		getSize: function (el, container, spacing, defaultLgSize, galleryItem) {
17618		// getSize: function (el, container, spacing, defaultLgSize) {
17619		//Uncode edit ##END##
17620			if (spacing === void 0) { spacing = 0; }
17621			var LGel = $LG(el);
17622			var lgSize = LGel.attr('data-lg-size') || defaultLgSize;
17623			//Uncode edit ##START##
17624			if ( typeof galleryItem.size && galleryItem.size != null ) {
17625				lgSize = galleryItem.size;
17626			}
17627			//Uncode edit ##END##
17628			if (!lgSize) {
17629				return;
17630			}
17631			var isResponsiveSizes = lgSize.split(',');
17632			// if at-least two viewport sizes are available
17633			if (isResponsiveSizes[1]) {
17634				var wWidth = window.innerWidth;
17635				for (var i = 0; i < isResponsiveSizes.length; i++) {
17636					var size_1 = isResponsiveSizes[i];
17637					var responsiveWidth = parseInt(size_1.split('-')[2], 10);
17638					if (responsiveWidth > wWidth) {
17639						lgSize = size_1;
17640						break;
17641					}
17642					// take last item as last option
17643					if (i === isResponsiveSizes.length - 1) {
17644						lgSize = size_1;
17645					}
17646				}
17647			}
17648			var size = lgSize.split('-');
17649			var width = parseInt(size[0], 10);
17650			var height = parseInt(size[1], 10);
17651			var cWidth = container.width();
17652			var cHeight = container.height() - spacing;
17653			var maxWidth = Math.min(cWidth, width);
17654			var maxHeight = Math.min(cHeight, height);
17655			var ratio = Math.min(maxWidth / width, maxHeight / height);
17656			return { width: width * ratio, height: height * ratio };
17657		},
17658		/**
17659		 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option
17660		 * @param {jQuery Element}
17661		 * @returns {String} Transform CSS string
17662		 */
17663		getTransform: function (el, container, top, bottom, imageSize) {
17664			if (!imageSize) {
17665				return;
17666			}
17667			var LGel = $LG(el).find('img').first();
17668			if (!LGel.get()) {
17669				return;
17670			}
17671			var containerRect = container.get().getBoundingClientRect();
17672			var wWidth = containerRect.width;
17673			// using innerWidth to include mobile safari bottom bar
17674			var wHeight = container.height() - (top + bottom);
17675			var elWidth = LGel.width();
17676			var elHeight = LGel.height();
17677			var elStyle = LGel.style();
17678			var x = (wWidth - elWidth) / 2 -
17679				LGel.offset().left +
17680				(parseFloat(elStyle.paddingLeft) || 0) +
17681				(parseFloat(elStyle.borderLeft) || 0) +
17682				$LG(window).scrollLeft() +
17683				containerRect.left;
17684			var y = (wHeight - elHeight) / 2 -
17685				LGel.offset().top +
17686				(parseFloat(elStyle.paddingTop) || 0) +
17687				(parseFloat(elStyle.borderTop) || 0) +
17688				$LG(window).scrollTop() +
17689				top;
17690			var scX = elWidth / imageSize.width;
17691			var scY = elHeight / imageSize.height;
17692			var transform = 'translate3d(' +
17693				(x *= -1) +
17694				'px, ' +
17695				(y *= -1) +
17696				'px, 0) scale3d(' +
17697				scX +
17698				', ' +
17699				scY +
17700				', 1)';
17701			return transform;
17702		},
17703		getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) {
17704			var title = iframeTitle ? 'title="' + iframeTitle + '"' : '';
17705			return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" 
vendor: 2,803 bytes, lines 17705-17777
17705+ iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n                    <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\"  allowfullscreen=\"true\"></iframe>\n                </div>";
17706		},
17707		getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) {
17708			var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : '';
17709			var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : '';
17710			var imgMarkup = "<img " + altAttr + " " + srcsetAttr + "  " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />";
17711			var sourceTag = '';
17712			if (sources) {
17713				var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources;
17714				sourceTag = sourceObj.map(function (source) {
17715					var attrs = '';
17716					Object.keys(source).forEach(function (key) {
17717						// Do not remove the first space as it is required to separate the attributes
17718						attrs += " " + key + "=\"" + source[key] + "\"";
17719					});
17720					return "<source " + attrs + "></source>";
17721				});
17722			}
17723			return "" + sourceTag + imgMarkup;
17724		},
17725		// Get src from responsive src
17726		getResponsiveSrc: function (srcItms) {
17727			var rsWidth = [];
17728			var rsSrc = [];
17729			var src = '';
17730			for (var i = 0; i < srcItms.length; i++) {
17731				var _src = srcItms[i].split(' ');
17732				// Manage empty space
17733				if (_src[0] === '') {
17734					_src.splice(0, 1);
17735				}
17736				rsSrc.push(_src[0]);
17737				rsWidth.push(_src[1]);
17738			}
17739			var wWidth = window.innerWidth;
17740			for (var j = 0; j < rsWidth.length; j++) {
17741				if (parseInt(rsWidth[j], 10) > wWidth) {
17742					src = rsSrc[j];
17743					break;
17744				}
17745			}
17746			return src;
17747		},
17748		isImageLoaded: function (img) {
17749			if (!img)
17750				return false;
17751			// During the onload event, IE correctly identifies any images that
17752			// weren’t downloaded as not complete. Others should too. Gecko-based
17753			// browsers act like NS4 in that they report this incorrectly.
17754			if (!img.complete) {
17755				return false;
17756			}
17757			// However, they do have two very useful properties: naturalWidth and
17758			// naturalHeight. These give the true size of the image. If it failed
17759			// to load, either of these should be zero.
17760			if (img.naturalWidth === 0) {
17761				return false;
17762			}
17763			// No other way of checking: assume it’s ok.
17764			return true;
17765		},
17766		getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) {
17767			var videoClass = '';
17768			if (_isVideo && _isVideo.youtube) {
17769				videoClass = 'lg-has-youtube';
17770			}
17771			else if (_isVideo && _isVideo.vimeo) {
17772				videoClass = 'lg-has-vimeo';
17773			}
17774			else {
17775				videoClass = 'lg-has-html5';
17776			}
17777			return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n                <div class=\"lg-video-play-button\">
vendor: 5,030 bytes, lines 17777-17888
17777\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>";
17778		},
17779		getFocusableElements: function (container) {
17780			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])');
17781			var visibleElements = [].filter.call(elements, function (element) {
17782				var style = window.getComputedStyle(element);
17783				return style.display !== 'none' && style.visibility !== 'hidden';
17784			});
17785			return visibleElements;
17786		},
17787		/**
17788		 * @desc Create dynamic elements array from gallery items when dynamic option is false
17789		 * It helps to avoid frequent DOM interaction
17790		 * and avoid multiple checks for dynamic elments
17791		 *
17792		 * @returns {Array} dynamicEl
17793		 */
17794		getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) {
17795			var dynamicElements = [];
17796			var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps);
17797			[].forEach.call(items, function (item) {
17798				var dynamicEl = {};
17799				for (var i = 0; i < item.attributes.length; i++) {
17800					var attr = item.attributes[i];
17801					if (attr.specified) {
17802						var dynamicAttr = convertToData(attr.name);
17803						var label = '';
17804						if (availableDynamicOptions.indexOf(dynamicAttr) > -1) {
17805							label = dynamicAttr;
17806						}
17807						if (label) {
17808							dynamicEl[label] = attr.value;
17809						}
17810					}
17811				}
17812				var currentItem = $LG(item);
17813				var alt = currentItem.find('img').first().attr('alt');
17814				var title = currentItem.attr('title');
17815				//Uncode edit ##START##
17816				// var thumb = exThumbImage
17817				var thumb = exThumbImage && currentItem.attr(exThumbImage)
17818				//Uncode edit ##END##
17819					? currentItem.attr(exThumbImage)
17820					: currentItem.find('img').first().attr('src');
17821				dynamicEl.thumb = thumb;
17822				//Uncode edit ##START##
17823				if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) {
17824					// dynamicEl.subHtml = title || alt || '';
17825					dynamicEl.subHtml = title || '';
17826				}
17827				// dynamicEl.alt = alt || title || '';
17828				dynamicEl.alt = title || '';
17829				var inlineType = currentItem.attr('data-type');
17830				dynamicEl.type = inlineType;
17831				//Uncode edit ##END##
17832				dynamicElements.push(dynamicEl);
17833			});
17834			return dynamicElements;
17835		},
17836		isMobile: function () {
17837			return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
17838		},
17839		/**
17840		 * @desc Check the given src is video
17841		 * @param {String} src
17842		 * @return {Object} video type
17843		 * Ex:{ youtube  :  ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] }
17844		 *
17845		 * @todo - this information can be moved to dynamicEl to avoid frequent calls
17846		 */
17847		isVideo: function (src, isHTML5VIdeo, index) {
17848			if (!src || src.match(/\.(mp4|m4v|ogg|webm)$/) ) {
17849				if (isHTML5VIdeo) {
17850					return {
17851						html5: true,
17852					};
17853				}
17854				else {
17855					console.warn('lightGallery :- data-src is not provided on slide item ' +
17856						(index + 1) +
17857						'. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/');
17858					return;
17859				}
17860			}
17861			var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i);
17862			var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i);
17863			var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/);
17864			if (youtube) {
17865				return {
17866					youtube: youtube,
17867				};
17868			}
17869			else if (vimeo) {
17870				return {
17871					vimeo: vimeo,
17872				};
17873			}
17874			else if (wistia) {
17875				return {
17876					wistia: wistia,
17877				};
17878			}
17879		},
17880	};
17881
17882	// @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
17883	// @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html
17884	// Unique id for each gallery
17885	var lgId = 0;
17886	var LightGallery = /** @class */ (function () {
17887		function LightGallery(element, options) {
17888			this.lgOpened = false;
vendor: 4,563 bytes, lines 17889-18023
17889			this.index = 0;
17890			// lightGallery modules
17891			this.plugins = [];
17892			// false when lightGallery load first slide content;
17893			this.lGalleryOn = false;
17894			// True when a slide animation is in progress
17895			this.lgBusy = false;
17896			this.currentItemsInDom = [];
17897			// Scroll top value before lightGallery is opened
17898			this.prevScrollTop = 0;
17899			this.bodyPaddingRight = 0;
17900			this.isDummyImageRemoved = false;
17901			this.dragOrSwipeEnabled = false;
17902			this.mediaContainerPosition = {
17903				top: 0,
17904				bottom: 0,
17905			};
17906			if (!element) {
17907				return this;
17908			}
17909			lgId++;
17910			this.lgId = lgId;
17911			this.el = element;
17912			this.LGel = $LG(element);
17913			this.generateSettings(options);
17914			this.buildModules();
17915			// When using dynamic mode, ensure dynamicEl is an array
17916			if (this.settings.dynamic &&
17917				this.settings.dynamicEl !== undefined &&
17918				!Array.isArray(this.settings.dynamicEl)) {
17919				throw 'When using dynamic mode, you must also define dynamicEl as an Array.';
17920			}
17921			this.galleryItems = this.getItems();
17922			this.normalizeSettings();
17923			// Gallery items
17924			this.init();
17925			//Uncode edit ##START##
17926			// this.validateLicense();
17927			//Uncode edit ##END##
17928			return this;
17929		}
17930		LightGallery.prototype.generateSettings = function (options) {
17931			// lightGallery settings
17932			this.settings = __assign(__assign({}, lightGalleryCoreSettings), options);
17933			if (this.settings.isMobile &&
17934				typeof this.settings.isMobile === 'function'
17935				? this.settings.isMobile()
17936				: utils.isMobile()) {
17937				var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings);
17938				this.settings = __assign(__assign({}, this.settings), mobileSettings);
17939			}
17940		};
17941		LightGallery.prototype.normalizeSettings = function () {
17942			if (this.settings.slideEndAnimation) {
17943				this.settings.hideControlOnEnd = false;
17944			}
17945			if (!this.settings.closable) {
17946				this.settings.swipeToClose = false;
17947			}
17948			// And reset it on close to get the correct value next time
17949			this.zoomFromOrigin = this.settings.zoomFromOrigin;
17950			// At the moment, Zoom from image doesn't support dynamic options
17951			// @todo add zoomFromOrigin support for dynamic images
17952			if (this.settings.dynamic) {
17953				this.zoomFromOrigin = false;
17954			}
17955			if (!this.settings.container) {
17956				this.settings.container = document.body;
17957			}
17958			// settings.preload should not be grater than $item.length
17959			this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length);
17960		};
17961		LightGallery.prototype.init = function () {
17962			var _this = this;
17963			this.addSlideVideoInfo(this.galleryItems);
17964			this.buildStructure();
17965			this.LGel.trigger(lGEvents.init, {
17966				instance: this,
17967			});
17968			if (this.settings.keyPress) {
17969				this.keyPress();
17970			}
17971			setTimeout(function () {
17972				_this.enableDrag();
17973				_this.enableSwipe();
17974				_this.triggerPosterClick();
17975			}, 50);
17976			this.arrow();
17977			if (this.settings.mousewheel) {
17978				this.mousewheel();
17979			}
17980			if (!this.settings.dynamic) {
17981				this.openGalleryOnItemClick();
17982			}
17983		};
17984		LightGallery.prototype.openGalleryOnItemClick = function () {
17985			var _this = this;
17986			var _loop_1 = function (index) {
17987				var element = this_1.items[index];
17988				var $element = $LG(element);
17989				// Using different namespace for click because click event should not unbind if selector is same object('this')
17990				// @todo manage all event listners - should have namespace that represent element
17991				var uuid = lgQuery.generateUUID();
17992				$element
17993					.attr('data-lg-id', uuid)
17994					.on("click.lgcustom-item-" + uuid, function (e) {
17995					e.preventDefault();
17996					var currentItemIndex = _this.settings.index || index;
17997					_this.openGallery(currentItemIndex, element);
17998				});
17999			};
18000			var this_1 = this;
18001			// Using for loop instead of using bubbling as the items can be any html element.
18002			for (var index = 0; index < this.items.length; index++) {
18003				_loop_1(index);
18004			}
18005		};
18006		/**
18007		 * Module constructor
18008		 * Modules are build incrementally.
18009		 * Gallery should be opened only once all the modules are initialized.
18010		 * use moduleBuildTimeout to make sure this
18011		 */
18012		LightGallery.prototype.buildModules = function () {
18013			var _this = this;
18014			this.settings.plugins.forEach(function (plugin) {
18015				_this.plugins.push(new plugin(_this, $LG));
18016			});
18017		};
18018		LightGallery.prototype.validateLicense = function () {
18019			if (!this.settings.licenseKey) {
18020				console.warn('Please provide a valid license key');
18021			}
18022			else if (this.settings.licenseKey === '0000-0000-000-0000') {
18023				console.warn("lightGallery: " + this.settings.licenseKey + " license key is not val
vendor: 17,473 bytes, lines 18023-18437
18023id for production use");
18024			}
18025		};
18026		LightGallery.prototype.getSlideItem = function (index) {
18027			return $LG(this.getSlideItemId(index));
18028		};
18029		LightGallery.prototype.getSlideItemId = function (index) {
18030			return "#lg-item-" + this.lgId + "-" + index;
18031		};
18032		LightGallery.prototype.getIdName = function (id) {
18033			return id + "-" + this.lgId;
18034		};
18035		LightGallery.prototype.getElementById = function (id) {
18036			return $LG("#" + this.getIdName(id));
18037		};
18038		LightGallery.prototype.manageSingleSlideClassName = function () {
18039			if (this.galleryItems.length < 2) {
18040				this.outer.addClass('lg-single-item');
18041			}
18042			else {
18043				this.outer.removeClass('lg-single-item');
18044			}
18045		};
18046		LightGallery.prototype.buildStructure = function () {
18047			var _this = this;
18048			var container = this.$container && this.$container.get();
18049			if (container) {
18050				return;
18051			}
18052			var controls = '';
18053			var subHtmlCont = '';
18054			// Create controls
18055			if (this.settings.controls) {
18056				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>";
18057			}
18058			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18059				subHtmlCont =
18060					'<div class="lg-sub-html" role="status" aria-live="polite"></div>';
18061			}
18062			var addClasses = '';
18063			if (this.settings.allowMediaOverlap) {
18064				// Do not remove space before last single quote
18065				addClasses += 'lg-media-overlap ';
18066			}
18067			var ariaLabelledby = this.settings.ariaLabelledby
18068				? 'aria-labelledby="' + this.settings.ariaLabelledby + '"'
18069				: '';
18070			var ariaDescribedby = this.settings.ariaDescribedby
18071				? 'aria-describedby="' + this.settings.ariaDescribedby + '"'
18072				: '';
18073			var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : '');
18074			var closeIcon = this.settings.closable && this.settings.showCloseIcon
18075				? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>"
18076				: '';
18077			var maximizeIcon = this.settings.showMaximizeIcon
18078				? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>"
18079				: '';
18080			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'
18081				? subHtmlCont
18082				: '') + "\n                <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n                    " + (this.settings.appendSubHtmlTo === '.lg-sub-html'
18083				? subHtmlCont
18084				: '') + "\n                </div>\n            </div>\n        </div>\n        ";
18085			$LG(this.settings.container).append(template);
18086			if (document.body !== this.settings.container) {
18087				$LG(this.settings.container).css('position', 'relative');
18088			}
18089			this.outer = this.getElementById('lg-outer');
18090			this.$lgComponents = this.getElementById('lg-components');
18091			this.$backdrop = this.getElementById('lg-backdrop');
18092			this.$container = this.getElementById('lg-container');
18093			this.$inner = this.getElementById('lg-inner');
18094			this.$content = this.getElementById('lg-content');
18095			this.$toolbar = this.getElementById('lg-toolbar');
18096			this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms');
18097			var outerClassNames = this.settings.mode + " ";
18098			this.manageSingleSlideClassName();
18099			if (this.settings.enableDrag) {
18100				outerClassNames += 'lg-grab ';
18101			}
18102			this.outer.addClass(outerClassNames);
18103			this.$inner.css('transition-timing-function', this.settings.easing);
18104			this.$inner.css('transition-duration', this.settings.speed + 'ms');
18105			if (this.settings.download) {
18106				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>");
18107			}
18108			this.counter();
18109			$LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () {
18110				_this.refreshOnResize();
18111			});
18112			this.hideBars();
18113			this.manageCloseGallery();
18114			this.toggleMaximize();
18115			this.initModules();
18116		};
18117		LightGallery.prototype.refreshOnResize = function () {
18118			if (this.lgOpened) {
18119				var currentGalleryItem = this.galleryItems[this.index];
18120				var __slideVideoInfo = currentGalleryItem.__slideVideoInfo;
18121				this.mediaContainerPosition = this.getMediaContainerPosition();
18122				var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom;
18123				//Uncode edit ##START##
18124				this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18125				// this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18126				//Uncode edit ##END##
18127				if (__slideVideoInfo) {
18128					this.resizeVideoSlide(this.index, this.currentImageSize);
18129				}
18130				if (this.zoomFromOrigin && !this.isDummyImageRemoved) {
18131					var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18132					this.outer
18133						.find('.lg-current .lg-dummy-img')
18134						.first()
18135						.attr('style', imgStyle);
18136				}
18137				this.LGel.trigger(lGEvents.containerResize);
18138			}
18139		};
18140		LightGallery.prototype.resizeVideoSlide = function (index, imageSize) {
18141			var lgVideoStyle = this.getVideoContStyle(imageSize);
18142			var currentSlide = this.getSlideItem(index);
18143			currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle);
18144		};
18145		/**
18146		 * Update slides dynamically.
18147		 * Add, edit or delete slides dynamically when lightGallery is opened.
18148		 * Modify the current gallery items and pass it via updateSlides method
18149		 * @note
18150		 * - Do not mutate existing lightGallery items directly.
18151		 * - Always pass new list of gallery items
18152		 * - You need to take care of thumbnails outside the gallery if any
18153		 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method.
18154		 * @param items Gallery items
18155		 * @param index After the update operation, which slide gallery should navigate to
18156		 * @category lGPublicMethods
18157		 * @example
18158		 * const plugin = lightGallery();
18159		 *
18160		 * // Adding slides dynamically
18161		 * let galleryItems = [
18162		 * // Access existing lightGallery items
18163		 * // galleryItems are automatically generated internally from the gallery HTML markup
18164		 * // or directly from galleryItems when dynamic gallery is used
18165		 *   ...plugin.galleryItems,
18166		 *     ...[
18167		 *       {
18168		 *         src: 'img/img-1.png',
18169		 *           thumb: 'img/thumb1.png',
18170		 *         },
18171		 *     ],
18172		 *   ];
18173		 *   plugin.updateSlides(
18174		 *     galleryItems,
18175		 *     plugin.index,
18176		 *   );
18177		 *
18178		 *
18179		 * // Remove slides dynamically
18180		 * galleryItems = JSON.parse(
18181		 *   JSON.stringify(updateSlideInstance.galleryItems),
18182		 * );
18183		 * galleryItems.shift();
18184		 * updateSlideInstance.updateSlides(galleryItems, 1);
18185		 * @see <a href="/demos/update-slides/">Demo</a>
18186		 */
18187		LightGallery.prototype.updateSlides = function (items, index) {
18188			if (this.index > items.length - 1) {
18189				this.index = items.length - 1;
18190			}
18191			if (items.length === 1) {
18192				this.index = 0;
18193			}
18194			if (!items.length) {
18195				this.closeGallery();
18196				return;
18197			}
18198			var currentSrc = this.galleryItems[index].src;
18199			this.galleryItems = items;
18200			this.updateControls();
18201			this.$inner.empty();
18202			this.currentItemsInDom = [];
18203			var _index = 0;
18204			// Find the current index based on source value of the slide
18205			this.galleryItems.some(function (galleryItem, itemIndex) {
18206				if (galleryItem.src === currentSrc) {
18207					_index = itemIndex;
18208					return true;
18209				}
18210				return false;
18211			});
18212			this.currentItemsInDom = this.organizeSlideItems(_index, -1);
18213			this.loadContent(_index, true);
18214			this.getSlideItem(_index).addClass('lg-current');
18215			this.index = _index;
18216			this.updateCurrentCounter(_index);
18217			this.LGel.trigger(lGEvents.updateSlides);
18218		};
18219		// Get gallery items based on multiple conditions
18220		LightGallery.prototype.getItems = function () {
18221			// Gallery items
18222			this.items = [];
18223			if (!this.settings.dynamic) {
18224				if (this.settings.selector === 'this') {
18225					this.items.push(this.el);
18226				}
18227				else if (this.settings.selector) {
18228					if (typeof this.settings.selector === 'string') {
18229						if (this.settings.selectWithin) {
18230							var selectWithin = $LG(this.settings.selectWithin);
18231							this.items = selectWithin
18232								.find(this.settings.selector)
18233								.get();
18234						}
18235						else {
18236							this.items = this.el.querySelectorAll(this.settings.selector);
18237						}
18238					}
18239					else {
18240						this.items = this.settings.selector;
18241					}
18242				}
18243				else {
18244					this.items = this.el.children;
18245				}
18246				return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage);
18247			}
18248			else {
18249				return this.settings.dynamicEl || [];
18250			}
18251		};
18252		LightGallery.prototype.shouldHideScrollbar = function () {
18253			return (this.settings.hideScrollbar &&
18254				document.body === this.settings.container);
18255		};
18256		LightGallery.prototype.hideScrollbar = function () {
18257			if (!this.shouldHideScrollbar()) {
18258				return;
18259			}
18260			this.bodyPaddingRight = parseFloat($LG('body').style().paddingRight);
18261			var bodyRect = document.documentElement.getBoundingClientRect();
18262			var scrollbarWidth = window.innerWidth - bodyRect.width;
18263			$LG(document.body).css('padding-right', scrollbarWidth + this.bodyPaddingRight + 'px');
18264			$LG(document.body).addClass('lg-overlay-open');
18265		};
18266		LightGallery.prototype.resetScrollBar = function () {
18267			if (!this.shouldHideScrollbar()) {
18268				return;
18269			}
18270			$LG(document.body).css('padding-right', this.bodyPaddingRight + 'px');
18271			$LG(document.body).removeClass('lg-overlay-open');
18272		};
18273		/**
18274		 * Open lightGallery.
18275		 * Open gallery with specific slide by passing index of the slide as parameter.
18276		 * @category lGPublicMethods
18277		 * @param {Number} index  - index of the slide
18278		 * @param {HTMLElement} element - Which image lightGallery should zoom from
18279		 *
18280		 * @example
18281		 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo');
18282		 * const dynamicGallery = lightGallery($dynamicGallery, {
18283		 *     dynamic: true,
18284		 *     dynamicEl: [
18285		 *         {
18286		 *              src: 'img/1.jpg',
18287		 *              thumb: 'img/thumb-1.jpg',
18288		 *              subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>',
18289		 *         },
18290		 *         ...
18291		 *     ],
18292		 * });
18293		 * $dynamicGallery.addEventListener('click', function () {
18294		 *     // Starts with third item.(Optional).
18295		 *     // This is useful if you want use dynamic mode with
18296		 *     // custom thumbnails (thumbnails outside gallery),
18297		 *     dynamicGallery.openGallery(2);
18298		 * });
18299		 *
18300		 */
18301		LightGallery.prototype.openGallery = function (index, element) {
18302			var _this = this;
18303			if (index === void 0) { index = this.settings.index; }
18304			// prevent accidental double execution
18305			if (this.lgOpened)
18306				return;
18307			this.lgOpened = true;
18308			this.outer.removeClass('lg-hide-items');
18309			this.hideScrollbar();
18310			// Add display block, but still has opacity 0
18311			this.$container.addClass('lg-show');
18312			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index);
18313			this.currentItemsInDom = itemsToBeInsertedToDom;
18314			var items = '';
18315			itemsToBeInsertedToDom.forEach(function (item) {
18316				items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18317			});
18318			this.$inner.append(items);
18319			this.addHtml(index);
18320			var transform = '';
18321			this.mediaContainerPosition = this.getMediaContainerPosition();
18322			var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
18323			if (!this.settings.allowMediaOverlap) {
18324				this.setMediaContainerPosition(top, bottom);
18325			}
18326			var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo;
18327			if (this.zoomFromOrigin && element) {
18328				//Uncode edit ##START##
18329				this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18330				// this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize);
18331				//Uncode edit ##END##
18332				transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize);
18333			}
18334			if (!this.zoomFromOrigin || !transform) {
18335				this.outer.addClass(this.settings.startClass);
18336				this.getSlideItem(index).removeClass('lg-complete');
18337			}
18338			var timeout = this.settings.zoomFromOrigin
18339				? 100
18340				: this.settings.backdropDuration;
18341			setTimeout(function () {
18342				_this.outer.addClass('lg-components-open');
18343			}, timeout);
18344			this.index = index;
18345			//Uncode edit ##START##
18346			// this.LGel.trigger(lGEvents.beforeOpen);
18347			this.LGel.trigger(lGEvents.beforeOpen, {
18348				galleryItems: this.galleryItems,
18349				items: this.items,
18350				outer: this.outer,
18351			});
18352			//Uncode edit ##END##
18353			// add class lg-current to remove initial transition
18354			this.getSlideItem(index).addClass('lg-current');
18355			this.lGalleryOn = false;
18356			// Store the current scroll top value to scroll back after closing the gallery..
18357			this.prevScrollTop = $LG(window).scrollTop();
18358			setTimeout(function () {
18359				// Need to check both zoomFromOrigin and transform values as we need to set set the
18360				// default opening animation if user missed to add the lg-size attribute
18361				if (_this.zoomFromOrigin && transform) {
18362					var currentSlide_1 = _this.getSlideItem(index);
18363					currentSlide_1.css('transform', transform);
18364					setTimeout(function () {
18365						currentSlide_1
18366							.addClass('lg-start-progress lg-start-end-progress')
18367							.css('transition-duration', _this.settings.startAnimationDuration + 'ms');
18368						_this.outer.addClass('lg-zoom-from-image');
18369					});
18370					setTimeout(function () {
18371						currentSlide_1.css('transform', 'translate3d(0, 0, 0)');
18372					}, 100);
18373				}
18374				setTimeout(function () {
18375					_this.$backdrop.addClass('in');
18376					_this.$container.addClass('lg-show-in');
18377				}, 10);
18378				setTimeout(function () {
18379					if (_this.settings.trapFocus &&
18380						document.body === _this.settings.container) {
18381						_this.trapFocus();
18382					}
18383				}, _this.settings.backdropDuration + 50);
18384				// lg-visible class resets gallery opacity to 1
18385				if (!_this.zoomFromOrigin || !transform) {
18386					setTimeout(function () {
18387						_this.outer.addClass('lg-visible');
18388					}, _this.settings.backdropDuration);
18389				}
18390				// initiate slide function
18391				_this.slide(index, false, false, false);
18392				_this.LGel.trigger(lGEvents.afterOpen);
18393			});
18394			if (document.body === this.settings.container) {
18395				$LG('html').addClass('lg-on');
18396			}
18397		};
18398		/**
18399		 * Note - Changing the position of the media on every slide transition creates a flickering effect.
18400		 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption.
18401		 * if you have dynamic captions for each media,
18402		 * you can provide an appropriate height for the captions via allowMediaOverlap option
18403		 */
18404		LightGallery.prototype.getMediaContainerPosition = function () {
18405			if (this.settings.allowMediaOverlap) {
18406				return {
18407					top: 0,
18408					bottom: 0,
18409				};
18410			}
18411			var top = this.$toolbar.get().clientHeight || 0;
18412			var subHtml = this.outer.find('.lg-components .lg-sub-html').get();
18413			var captionHeight = this.settings.defaultCaptionHeight ||
18414				(subHtml && subHtml.clientHeight) ||
18415				0;
18416			var thumbContainer = this.outer.find('.lg-thumb-outer').get();
18417			var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0;
18418			var bottom = thumbHeight + captionHeight;
18419			//Uncode edit ##START##
18420			bottom = bottom < 55 ? 55 : bottom;
18421			//Uncode edit ##END##
18422			return {
18423				top: top,
18424				bottom: bottom,
18425			};
18426		};
18427		LightGallery.prototype.setMediaContainerPosition = function (top, bottom) {
18428			if (top === void 0) { top = 0; }
18429			if (bottom === void 0) { bottom = 0; }
18430			this.$content.css('top', top + 'px').css('bottom', bottom + 'px');
18431		};
18432		LightGallery.prototype.hideBars = function () {
18433			var _this = this;
18434			// Hide controllers if mouse doesn't move for some period
18435			setTimeout(function () {
18436				_this.outer.removeClass('lg-hide-items');
18437				if (_this.settings.hideBarsDelay > 0) {
vendor: 4,223 bytes, lines 18438-18568
18438					_this.outer.on('mousemove.lg click.lg touchstart.lg', function () {
18439						_this.outer.removeClass('lg-hide-items');
18440						clearTimeout(_this.hideBarTimeout);
18441						// Timeout will be cleared on each slide movement also
18442						_this.hideBarTimeout = setTimeout(function () {
18443							_this.outer.addClass('lg-hide-items');
18444						}, _this.settings.hideBarsDelay);
18445					});
18446					_this.outer.trigger('mousemove.lg');
18447				}
18448			}, this.settings.showBarsAfter);
18449		};
18450		LightGallery.prototype.initPictureFill = function ($img) {
18451			if (this.settings.supportLegacyBrowser) {
18452				try {
18453					picturefill({
18454						elements: [$img.get()],
18455					});
18456				}
18457				catch (e) {
18458					console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.');
18459				}
18460			}
18461		};
18462		/**
18463		 *  @desc Create image counter
18464		 *  Ex: 1/10
18465		 */
18466		LightGallery.prototype.counter = function () {
18467			if (this.settings.counter) {
18468				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>";
18469				this.outer.find(this.settings.appendCounterTo).append(counterHtml);
18470			}
18471		};
18472		/**
18473		 *  @desc add sub-html into the slide
18474		 *  @param {Number} index - index of the slide
18475		 */
18476		LightGallery.prototype.addHtml = function (index) {
18477			var subHtml;
18478			var subHtmlUrl;
18479			if (this.galleryItems[index].subHtmlUrl) {
18480				subHtmlUrl = this.galleryItems[index].subHtmlUrl;
18481			}
18482			else {
18483				subHtml = this.galleryItems[index].subHtml;
18484			}
18485			if (!subHtmlUrl) {
18486				if (subHtml) {
18487					// get first letter of sub-html
18488					// if first letter starts with . or # get the html form the jQuery object
18489					var fL = subHtml.substring(0, 1);
18490					if (fL === '.' || fL === '#') {
18491						if (this.settings.subHtmlSelectorRelative &&
18492							!this.settings.dynamic) {
18493							subHtml = $LG(this.items)
18494								.eq(index)
18495								.find(subHtml)
18496								.first()
18497								.html();
18498						}
18499						else {
18500							subHtml = $LG(subHtml).first().html();
18501						}
18502					}
18503				}
18504				else {
18505					subHtml = '';
18506				}
18507			}
18508			if (this.settings.appendSubHtmlTo !== '.lg-item') {
18509				if (subHtmlUrl) {
18510					this.outer.find('.lg-sub-html').load(subHtmlUrl);
18511				}
18512				else {
18513					this.outer.find('.lg-sub-html').html(subHtml);
18514				}
18515			}
18516			else {
18517				var currentSlide = $LG(this.getSlideItemId(index));
18518				if (subHtmlUrl) {
18519					currentSlide.load(subHtmlUrl);
18520				}
18521				else {
18522					currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>");
18523				}
18524			}
18525			// Add lg-empty-html class if title doesn't exist
18526			if (typeof subHtml !== 'undefined' && subHtml !== null) {
18527				if (subHtml === '') {
18528					this.outer
18529						.find(this.settings.appendSubHtmlTo)
18530						.addClass('lg-empty-html');
18531				}
18532				else {
18533					this.outer
18534						.find(this.settings.appendSubHtmlTo)
18535						.removeClass('lg-empty-html');
18536				}
18537			}
18538			this.LGel.trigger(lGEvents.afterAppendSubHtml, {
18539				index: index,
18540			});
18541		};
18542		/**
18543		 *  @desc Preload slides
18544		 *  @param {Number} index - index of the slide
18545		 * @todo preload not working for the first slide, Also, should work for the first and last slide as well
18546		 */
18547		LightGallery.prototype.preload = function (index) {
18548			for (var i = 1; i <= this.settings.preload; i++) {
18549				if (i >= this.galleryItems.length - index) {
18550					break;
18551				}
18552				this.loadContent(index + i, false);
18553			}
18554			for (var j = 1; j <= this.settings.preload; j++) {
18555				if (index - j < 0) {
18556					break;
18557				}
18558				this.loadContent(index - j, false);
18559			}
18560		};
18561		LightGallery.prototype.getDummyImgStyles = function (imageSize) {
18562			if (!imageSize)
18563				return '';
18564			return "width:" + imageSize.width + "px;\n                margin-left: -" + imageSize.width / 2 + "px;\n                margin-top: -" + imageSize.height / 2 + "px;\n                height:" + imageSize.height + "px";
18565		};
18566		LightGallery.prototype.getVideoContStyle = function (imageSize) {
18567			if (!imageSize)
18568				return '';
18569			return "width:" + imageSize.width + "px;\n                height:" + imageSize.height + "px";
18570		};
18571		LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) {
18572			var $currentItem;
18573			if (!this.settings.dynamic) {
18574				$currentItem = $LG(this.items).eq(index);
18575			}
18576			if ($currentItem) {
18577				var _dummyImgSrc = void 0;
18578				if (!this.settings.exThumbImage) {
18579					_dummyImgSrc = $currentItem.find('img').first().attr('src');
18580				}
18581				else {
18582					_dummyImgSrc = $currentItem.attr(this.settings.exThumbImage);
18583				}
18584				if (!_dummyImgSrc)
18585					return '';
18586				var imgStyle = this.getDummyImgStyles(this.currentImageSize);
18587				var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />";
18588				$currentSlide.addClass('lg-first-slide');
18589				this.outer.addClass('lg-first-slide-loading');
18590				return dummyImgContent;
18591			}
18592			return '';
18593		};
18594		LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) {
18595			var currentGalleryItem = this.galleryItems[index];
18596			var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18597			// Use the thumbnail as dummy image which will be resized to actual image size and
18598			// displayed on top of actual image
18599			var imgContent = '';
18600			var altAttr = alt ? 'alt="' + alt + '"' : '';
18601			if (this.isFirstSlideWithZoomAnimation()) {
18602				imgContent = this.getDummyImageContent($currentSlide, index, altAttr);
18603			}
18604			else {
18605				imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources);
18606			}
18607			var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>";
18608			$currentSlide.prepend(imgMarkup);
18609		};
18610		LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) {
18611			var mediaObject = $slide.find('.lg-object').first();
18612			if (utils.isImageLoaded(mediaObject.get()) ||
18613				isHTML5VideoWithoutPoster) {
18614				onLoad();
18615			}
18616			else {
18617				mediaObject.on('load.lg error.lg', function () {
18618					onLoad && onLoad();
18619				});
18620				mediaObject.on('error.lg', function () {
18621					onError && onError();
18622				});
18623			}
18624		};
18625		/**
18626		 *
18627		 * @param $el Current slide item
18628		 * @param index
18629		 * @param delay Delay is 0 except first time
18630		 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin
18631		 * @param isFirstSlide
18632		 */
18633		LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) {
18634			var _this = this;
18635			//Uncode edit ##START##
18636			var $item = _this.galleryItems[index],
18637				type = $item.type;
18638
18639			if ( typeof $item.src !== 'undefined' ) {
18640				var inline_id = $item.src.replace('#', ''),
18641					$inline = document.getElementById(inline_id),
18642					inline_html;
18643
18644				if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18645					inline_html = $inline.innerHTML;
18646				} else {
18647					inline_html = '';
18648				}
18649			}
18650			//Uncode edit ##END##
18651			this.onSlideObjectLoad(currentSlide, true, function () {
18652				_this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide);
18653			}, function () {
18654				currentSlide.addClass('lg-complete lg-complete_');
18655				//Uncode edit ##START##
18656				// currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18657				if ( inline_html !== '' ) {
18658					currentSlide.html(inline_html);
18659				} else {
18660					currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>');
18661				}
18662				//Uncode edit ##END##
18663			});
18664		};
18665		LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) {
18666			var _this = this;
18667			var currentGalleryItem = this.galleryItems[index];
18668			// Adding delay for video slides without poster for better performance and user experience
18669			// Videos should start playing once once the gallery is completely loaded
18670			var _speed = isFirstSlide &&
vendor: 3,676 bytes, lines 18671-18759
18671				this.getSlideType(currentGalleryItem) === 'video' &&
18672				!currentGalleryItem.poster
18673				? speed
18674				: 0;
18675			setTimeout(function () {
18676				$currentSlide.addClass('lg-complete lg-complete_');
18677				_this.LGel.trigger(lGEvents.slideItemLoad, {
18678					index: index,
18679					delay: delay || 0,
18680					isFirstSlide: isFirstSlide,
18681				});
18682			}, _speed);
18683		};
18684		LightGallery.prototype.isFirstSlideWithZoomAnimation = function () {
18685			return !!(!this.lGalleryOn &&
18686				this.zoomFromOrigin &&
18687				this.currentImageSize);
18688		};
18689		// Add video slideInfo
18690		LightGallery.prototype.addSlideVideoInfo = function (items) {
18691			var _this = this;
18692			items.forEach(function (element, index) {
18693				element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index);
18694				if (element.__slideVideoInfo &&
18695					_this.settings.loadYouTubePoster &&
18696					!element.poster &&
18697					element.__slideVideoInfo.youtube) {
18698					element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg";
18699				}
18700			});
18701		};
18702		/**
18703		 *  Load slide content into slide.
18704		 *  This is used to load content into slides that is not visible too
18705		 *  @param {Number} index - index of the slide.
18706		 *  @param {Boolean} rec - if true call loadcontent() function again.
18707		 */
18708		LightGallery.prototype.loadContent = function (index, rec) {
18709			var _this = this;
18710			var currentGalleryItem = this.galleryItems[index];
18711			var $currentSlide = $LG(this.getSlideItemId(index));
18712			var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources;
18713			var src = currentGalleryItem.src;
18714			var video = currentGalleryItem.video;
18715			var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video;
18716			if (currentGalleryItem.responsive) {
18717				var srcDyItms = currentGalleryItem.responsive.split(',');
18718				src = utils.getResponsiveSrc(srcDyItms) || src;
18719			}
18720			var videoInfo = currentGalleryItem.__slideVideoInfo;
18721			var lgVideoStyle = '';
18722			var iframe = !!currentGalleryItem.iframe;
18723			var isFirstSlide = !this.lGalleryOn;
18724			// delay for adding complete class. it is 0 except first time.
18725			var delay = 0;
18726			if (isFirstSlide) {
18727				if (this.zoomFromOrigin && this.currentImageSize) {
18728					delay = this.settings.startAnimationDuration + 10;
18729				}
18730				else {
18731					delay = this.settings.backdropDuration + 10;
18732				}
18733			}
18734			if (!$currentSlide.hasClass('lg-loaded')) {
18735				if (videoInfo) {
18736					var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom;
18737					//Uncode edit ##START##
18738					var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
18739					// var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize);
18740					//Uncode edit ##END##
18741					lgVideoStyle = this.getVideoContStyle(videoSize);
18742				}
18743				if (iframe) {
18744					var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle);
18745					$currentSlide.prepend(markup);
18746				}
18747				else if (poster) {
18748					var dummyImg = '';
18749					var hasStartAnimation = isFirstSlide &&
18750						this.zoomFromOrigin &&
18751						this.currentImageSize;
18752					if (hasStartAnimation) {
18753						dummyImg = this.getDummyImageContent($currentSlide, index, '');
18754					}
18755					var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo);
18756					$currentSlide.prepend(markup);
18757				}
18758				//Uncode edit ##START##
18759				// else if (videoInfo) {
18760				else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') {
18761					if (! _html5Video) {
18762						var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>";
18763					}
18764					//Uncode edit ##END##
18765					$currentSlide.prepend(markup);
18766				}
18767				else {
18768					//Uncode edit ##START##
18769					var $item = _this.galleryItems[index],
18770						type = $item.type;
18771
18772					if ( typeof $item.src !== 'undefined' ) {
18773						var inline_id = $item.src.replace('#', ''),
18774							$inline = document.getElementById(inline_id),
18775							inline_html;
18776
18777						if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) {
18778							inline_html = $inline.innerHTML;
18779						} else {
18780							inline_html = '';
18781						}
18782					}
18783					if ( inline_html !== '' ) {
18784						$currentSlide.html(inline_html);
18785					} else {
18786						this.setImgMarkup(src, $currentSlide, index);
18787						if (srcset || sources) {
18788							var $img = $currentSlide.find('.lg-object');
18789							this.initPictureFill($img);
18790						}
18791					}
18792					/*this.setImgMarkup(src, $currentSlide, index);
18793					if (srcset || sources) {
18794						var $img = $currentSlide.find('.lg-object');
18795						this.initPictureFill($img);
18796					}*/
18797					//Uncode edit ##END##
18798				}
18799				if (poster || videoInfo) {
18800					this.LGel.trigger(lGEvents.hasVideo, {
18801						index: index,
18802						src: src,
18803						html5Video: _html5Video,
18804						hasPoster: !!poster,
18805					});
18806				}
18807				this.LGel.trigger(lGEvents.afterAppendSlide, { index: index });
18808				if (this.lGalleryOn &&
18809					this.settings.appendSubHtmlTo === '.lg-item') {
18810					this.addHtml(index);
18811				}
18812			}
18813			// For first time add some delay for displaying the start animation.
18814			var _speed = 0;
18815			// Do not change the delay value because it is required for zoom plugin.
18816			// If gallery opened from direct url (hash) speed value should be 0
18817			if (delay && !$LG(document.body).hasClass('lg-from-hash')) {
18818				_speed = delay;
18819			}
18820			// Only for first slide and zoomFromOrigin is enabled
18821			if (this.isFirstSlideWithZoomAnimation()) {
18822				setTimeout(function () {
18823					$currentSlide
18824						.removeClass('lg-start-end-progress lg-start-progress')
18825						.removeAttr('style');
18826				}, this.settings.startAnimationDuration + 100);
18827				if (!$currentSlide.hasClass('lg-loaded')) {
18828					setTimeout(function () {
18829						if (_this.getSlideType(currentGalleryItem) === 'image') {
18830							var alt = currentGalleryItem.alt;
18831							var altAttr = alt ? 'alt="' + alt + '"' : '';
18832							$currentSlide
18833								.find('.lg-img-wrap')
18834								.append(utils.getImgMarkup(index, src, altAttr, srcset, sizes, currentGalleryItem.sources));
18835							if (srcset || sources) {
18836								var $img = $currentSlide.find('.lg-object');
18837								_this.initPictureFill($img);
18838							}
18839						}
18840						if (_this.getSlideType(currentGalleryItem) === 'image' ||
18841							(_this.getSlideType(currentGalleryItem) === 'video' &&
18842								poster)) {
18843							_this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false);
18844							// load remaining slides once the slide is completely loaded
18845							_this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () {
18846								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18847							}, function () {
18848								_this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed);
18849							});
18850						}
18851					}, this.settings.startAnimationDuration + 100);
18852				}
18853			}
18854			// SLide content has been added to dom
18855			$currentSlide.addClass('lg-loaded');
18856			if (!this.isFirstSlideWithZoomAnimation() ||
18857				(this.getSlideType(currentGalleryItem) === 'video' && !poster)) {
18858				//Uncode edit ##START##
18859				// this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster));
18860				this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.get
vendor: 31,133 bytes, lines 18860-19784
18860SlideType(currentGalleryItem) === 'audio'));
18861				//Uncode edit ##END##
18862			}
18863			// When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling
18864			if ((!this.zoomFromOrigin || !this.currentImageSize) &&
18865				$currentSlide.hasClass('lg-complete_') &&
18866				!this.lGalleryOn) {
18867				setTimeout(function () {
18868					$currentSlide.addClass('lg-complete');
18869				}, this.settings.backdropDuration);
18870			}
18871			// Content loaded
18872			// Need to set lGalleryOn before calling preload function
18873			this.lGalleryOn = true;
18874			if (rec === true) {
18875				if (!$currentSlide.hasClass('lg-complete_')) {
18876					$currentSlide
18877						.find('.lg-object')
18878						.first()
18879						.on('load.lg error.lg', function () {
18880						_this.preload(index);
18881					});
18882				}
18883				else {
18884					this.preload(index);
18885				}
18886			}
18887		};
18888		/**
18889		 * @desc Remove dummy image content and load next slides
18890		 * Called only for the first time if zoomFromOrigin animation is enabled
18891		 * @param index
18892		 * @param $currentSlide
18893		 * @param speed
18894		 */
18895		LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) {
18896			var _this = this;
18897			setTimeout(function () {
18898				$currentSlide.find('.lg-dummy-img').remove();
18899				$currentSlide.removeClass('lg-first-slide');
18900				_this.outer.removeClass('lg-first-slide-loading');
18901				_this.isDummyImageRemoved = true;
18902				_this.preload(index);
18903			}, speed + 300);
18904		};
18905		LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) {
18906			var _this = this;
18907			if (numberOfItems === void 0) { numberOfItems = 0; }
18908			var itemsToBeInsertedToDom = [];
18909			// Minimum 2 items should be there
18910			var possibleNumberOfItems = Math.max(numberOfItems, 3);
18911			possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length);
18912			var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex;
18913			if (this.galleryItems.length <= 3) {
18914				this.galleryItems.forEach(function (_element, index) {
18915					itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index);
18916				});
18917				return itemsToBeInsertedToDom;
18918			}
18919			if (index < (this.galleryItems.length - 1) / 2) {
18920				for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) {
18921					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18922				}
18923				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18924				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18925					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1));
18926				}
18927			}
18928			else {
18929				for (var idx = index; idx <= this.galleryItems.length - 1 &&
18930					idx < index + possibleNumberOfItems / 2; idx++) {
18931					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx);
18932				}
18933				var numberOfExistingItems = itemsToBeInsertedToDom.length;
18934				for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) {
18935					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1));
18936				}
18937			}
18938			if (this.settings.loop) {
18939				if (index === this.galleryItems.length - 1) {
18940					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0);
18941				}
18942				else if (index === 0) {
18943					itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1));
18944				}
18945			}
18946			if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) {
18947				itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex);
18948			}
18949			return itemsToBeInsertedToDom;
18950		};
18951		LightGallery.prototype.organizeSlideItems = function (index, prevIndex) {
18952			var _this = this;
18953			var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom);
18954			itemsToBeInsertedToDom.forEach(function (item) {
18955				if (_this.currentItemsInDom.indexOf(item) === -1) {
18956					_this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>");
18957				}
18958			});
18959			this.currentItemsInDom.forEach(function (item) {
18960				if (itemsToBeInsertedToDom.indexOf(item) === -1) {
18961					$LG("#" + item).remove();
18962				}
18963			});
18964			return itemsToBeInsertedToDom;
18965		};
18966		/**
18967		 * Get previous index of the slide
18968		 */
18969		LightGallery.prototype.getPreviousSlideIndex = function () {
18970			var prevIndex = 0;
18971			try {
18972				var currentItemId = this.outer
18973					.find('.lg-current')
18974					.first()
18975					.attr('id');
18976				prevIndex = parseInt(currentItemId.split('-')[3]) || 0;
18977			}
18978			catch (error) {
18979				prevIndex = 0;
18980			}
18981			return prevIndex;
18982		};
18983		LightGallery.prototype.setDownloadValue = function (index) {
18984			if (this.settings.download) {
18985				var currentGalleryItem = this.galleryItems[index];
18986				var hideDownloadBtn = currentGalleryItem.downloadUrl === false ||
18987					currentGalleryItem.downloadUrl === 'false';
18988				if (hideDownloadBtn) {
18989					this.outer.addClass('lg-hide-download');
18990				}
18991				else {
18992					var $download = this.getElementById('lg-download');
18993					this.outer.removeClass('lg-hide-download');
18994					$download.attr('href', currentGalleryItem.downloadUrl ||
18995						currentGalleryItem.src);
18996					if (currentGalleryItem.download) {
18997						//Uncode edit ##START##
18998						if ( typeof currentGalleryItem.video !== 'undefined' && currentGalleryItem.video ) {
18999							var currentVideo = JSON.parse( currentGalleryItem.video ),
19000								download_name = currentVideo.source[0].src;
19001							$download.attr('href', download_name).removeAttr('download');
19002						} else {
19003							var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src,
19004								download_name = download_url.substring(download_url.lastIndexOf('/')+1);
19005							$download.attr('download', download_name);
19006						}
19007						// $download.attr('download', currentGalleryItem.download);
19008						//Uncode edit ##END##
19009					}
19010				}
19011			}
19012		};
19013		LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) {
19014			var _this = this;
19015			if (this.lGalleryOn) {
19016				previousSlideItem.addClass('lg-slide-progress');
19017			}
19018			setTimeout(function () {
19019				// remove all transitions
19020				_this.outer.addClass('lg-no-trans');
19021				_this.outer
19022					.find('.lg-item')
19023					.removeClass('lg-prev-slide lg-next-slide');
19024				if (direction === 'prev') {
19025					//prevslide
19026					currentSlideItem.addClass('lg-prev-slide');
19027					previousSlideItem.addClass('lg-next-slide');
19028				}
19029				else {
19030					// next slide
19031					currentSlideItem.addClass('lg-next-slide');
19032					previousSlideItem.addClass('lg-prev-slide');
19033				}
19034				// give 50 ms for browser to add/remove class
19035				setTimeout(function () {
19036					_this.outer.find('.lg-item').removeClass('lg-current');
19037					currentSlideItem.addClass('lg-current');
19038					// reset all transitions
19039					_this.outer.removeClass('lg-no-trans');
19040				}, 50);
19041			}, this.lGalleryOn ? this.settings.slideDelay : 0);
19042		};
19043		/**
19044		 * Goto a specific slide.
19045		 * @param {Number} index - index of the slide
19046		 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag
19047		 * @param {Boolean} fromThumb - true if slide function called via thumbnail click
19048		 * @param {String} direction - Direction of the slide(next/prev)
19049		 * @category lGPublicMethods
19050		 * @example
19051		 *  const plugin = lightGallery();
19052		 *  // to go to 3rd slide
19053		 *  plugin.slide(2);
19054		 *
19055		 */
19056		LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) {
19057			var _this = this;
19058			var prevIndex = this.getPreviousSlideIndex();
19059			this.currentItemsInDom = this.organizeSlideItems(index, prevIndex);
19060			// Prevent multiple call, Required for hsh plugin
19061			if (this.lGalleryOn && prevIndex === index) {
19062				return;
19063			}
19064			var numberOfGalleryItems = this.galleryItems.length;
19065			if (!this.lgBusy) {
19066				if (this.settings.counter) {
19067					this.updateCurrentCounter(index);
19068				}
19069				var currentSlideItem = this.getSlideItem(index);
19070				var previousSlideItem_1 = this.getSlideItem(prevIndex);
19071				var currentGalleryItem = this.galleryItems[index];
19072				var videoInfo = currentGalleryItem.__slideVideoInfo;
19073				this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem));
19074				this.setDownloadValue(index);
19075				if (videoInfo) {
19076					var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom;
19077					//Uncode edit ##START##
19078					var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]);
19079					// var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize);
19080					//Uncode edit ##END##
19081					this.resizeVideoSlide(index, videoSize);
19082				}
19083				this.LGel.trigger(lGEvents.beforeSlide, {
19084					prevIndex: prevIndex,
19085					index: index,
19086					fromTouch: !!fromTouch,
19087					fromThumb: !!fromThumb,
19088					//Uncode edit ##START##
19089					currentSlide: currentSlideItem,
19090					previousSlide: previousSlideItem_1,
19091					info: currentGalleryItem,
19092					item: this.items[index]
19093					//Uncode edit ##END##
19094				});
19095				this.lgBusy = true;
19096				clearTimeout(this.hideBarTimeout);
19097				this.arrowDisable(index);
19098				if (!direction) {
19099					if (index < prevIndex) {
19100						direction = 'prev';
19101					}
19102					else if (index > prevIndex) {
19103						direction = 'next';
19104					}
19105				}
19106				if (!fromTouch) {
19107					this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1);
19108				}
19109				else {
19110					this.outer
19111						.find('.lg-item')
19112						.removeClass('lg-prev-slide lg-current lg-next-slide');
19113					var touchPrev = void 0;
19114					var touchNext = void 0;
19115					if (numberOfGalleryItems > 2) {
19116						touchPrev = index - 1;
19117						touchNext = index + 1;
19118						if (index === 0 && prevIndex === numberOfGalleryItems - 1) {
19119							// next slide
19120							touchNext = 0;
19121							touchPrev = numberOfGalleryItems - 1;
19122						}
19123						else if (index === numberOfGalleryItems - 1 &&
19124							prevIndex === 0) {
19125							// prev slide
19126							touchNext = 0;
19127							touchPrev = numberOfGalleryItems - 1;
19128						}
19129					}
19130					else {
19131						touchPrev = 0;
19132						touchNext = 1;
19133					}
19134					if (direction === 'prev') {
19135						this.getSlideItem(touchNext).addClass('lg-next-slide');
19136					}
19137					else {
19138						this.getSlideItem(touchPrev).addClass('lg-prev-slide');
19139					}
19140					currentSlideItem.addClass('lg-current');
19141				}
19142				// Do not put load content in set timeout as it needs to load immediately when the gallery is opened
19143				if (!this.lGalleryOn) {
19144					this.loadContent(index, true);
19145				}
19146				else {
19147					setTimeout(function () {
19148						_this.loadContent(index, true);
19149						// Add title if this.settings.appendSubHtmlTo === lg-sub-html
19150						if (_this.settings.appendSubHtmlTo !== '.lg-item') {
19151							_this.addHtml(index);
19152						}
19153					}, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay));
19154				}
19155				setTimeout(function () {
19156					_this.lgBusy = false;
19157					previousSlideItem_1.removeClass('lg-slide-progress');
19158					_this.LGel.trigger(lGEvents.afterSlide, {
19159						prevIndex: prevIndex,
19160						index: index,
19161						fromTouch: fromTouch,
19162						fromThumb: fromThumb,
19163					});
19164				}, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay));
19165			}
19166			this.index = index;
19167		};
19168		LightGallery.prototype.updateCurrentCounter = function (index) {
19169			this.getElementById('lg-counter-current').html(index + 1 + '');
19170		};
19171		LightGallery.prototype.updateCounterTotal = function () {
19172			this.getElementById('lg-counter-all').html(this.galleryItems.length + '');
19173		};
19174		LightGallery.prototype.getSlideType = function (item) {
19175			if (item.__slideVideoInfo) {
19176				return 'video';
19177			}
19178			else if (item.iframe) {
19179				return 'iframe';
19180			}
19181			//Uncode edit ##START##
19182			else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) {
19183				return 'audio';
19184			}
19185			//Uncode edit ##END##
19186			else {
19187				return 'image';
19188			}
19189		};
19190		LightGallery.prototype.touchMove = function (startCoords, endCoords, e) {
19191			var distanceX = endCoords.pageX - startCoords.pageX;
19192			var distanceY = endCoords.pageY - startCoords.pageY;
19193			var allowSwipe = false;
19194			if (this.swipeDirection) {
19195				allowSwipe = true;
19196			}
19197			else {
19198				if (Math.abs(distanceX) > 15) {
19199					this.swipeDirection = 'horizontal';
19200					allowSwipe = true;
19201				}
19202				else if (Math.abs(distanceY) > 15) {
19203					this.swipeDirection = 'vertical';
19204					allowSwipe = true;
19205				}
19206			}
19207			if (!allowSwipe) {
19208				return;
19209			}
19210			var $currentSlide = this.getSlideItem(this.index);
19211			if (this.swipeDirection === 'horizontal') {
19212				e === null || e === void 0 ? void 0 : e.preventDefault();
19213				// reset opacity and transition duration
19214				this.outer.addClass('lg-dragging');
19215				// move current slide
19216				this.setTranslate($currentSlide, distanceX, 0);
19217				// move next and prev slide with current slide
19218				var width = $currentSlide.get().offsetWidth;
19219				var slideWidthAmount = (width * 15) / 100;
19220				var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100);
19221				this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0);
19222				this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0);
19223			}
19224			else if (this.swipeDirection === 'vertical') {
19225				if (this.settings.swipeToClose) {
19226					e === null || e === void 0 ? void 0 : e.preventDefault();
19227					this.$container.addClass('lg-dragging-vertical');
19228					var opacity = 1 - Math.abs(distanceY) / window.innerHeight;
19229					this.$backdrop.css('opacity', opacity);
19230					var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2);
19231					this.setTranslate($currentSlide, 0, distanceY, scale, scale);
19232					if (Math.abs(distanceY) > 100) {
19233						this.outer
19234							.addClass('lg-hide-items')
19235							.removeClass('lg-components-open');
19236					}
19237				}
19238			}
19239		};
19240		LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) {
19241			var _this = this;
19242			var distance;
19243			// keep slide animation for any mode while dragg/swipe
19244			if (this.settings.mode !== 'lg-slide') {
19245				this.outer.addClass('lg-slide');
19246			}
19247			// set transition duration
19248			setTimeout(function () {
19249				_this.$container.removeClass('lg-dragging-vertical');
19250				_this.outer
19251					.removeClass('lg-dragging lg-hide-items')
19252					.addClass('lg-components-open');
19253				var triggerClick = true;
19254				if (_this.swipeDirection === 'horizontal') {
19255					distance = endCoords.pageX - startCoords.pageX;
19256					var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX);
19257					if (distance < 0 &&
19258						distanceAbs > _this.settings.swipeThreshold) {
19259						_this.goToNextSlide(true);
19260						triggerClick = false;
19261					}
19262					else if (distance > 0 &&
19263						distanceAbs > _this.settings.swipeThreshold) {
19264						_this.goToPrevSlide(true);
19265						triggerClick = false;
19266					}
19267				}
19268				else if (_this.swipeDirection === 'vertical') {
19269					distance = Math.abs(endCoords.pageY - startCoords.pageY);
19270					if (_this.settings.closable &&
19271						_this.settings.swipeToClose &&
19272						distance > 100) {
19273						_this.closeGallery();
19274						return;
19275					}
19276					else {
19277						_this.$backdrop.css('opacity', 1);
19278					}
19279				}
19280				_this.outer.find('.lg-item').removeAttr('style');
19281				if (triggerClick &&
19282					Math.abs(endCoords.pageX - startCoords.pageX) < 5) {
19283					// Trigger click if distance is less than 5 pix
19284					var target = $LG(event.target);
19285					if (_this.isPosterElement(target)) {
19286						_this.LGel.trigger(lGEvents.posterClick);
19287					}
19288				}
19289				_this.swipeDirection = undefined;
19290			});
19291			// remove slide class once drag/swipe is completed if mode is not slide
19292			setTimeout(function () {
19293				if (!_this.outer.hasClass('lg-dragging') &&
19294					_this.settings.mode !== 'lg-slide') {
19295					_this.outer.removeClass('lg-slide');
19296				}
19297			}, this.settings.speed + 100);
19298		};
19299		LightGallery.prototype.enableSwipe = function () {
19300			var _this = this;
19301			var startCoords = {};
19302			var endCoords = {};
19303			var isMoved = false;
19304			var isSwiping = false;
19305			if (this.settings.enableSwipe) {
19306				this.$inner.on('touchstart.lg', function (e) {
19307					_this.dragOrSwipeEnabled = true;
19308					var $item = _this.getSlideItem(_this.index);
19309					if (($LG(e.target).hasClass('lg-item') ||
19310						$item.get().contains(e.target)) &&
19311						!_this.outer.hasClass('lg-zoomed') &&
19312						!_this.lgBusy &&
19313						e.targetTouches.length === 1) {
19314						isSwiping = true;
19315						_this.touchAction = 'swipe';
19316						_this.manageSwipeClass();
19317						startCoords = {
19318							pageX: e.targetTouches[0].pageX,
19319							pageY: e.targetTouches[0].pageY,
19320						};
19321					}
19322				});
19323				this.$inner.on('touchmove.lg', function (e) {
19324					if (isSwiping &&
19325						_this.touchAction === 'swipe' &&
19326						e.targetTouches.length === 1) {
19327						endCoords = {
19328							pageX: e.targetTouches[0].pageX,
19329							pageY: e.targetTouches[0].pageY,
19330						};
19331						_this.touchMove(startCoords, endCoords, e);
19332						isMoved = true;
19333					}
19334				});
19335				this.$inner.on('touchend.lg', function (event) {
19336					if (_this.touchAction === 'swipe') {
19337						if (isMoved) {
19338							isMoved = false;
19339							_this.touchEnd(endCoords, startCoords, event);
19340						}
19341						else if (isSwiping) {
19342							var target = $LG(event.target);
19343							if (_this.isPosterElement(target)) {
19344								_this.LGel.trigger(lGEvents.posterClick);
19345							}
19346						}
19347						_this.touchAction = undefined;
19348						isSwiping = false;
19349					}
19350				});
19351			}
19352		};
19353		LightGallery.prototype.enableDrag = function () {
19354			var _this = this;
19355			var startCoords = {};
19356			var endCoords = {};
19357			var isDraging = false;
19358			var isMoved = false;
19359			if (this.settings.enableDrag) {
19360				this.outer.on('mousedown.lg', function (e) {
19361					_this.dragOrSwipeEnabled = true;
19362					var $item = _this.getSlideItem(_this.index);
19363					if ($LG(e.target).hasClass('lg-item') ||
19364						$item.get().contains(e.target)) {
19365						if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) {
19366							e.preventDefault();
19367							if (!_this.lgBusy) {
19368								_this.manageSwipeClass();
19369								startCoords = {
19370									pageX: e.pageX,
19371									pageY: e.pageY,
19372								};
19373								isDraging = true;
19374								// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
19375								_this.outer.get().scrollLeft += 1;
19376								_this.outer.get().scrollLeft -= 1;
19377								// *
19378								_this.outer
19379									.removeClass('lg-grab')
19380									.addClass('lg-grabbing');
19381								_this.LGel.trigger(lGEvents.dragStart);
19382							}
19383						}
19384					}
19385				});
19386				$LG(window).on("mousemove.lg.global" + this.lgId, function (e) {
19387					if (isDraging && _this.lgOpened) {
19388						isMoved = true;
19389						endCoords = {
19390							pageX: e.pageX,
19391							pageY: e.pageY,
19392						};
19393						_this.touchMove(startCoords, endCoords);
19394						_this.LGel.trigger(lGEvents.dragMove);
19395					}
19396				});
19397				$LG(window).on("mouseup.lg.global" + this.lgId, function (event) {
19398					if (!_this.lgOpened) {
19399						return;
19400					}
19401					var target = $LG(event.target);
19402					if (isMoved) {
19403						isMoved = false;
19404						_this.touchEnd(endCoords, startCoords, event);
19405						_this.LGel.trigger(lGEvents.dragEnd);
19406					}
19407					else if (_this.isPosterElement(target)) {
19408						_this.LGel.trigger(lGEvents.posterClick);
19409					}
19410					// Prevent execution on click
19411					if (isDraging) {
19412						isDraging = false;
19413						_this.outer.removeClass('lg-grabbing').addClass('lg-grab');
19414					}
19415				});
19416			}
19417		};
19418		LightGallery.prototype.triggerPosterClick = function () {
19419			var _this = this;
19420			this.$inner.on('click.lg', function (event) {
19421				if (!_this.dragOrSwipeEnabled &&
19422					_this.isPosterElement($LG(event.target))) {
19423					_this.LGel.trigger(lGEvents.posterClick);
19424				}
19425			});
19426		};
19427		LightGallery.prototype.manageSwipeClass = function () {
19428			var _touchNext = this.index + 1;
19429			var _touchPrev = this.index - 1;
19430			if (this.settings.loop && this.galleryItems.length > 2) {
19431				if (this.index === 0) {
19432					_touchPrev = this.galleryItems.length - 1;
19433				}
19434				else if (this.index === this.galleryItems.length - 1) {
19435					_touchNext = 0;
19436				}
19437			}
19438			this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide');
19439			if (_touchPrev > -1) {
19440				this.getSlideItem(_touchPrev).addClass('lg-prev-slide');
19441			}
19442			this.getSlideItem(_touchNext).addClass('lg-next-slide');
19443		};
19444		/**
19445		 * Go to next slide
19446		 * @param {Boolean} fromTouch - true if slide function called via touch event
19447		 * @category lGPublicMethods
19448		 * @example
19449		 *  const plugin = lightGallery();
19450		 *  plugin.goToNextSlide();
19451		 * @see <a href="/demos/methods/">Demo</a>
19452		 */
19453		LightGallery.prototype.goToNextSlide = function (fromTouch) {
19454			var _this = this;
19455			var _loop = this.settings.loop;
19456			if (fromTouch && this.galleryItems.length < 3) {
19457				_loop = false;
19458			}
19459			if (!this.lgBusy) {
19460				if (this.index + 1 < this.galleryItems.length) {
19461					this.index++;
19462					this.LGel.trigger(lGEvents.beforeNextSlide, {
19463						index: this.index,
19464					});
19465					this.slide(this.index, !!fromTouch, false, 'next');
19466				}
19467				else {
19468					if (_loop) {
19469						this.index = 0;
19470						this.LGel.trigger(lGEvents.beforeNextSlide, {
19471							index: this.index,
19472						});
19473						this.slide(this.index, !!fromTouch, false, 'next');
19474					}
19475					else if (this.settings.slideEndAnimation && !fromTouch) {
19476						this.outer.addClass('lg-right-end');
19477						setTimeout(function () {
19478							_this.outer.removeClass('lg-right-end');
19479						}, 400);
19480					}
19481				}
19482			}
19483		};
19484		/**
19485		 * Go to previous slides
19486		 * @param {Boolean} fromTouch - true if slide function called via touch event
19487		 * @category lGPublicMethods
19488		 * @example
19489		 *  const plugin = lightGallery({});
19490		 *  plugin.goToPrevSlide();
19491		 * @see <a href="/demos/methods/">Demo</a>
19492		 *
19493		 */
19494		LightGallery.prototype.goToPrevSlide = function (fromTouch) {
19495			var _this = this;
19496			var _loop = this.settings.loop;
19497			if (fromTouch && this.galleryItems.length < 3) {
19498				_loop = false;
19499			}
19500			if (!this.lgBusy) {
19501				if (this.index > 0) {
19502					this.index--;
19503					this.LGel.trigger(lGEvents.beforePrevSlide, {
19504						index: this.index,
19505						fromTouch: fromTouch,
19506					});
19507					this.slide(this.index, !!fromTouch, false, 'prev');
19508				}
19509				else {
19510					if (_loop) {
19511						this.index = this.galleryItems.length - 1;
19512						this.LGel.trigger(lGEvents.beforePrevSlide, {
19513							index: this.index,
19514							fromTouch: fromTouch,
19515						});
19516						this.slide(this.index, !!fromTouch, false, 'prev');
19517					}
19518					else if (this.settings.slideEndAnimation && !fromTouch) {
19519						this.outer.addClass('lg-left-end');
19520						setTimeout(function () {
19521							_this.outer.removeClass('lg-left-end');
19522						}, 400);
19523					}
19524				}
19525			}
19526		};
19527		LightGallery.prototype.keyPress = function () {
19528			var _this = this;
19529			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19530				if (_this.lgOpened &&
19531					_this.settings.escKey === true &&
19532					e.keyCode === 27) {
19533					e.preventDefault();
19534					if (_this.settings.allowMediaOverlap &&
19535						_this.outer.hasClass('lg-can-toggle') &&
19536						_this.outer.hasClass('lg-components-open')) {
19537						_this.outer.removeClass('lg-components-open');
19538					}
19539					else {
19540						_this.closeGallery();
19541					}
19542				}
19543				if (_this.lgOpened && _this.galleryItems.length > 1) {
19544					if (e.keyCode === 37) {
19545						e.preventDefault();
19546						_this.goToPrevSlide();
19547					}
19548					if (e.keyCode === 39) {
19549						e.preventDefault();
19550						_this.goToNextSlide();
19551					}
19552				}
19553			});
19554		};
19555		LightGallery.prototype.arrow = function () {
19556			var _this = this;
19557			this.getElementById('lg-prev').on('click.lg', function () {
19558				_this.goToPrevSlide();
19559			});
19560			this.getElementById('lg-next').on('click.lg', function () {
19561				_this.goToNextSlide();
19562			});
19563		};
19564		LightGallery.prototype.arrowDisable = function (index) {
19565			// Disable arrows if settings.hideControlOnEnd is true
19566			if (!this.settings.loop && this.settings.hideControlOnEnd) {
19567				var $prev = this.getElementById('lg-prev');
19568				var $next = this.getElementById('lg-next');
19569				if (index + 1 === this.galleryItems.length) {
19570					$next.attr('disabled', 'disabled').addClass('disabled');
19571				}
19572				else {
19573					$next.removeAttr('disabled').removeClass('disabled');
19574				}
19575				if (index === 0) {
19576					$prev.attr('disabled', 'disabled').addClass('disabled');
19577				}
19578				else {
19579					$prev.removeAttr('disabled').removeClass('disabled');
19580				}
19581			}
19582		};
19583		LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) {
19584			if (scaleX === void 0) { scaleX = 1; }
19585			if (scaleY === void 0) { scaleY = 1; }
19586			$el.css('transform', 'translate3d(' +
19587				xValue +
19588				'px, ' +
19589				yValue +
19590				'px, 0px) scale3d(' +
19591				scaleX +
19592				', ' +
19593				scaleY +
19594				', 1)');
19595		};
19596		LightGallery.prototype.mousewheel = function () {
19597			var _this = this;
19598			var lastCall = 0;
19599			this.outer.on('wheel.lg', function (e) {
19600				if (!e.deltaY || _this.galleryItems.length < 2) {
19601					return;
19602				}
19603				e.preventDefault();
19604				var now = new Date().getTime();
19605				if (now - lastCall < 1000) {
19606					return;
19607				}
19608				lastCall = now;
19609				if (e.deltaY > 0) {
19610					_this.goToNextSlide();
19611				}
19612				else if (e.deltaY < 0) {
19613					_this.goToPrevSlide();
19614				}
19615			});
19616		};
19617		LightGallery.prototype.isSlideElement = function (target) {
19618			return (target.hasClass('lg-outer') ||
19619				target.hasClass('lg-item') ||
19620				target.hasClass('lg-img-wrap'));
19621		};
19622		LightGallery.prototype.isPosterElement = function (target) {
19623			var playButton = this.getSlideItem(this.index)
19624				.find('.lg-video-play-button')
19625				.get();
19626			return (target.hasClass('lg-video-poster') ||
19627				target.hasClass('lg-video-play-button') ||
19628				(playButton && playButton.contains(target.get())));
19629		};
19630		/**
19631		 * Maximize minimize inline gallery.
19632		 * @category lGPublicMethods
19633		 */
19634		LightGallery.prototype.toggleMaximize = function () {
19635			var _this = this;
19636			this.getElementById('lg-maximize').on('click.lg', function () {
19637				_this.$container.toggleClass('lg-inline');
19638				_this.refreshOnResize();
19639			});
19640		};
19641		LightGallery.prototype.invalidateItems = function () {
19642			for (var index = 0; index < this.items.length; index++) {
19643				var element = this.items[index];
19644				var $element = $LG(element);
19645				$element.off("click.lgcustom-item-" + $element.attr('data-lg-id'));
19646			}
19647		};
19648		LightGallery.prototype.trapFocus = function () {
19649			var _this = this;
19650			this.$container.get().focus({
19651				preventScroll: true,
19652			});
19653			$LG(window).on("keydown.lg.global" + this.lgId, function (e) {
19654				if (!_this.lgOpened) {
19655					return;
19656				}
19657				var isTabPressed = e.key === 'Tab' || e.keyCode === 9;
19658				if (!isTabPressed) {
19659					return;
19660				}
19661				var focusableEls = utils.getFocusableElements(_this.$container.get());
19662				var firstFocusableEl = focusableEls[0];
19663				var lastFocusableEl = focusableEls[focusableEls.length - 1];
19664				if (e.shiftKey) {
19665					if (document.activeElement === firstFocusableEl) {
19666						lastFocusableEl.focus();
19667						e.preventDefault();
19668					}
19669				}
19670				else {
19671					if (document.activeElement === lastFocusableEl) {
19672						firstFocusableEl.focus();
19673						e.preventDefault();
19674					}
19675				}
19676			});
19677		};
19678		LightGallery.prototype.manageCloseGallery = function () {
19679			var _this = this;
19680			if (!this.settings.closable)
19681				return;
19682			var mousedown = false;
19683			this.getElementById('lg-close').on('click.lg', function () {
19684				_this.closeGallery();
19685			});
19686			if (this.settings.closeOnTap) {
19687				// If you drag the slide and release outside gallery gets close on chrome
19688				// for preventing this check mousedown and mouseup happened on .lg-item or lg-outer
19689				this.outer.on('mousedown.lg', function (e) {
19690					var target = $LG(e.target);
19691					if (_this.isSlideElement(target)) {
19692						mousedown = true;
19693					}
19694					else {
19695						mousedown = false;
19696					}
19697				});
19698				this.outer.on('mousemove.lg', function () {
19699					mousedown = false;
19700				});
19701				this.outer.on('mouseup.lg', function (e) {
19702					var target = $LG(e.target);
19703					if (_this.isSlideElement(target) && mousedown) {
19704						if (!_this.outer.hasClass('lg-dragging')) {
19705							_this.closeGallery();
19706						}
19707					}
19708				});
19709			}
19710		};
19711		/**
19712		 * Close lightGallery if it is opened.
19713		 *
19714		 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery
19715		 * @return returns the estimated time to close gallery completely including the close animation duration
19716		 * @category lGPublicMethods
19717		 * @example
19718		 *  const plugin = lightGallery();
19719		 *  plugin.closeGallery();
19720		 *
19721		 */
19722		LightGallery.prototype.closeGallery = function (force) {
19723			var _this = this;
19724			if (!this.lgOpened || (!this.settings.closable && !force)) {
19725				return 0;
19726			}
19727			this.LGel.trigger(lGEvents.beforeClose);
19728			if (this.settings.resetScrollPosition && !this.settings.hideScrollbar) {
19729				$LG(window).scrollTop(this.prevScrollTop);
19730			}
19731			var currentItem = this.items[this.index];
19732			var transform;
19733			if (this.zoomFromOrigin && currentItem) {
19734				var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom;
19735				var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster;
19736				//Uncode edit ##START##
19737				var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]);
19738				// var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize);
19739				//Uncode edit ##END##
19740				transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize);
19741			}
19742			if (this.zoomFromOrigin && transform) {
19743				this.outer.addClass('lg-closing lg-zoom-from-image');
19744				this.getSlideItem(this.index)
19745					.addClass('lg-start-end-progress')
19746					.css('transition-duration', this.settings.startAnimationDuration + 'ms')
19747					.css('transform', transform);
19748			}
19749			else {
19750				this.outer.addClass('lg-hide-items');
19751				// lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true
19752				// If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts
19753				this.outer.removeClass('lg-zoom-from-image');
19754			}
19755			// Unbind all events added by lightGallery
19756			// @todo
19757			//this.$el.off('.lg.tm');
19758			this.destroyModules();
19759			this.lGalleryOn = false;
19760			this.isDummyImageRemoved = false;
19761			this.zoomFromOrigin = this.settings.zoomFromOrigin;
19762			clearTimeout(this.hideBarTimeout);
19763			this.hideBarTimeout = false;
19764			$LG('html').removeClass('lg-on');
19765			this.outer.removeClass('lg-visible lg-components-open');
19766			// Resetting opacity to 0 isd required as  vertical swipe to close function adds inline opacity.
19767			this.$backdrop.removeClass('in').css('opacity', 0);
19768			var removeTimeout = this.zoomFromOrigin && transform
19769				? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration)
19770				: this.settings.backdropDuration;
19771			this.$container.removeClass('lg-show-in');
19772			// Once the closign animation is completed and gallery is invisible
19773			setTimeout(function () {
19774				if (_this.zoomFromOrigin && transform) {
19775					_this.outer.removeClass('lg-zoom-from-image');
19776				}
19777				_this.$container.removeClass('lg-show');
19778				// Reset scrollbar
19779				_this.resetScrollBar();
19780				// Need to remove inline opacity as it is used in the stylesheet as well
19781				_this.$backdrop
19782					.removeAttr('style')
19783					.css('transition-duration', _this.settings.backdropDuration + 'ms');
19784				_this.outer.removeClass("lg-closing " + _this.settings.startClass);
vendor: 6,259 bytes, lines 19785-19988
19785				_this.getSlideItem(_this.index).removeClass('lg-start-end-progress');
19786				_this.$inner.empty();
19787				if (_this.lgOpened) {
19788					_this.LGel.trigger(lGEvents.afterClose, {
19789						instance: _this,
19790					});
19791				}
19792				if (_this.$container.get()) {
19793					_this.$container.get().blur();
19794				}
19795				_this.lgOpened = false;
19796			}, removeTimeout + 100);
19797			return removeTimeout + 100;
19798		};
19799		LightGallery.prototype.initModules = function () {
19800			this.plugins.forEach(function (module) {
19801				try {
19802					module.init();
19803				}
19804				catch (err) {
19805					console.warn("lightGallery:- make sure lightGallery module is properly initiated");
19806				}
19807			});
19808		};
19809		LightGallery.prototype.destroyModules = function (destroy) {
19810			this.plugins.forEach(function (module) {
19811				try {
19812					if (destroy) {
19813						module.destroy();
19814					}
19815					else {
19816						module.closeGallery && module.closeGallery();
19817					}
19818				}
19819				catch (err) {
19820					console.warn("lightGallery:- make sure lightGallery module is properly destroyed");
19821				}
19822			});
19823		};
19824		/**
19825		 * Refresh lightGallery with new set of children.
19826		 *
19827		 * @description This is useful to update the gallery when the child elements are changed without calling destroy method.
19828		 *
19829		 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery
19830		 * @see <a href="/demos/dynamic-mode/">Demo</a>
19831		 * @category lGPublicMethods
19832		 * @example
19833		 *  const plugin = lightGallery();
19834		 *  // Delete or add children, then call
19835		 *  plugin.refresh();
19836		 *
19837		 */
19838		LightGallery.prototype.refresh = function (galleryItems) {
19839			if (!this.settings.dynamic) {
19840				this.invalidateItems();
19841			}
19842			if (galleryItems) {
19843				this.galleryItems = galleryItems;
19844			}
19845			else {
19846				this.galleryItems = this.getItems();
19847			}
19848			this.updateControls();
19849			this.openGalleryOnItemClick();
19850			this.LGel.trigger(lGEvents.updateSlides);
19851		};
19852		LightGallery.prototype.updateControls = function () {
19853			this.addSlideVideoInfo(this.galleryItems);
19854			this.updateCounterTotal();
19855			this.manageSingleSlideClassName();
19856		};
19857		/**
19858		 * Destroy lightGallery.
19859		 * Destroy lightGallery and its plugin instances completely
19860		 *
19861		 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance.
19862		 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed.
19863		 * You can use refresh method most of the times.
19864		 * @category lGPublicMethods
19865		 * @example
19866		 *  const plugin = lightGallery();
19867		 *  plugin.destroy();
19868		 *
19869		 */
19870		LightGallery.prototype.destroy = function () {
19871			var _this = this;
19872			var closeTimeout = this.closeGallery(true);
19873			setTimeout(function () {
19874				_this.destroyModules(true);
19875				if (!_this.settings.dynamic) {
19876					_this.invalidateItems();
19877				}
19878				$LG(window).off(".lg.global" + _this.lgId);
19879				_this.LGel.off('.lg');
19880				_this.$container.remove();
19881			}, closeTimeout);
19882			return closeTimeout;
19883		};
19884		return LightGallery;
19885	}());
19886
19887	function lightGallery(el, options) {
19888		return new LightGallery(el, options);
19889	}
19890
19891	return lightGallery;
19892
19893})));
19894
19895/*!
19896 * lightgallery | 2.5.0 | June 13th 2022
19897 * http://www.lightgalleryjs.com/
19898 * Copyright (c) 2020 Sachin Neravath;
19899 * @license GPLv3
19900 */
19901
19902(function (global, factory) {
19903	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
19904	typeof define === 'function' && define.amd ? define(factory) :
19905	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory());
19906}(this, (function () { 'use strict';
19907
19908	/*! *****************************************************************************
19909	Copyright (c) Microsoft Corporation.
19910
19911	Permission to use, copy, modify, and/or distribute this software for any
19912	purpose with or without fee is hereby granted.
19913
19914	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19915	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19916	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
19917	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
19918	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19919	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19920	PERFORMANCE OF THIS SOFTWARE.
19921	***************************************************************************** */
19922
19923	var __assign = function() {
19924		__assign = Object.assign || function __assign(t) {
19925			for (var s, i = 1, n = arguments.length; i < n; i++) {
19926				s = arguments[i];
19927				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
19928			}
19929			return t;
19930		};
19931		return __assign.apply(this, arguments);
19932	};
19933
19934	var zoomSettings = {
19935		scale: 1,
19936		zoom: true,
19937		actualSize: true,
19938		showZoomInOutIcons: false,
19939		actualSizeIcons: {
19940			zoomIn: 'lg-zoom-in',
19941			zoomOut: 'lg-zoom-out',
19942		},
19943		enableZoomAfter: 300,
19944		zoomPluginStrings: {
19945			zoomIn: 'Zoom in',
19946			zoomOut: 'Zoom out',
19947			viewActualSize: 'View actual size',
19948		},
19949	};
19950
19951	/**
19952	 * List of lightGallery events
19953	 * All events should be documented here
19954	 * Below interfaces are used to build the website documentations
19955	 * */
19956	var lGEvents = {
19957		afterAppendSlide: 'lgAfterAppendSlide',
19958		init: 'lgInit',
19959		hasVideo: 'lgHasVideo',
19960		containerResize: 'lgContainerResize',
19961		updateSlides: 'lgUpdateSlides',
19962		afterAppendSubHtml: 'lgAfterAppendSubHtml',
19963		beforeOpen: 'lgBeforeOpen',
19964		afterOpen: 'lgAfterOpen',
19965		slideItemLoad: 'lgSlideItemLoad',
19966		beforeSlide: 'lgBeforeSlide',
19967		afterSlide: 'lgAfterSlide',
19968		posterClick: 'lgPosterClick',
19969		dragStart: 'lgDragStart',
19970		dragMove: 'lgDragMove',
19971		dragEnd: 'lgDragEnd',
19972		beforeNextSlide: 'lgBeforeNextSlide',
19973		beforePrevSlide: 'lgBeforePrevSlide',
19974		beforeClose: 'lgBeforeClose',
19975		afterClose: 'lgAfterClose',
19976		rotateLeft: 'lgRotateLeft',
19977		rotateRight: 'lgRotateRight',
19978		flipHorizontal: 'lgFlipHorizontal',
19979		flipVertical: 'lgFlipVertical',
19980		autoplay: 'lgAutoplay',
19981		autoplayStart: 'lgAutoplayStart',
19982		autoplayStop: 'lgAutoplayStop',
19983	};
19984
19985	var Zoom = /** @class */ (function () {
19986		function Zoom(instance, $LG) {
19987			// get lightGallery core plugin instance
19988			this.core = instance;
19989			this.$LG = $LG;
19990			this.settings = __assign(__assign({}, zoomSettings), this.core.settings);
19991			return this;
19992		}
19993		// Append Zoom controls. Actual size, Zoom-in, Zoom-out
19994		Zoom.prototype.buildTemplates = function () {
19995			var zoomIcons = this.settings.showZoomInOutIcons
19996				? "<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>"
19997				: '';
19998			if (this.settings.actualSize) {
19999				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>";
20000			}
20001			this.core.outer.addClass('lg-use-transition-for-zoom');
20002			this.core.$toolbar.first().append(zoomIcons);
20003		};
20004		/**
20005		 * @desc Enable zoom option only once the image is completely loaded
20006		 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted
20007		 *
20008		 * Zoom styles are defined under lg-zoomable CSS class.
20009		 */
20010		Zoom.prototype.enableZoom = function (event) {
20011			var _this = this;
20012			// delay will be 0 except first time
20013			var _speed = this.settings.enableZoomAfter + event.detail.delay;
20014			// set _speed value 0 if gallery opened from direct url and if it is first slide
20015			if (this.$LG('body').first().hasClass('lg-from-hash') &&
20016				event.detail.delay) {
20017				// will execute only once
20018				_speed = 0;
20019			}
20020			else {
20021				// Remove lg-from-hash to enable starting animation.
20022				this.$LG('body').first().removeClass('lg-from-hash');
20023			}
20024			this.zoomableTimeout = setTimeout(function () {
20025				if (!_this.isImageSlide()) {
20026					return;
20027				}
20028				_this.core.getSlideItem(event.detail.index).addClass('lg-zoomable');
20029				if (event.detail.index === _this.core.index) {
20030					_this.setZoomEssentials();
20031				}
20032			}, _speed + 30);
20033		};
20034		Zoom.prototype.enableZoomOnSlideItemLoad = function () {
20035			// Add zoomable class
20036			this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this));
20037		};
20038		Zoom.prototype.getModifier = function (rotateValue, axis, el) {
20039			var originalRotate = rotateValue;
20040			rotateValue = Math.abs(rotateValue);
20041			var transformValues = this.getCurrentTransform(el);
20042			if (!transformValues) {
20043				return 1;
20044			}
20045			var modifier = 1;
20046			if (axis === 'X') {
20047				var flipHorizontalValue = Math.sign(parseFloat(transformValues[0]));
20048				if (rotateValue === 0 || rotateValue === 180) {
20049					modifier = 1;
20050				}
20051				else if (rotateValue === 90) {
20052					if ((originalRotate === -90 && flipHorizontalValue === 1) ||
20053						(originalRotate === 90 && flipHorizontalValue === -1)) {
20054						modifier = -1;
20055					}
20056					else {
20057						modifier = 1;
20058					}
20059				}
20060				modifier = modifier * flipHorizontalValue;
20061			}
20062			else {
20063				var flipVerticalValue = Math.sign(parseFloat(transformValues[3]));
20064				if (rotateValue === 0 || rotateValue === 180) {
20065					modifier = 1;
20066				}
20067				else if (rotateValue === 90) {
20068					var sinX = parseFloat(transformValues[1]);
20069					var sinMinusX = parseFloat(transformValues[2]);
20070					modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue);
20071				}
20072				modifier = modifier * flipVerticalValue;
20073			}
20074			return modifier;
20075		};
20076		Zoom.prototype.getImageSize = function ($image, rotateValue, axis) {
20077			var imageSizes = {
20078				y: 'offsetHeight',
20079				x: 'offsetWidth',
20080			};
20081			if (Math.abs(rotateValue) === 90) {
20082				// Swap axis
20083				if (axis === 'x') {
20084					axis = 'y';
20085				}
20086				else {
20087					axis = 'x';
20088				}
20089			}
20090			return $image[imageSizes[axis]];
20091		};
20092		Zoom.prototype.getDragCords = function (e, rotateValue) {
20093			if (rotateValue === 90) {
20094				return {
20095					x: e.pageY,
20096					y: e.pageX,
20097				};
20098			}
20099			else {
20100				return {
20101					x: e.pageX,
20102					y: e.pageY,
20103				};
20104			}
20105		};
20106		Zoom.prototype.getSwipeCords = function (e, rotateValue) {
20107			var x = e.targetTouches[0].pageX;
20108			var y = e.targetTouches[0].pageY;
20109			if (rotateValue === 90) {
20110				return {
20111					x: y,
20112					y: x,
20113				};
20114			}
20115			else {
20116				return {
20117					x: x,
20118					y: y,
20119				};
20120			}
20121		};
20122		Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) {
20123			scale = scale || this.scale || 1;
20124			var allowY = this.imageYSize * scale > this.containerRect.height;
20125			var allowX = this.imageXSize * scale > this.containerRect.width;
20126			if (rotateValue === 90) {
20127				return {
20128					allowX: allowY,
20129					allowY: allowX,
20130				};
20131			}
20132			else {
20133				return {
20134					allowX: allowX,
20135					allowY: allowY,
20136				};
20137			}
20138		};
20139		/**
20140		 *
20141		 * @param {Element} el
20142		 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0);
20143		 * Get the current transform value
20144		 */
20145		Zoom.prototype.getCurrentTransform = function (el) {
20146			if (!el) {
20147				return;
20148			}
20149			var st = window.getComputedStyle(el, null);
20150			var tm = st.getPropertyValue('-webkit-transform') ||
20151				st.getPropertyValue('-moz-transform') ||
20152				st.getPropertyValue('-ms-transform') ||
20153				st.getPropertyValue('-o-transform') ||
20154				st.getPropertyValue('transform') ||
20155				'none';
20156			if (tm !== 'none') {
20157				return tm.split('(')[1].split(')')[0].split(',');
20158			}
20159			return;
20160		};
20161		Zoom.prototype.getCurrentRotation = function (el) {
20162			if (!el) {
20163				return 0;
20164			}
20165			var values = this.getCurrentTransform(el);
20166			if (values) {
20167				return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) *
20168					(180 / Math.PI));
20169				// If you want rotate in 360
20170				//return (angle < 0 ? angle + 360 : angle);
20171			}
20172			return 0;
20173		};
20174		Zoom.prototype.setZoomEssentials = function () {
20175			var $image = this.core
20176				.getSlideItem(this.core.index)
20177				.find('.lg-image')
20178				.first();
20179			var rotateEl = this.core
20180				.getSlideItem(this.core.index)
20181				.find('.lg-img-rotate')
20182				.first()
20183				.get();
20184			this.rotateValue = this.getCurrentRotation(rotateEl);
20185			this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y');
20186			this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x');
20187			this.containerRect = this.core.outer.get().getBoundingClientRect();
20188			this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl);
20189			this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl);
20190		};
20191		/**
20192		 * @desc Image zoom
20193		 * Translate the wrap and scale the image to get better user experience
20194		 *
20195		 * @param {String} scale - Zoom decrement/increment value
20196		 */
20197		Zoom.prototype.zoomImage = function (scale) {
20198			// Find offset manually to avoid issue after zoom
20199			var offsetX = (this.containerRect.width - this.imageXSize) / 2 +
20200				this.containerRect.left;
20201			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20202			var topBottomSpacing = Math.abs(top - bottom) / 2;
20203			var offsetY = (this.containerRect.height -
20204				this.imageYSize -
20205				topBottomSpacing * this.modifierX) /
20206				2 +
20207				this.scrollTop +
20208				this.containerRect.top;
20209			var originalX;
20210			var originalY;
20211			if (scale === 1) {
20212				this.positionChanged = false;
20213			}
20214			var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale);
20215			var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX;
20216			if (this.positionChanged) {
20217				originalX = this.left / (this.scale - 1);
20218				originalY = this.top / (this.scale - 1);
20219				this.pageX = Math.abs(originalX) + offsetX;
20220				this.pageY = Math.abs(originalY) + offsetY;
20221				this.positionChanged = false;
20222			}
20223			var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale);
20224			var _x = offsetX - this.pageX;
20225			var _y = offsetY - this.pageY;
20226			var x = (scale - 1) * _x;
20227			var y = (scale - 1) * _y;
20228			if (allowX) {
20229				if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) {
20230					x = possibleSwipeCords.minX;
20231				}
20232				else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) {
20233					x = possibleSwipeCords.maxX;
20234				}
20235			}
20236			else {
20237				if (scale > 1) {
20238					if (x < possibleSwipeCords.minX) {
20239						x = possibleSwipeCords.minX;
20240					}
20241					else if (x > possibleSwipeCords.maxX) {
20242						x = possibleSwipeCords.maxX;
20243					}
20244				}
20245			}
20246			if (allowY) {
20247				if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) {
20248					y = possibleSwipeCords.minY;
20249				}
20250				else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) {
20251					y = possibleSwipeCords.maxY;
20252				}
20253			}
20254			else {
20255				// If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out
20256				if (scale > 1) {
20257					//If image goes beyond viewport top, use the minim possible translate value
20258					if (y < possibleSwipeCords.minY) {
20259						y = possibleSwipeCords.minY;
20260					}
20261					else if (y > possibleSwipeCords.maxY) {
20262						y = possibleSwipeCords.maxY;
20263					}
20264				}
20265			}
20266			this.setZoomStyles({
20267				x: x,
20268				y: y,
20269				scale: scale,
20270			});
20271		};
20272		/**
20273		 * @desc apply scale3d to image and translate to image wrap
20274		 * @param {style} X,Y and scale
20275		 */
20276		Zoom.prototype.setZoomStyles = function (style) {
20277			var $image = this.core
20278				.getSlideItem(this.core.index)
20279				.find('.lg-image')
20280				.first();
20281			var $dummyImage = this.core.outer
20282				.find('.lg-current .lg-dummy-img')
20283				.first();
20284			var $imageWrap = $image.parent();
20285			this.scale = style.scale;
20286			$image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20287			$dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)');
20288			var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)';
20289			$imageWrap.css('transform', transform);
20290			this.left = style.x;
20291			this.top = style.y;
20292		};
20293		/**
20294		 * @param index - Index of the current slide
20295		 * @param event - event will be available only if the function is called on clicking/taping the imags
20296		 */
20297		Zoom.prototype.setActualSize = function (index, event) {
20298			var _this = this;
20299			// Allow zoom only on image
20300			if (!this.isImageSlide() ||
20301				this.core.outer.hasClass('lg-first-slide-loading')) {
20302				return;
20303			}
20304			var scale = this.getCurrentImageActualSizeScale();
20305			if (this.core.outer.hasClass('lg-zoomed')) {
20306				this.scale = 1;
20307			}
20308			else {
20309				this.scale = this.getScale(scale);
20310			}
20311			this.setPageCords(event);
20312			this.beginZoom(this.scale);
20313			this.zoomImage(this.scale);
20314			setTimeout(function () {
20315				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20316			}, 10);
20317		};
20318		Zoom.prototype.getNaturalWidth = function (index) {
20319			var $image = this.core.getSlideItem(index).find('.lg-image').first();
20320			var naturalWidth = this.core.galleryItems[index].width;
20321			return naturalWidth
20322				? parseFloat(naturalWidth)
20323				: $image.get().naturalWidth;
20324		};
20325		Zoom.prototype.getActualSizeScale = function (naturalWidth, width) {
20326			var _scale;
20327			var scale;
20328			if (naturalWidth > width) {
20329				_scale = naturalWidth / width;
20330				scale = _scale || 2;
20331			}
20332			else {
20333				scale = 1;
20334			}
20335			return scale;
20336		};
20337		Zoom.prototype.getCurrentImageActualSizeScale = function () {
20338			var $image = this.core
20339				.getSlideItem(this.core.index)
20340				.find('.lg-image')
20341				.first();
20342			var width = $image.get().offsetWidth;
20343			var naturalWidth = this.getNaturalWidth(this.core.index) || width;
20344			return this.getActualSizeScale(naturalWidth, width);
20345		};
20346		Zoom.prototype.getPageCords = function (event) {
20347			var cords = {};
20348			if (event) {
20349				cords.x = event.pageX || event.targetTouches[0].pageX;
20350				cords.y = event.pageY || event.targetTouches[0].pageY;
20351			}
20352			else {
20353				var containerRect = this.core.outer.get().getBoundingClientRect();
20354				cords.x = containerRect.width / 2 + containerRect.left;
20355				cords.y =
20356					containerRect.height / 2 + this.scrollTop + containerRect.top;
20357			}
20358			return cords;
20359		};
20360		Zoom.prototype.setPageCords = function (event) {
20361			var pageCords = this.getPageCords(event);
20362			this.pageX = pageCords.x;
20363			this.pageY = pageCords.y;
20364		};
20365		// If true, zoomed - in else zoomed out
20366		Zoom.prototype.beginZoom = function (scale) {
20367			this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20368			if (scale > 1) {
20369				this.core.outer.addClass('lg-zoomed');
20370				var $actualSize = this.core.getElementById('lg-actual-size');
20371				$actualSize
20372					.removeClass(this.settings.actualSizeIcons.zoomIn)
20373					.addClass(this.settings.actualSizeIcons.zoomOut);
20374			}
20375			else {
20376				this.resetZoom();
20377			}
20378			return scale > 1;
20379		};
20380		Zoom.prototype.getScale = function (scale) {
20381			var actualSizeScale = this.getCurrentImageActualSizeScale();
20382			if (scale < 1) {
20383				scale = 1;
20384			}
20385			else if (scale > actualSizeScale) {
20386				scale = actualSizeScale;
20387			}
20388			return scale;
20389		};
20390		Zoom.prototype.init = function () {
20391			var _this = this;
20392			if (!this.settings.zoom) {
20393				return;
20394			}
20395			this.buildTemplates();
20396			this.enableZoomOnSlideItemLoad();
20397			var tapped = null;
20398			this.core.outer.on('dblclick.lg', function (event) {
20399				if (!_this.$LG(event.target).hasClass('lg-image')) {
20400					return;
20401				}
20402				_this.setActualSize(_this.core.index, event);
20403			});
20404			this.core.outer.on('touchstart.lg', function (event) {
20405				var $target = _this.$LG(event.target);
20406				if (event.targetTouches.length === 1 &&
20407					$target.hasClass('lg-image')) {
20408					if (!tapped) {
20409						tapped = setTimeout(function () {
20410							tapped = null;
20411						}, 300);
20412					}
20413					else {
20414						clearTimeout(tapped);
20415						tapped = null;
20416						event.preventDefault();
20417						_this.setActualSize(_this.core.index, event);
20418					}
20419				}
20420			});
20421			// Update zoom on resize and orientationchange
20422			this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () {
20423				if (!_this.core.lgOpened || !_this.isImageSlide())
20424					return;
20425				_this.setPageCords();
20426				_this.setZoomEssentials();
20427				_this.zoomImage(_this.scale);
20428			});
20429			// Update zoom on resize and orientationchange
20430			this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () {
20431				if (!_this.core.lgOpened)
20432					return;
20433				_this.scrollTop = _this.$LG(window).scrollTop();
20434			});
20435			this.core.getElementById('lg-zoom-out').on('click.lg', function () {
20436				if (_this.core.outer.find('.lg-current .lg-image').get()) {
20437					_this.scale -= _this.settings.scale;
20438					_this.scale = _this.getScale(_this.scale);
20439					_this.beginZoom(_this.scale);
20440					_this.zoomImage(_this.scale);
20441				}
20442			});
20443			this.core.getElementById('lg-zoom-in').on('click.lg', function () {
20444				_this.zoomIn();
20445			});
20446			this.core.getElementById('lg-actual-size').on('click.lg', function () {
20447				_this.setActualSize(_this.core.index);
20448			});
20449			this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () {
20450				_this.core.outer.find('.lg-item').removeClass('lg-zoomable');
20451			});
20452			this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () {
20453				_this.scrollTop = _this.$LG(window).scrollTop();
20454				// Set the initial value center
20455				_this.pageX = _this.core.outer.width() / 2;
20456				_this.pageY = _this.core.outer.height() / 2 + _this.scrollTop;
20457				_this.scale = 1;
20458			});
20459			// Reset zoom on slide change
20460			this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) {
20461				var prevIndex = event.detail.prevIndex;
20462				_this.scale = 1;
20463				_this.positionChanged = false;
20464				_this.resetZoom(prevIndex);
20465				if (_this.isImageSlide()) {
20466					_this.setZoomEssentials();
20467				}
20468			});
20469			// Drag option after zoom
20470			this.zoomDrag();
20471			this.pinchZoom();
20472			this.zoomSwipe();
20473			// Store the zoomable timeout value just to clear it while closing
20474			this.zoomableTimeout = false;
20475			this.positionChanged = false;
20476		};
20477		Zoom.prototype.zoomIn = function (scale) {
20478			// Allow zoom only on image
20479			if (!this.isImageSlide()) {
20480				return;
20481			}
20482			if (scale) {
20483				this.scale = scale;
20484			}
20485			else {
20486				this.scale += this.settings.scale;
20487			}
20488			this.scale = this.getScale(this.scale);
20489			this.beginZoom(this.scale);
20490			this.zoomImage(this.scale);
20491		};
20492		// Reset zoom effect
20493		Zoom.prototype.resetZoom = function (index) {
20494			this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition');
20495			var $actualSize = this.core.getElementById('lg-actual-size');
20496			var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index);
20497			$actualSize
20498				.removeClass(this.settings.actualSizeIcons.zoomOut)
20499				.addClass(this.settings.actualSizeIcons.zoomIn);
20500			$item.find('.lg-img-wrap').first().removeAttr('style');
20501			$item.find('.lg-image').first().removeAttr('style');
20502			this.scale = 1;
20503			this.left = 0;
20504			this.top = 0;
20505			// Reset pagx pagy values to center
20506			this.setPageCords();
20507		};
20508		Zoom.prototype.getTouchDistance = function (e) {
20509			return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) *
20510				(e.targetTouches[0].pageX - e.targetTouches[1].pageX) +
20511				(e.targetTouches[0].pageY - e.targetTouches[1].pageY) *
20512					(e.targetTouches[0].pageY - e.targetTouches[1].pageY));
20513		};
20514		Zoom.prototype.pinchZoom = function () {
20515			var _this = this;
20516			var startDist = 0;
20517			var pinchStarted = false;
20518			var initScale = 1;
20519			var $item = this.core.getSlideItem(this.core.index);
20520			this.core.$inner.on('touchstart.lg', function (e) {
20521				$item = _this.core.getSlideItem(_this.core.index);
20522				if (!_this.isImageSlide()) {
20523					return;
20524				}
20525				if (e.targetTouches.length === 2 &&
20526					!_this.core.outer.hasClass('lg-first-slide-loading') &&
20527					(_this.$LG(e.target).hasClass('lg-item') ||
20528						$item.get().contains(e.target))) {
20529					initScale = _this.scale || 1;
20530					_this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging');
20531					_this.core.touchAction = 'pinch';
20532					startDist = _this.getTouchDistance(e);
20533				}
20534			});
20535			this.core.$inner.on('touchmove.lg', function (e) {
20536				if (e.targetTouches.length === 2 &&
20537					_this.core.touchAction === 'pinch' &&
20538					(_this.$LG(e.target).hasClass('lg-item') ||
20539						$item.get().contains(e.target))) {
20540					e.preventDefault();
20541					var endDist = _this.getTouchDistance(e);
20542					var distance = startDist - endDist;
20543					if (!pinchStarted && Math.abs(distance) > 5) {
20544						pinchStarted = true;
20545					}
20546					if (pinchStarted) {
20547						_this.scale = Math.max(1, initScale + -distance * 0.008);
20548						_this.zoomImage(_this.scale);
20549					}
20550				}
20551			});
20552			this.core.$inner.on('touchend.lg', function (e) {
20553				if (_this.core.touchAction === 'pinch' &&
20554					(_this.$LG(e.target).hasClass('lg-item') ||
20555						$item.get().contains(e.target))) {
20556					pinchStarted = false;
20557					startDist = 0;
20558					if (_this.scale <= 1) {
20559						_this.resetZoom();
20560					}
20561					else {
20562						_this.scale = _this.getScale(_this.scale);
20563						_this.zoomImage(_this.scale);
20564						_this.core.outer.addClass('lg-zoomed');
20565					}
20566					_this.core.touchAction = undefined;
20567				}
20568			});
20569		};
20570		Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) {
20571			var distanceXnew = endCoords.x - startCoords.x;
20572			var distanceYnew = endCoords.y - startCoords.y;
20573			var speedX = Math.abs(distanceXnew) / touchDuration + 1;
20574			var speedY = Math.abs(distanceYnew) / touchDuration + 1;
20575			if (speedX > 2) {
20576				speedX += 1;
20577			}
20578			if (speedY > 2) {
20579				speedY += 1;
20580			}
20581			distanceXnew = distanceXnew * speedX;
20582			distanceYnew = distanceYnew * speedY;
20583			var _LGel = this.core
20584				.getSlideItem(this.core.index)
20585				.find('.lg-img-wrap')
20586				.first();
20587			var distance = {};
20588			distance.x = this.left + distanceXnew * this.modifierX;
20589			distance.y = this.top + distanceYnew * this.modifierY;
20590			var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue);
20591			if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) {
20592				if (allowY) {
20593					if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20594						distance.y = possibleSwipeCords.minY;
20595					}
20596					else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20597						distance.y = possibleSwipeCords.maxY;
20598					}
20599				}
20600				if (allowX) {
20601					if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20602						distance.x = possibleSwipeCords.minX;
20603					}
20604					else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20605						distance.x = possibleSwipeCords.maxX;
20606					}
20607				}
20608				if (allowY) {
20609					this.top = distance.y;
20610				}
20611				else {
20612					distance.y = this.top;
20613				}
20614				if (allowX) {
20615					this.left = distance.x;
20616				}
20617				else {
20618					distance.x = this.left;
20619				}
20620				this.setZoomSwipeStyles(_LGel, distance);
20621				this.positionChanged = true;
20622			}
20623		};
20624		Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) {
20625			var distance = {};
20626			if (allowY) {
20627				distance.y =
20628					this.top + (endCoords.y - startCoords.y) * this.modifierY;
20629				if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) {
20630					var diffMinY = possibleSwipeCords.minY - distance.y;
20631					distance.y = possibleSwipeCords.minY - diffMinY / 6;
20632				}
20633				else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) {
20634					var diffMaxY = distance.y - possibleSwipeCords.maxY;
20635					distance.y = possibleSwipeCords.maxY + diffMaxY / 6;
20636				}
20637			}
20638			else {
20639				distance.y = this.top;
20640			}
20641			if (allowX) {
20642				distance.x =
20643					this.left + (endCoords.x - startCoords.x) * this.modifierX;
20644				if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) {
20645					var diffMinX = possibleSwipeCords.minX - distance.x;
20646					distance.x = possibleSwipeCords.minX - diffMinX / 6;
20647				}
20648				else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) {
20649					var difMaxX = distance.x - possibleSwipeCords.maxX;
20650					distance.x = possibleSwipeCords.maxX + difMaxX / 6;
20651				}
20652			}
20653			else {
20654				distance.x = this.left;
20655			}
20656			return distance;
20657		};
20658		Zoom.prototype.isBeyondPossibleLeft = function (x, minX) {
20659			return x >= minX;
20660		};
20661		Zoom.prototype.isBeyondPossibleRight = function (x, maxX) {
20662			return x <= maxX;
20663		};
20664		Zoom.prototype.isBeyondPossibleTop = function (y, minY) {
20665			return y >= minY;
20666		};
20667		Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) {
20668			return y <= maxY;
20669		};
20670		Zoom.prototype.isImageSlide = function () {
20671			var currentItem = this.core.galleryItems[this.core.index];
20672			return this.core.getSlideType(currentItem) === 'image';
20673		};
20674		Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) {
20675			var dataScale = scale || this.scale || 1;
20676			var elDataScale = Math.abs(dataScale);
20677			var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom;
20678			var topBottomSpacing = Math.abs(top - bottom) / 2;
20679			var minY = (this.imageYSize - this.containerRect.height) / 2 +
20680				topBottomSpacing * this.modifierX;
20681			var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY;
20682			var minX = (this.imageXSize - this.containerRect.width) / 2;
20683			var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX;
20684			var possibleSwipeCords = {
20685				minY: minY,
20686				maxY: maxY,
20687				minX: minX,
20688				maxX: maxX,
20689			};
20690			if (Math.abs(rotateValue) === 90) {
20691				possibleSwipeCords = {
20692					minY: minX,
20693					maxY: maxX,
20694					minX: minY,
20695					maxX: maxY,
20696				};
20697			}
20698			return possibleSwipeCords;
20699		};
20700		Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) {
20701			LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)');
20702		};
20703		Zoom.prototype.zoomSwipe = function () {
20704			var _this = this;
20705			var startCoords = {};
20706			var endCoords = {};
20707			var isMoved = false;
20708			// Allow x direction drag
20709			var allowX = false;
20710			// Allow Y direction drag
20711			var allowY = false;
20712			var startTime = new Date();
20713			var endTime = new Date();
20714			var possibleSwipeCords;
20715			var _LGel;
20716			var $item = this.core.getSlideItem(this.core.index);
20717			this.core.$inner.on('touchstart.lg', function (e) {
20718				// Allow zoom only on image
20719				if (!_this.isImageSlide()) {
20720					return;
20721				}
20722				$item = _this.core.getSlideItem(_this.core.index);
20723				if ((_this.$LG(e.target).hasClass('lg-item') ||
20724					$item.get().contains(e.target)) &&
20725					e.targetTouches.length === 1 &&
20726					_this.core.outer.hasClass('lg-zoomed')) {
20727					e.preventDefault();
20728					startTime = new Date();
20729					_this.core.touchAction = 'zoomSwipe';
20730					_LGel = _this.core
20731						.getSlideItem(_this.core.index)
20732						.find('.lg-img-wrap')
20733						.first();
20734					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20735					allowY = dragAllowedAxises.allowY;
20736					allowX = dragAllowedAxises.allowX;
20737					if (allowX || allowY) {
20738						startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20739					}
20740					possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20741					// reset opacity and transition duration
20742					_this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition');
20743				}
20744			});
20745			this.core.$inner.on('touchmove.lg', function (e) {
20746				if (e.targetTouches.length === 1 &&
20747					_this.core.touchAction === 'zoomSwipe' &&
20748					(_this.$LG(e.target).hasClass('lg-item') ||
20749						$item.get().contains(e.target))) {
20750					e.preventDefault();
20751					_this.core.touchAction = 'zoomSwipe';
20752					endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue));
20753					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20754					if (Math.abs(endCoords.x - startCoords.x) > 15 ||
20755						Math.abs(endCoords.y - startCoords.y) > 15) {
20756						isMoved = true;
20757						_this.setZoomSwipeStyles(_LGel, distance);
20758					}
20759				}
20760			});
20761			this.core.$inner.on('touchend.lg', function (e) {
20762				if (_this.core.touchAction === 'zoomSwipe' &&
20763					(_this.$LG(e.target).hasClass('lg-item') ||
20764						$item.get().contains(e.target))) {
20765					_this.core.touchAction = undefined;
20766					_this.core.outer.removeClass('lg-zoom-dragging');
20767					if (!isMoved) {
20768						return;
20769					}
20770					isMoved = false;
20771					endTime = new Date();
20772					var touchDuration = endTime.valueOf() - startTime.valueOf();
20773					_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20774				}
20775			});
20776		};
20777		Zoom.prototype.zoomDrag = function () {
20778			var _this = this;
20779			var startCoords = {};
20780			var endCoords = {};
20781			var isDragging = false;
20782			var isMoved = false;
20783			// Allow x direction drag
20784			var allowX = false;
20785			// Allow Y direction drag
20786			var allowY = false;
20787			var startTime;
20788			var endTime;
20789			var possibleSwipeCords;
20790			var _LGel;
20791			this.core.outer.on('mousedown.lg.zoom', function (e) {
20792				// Allow zoom only on image
20793				if (!_this.isImageSlide()) {
20794					return;
20795				}
20796				var $item = _this.core.getSlideItem(_this.core.index);
20797				if (_this.$LG(e.target).hasClass('lg-item') ||
20798					$item.get().contains(e.target)) {
20799					startTime = new Date();
20800					_LGel = _this.core
20801						.getSlideItem(_this.core.index)
20802						.find('.lg-img-wrap')
20803						.first();
20804					var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue));
20805					allowY = dragAllowedAxises.allowY;
20806					allowX = dragAllowedAxises.allowX;
20807					if (_this.core.outer.hasClass('lg-zoomed')) {
20808						if (_this.$LG(e.target).hasClass('lg-object') &&
20809							(allowX || allowY)) {
20810							e.preventDefault();
20811							startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20812							possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue);
20813							isDragging = true;
20814							// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
20815							_this.core.outer.get().scrollLeft += 1;
20816							_this.core.outer.get().scrollLeft -= 1;
20817							_this.core.outer
20818								.removeClass('lg-grab')
20819								.addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging');
20820							// reset opacity and transition duration
20821						}
20822					}
20823				}
20824			});
20825			this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) {
20826				if (isDragging) {
20827					isMoved = true;
20828					endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20829					var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords);
20830					_this.setZoomSwipeStyles(_LGel, distance);
20831				}
20832			});
20833			this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) {
20834				if (isDragging) {
20835					endTime = new Date();
20836					isDragging = false;
20837					_this.core.outer.removeClass('lg-zoom-dragging');
20838					// Fix for chrome mouse move on click
20839					if (isMoved &&
20840						(startCoords.x !== endCoords.x ||
20841							startCoords.y !== endCoords.y)) {
20842						endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue));
20843						var touchDuration = endTime.valueOf() - startTime.valueOf();
20844						_this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue);
20845					}
20846					isMoved = false;
20847				}
20848				_this.core.outer.removeClass('lg-grabbing').addClass('lg-grab');
20849			});
20850		};
20851		Zoom.prototype.closeGallery = function () {
20852			this.resetZoom();
20853		};
20854		Zoom.prototype.destroy = function () {
20855			// Unbind all events added by lightGallery zoom plugin
20856			this.$LG(window).off(".lg.zoom.global" + this.core.lgId);
20857			this.core.LGel.off('.lg.zoom');
20858			this.core.LGel.off('.zoom');
20859			clearTimeout(this.zoomableTimeout);
20860			this.zoomableTimeout = false;
20861		};
20862		return Zoom;
20863	}());
20864
20865	return Zoom;
20866
20867})));
20868/*!
20869 * lightgallery | 2.5.0 | June 13th 2022
20870 * http://www.lightgalleryjs.com/
20871 * Copyright (c) 2020 Sachin Neravath;
20872 * @license GPLv3
20873 */
20874
20875(function (global, factory) {
20876	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
20877	typeof define === 'function' && define.amd ? define(factory) :
20878	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory());
20879}(this, (function () { 'use strict';
20880
20881	/*! *****************************************************************************
20882	Copyright (c) Microsoft Corporation.
20883
20884	Permission to use, copy, modify, and/or distribute this software for any
20885	purpose with or without fee is hereby granted.
20886
20887	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
20888	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20889	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20890	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20891	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
20892	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20893	PERFORMANCE OF THIS SOFTWARE.
20894	***************************************************************************** */
20895
20896	var __assign = function() {
20897		__assign = Object.assign || function __assign(t) {
20898			for (var s, i = 1, n = arguments.length; i < n; i++) {
20899				s = arguments[i];
20900				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
20901			}
20902			return t;
20903		};
20904		return __assign.apply(this, arguments);
20905	};
20906
20907	var fullscreenSettings = {
20908		fullScreen: true,
20909		fullscreenPluginStrings: {
20910			toggleFullscreen: 'Toggle Fullscreen',
20911		},
20912	};
20913
20914	var FullScreen = /** @class */ (function () {
20915		function FullScreen(instance, $LG) {
20916			// get lightGallery core plugin instance
20917			this.core = instance;
20918			this.$LG = $LG;
20919			// extend module default settings with lightGallery core settings
20920			this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings);
20921			return this;
20922		}
20923		FullScreen.prototype.init = function () {
20924			var fullScreen = '';
20925			if (this.settings.fullScreen) {
20926				// check for fullscreen browser support
20927				if (!document.fullscreenEnabled &&
20928					!document.webkitFullscreenEnabled &&
20929					!document.mozFullScreenEnabled &&
20930					!document.msFullscreenEnabled) {
20931					return;
20932				}
20933				else {
20934					fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>";
20935					this.core.$toolbar.append(fullScreen);
20936					this.fullScreen();
20937				}
20938			}
20939		};
20940		FullScreen.prototype.isFullScreen = function () {
20941			return (document.fullscreenElement ||
20942				document.mozFullScreenElement ||
20943				document.webkitFullscreenElement ||
20944				document.msFullscreenElement);
20945		};
20946		FullScreen.prototype.requestFullscreen = function () {
20947			var el = document.documentElement;
20948			if (el.requestFullscreen) {
20949				el.requestFullscreen();
20950			}
20951			else if (el.msRequestFullscreen) {
20952				el.msRequestFullscreen();
20953			}
20954			else if (el.mozRequestFullScreen) {
20955				el.mozRequestFullScreen();
20956			}
20957			else if (el.webkitRequestFullscreen) {
20958				el.webkitRequestFullscreen();
20959			}
20960		};
20961		FullScreen.prototype.exitFullscreen = function () {
20962			if (document.exitFullscreen) {
20963				document.exitFullscreen();
20964			}
20965			else if (document.msExitFullscreen) {
20966				document.msExitFullscreen();
20967			}
20968			else if (document.mozCancelFullScreen) {
20969				document.mozCancelFullScreen();
20970			}
20971			else if (document.webkitExitFullscreen) {
20972				document.webkitExitFullscreen();
20973			}
20974		};
20975		// https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
20976		FullScreen.prototype.fullScreen = function () {
20977			var _this = this;
20978			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 () {
20979				if (!_this.core.lgOpened)
20980					return;
20981				_this.core.outer.toggleClass('lg-fullscreen-on');
20982			});
20983			this.core.outer
20984				.find('.lg-fullscreen')
20985				.first()
20986				.on('click.lg', function () {
20987				if (_this.isFullScreen()) {
20988					_this.exitFullscreen();
20989				}
20990				else {
20991					_this.requestFullscreen();
20992				}
20993			});
20994		};
20995		FullScreen.prototype.closeGallery = function () {
20996			// exit from fullscreen if activated
20997			if (this.isFullScreen()) {
20998				this.exitFullscreen();
20999			}
21000		};
21001		FullScreen.prototype.destroy = function () {
21002			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);
21003		};
21004		return FullScreen;
21005	}());
21006
21007	return FullScreen;
21008
21009})));
21010
21011/*!
21012 * lightgallery | 2.5.0 | June 13th 2022
21013 * http://www.lightgalleryjs.com/
21014 * Copyright (c) 2020 Sachin Neravath;
21015 * @license GPLv3
21016 */
21017
21018(function (global, factory) {
21019	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21020	typeof define === 'function' && define.amd ? define(factory) :
21021	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory());
21022}(this, (function () { 'use strict';
21023
21024	/*! *****************************************************************************
21025	Copyright (c) Microsoft Corporation.
21026
21027	Permission to use, copy, modify, and/or distribute this software for any
21028	purpose with or without fee is hereby granted.
21029
21030	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21031	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21032	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21033	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21034	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21035	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21036	PERFORMANCE OF THIS SOFTWARE.
21037	***************************************************************************** */
21038
21039	var __assign = function() {
21040		__assign = Object.assign || function __assign(t) {
21041			for (var s, i = 1, n = arguments.length; i < n; i++) {
21042				s = arguments[i];
21043				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21044			}
21045			return t;
21046		};
21047		return __assign.apply(this, arguments);
21048	};
21049
21050	/**
21051	 * List of lightGallery events
21052	 * All events should be documented here
21053	 * Below interfaces are used to build the website documentations
21054	 * */
21055	var lGEvents = {
21056		afterAppendSlide: 'lgAfterAppendSlide',
21057		init: 'lgInit',
21058		hasVideo: 'lgHasVideo',
21059		containerResize: 'lgContainerResize',
21060		updateSlides: 'lgUpdateSlides',
21061		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21062		beforeOpen: 'lgBeforeOpen',
21063		afterOpen: 'lgAfterOpen',
21064		slideItemLoad: 'lgSlideItemLoad',
21065		beforeSlide: 'lgBeforeSlide',
21066		afterSlide: 'lgAfterSlide',
21067		posterClick: 'lgPosterClick',
21068		dragStart: 'lgDragStart',
21069		dragMove: 'lgDragMove',
21070		dragEnd: 'lgDragEnd',
21071		beforeNextSlide: 'lgBeforeNextSlide',
21072		beforePrevSlide: 'lgBeforePrevSlide',
21073		beforeClose: 'lgBeforeClose',
21074		afterClose: 'lgAfterClose',
21075		rotateLeft: 'lgRotateLeft',
21076		rotateRight: 'lgRotateRight',
21077		flipHorizontal: 'lgFlipHorizontal',
21078		flipVertical: 'lgFlipVertical',
21079		autoplay: 'lgAutoplay',
21080		autoplayStart: 'lgAutoplayStart',
21081		autoplayStop: 'lgAutoplayStop',
21082	};
21083
21084	var hashSettings = {
21085		hash: true,
21086		galleryId: '1',
21087		customSlideName: false,
21088	};
21089
21090	var Hash = /** @class */ (function () {
21091		function Hash(instance, $LG) {
21092			// get lightGallery core plugin instance
21093			this.core = instance;
21094			this.$LG = $LG;
21095			// extend module default settings with lightGallery core settings
21096			this.settings = __assign(__assign({}, hashSettings), this.core.settings);
21097			return this;
21098		}
21099		Hash.prototype.init = function () {
21100			var _this = this;
21101			if (!this.settings.hash) {
21102				return;
21103			}
21104			this.oldHash = window.location.hash;
21105			setTimeout(function () {
21106				_this.buildFromHash();
21107			}, 100);
21108			// Change hash value on after each slide transition
21109			this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this));
21110			this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this));
21111			// Listen hash change and change the slide according to slide value
21112			this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this));
21113		};
21114		Hash.prototype.onAfterSlide = function (event) {
21115			var slideName = this.core.galleryItems[event.detail.index].slideName;
21116			slideName = this.settings.customSlideName
21117				? slideName || event.detail.index
21118				: event.detail.index;
21119			if (history.replaceState) {
21120				history.replaceState(null, '', window.location.pathname +
21121					window.location.search +
21122					'#lg=' +
21123					this.settings.galleryId +
21124					'&slide=' +
21125					slideName);
21126			}
21127			else {
21128				window.location.hash =
21129					'lg=' + this.settings.galleryId + '&slide=' + slideName;
21130			}
21131		};
21132		/**
21133		 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin
21134		 * @param {String} hash
21135		 * @returns {Number} Index of the slide.
21136		 */
21137		Hash.prototype.getIndexFromUrl = function (hash) {
21138			if (hash === void 0) { hash = window.location.hash; }
21139			var slideName = hash.split('&slide=')[1];
21140			var _idx = 0;
21141			if (this.settings.customSlideName) {
21142				for (var index = 0; index < this.core.galleryItems.length; index++) {
21143					var dynamicEl = this.core.galleryItems[index];
21144					if (dynamicEl.slideName === slideName) {
21145						_idx = index;
21146						break;
21147					}
21148				}
21149			}
21150			else {
21151				_idx = parseInt(slideName, 10);
21152			}
21153			return isNaN(_idx) ? 0 : _idx;
21154		};
21155		// Build Gallery if gallery id exist in the URL
21156		Hash.prototype.buildFromHash = function () {
21157			// if dynamic option is enabled execute immediately
21158			var _hash = window.location.hash;
21159			//Uncode edit ##START##
21160			// if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) {
21161			if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) {
21162			//Uncode edit ##END##
21163				// This class is used to remove the initial animation if galleryId present in the URL
21164				this.$LG(document.body).addClass('lg-from-hash');
21165				var index = this.getIndexFromUrl(_hash);
21166				this.core.openGallery(index);
21167				return true;
21168			}
21169		};
21170		Hash.prototype.onCloseAfter = function () {
21171			// Reset to old hash value
21172			if (this.oldHash &&
21173				this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) {
21174				if (history.replaceState) {
21175					history.replaceState(null, '', this.oldHash);
21176				}
21177				else {
21178					window.location.hash = this.oldHash;
21179				}
21180			}
21181			else {
21182				if (history.replaceState) {
21183					history.replaceState(null, document.title, window.location.pathname + window.location.search);
21184				}
21185				else {
21186					window.location.hash = '';
21187				}
21188			}
21189		};
21190		Hash.prototype.onHashchange = function () {
21191			if (!this.core.lgOpened)
21192				return;
21193			var _hash = window.location.hash;
21194			var index = this.getIndexFromUrl(_hash);
21195			// it galleryId doesn't exist in the url close the gallery
21196			if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) {
21197				this.core.slide(index, false, false);
21198			}
21199			else if (this.core.lGalleryOn) {
21200				this.core.closeGallery();
21201			}
21202		};
21203		Hash.prototype.closeGallery = function () {
21204			if (this.settings.hash) {
21205				this.$LG(document.body).removeClass('lg-from-hash');
21206			}
21207		};
21208		Hash.prototype.destroy = function () {
21209			this.core.LGel.off('.lg.hash');
21210			this.core.LGel.off('.hash');
21211			this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId);
21212		};
21213		return Hash;
21214	}());
21215
21216	return Hash;
21217
21218})));
21219/*!
21220 * lightgallery | 2.5.0 | June 13th 2022
21221 * http://www.lightgalleryjs.com/
21222 * Copyright (c) 2020 Sachin Neravath;
21223 * @license GPLv3
21224 */
21225
21226(function (global, factory) {
21227	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21228	typeof define === 'function' && define.amd ? define(factory) :
21229	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory());
21230}(this, (function () { 'use strict';
21231
21232	/*! *****************************************************************************
21233	Copyright (c) Microsoft Corporation.
21234
21235	Permission to use, copy, modify, and/or distribute this software for any
21236	purpose with or without fee is hereby granted.
21237
21238	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21239	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21240	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21241	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21242	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21243	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21244	PERFORMANCE OF THIS SOFTWARE.
21245	***************************************************************************** */
21246
21247	var __assign = function() {
21248		__assign = Object.assign || function __assign(t) {
21249			for (var s, i = 1, n = arguments.length; i < n; i++) {
21250				s = arguments[i];
21251				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21252			}
21253			return t;
21254		};
21255		return __assign.apply(this, arguments);
21256	};
21257
21258	function __spreadArrays() {
21259		for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
21260		for (var r = Array(s), k = 0, i = 0; i < il; i++)
21261			for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
21262				r[k] = a[j];
21263		return r;
21264	}
21265
21266	var shareSettings = {
21267		share: true,
21268		facebook: true,
21269		facebookDropdownText: 'Facebook',
21270		twitter: true,
21271		twitterDropdownText: 'Twitter',
21272		pinterest: true,
21273		pinterestDropdownText: 'Pinterest',
21274		additionalShareOptions: [],
21275		sharePluginStrings: { share: 'Share' },
21276	};
21277
21278	function getFacebookShareLink(galleryItem) {
21279		var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u=';
21280		return (facebookBaseUrl +
21281			encodeURIComponent(galleryItem.facebookShareUrl || window.location.href));
21282	}
21283
21284	function getTwitterShareLink(galleryItem) {
21285		var twitterBaseUrl = '//twitter.com/intent/tweet?text=';
21286		var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href);
21287		var text = galleryItem.tweetText;
21288		return twitterBaseUrl + text + '&url=' + url;
21289	}
21290
21291	function getPinterestShareLink(galleryItem) {
21292		var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url=';
21293		var description = galleryItem.pinterestText;
21294		var media = encodeURIComponent(galleryItem.src);
21295		var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href);
21296		return (pinterestBaseUrl +
21297			url +
21298			'&media=' +
21299			media +
21300			'&description=' +
21301			description);
21302	}
21303
21304	/**
21305	 * List of lightGallery events
21306	 * All events should be documented here
21307	 * Below interfaces are used to build the website documentations
21308	 * */
21309	var lGEvents = {
21310		afterAppendSlide: 'lgAfterAppendSlide',
21311		init: 'lgInit',
21312		hasVideo: 'lgHasVideo',
21313		containerResize: 'lgContainerResize',
21314		updateSlides: 'lgUpdateSlides',
21315		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21316		beforeOpen: 'lgBeforeOpen',
21317		afterOpen: 'lgAfterOpen',
21318		slideItemLoad: 'lgSlideItemLoad',
21319		beforeSlide: 'lgBeforeSlide',
21320		afterSlide: 'lgAfterSlide',
21321		posterClick: 'lgPosterClick',
21322		dragStart: 'lgDragStart',
21323		dragMove: 'lgDragMove',
21324		dragEnd: 'lgDragEnd',
21325		beforeNextSlide: 'lgBeforeNextSlide',
21326		beforePrevSlide: 'lgBeforePrevSlide',
21327		beforeClose: 'lgBeforeClose',
21328		afterClose: 'lgAfterClose',
21329		rotateLeft: 'lgRotateLeft',
21330		rotateRight: 'lgRotateRight',
21331		flipHorizontal: 'lgFlipHorizontal',
21332		flipVertical: 'lgFlipVertical',
21333		autoplay: 'lgAutoplay',
21334		autoplayStart: 'lgAutoplayStart',
21335		autoplayStop: 'lgAutoplayStop',
21336	};
21337
21338	var Share = /** @class */ (function () {
21339		function Share(instance) {
21340			this.shareOptions = [];
21341			// get lightGallery core plugin instance
21342			this.core = instance;
21343			// extend module default settings with lightGallery core settings
21344			this.settings = __assign(__assign({}, shareSettings), this.core.settings);
21345			return this;
21346		}
21347		Share.prototype.init = function () {
21348			if (!this.settings.share) {
21349				return;
21350			}
21351			this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions);
21352			this.setLgShareMarkup();
21353			this.core.outer
21354				.find('.lg-share .lg-dropdown')
21355				.append(this.getShareListHtml());
21356			this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this));
21357		};
21358		Share.prototype.getShareListHtml = function () {
21359			var shareHtml = '';
21360			this.shareOptions.forEach(function (shareOption) {
21361				shareHtml += shareOption.dropdownHTML;
21362			});
21363			return shareHtml;
21364		};
21365		Share.prototype.setLgShareMarkup = function () {
21366			var _this = this;
21367			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>");
21368			this.core.outer.append('<div class="lg-dropdown-overlay"></div>');
21369			var $shareButton = this.core.outer.find('.lg-share');
21370			$shareButton.first().on('click.lg', function () {
21371				_this.core.outer.toggleClass('lg-dropdown-active');
21372				if (_this.core.outer.hasClass('lg-dropdown-active')) {
21373					_this.core.outer.attr('aria-expanded', true);
21374				}
21375				else {
21376					_this.core.outer.attr('aria-expanded', false);
21377				}
21378			});
21379			this.core.outer
21380				.find('.lg-dropdown-overlay')
21381				.first()
21382				.on('click.lg', function () {
21383				_this.core.outer.removeClass('lg-dropdown-active');
21384				_this.core.outer.attr('aria-expanded', false);
21385			});
21386		};
21387		Share.prototype.onAfterSlide = function (event) {
21388			var _this = this;
21389			var index = event.detail.index;
21390			var currentItem = this.core.galleryItems[index];
21391			setTimeout(function () {
21392				_this.shareOptions.forEach(function (shareOption) {
21393					var selector = shareOption.selector;
21394					_this.core.outer
21395						.find(selector)
21396						.attr('href', shareOption.generateLink(currentItem));
21397				});
21398			}, 100);
21399		};
21400		Share.prototype.getShareListItemHTML = function (type, text) {
21401			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>";
21402		};
21403		Share.prototype.getDefaultShareOptions = function () {
21404			return __spreadArrays((this.settings.facebook
21405				? [
21406					{
21407						type: 'facebook',
21408						generateLink: getFacebookShareLink,
21409						dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText),
21410						selector: '.lg-share-facebook',
21411					},
21412				]
21413				: []), (this.settings.twitter
21414				? [
21415					{
21416						type: 'twitter',
21417						generateLink: getTwitterShareLink,
21418						dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText),
21419						selector: '.lg-share-twitter',
21420					},
21421				]
21422				: []), (this.settings.pinterest
21423				? [
21424					{
21425						type: 'pinterest',
21426						generateLink: getPinterestShareLink,
21427						dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText),
21428						selector: '.lg-share-pinterest',
21429					},
21430				]
21431				: []));
21432		};
21433		Share.prototype.destroy = function () {
21434			this.core.outer.find('.lg-dropdown-overlay').remove();
21435			this.core.outer.find('.lg-share').remove();
21436			this.core.LGel.off('.lg.share');
21437			this.core.LGel.off('.share');
21438		};
21439		return Share;
21440	}());
21441
21442	return Share;
21443
21444})));
21445/*!
21446 * lightgallery | 2.5.0 | June 13th 2022
21447 * http://www.lightgalleryjs.com/
21448 * Copyright (c) 2020 Sachin Neravath;
21449 * @license GPLv3
21450 */
21451
21452(function (global, factory) {
21453	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21454	typeof define === 'function' && define.amd ? define(factory) :
21455	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory());
21456}(this, (function () { 'use strict';
21457
21458	/*! *****************************************************************************
21459	Copyright (c) Microsoft Corporation.
21460
21461	Permission to use, copy, modify, and/or distribute this software for any
21462	purpose with or without fee is hereby granted.
21463
21464	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21465	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21466	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21467	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21468	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21469	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21470	PERFORMANCE OF THIS SOFTWARE.
21471	***************************************************************************** */
21472
21473	var __assign = function() {
21474		__assign = Object.assign || function __assign(t) {
21475			for (var s, i = 1, n = arguments.length; i < n; i++) {
21476				s = arguments[i];
21477				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21478			}
21479			return t;
21480		};
21481		return __assign.apply(this, arguments);
21482	};
21483
21484	var thumbnailsSettings = {
21485		thumbnail: true,
21486		animateThumb: true,
21487		currentPagerPosition: 'middle',
21488		alignThumbnails: 'middle',
21489		thumbWidth: 100,
21490		thumbHeight: '80px',
21491		thumbMargin: 5,
21492		appendThumbnailsTo: '.lg-components',
21493		toggleThumb: false,
21494		enableThumbDrag: true,
21495		enableThumbSwipe: true,
21496		thumbnailSwipeThreshold: 10,
21497		loadYouTubeThumbnail: true,
21498		youTubeThumbSize: 1,
21499		thumbnailPluginStrings: {
21500			toggleThumbnails: 'Toggle thumbnails',
21501		},
21502	};
21503
21504	/**
21505	 * List of lightGallery events
21506	 * All events should be documented here
21507	 * Below interfaces are used to build the website documentations
21508	 * */
21509	var lGEvents = {
21510		afterAppendSlide: 'lgAfterAppendSlide',
21511		init: 'lgInit',
21512		hasVideo: 'lgHasVideo',
21513		containerResize: 'lgContainerResize',
21514		updateSlides: 'lgUpdateSlides',
21515		afterAppendSubHtml: 'lgAfterAppendSubHtml',
21516		beforeOpen: 'lgBeforeOpen',
21517		afterOpen: 'lgAfterOpen',
21518		slideItemLoad: 'lgSlideItemLoad',
21519		beforeSlide: 'lgBeforeSlide',
21520		afterSlide: 'lgAfterSlide',
21521		posterClick: 'lgPosterClick',
21522		dragStart: 'lgDragStart',
21523		dragMove: 'lgDragMove',
21524		dragEnd: 'lgDragEnd',
21525		beforeNextSlide: 'lgBeforeNextSlide',
21526		beforePrevSlide: 'lgBeforePrevSlide',
21527		beforeClose: 'lgBeforeClose',
21528		afterClose: 'lgAfterClose',
21529		rotateLeft: 'lgRotateLeft',
21530		rotateRight: 'lgRotateRight',
21531		flipHorizontal: 'lgFlipHorizontal',
21532		flipVertical: 'lgFlipVertical',
21533		autoplay: 'lgAutoplay',
21534		autoplayStart: 'lgAutoplayStart',
21535		autoplayStop: 'lgAutoplayStop',
21536	};
21537
21538	var Thumbnail = /** @class */ (function () {
21539		function Thumbnail(instance, $LG) {
21540			this.thumbOuterWidth = 0;
21541			this.thumbTotalWidth = 0;
21542			this.translateX = 0;
21543			this.thumbClickable = false;
21544			// get lightGallery core plugin instance
21545			this.core = instance;
21546			this.$LG = $LG;
21547			return this;
21548		}
21549		Thumbnail.prototype.init = function () {
21550			// extend module default settings with lightGallery core settings
21551			this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings);
21552			this.thumbOuterWidth = 0;
21553			this.thumbTotalWidth =
21554				this.core.galleryItems.length *
21555					(this.settings.thumbWidth + this.settings.thumbMargin);
21556			// Thumbnail animation value
21557			this.translateX = 0;
21558			this.setAnimateThumbStyles();
21559			if (!this.core.settings.allowMediaOverlap) {
21560				this.settings.toggleThumb = false;
21561			}
21562			if (this.settings.thumbnail) {
21563				this.build();
21564				if (this.settings.animateThumb) {
21565					if (this.settings.enableThumbDrag) {
21566						this.enableThumbDrag();
21567					}
21568					if (this.settings.enableThumbSwipe) {
21569						this.enableThumbSwipe();
21570					}
21571					this.thumbClickable = false;
21572				}
21573				else {
21574					this.thumbClickable = true;
21575				}
21576				this.toggleThumbBar();
21577				this.thumbKeyPress();
21578			}
21579		};
21580		Thumbnail.prototype.build = function () {
21581			var _this = this;
21582			this.setThumbMarkup();
21583			this.manageActiveClassOnSlideChange();
21584			this.$lgThumb.first().on('click.lg touchend.lg', function (e) {
21585				var $target = _this.$LG(e.target);
21586				if (!$target.hasAttribute('data-lg-item-id')) {
21587					return;
21588				}
21589				setTimeout(function () {
21590					// In IE9 and bellow touch does not support
21591					// Go to slide if browser does not support css transitions
21592					if (_this.thumbClickable && !_this.core.lgBusy) {
21593						var index = parseInt($target.attr('data-lg-item-id'));
21594						_this.core.slide(index, false, true, false);
21595					}
21596				}, 50);
21597			});
21598			//Uncode edit ##START##
21599			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21600			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21601			//Uncode edit ##END##
21602				var index = event.detail.index;
21603				_this.animateThumb(index);
21604			});
21605			//Uncode edit ##START##
21606			// this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () {
21607			this.core.LGel.on(lGEvents.beforeOpen, function () {
21608			//Uncode edit ##END##
21609				_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21610			});
21611			//Uncode edit ##START##
21612			// this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () {
21613			this.core.LGel.on(lGEvents.updateSlides, function () {
21614			//Uncode edit ##END##
21615				_this.rebuildThumbnails();
21616			});
21617			//Uncode edit ##START##
21618			// this.core.LGel.on(lGEvents.containerResize + ".thumb", function () {
21619			this.core.LGel.on(lGEvents.containerResize, function () {
21620			//Uncode edit ##END##
21621				if (!_this.core.lgOpened)
21622					return;
21623				setTimeout(function () {
21624					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21625					_this.animateThumb(_this.core.index);
21626					_this.thumbOuterWidth = _this.core.outer.get().offsetWidth;
21627				}, 50);
21628			});
21629		};
21630		Thumbnail.prototype.setThumbMarkup = function () {
21631			var thumbOuterClassNames = 'lg-thumb-outer ';
21632			if (this.settings.alignThumbnails) {
21633				thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails;
21634			}
21635			var html = "<div class=\"" + thumbOuterClassNames + "\">\n        <div class=\"lg-thumb lg-group\">\n        </div>\n        </div>";
21636			this.core.outer.addClass('lg-has-thumb');
21637			if (this.settings.appendThumbnailsTo === '.lg-components') {
21638				this.core.$lgComponents.append(html);
21639			}
21640			else {
21641				this.core.outer.append(html);
21642			}
21643			this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first();
21644			this.$lgThumb = this.core.outer.find('.lg-thumb').first();
21645			if (this.settings.animateThumb) {
21646				this.core.outer
21647					.find('.lg-thumb')
21648					.css('transition-duration', this.core.settings.speed + 'ms')
21649					.css('width', this.thumbTotalWidth + 'px')
21650					.css('position', 'relative');
21651			}
21652			this.setThumbItemHtml(this.core.galleryItems);
21653		};
21654		Thumbnail.prototype.enableThumbDrag = function () {
21655			var _this = this;
21656			var thumbDragUtils = {
21657				cords: {
21658					startX: 0,
21659					endX: 0,
21660				},
21661				isMoved: false,
21662				newTranslateX: 0,
21663				startTime: new Date(),
21664				endTime: new Date(),
21665				touchMoveTime: 0,
21666			};
21667			var isDragging = false;
21668			this.$thumbOuter.addClass('lg-grab');
21669			this.core.outer
21670				.find('.lg-thumb')
21671				.first()
21672				.on('mousedown.lg.thumb', function (e) {
21673				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21674					// execute only on .lg-object
21675					e.preventDefault();
21676					thumbDragUtils.cords.startX = e.pageX;
21677					thumbDragUtils.startTime = new Date();
21678					_this.thumbClickable = false;
21679					isDragging = true;
21680					// ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723
21681					_this.core.outer.get().scrollLeft += 1;
21682					_this.core.outer.get().scrollLeft -= 1;
21683					// *
21684					_this.$thumbOuter
21685						.removeClass('lg-grab')
21686						.addClass('lg-grabbing');
21687				}
21688			});
21689			this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) {
21690				if (!_this.core.lgOpened)
21691					return;
21692				if (isDragging) {
21693					thumbDragUtils.cords.endX = e.pageX;
21694					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21695				}
21696			});
21697			this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () {
21698				if (!_this.core.lgOpened)
21699					return;
21700				if (thumbDragUtils.isMoved) {
21701					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21702				}
21703				else {
21704					_this.thumbClickable = true;
21705				}
21706				if (isDragging) {
21707					isDragging = false;
21708					_this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab');
21709				}
21710			});
21711		};
21712		Thumbnail.prototype.enableThumbSwipe = function () {
21713			var _this = this;
21714			var thumbDragUtils = {
21715				cords: {
21716					startX: 0,
21717					endX: 0,
21718				},
21719				isMoved: false,
21720				newTranslateX: 0,
21721				startTime: new Date(),
21722				endTime: new Date(),
21723				touchMoveTime: 0,
21724			};
21725			this.$lgThumb.on('touchstart.lg', function (e) {
21726				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21727					e.preventDefault();
21728					thumbDragUtils.cords.startX = e.targetTouches[0].pageX;
21729					_this.thumbClickable = false;
21730					thumbDragUtils.startTime = new Date();
21731				}
21732			});
21733			this.$lgThumb.on('touchmove.lg', function (e) {
21734				if (_this.thumbTotalWidth > _this.thumbOuterWidth) {
21735					e.preventDefault();
21736					thumbDragUtils.cords.endX = e.targetTouches[0].pageX;
21737					thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils);
21738				}
21739			});
21740			this.$lgThumb.on('touchend.lg', function () {
21741				if (thumbDragUtils.isMoved) {
21742					thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils);
21743				}
21744				else {
21745					_this.thumbClickable = true;
21746				}
21747			});
21748		};
21749		// Rebuild thumbnails
21750		Thumbnail.prototype.rebuildThumbnails = function () {
21751			var _this = this;
21752			// Remove transitions
21753			this.$thumbOuter.addClass('lg-rebuilding-thumbnails');
21754			setTimeout(function () {
21755				_this.thumbTotalWidth =
21756					_this.core.galleryItems.length *
21757						(_this.settings.thumbWidth + _this.settings.thumbMargin);
21758				_this.$lgThumb.css('width', _this.thumbTotalWidth + 'px');
21759				_this.$lgThumb.empty();
21760				_this.setThumbItemHtml(_this.core.galleryItems);
21761				_this.animateThumb(_this.core.index);
21762			}, 50);
21763			setTimeout(function () {
21764				_this.$thumbOuter.removeClass('lg-rebuilding-thumbnails');
21765			}, 200);
21766		};
21767		// @ts-check
21768		Thumbnail.prototype.setTranslate = function (value) {
21769			this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)');
21770		};
21771		Thumbnail.prototype.getPossibleTransformX = function (left) {
21772			if (left > this.thumbTotalWidth - this.thumbOuterWidth) {
21773				left = this.thumbTotalWidth - this.thumbOuterWidth;
21774			}
21775			if (left < 0) {
21776				left = 0;
21777			}
21778			return left;
21779		};
21780		Thumbnail.prototype.animateThumb = function (index) {
21781			this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms');
21782			if (this.settings.animateThumb) {
21783				var position = 0;
21784				switch (this.settings.currentPagerPosition) {
21785					case 'left':
21786						position = 0;
21787						break;
21788					case 'middle':
21789						position =
21790							this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2;
21791						break;
21792					case 'right':
21793						position = this.thumbOuterWidth - this.settings.thumbWidth;
21794				}
21795				this.translateX =
21796					(this.settings.thumbWidth + this.settings.thumbMargin) * index -
21797						1 -
21798						position;
21799				if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) {
21800					this.translateX = this.thumbTotalWidth - this.thumbOuterWidth;
21801				}
21802				if (this.translateX < 0) {
21803					this.translateX = 0;
21804				}
21805				this.setTranslate(this.translateX);
21806			}
21807		};
21808		Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) {
21809			thumbDragUtils.newTranslateX = this.translateX;
21810			thumbDragUtils.isMoved = true;
21811			thumbDragUtils.touchMoveTime = new Date().valueOf();
21812			thumbDragUtils.newTranslateX -=
21813				thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21814			thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX);
21815			// move current slide
21816			this.setTranslate(thumbDragUtils.newTranslateX);
21817			this.$thumbOuter.addClass('lg-dragging');
21818			return thumbDragUtils;
21819		};
21820		Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) {
21821			thumbDragUtils.isMoved = false;
21822			thumbDragUtils.endTime = new Date();
21823			this.$thumbOuter.removeClass('lg-dragging');
21824			var touchDuration = thumbDragUtils.endTime.valueOf() -
21825				thumbDragUtils.startTime.valueOf();
21826			var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX;
21827			var speedX = Math.abs(distanceXnew) / touchDuration;
21828			// Some magical numbers
21829			// Can be improved
21830			if (speedX > 0.15 &&
21831				thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) {
21832				speedX += 1;
21833				if (speedX > 2) {
21834					speedX += 1;
21835				}
21836				speedX =
21837					speedX +
21838						speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth);
21839				this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings');
21840				distanceXnew = distanceXnew * speedX;
21841				this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew);
21842				this.setTranslate(this.translateX);
21843			}
21844			else {
21845				this.translateX = thumbDragUtils.newTranslateX;
21846			}
21847			if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) <
21848				this.settings.thumbnailSwipeThreshold) {
21849				this.thumbClickable = true;
21850			}
21851			return thumbDragUtils;
21852		};
21853		Thumbnail.prototype.getThumbHtml = function (thumb, index) {
21854			var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
21855			var thumbImg;
21856			if (slideVideoInfo.youtube) {
21857				if (this.settings.loadYouTubeThumbnail) {
21858					thumbImg =
21859						'//img.youtube.com/vi/' +
21860							slideVideoInfo.youtube[1] +
21861							'/' +
21862							this.settings.youTubeThumbSize +
21863							'.jpg';
21864				}
21865				else {
21866					thumbImg = thumb;
21867				}
21868			}
21869			else {
21870				thumbImg = thumb;
21871			}
21872			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>";
21873		};
21874		Thumbnail.prototype.getThumbItemHtml = function (items) {
21875			var thumbList = '';
21876			for (var i = 0; i < items.length; i++) {
21877				thumbList += this.getThumbHtml(items[i].thumb, i);
21878			}
21879			return thumbList;
21880		};
21881		Thumbnail.prototype.setThumbItemHtml = function (items) {
21882			var thumbList = this.getThumbItemHtml(items);
21883			this.$lgThumb.html(thumbList);
21884		};
21885		Thumbnail.prototype.setAnimateThumbStyles = function () {
21886			if (this.settings.animateThumb) {
21887				this.core.outer.addClass('lg-animate-thumb');
21888			}
21889		};
21890		// Manage thumbnail active calss
21891		Thumbnail.prototype.manageActiveClassOnSlideChange = function () {
21892			var _this = this;
21893			// manage active class for thumbnail
21894			//Uncode edit ##START##
21895			// this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) {
21896			this.core.LGel.on(lGEvents.beforeSlide, function (event) {
21897			//Uncode edit ##END##
21898				var $thumb = _this.core.outer.find('.lg-thumb-item');
21899				var index = event.detail.index;
21900				$thumb.removeClass('active');
21901				$thumb.eq(index).addClass('active');
21902			});
21903		};
21904		// Toggle thumbnail bar
21905		Thumbnail.prototype.toggleThumbBar = function () {
21906			var _this = this;
21907			if (this.settings.toggleThumb) {
21908				this.core.outer.addClass('lg-can-toggle');
21909				this.core.$toolbar.append('<button type="button" aria-label="' +
21910					this.settings.thumbnailPluginStrings['toggleThumbnails'] +
21911					'" class="lg-toggle-thumb lg-icon"></button>');
21912				this.core.outer
21913					.find('.lg-toggle-thumb')
21914					.first()
21915					.on('click.lg', function () {
21916					_this.core.outer.toggleClass('lg-components-open');
21917				});
21918			}
21919		};
21920		Thumbnail.prototype.thumbKeyPress = function () {
21921			var _this = this;
21922			this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) {
21923				if (!_this.core.lgOpened || !_this.settings.toggleThumb)
21924					return;
21925				if (e.keyCode === 38) {
21926					e.preventDefault();
21927					_this.core.outer.addClass('lg-components-open');
21928				}
21929				else if (e.keyCode === 40) {
21930					e.preventDefault();
21931					_this.core.outer.removeClass('lg-components-open');
21932				}
21933			});
21934		};
21935		Thumbnail.prototype.destroy = function () {
21936			if (this.settings.thumbnail) {
21937				this.$LG(window).off(".lg.thumb.global" + this.core.lgId);
21938				this.core.LGel.off('.lg.thumb');
21939				this.core.LGel.off('.thumb');
21940				this.$thumbOuter.remove();
21941				this.core.outer.removeClass('lg-has-thumb');
21942			}
21943		};
21944		return Thumbnail;
21945	}());
21946
21947	return Thumbnail;
21948
21949})));
21950/*!
21951 * lightgallery | 2.5.0 | June 13th 2022
21952 * http://www.lightgalleryjs.com/
21953 * Copyright (c) 2020 Sachin Neravath;
21954 * @license GPLv3
21955 */
21956
21957(function (global, factory) {
21958	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
21959	typeof define === 'function' && define.amd ? define(factory) :
21960	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory());
21961}(this, (function () { 'use strict';
21962
21963	/*! *****************************************************************************
21964	Copyright (c) Microsoft Corporation.
21965
21966	Permission to use, copy, modify, and/or distribute this software for any
21967	purpose with or without fee is hereby granted.
21968
21969	THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
21970	REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
21971	AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21972	INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21973	LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
21974	OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
21975	PERFORMANCE OF THIS SOFTWARE.
21976	***************************************************************************** */
21977
21978	var __assign = function() {
21979		__assign = Object.assign || function __assign(t) {
21980			for (var s, i = 1, n = arguments.length; i < n; i++) {
21981				s = arguments[i];
21982				for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
21983			}
21984			return t;
21985		};
21986		return __assign.apply(this, arguments);
21987	};
21988
21989	var videoSettings = {
21990		autoplayFirstVideo: true,
21991		youTubePlayerParams: false,
21992		vimeoPlayerParams: false,
21993		wistiaPlayerParams: false,
21994		gotoNextSlideOnVideoEnd: true,
21995		autoplayVideoOnSlide: false,
21996		videojs: false,
21997		videojsTheme: '',
21998		videojsOptions: {},
21999	};
22000
22001	/**
22002	 * List of lightGallery events
22003	 * All events should be documented here
22004	 * Below interfaces are used to build the website documentations
22005	 * */
22006	var lGEvents = {
22007		afterAppendSlide: 'lgAfterAppendSlide',
22008		init: 'lgInit',
22009		hasVideo: 'lgHasVideo',
22010		containerResize: 'lgContainerResize',
22011		updateSlides: 'lgUpdateSlides',
22012		afterAppendSubHtml: 'lgAfterAppendSubHtml',
22013		beforeOpen: 'lgBeforeOpen',
22014		afterOpen: 'lgAfterOpen',
22015		slideItemLoad: 'lgSlideItemLoad',
22016		beforeSlide: 'lgBeforeSlide',
22017		afterSlide: 'lgAfterSlide',
22018		posterClick: 'lgPosterClick',
22019		dragStart: 'lgDragStart',
22020		dragMove: 'lgDragMove',
22021		dragEnd: 'lgDragEnd',
22022		beforeNextSlide: 'lgBeforeNextSlide',
22023		beforePrevSlide: 'lgBeforePrevSlide',
22024		beforeClose: 'lgBeforeClose',
22025		afterClose: 'lgAfterClose',
22026		rotateLeft: 'lgRotateLeft',
22027		rotateRight: 'lgRotateRight',
22028		flipHorizontal: 'lgFlipHorizontal',
22029		flipVertical: 'lgFlipVertical',
22030		autoplay: 'lgAutoplay',
22031		autoplayStart: 'lgAutoplayStart',
22032		autoplayStop: 'lgAutoplayStop',
22033	};
22034
22035	var param = function (obj) {
22036		return Object.keys(obj)
22037			.map(function (k) {
22038			return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]);
22039		})
22040			.join('&');
22041	};
22042	var getVimeoURLParams = function (defaultParams, videoInfo) {
22043		if (!videoInfo || !videoInfo.vimeo)
22044			return '';
22045		var urlParams = videoInfo.vimeo[2] || '';
22046		var defaultPlayerParams = defaultParams && Object.keys(defaultParams).length !== 0
22047			? '&' + param(defaultParams)
22048			: '';
22049		// Support private video
22050		var urlWithHash = videoInfo.vimeo[0].split('/').pop() || '';
22051		var urlWithHashWithParams = urlWithHash.split('?')[0] || '';
22052		var hash = urlWithHashWithParams.split('#')[0];
22053		var isPrivate = videoInfo.vimeo[1] !== hash;
22054		if (isPrivate) {
22055			urlParams = urlParams.replace("/" + hash, '');
22056		}
22057		urlParams =
22058			urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || '';
22059		// For vimeo last params gets priority if duplicates found
22060		// Uncode edit ##START##
22061		var vimeoPlayerParams = '?autoplay=0';
22062		if ( videoInfo.autoplay !== '' ) {
22063			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22064			vimeoPlayerParams = vimeoPlayerParams.replace(new RegExp('([?&])autoplay(&|$)'), '$1$2' );
22065		} else {
22066			if ( typeof SiteParameters !== 'undefined' && typeof SiteParameters.vimeoPlayerParams !== 'undefined' && SiteParameters.vimeoPlayerParams !== '' ) {
22067				vimeoPlayerParams = SiteParameters.vimeoPlayerParams;
22068			}
22069		}
22070		if ( videoInfo.muted !== '' ) {
22071			vimeoPlayerParams += '&muted=' + (videoInfo.muted === 'yes');
22072		} else {
22073			if ( urlParams.indexOf('muted=') < 0 && vimeoPlayerParams.indexOf('muted=') < 0 ) {
22074				vimeoPlayerParams += '&muted=1';
22075			}
22076		}
22077		// var vimeoPlayerParams = "?autoplay=0&muted=1" + (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22078		vimeoPlayerParams += (isPrivate ? "&h=" + hash : '') + defaultPlayerParams + urlParams;
22079		// Uncode edit ##END##
22080		return vimeoPlayerParams;
22081	};
22082
22083	/**
22084	 * Video module for lightGallery
22085	 * Supports HTML5, YouTube, Vimeo, wistia videos
22086	 *
22087	 *
22088	 * @ref Wistia
22089	 * https://wistia.com/support/integrations/wordpress(How to get url)
22090	 * https://wistia.com/support/developers/embed-options#using-embed-options
22091	 * https://wistia.com/support/developers/player-api
22092	 * https://wistia.com/support/developers/construct-an-embed-code
22093	 * http://jsfiddle.net/xvnm7xLm/
22094	 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video
22095	 * https://wistia.com/support/embed-and-share/sharing-videos
22096	 * https://private-sharing.wistia.com/medias/mwhrulrucj
22097	 *
22098	 * @ref Youtube
22099	 * https://developers.google.com/youtube/player_parameters#enablejsapi
22100	 * https://developers.google.com/youtube/iframe_api_reference
22101	 * https://developer.chrome.com/blog/autoplay/#iframe-delegation
22102	 *
22103	 * @ref Vimeo
22104	 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url
22105	 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode
22106	 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters
22107	 */
22108	var Video = /** @class */ (function () {
22109		function Video(instance) {
22110			// get lightGallery core plugin instance
22111			this.core = instance;
22112			this.settings = __assign(__assign({}, videoSettings), this.core.settings);
22113			return this;
22114		}
22115		Video.prototype.init = function () {
22116			var _this = this;
22117			/**
22118			 * Event triggered when video url found without poster
22119			 * Append video HTML
22120			 * Play if autoplayFirstVideo is true
22121			 */
22122			this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this));
22123			this.core.LGel.on(lGEvents.posterClick + ".video", function () {
22124				var $el = _this.core.getSlideItem(_this.core.index);
22125				_this.loadVideoOnPosterClick($el);
22126			});
22127			this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this));
22128			// @desc fired immediately before each slide transition.
22129			this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this));
22130			// @desc fired immediately after each slide transition.
22131			this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this));
22132		};
22133		/**
22134		 * @desc Event triggered when a slide is completely loaded
22135		 *
22136		 * @param {Event} event - lightGalley custom event
22137		 */
22138		Video.prototype.onSlideItemLoad = function (event) {
22139			var _this = this;
22140			var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index;
22141			// Should check the active slide as well as user may have moved to different slide before the first slide is loaded
22142			if (this.settings.autoplayFirstVideo &&
22143				isFirstSlide &&
22144				index === this.core.index) {
22145				// Delay is just for the transition effect on video load
22146				setTimeout(function () {
22147					_this.loadAndPlayVideo(index);
22148				}, 200);
22149			}
22150			// Should not call on first slide. should check only if the slide is active
22151			if (!isFirstSlide &&
22152				this.settings.autoplayVideoOnSlide &&
22153				index === this.core.index) {
22154					setTimeout(function () {
22155						_this.loadAndPlayVideo(index);
22156					}, 500);
22157				}
22158		};
22159		/**
22160		 * @desc Event triggered when video url or poster found
22161		 * Append video HTML is poster is not given
22162		 * Play if autoplayFirstVideo is true
22163		 *
22164		 * @param {Event} event - Javascript Event object.
22165		 */
22166		Video.prototype.onHasVideo = function (event) {
22167			var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster;
22168			if (!hasPoster) {
22169				// All functions are called separately if poster exist in loadVideoOnPosterClick function
22170				this.appendVideos(this.core.getSlideItem(index), {
22171					src: src,
22172					addClass: 'lg-object',
22173					index: index,
22174					html5Video: html5Video,
22175					// Uncode edit ##START##
22176					autoplay: event.target.getAttribute('data-lb-autoplay'),
22177					muted: event.target.getAttribute('data-lb-muted'),
22178					// Uncode edit ##END##
22179				});
22180				// Automatically navigate to next slide once video reaches the end.
22181				this.gotoNextSlideOnVideoEnd(src, index);
22182			}
22183		};
22184		/**
22185		 * @desc fired immediately before each slide transition.
22186		 * Pause the previous video
22187		 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos.
22188		 *
22189		 * @param {Event} event - Javascript Event object.
22190		 * @param {number} prevIndex - Previous index of the slide.
22191		 * @param {number} index - Current index of the slide
22192		 */
22193		Video.prototype.onBeforeSlide = function (event) {
22194			if (this.core.lGalleryOn) {
22195				var prevIndex = event.detail.prevIndex;
22196				this.pauseVideo(prevIndex);
22197			}
22198			// Uncode edit ##START##
22199			var _a = event.detail, index = _a.index;
22200			var $slide = this.core.getSlideItem(index);
22201			
22202			var iframe = $slide.selector.querySelector('iframe');
22203			if ( iframe != null ) {
22204
22205				var data_play = iframe.getAttribute('data-autoplay');
22206				if ( typeof data_play !== 'undefined' && data_play === '1' ) {
22207					this.loadAndPlayVideo(index);
22208
22209					var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {},
22210						$videoElement = this.core.getSlideItem(index).find('.lg-video-object').first();
22211					if (videoInfo.vimeo) {
22212						var vimeoPlayer = new Vimeo.Player($videoElement.get());
22213						vimeoPlayer.on('play', function () {
22214							vimeoPlayer.setCurrentTime(0);
22215						});
22216					} else if ( videoInfo.youtube ) {
22217						try {
22218							$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*');
22219						}
22220						catch (e) {
22221							console.warn(e);
22222						}
22223					}
22224				}
22225			}
22226			// Uncode edit ##END##
22227		};
22228		/**
22229		 * @desc fired immediately after each slide transition.
22230		 * Play video if autoplayVideoOnSlide option is enabled.
22231		 *
22232		 * @param {Event} event - Javascript Event object.
22233		 * @param {number} prevIndex - Previous index of the slide.
22234		 * @param {number} index - Current index of the slide
22235		 * @todo should check on onSlideLoad as well if video is not loaded on after slide
22236		 */
22237		Video.prototype.onAfterSlide = function (event) {
22238			var _this = this;
22239			var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
22240			// Do not call on first slide
22241			var $slide = this.core.getSlideItem(index);
22242			if (this.settings.autoplayVideoOnSlide && index !== prevIndex) {
22243				if ($slide.hasClass('lg-complete')) {
22244					setTimeout(function () {
22245						_this.loadAndPlayVideo(index);
22246					}, 100);
22247				}
22248			}
22249		};
22250		Video.prototype.loadAndPlayVideo = function (index) {
22251			var $slide = this.core.getSlideItem(index);
22252			var currentGalleryItem = this.core.galleryItems[index];
22253			if (currentGalleryItem.poster) {
22254				this.loadVideoOnPosterClick($slide, true);
22255			}
22256			else {
22257				//Uncode edit ##START##
22258				// this.playVideo(index);
22259				var iframe = $slide.selector.querySelector('iframe');
22260				if ( iframe != null ) {
22261					var data_play = iframe.getAttribute('data-autoplay');
22262					if ( typeof data_play !== 'undefined' ) {
22263						if ( data_play === '1' && this.core.index == index ) {
22264							this.playVideo(index);
22265						} else {
22266							this.pauseVideo(index);
22267						}
22268					}
22269				}
22270				//Uncode edit ##END##
22271			}
22272		};
22273		/**
22274		 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22275		 * @param {number} index - Index of the slide
22276		 */
22277		Video.prototype.playVideo = function (index) {
22278			this.controlVideo(index, 'play');
22279		};
22280		/**
22281		 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide.
22282		 * @param {number} index - Index of the slide
22283		 */
22284		Video.prototype.pauseVideo = function (index) {
22285			this.controlVideo(index, 'pause');
22286		};
22287		// Uncode edit ##START##
22288		//Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) {
22289		Video.prototype.getVideoHtml = function (src, addClass, index, html5Video, autoplay, muted) {
22290		// Uncode edit ##END##
22291			var video = '';
22292			var videoInfo = this.core.galleryItems[index]
22293				.__slideVideoInfo || {};
22294			var currentGalleryItem = this.core.galleryItems[index];
22295			var videoTitle = currentGalleryItem.title || currentGalleryItem.alt;
22296			videoTitle = videoTitle ? 'title="' + videoTitle + '"' : '';
22297			var commonIframeProps = "allowtransparency=\"true\"\n            frameborder=\"0\"\n            scrolling=\"no\"\n            allowfullscreen\n            mozallowfullscreen\n            webkitallowfullscreen\n            oallowfullscreen\n            msallowfullscreen";
22298			if (videoInfo.youtube) {
22299				var videoId = 'lg-youtube' + index;
22300				var slideUrlParams = videoInfo.youtube[2]
22301					? videoInfo.youtube[2] + '&'
22302					: '';
22303				// For youtube first parms gets priority if duplicates found
22304				// Uncode edit ##START##
22305				// var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1";
22306				var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&enablejsapi=1";
22307				if ( ( slideUrlParams.indexOf('autoplay=') < 0 && youTubePlayerParams.indexOf('autoplay=') < 0 ) ) {
22308					youTubePlayerParams += '&autoplay=0';
22309				}
22310				if ( slideUrlParams.indexOf('mute=') < 0 && youTubePlayerParams.indexOf('mute=') < 0 ) {
22311					youTubePlayerParams += '&mute=1';
22312				}
22313				var data_video = '';
22314				if ( autoplay !== '' ) {
22315					//youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1autoplay=' + (autoplay === 'yes' ? 1 : 0) + '$3' );
22316					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay=(.*?)(&|$)'), '$1$3' );
22317					youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])autoplay'), '$1' );
22318					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22319				}
22320				// if ( muted !== '' ) {
22321				// 	youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1mute=' + (muted === 'yes' ? 1 : 0) + '$3' );
22322				// }
22323				youTubePlayerParams = youTubePlayerParams.replace(new RegExp('([?&])mute=(.*?)(&|$)'), '$1$3' );
22324
22325				youTubePlayerParams = youTubePlayerParams.replace('??', '?');
22326				// Uncode edit ##END##
22327				var playerParams = youTubePlayerParams +
22328					(this.settings.youTubePlayerParams
22329						? '&' + param(this.settings.youTubePlayerParams)
22330						: '');
22331				// Uncode edit ##START##
22332				// 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>";
22333				var nocookie = typeof SiteParameters.uncode_nocookie !== 'undefined' ? SiteParameters.uncode_nocookie : '';
22334				video = "<iframe allow=\"autoplay\"" + data_video + " id=" + videoId + " class=\"lg-video-object lg-youtube " + addClass + "\" " + videoTitle + " src=\"//www.youtube" + nocookie + ".com/embed/" + (videoInfo.youtube[1] + playerParams) + "\" " + commonIframeProps + "></iframe>";
22335				var tag = document.createElement('script');
22336				tag.src = "//www.youtube.com/player_api";
22337				var firstScriptTag = document.getElementsByTagName('script')[0];
22338				firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
22339
22340				// Replace the 'ytplayer' element with an <iframe> and
22341				// YouTube player after the API code downloads.
22342				var ytIframeplayer,
22343					setMute = muted === 'yes' ? 0 : 100;
22344				window.onYouTubePlayerAPIReady = function() {
22345					ytIframeplayer = new YT.Player(videoId, {
22346						videoId: videoInfo.youtube[1],
22347						events: {
22348							'onReady': function (event) {
22349								event.target.setVolume(setMute);
22350							}
22351						}
22352					});
22353				}
22354				// Uncode edit ##END##
22355			}
22356			else if (videoInfo.vimeo) {
22357				var videoId = 'lg-vimeo' + index;
22358				// Uncode edit ##START##
22359				videoInfo.autoplay = autoplay;
22360				videoInfo.muted = muted;
22361				// Uncode edit ##END##
22362				var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo);
22363				// Uncode edit ##START##
22364				// 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>";
22365				var data_video = '';
22366				if ( autoplay !== '' ) {
22367					data_video = ' data-autoplay="' + (autoplay === 'yes' ? 1 : 0) + '"';
22368				}
22369				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>";
22370				// Uncode edit ##END##
22371			}
22372			else if (videoInfo.wistia) {
22373				var wistiaId = 'lg-wistia' + index;
22374				var playerParams = param(this.settings.wistiaPlayerParams);
22375				playerParams = playerParams ? '?' + playerParams : '';
22376				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>";
22377			}
22378			else if (videoInfo.html5) {
22379				var html5VideoMarkup = '';
22380				for (var i = 0; i < html5Video.source.length; i++) {
22381					html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">";
22382				}
22383				if (html5Video.tracks) {
22384					var _loop_1 = function (i) {
22385						var trackAttributes = '';
22386						var track = html5Video.tracks[i];
22387						Object.keys(track || {}
22387).forEach(function (key) {
22388							trackAttributes += key + "=\"" + track[key] + "\" ";
22389						});
22390						html5VideoMarkup += "<track " + trackAttributes + ">";
22391					};
22392					for (var i = 0; i < html5Video.tracks.length; i++) {
22393						_loop_1(i);
22394					}
22395				}
22396				var html5VideoAttrs_1 = '';
22397				var videoAttributes_1 = html5Video.attributes || {};
22398				Object.keys(videoAttributes_1 || {}).forEach(function (key) {
22399					html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" ";
22400				});
22401				video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs && this.settings.videojsTheme
22402					? this.settings.videojsTheme + ' '
22403					: '') + " " + (this.settings.videojs ? ' video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n                " + html5VideoMarkup + "\n                Your browser does not support HTML5 video.\n            </video>";
22404			}
22405			return video;
22406		};
22407		/**
22408		 * @desc - Append videos to the slide
22409		 *
22410		 * @param {HTMLElement} el - slide element
22411		 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo
22412		 */
22413		Video.prototype.appendVideos = function (el, videoParams) {
22414			var _a;
22415			// Uncode edit ##START##
22416			// var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video);
22417			var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video, videoParams.autoplay, videoParams.muted);
22418			// Uncode edit ##END##
22419			el.find('.lg-video-cont').append(videoHtml);
22420			var $videoElement = el.find('.lg-video-object').first();
22421			if (videoParams.html5Video) {
22422				$videoElement.on('mousedown.lg.video', function (e) {
22423					e.stopPropagation();
22424				});
22425			}
22426			if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) {
22427				try {
22428					return videojs($videoElement.get(), this.settings.videojsOptions);
22429				}
22430				catch (e) {
22431					console.warn('lightGallery:- Make sure you have included videojs');
22432				}
22433			}
22434		};
22435		Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) {
22436			var _this = this;
22437			var $videoElement = this.core
22438				.getSlideItem(index)
22439				.find('.lg-video-object')
22440				.first();
22441			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22442			if (this.settings.gotoNextSlideOnVideoEnd) {
22443				if (videoInfo.html5) {
22444					$videoElement.on('ended', function () {
22445						_this.core.goToNextSlide();
22446					});
22447				}
22448				else if (videoInfo.vimeo) {
22449					try {
22450						// https://github.com/vimeo/player.js/#ended
22451						new Vimeo.Player($videoElement.get()).on('ended', function () {
22452							_this.core.goToNextSlide();
22453						});
22454					}
22455					catch (e) {
22456						console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22457					}
22458				}
22459				else if (videoInfo.wistia) {
22460					try {
22461						window._wq = window._wq || [];
22462						// @todo Event is gettign triggered multiple times
22463						window._wq.push({
22464							id: $videoElement.attr('id'),
22465							onReady: function (video) {
22466								video.bind('end', function () {
22467									_this.core.goToNextSlide();
22468								});
22469							},
22470						});
22471					}
22472					catch (e) {
22473						console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22474					}
22475				}
22476			}
22477		};
22478		Video.prototype.controlVideo = function (index, action) {
22479			var $videoElement = this.core
22480				.getSlideItem(index)
22481				.find('.lg-video-object')
22482				.first();
22483			var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {};
22484			if (!$videoElement.get())
22485				return;
22486			if (videoInfo.youtube) {
22487				try {
22488					$videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*');
22489				}
22490				catch (e) {
22491					console.warn("lightGallery:- " + e);
22492				}
22493			}
22494			else if (videoInfo.vimeo) {
22495				try {
22496					new Vimeo.Player($videoElement.get())[action]();
22497				}
22498				catch (e) {
22499					console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js');
22500				}
22501			}
22502			else if (videoInfo.html5) {
22503				if (this.settings.videojs) {
22504					try {
22505						videojs($videoElement.get())[action]();
22506					}
22507					catch (e) {
22508						console.warn('lightGallery:- Make sure you have included videojs');
22509					}
22510				}
22511				else {
22512					$videoElement.get()[action]();
22513				}
22514			}
22515			else if (videoInfo.wistia) {
22516				try {
22517					window._wq = window._wq || [];
22518					// @todo Find a way to destroy wistia player instance
22519					window._wq.push({
22520						id: $videoElement.attr('id'),
22521						onReady: function (video) {
22522							video[action]();
22523						},
22524					});
22525				}
22526				catch (e) {
22527					console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js');
22528				}
22529			}
22530		};
22531		Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) {
22532			var _this = this;
22533			// check slide has poster
22534			if (!$el.hasClass('lg-video-loaded')) {
22535				// check already video element present
22536				if (!$el.hasClass('lg-has-video')) {
22537					$el.addClass('lg-has-video');
22538					var _html = void 0;
22539					var _src = this.core.galleryItems[this.core.index].src;
22540					var video = this.core.galleryItems[this.core.index].video;
22541					if (video) {
22542						_html =
22543							typeof video === 'string' ? JSON.parse(video) : video;
22544					}
22545					var videoJsPlayer_1 = this.appendVideos($el, {
22546						src: _src,
22547						addClass: '',
22548						index: this.core.index,
22549						html5Video: _html,
22550					});
22551					this.gotoNextSlideOnVideoEnd(_src, this.core.index);
22552					var $tempImg = $el.find('.lg-object').first().get();
22553					// @todo make sure it is working
22554					$el.find('.lg-video-cont').first().append($tempImg);
22555					$el.addClass('lg-video-loading');
22556					videoJsPlayer_1 &&
22557						videoJsPlayer_1.ready(function () {
22558							videoJsPlayer_1.on('loadedmetadata', function () {
22559								_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22560							});
22561						});
22562					$el.find('.lg-video-object')
22563						.first()
22564						.on('load.lg error.lg loadedmetadata.lg', function () {
22565						setTimeout(function () {
22566							_this.onVideoLoadAfterPosterClick($el, _this.core.index);
22567						}, 50);
22568					});
22569				}
22570				else {
22571					this.playVideo(this.core.index);
22572				}
22573			}
22574			else if (forcePlay) {
22575				this.playVideo(this.core.index);
22576			}
22577		};
22578		Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) {
22579			$el.addClass('lg-video-loaded');
22580			this.playVideo(index);
22581		};
22582		Video.prototype.destroy = function () {
22583			this.core.LGel.off('.lg.video');
22584			this.core.LGel.off('.video');
22585		};
22586		return Video;
22587	}());
22588
22589	return Video;
22590
22591})));
22592
22593
22594/*! @vimeo/player v2.17.1 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */
22595!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:{}}
22595),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 22595
22595var 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)}
22595},{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 22595-23802
22595))}(),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});
22596
22597/**
22598 * Owl carousel
22599 * @version 2.0.0-beta.3
22600 * @author Bartosz Wojciechowski
22601 * @license The MIT License (MIT)
22602 * @todo Lazy Load Icon
22603 * @todo prevent animationend bubling
22604 * @todo itemsScaleUp
22605 * @todo Test Zepto
22606 * @todo stagePadding calculate wrong active classes
22607 */
22608;(function($, window, document, undefined) {
22609
22610	/**
22611	 * Creates a carousel.
22612	 * @class The Owl Carousel.
22613	 * @public
22614	 * @param {HTMLElement|jQuery} element - The element to create the carousel for.
22615	 * @param {Object} [options] - The options
22616	 */
22617	function Owl(element, options) {
22618
22619		/**
22620		 * Current settings for the carousel.
22621		 * @public
22622		 */
22623		this.settings = null;
22624
22625		/**
22626		 * Current options set by the caller including defaults.
22627		 * @public
22628		 */
22629		this.options = $.extend({}, Owl.Defaults, options);
22630
22631		/**
22632		 * Plugin element.
22633		 * @public
22634		 */
22635		this.$element = $(element);
22636
22637		/**
22638		 * Proxied event handlers.
22639		 * @protected
22640		 */
22641		this._handlers = {};
22642
22643		/**
22644		 * References to the running plugins of this carousel.
22645		 * @protected
22646		 */
22647		this._plugins = {};
22648
22649		/**
22650		 * Currently suppressed events to prevent them from beeing retriggered.
22651		 * @protected
22652		 */
22653		this._supress = {};
22654
22655		/**
22656		 * Absolute current position.
22657		 * @protected
22658		 */
22659		this._current = null;
22660
22661		/**
22662		 * Animation speed in milliseconds.
22663		 * @protected
22664		 */
22665		this._speed = null;
22666
22667		/**
22668		 * Coordinates of all items in pixel.
22669		 * @todo The name of this member is missleading.
22670		 * @protected
22671		 */
22672		this._coordinates = [];
22673
22674		/**
22675		 * Current breakpoint.
22676		 * @todo Real media queries would be nice.
22677		 * @protected
22678		 */
22679		this._breakpoint = null;
22680
22681		/**
22682		 * Current width of the plugin element.
22683		 */
22684		this._width = null;
22685
22686		/**
22687		 * All real items.
22688		 * @protected
22689		 */
22690		this._items = [];
22691
22692		/**
22693		 * All cloned items.
22694		 * @protected
22695		 */
22696		this._clones = [];
22697
22698		/**
22699		 * Merge values of all items.
22700		 * @todo Maybe this could be part of a plugin.
22701		 * @protected
22702		 */
22703		this._mergers = [];
22704
22705		/**
22706		 * Widths of all items.
22707		 */
22708		this._widths = [];
22709
22710		/**
22711		 * Invalidated parts within the update process.
22712		 * @protected
22713		 */
22714		this._invalidated = {};
22715
22716		/**
22717		 * Ordered list of workers for the update process.
22718		 * @protected
22719		 */
22720		this._pipe = [];
22721
22722		/**
22723		 * Current state information for the drag operation.
22724		 * @todo #261
22725		 * @protected
22726		 */
22727		this._drag = {
22728			time: null,
22729			target: null,
22730			pointer: null,
22731			stage: {
22732				start: null,
22733				current: null
22734			},
22735			direction: null
22736		};
22737
22738		/**
22739		 * Current state information and their tags.
22740		 * @type {Object}
22741		 * @protected
22742		 */
22743		this._states = {
22744			current: {},
22745			tags: {
22746				'initializing': [ 'busy' ],
22747				'animating': [ 'busy' ],
22748				'dragging': [ 'interacting' ]
22749			}
22750		};
22751
22752		$.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
22753			this._handlers[handler] = $.proxy(this[handler], this);
22754		}, this));
22755
22756		$.each(Owl.Plugins, $.proxy(function(key, plugin) {
22757			this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
22758				= new plugin(this);
22759		}, this));
22760
22761		$.each(Owl.Workers, $.proxy(function(priority, worker) {
22762			this._pipe.push({
22763				'filter': worker.filter,
22764				'run': $.proxy(worker.run, this)
22765			});
22766		}, this));
22767
22768		this.setup();
22769		this.initialize();
22770	}
22771
22772	/**
22773	 * Default options for the carousel.
22774	 * @public
22775	 */
22776	Owl.Defaults = {
22777		items: 3,
22778		loop: false,
22779		center: false,
22780		rewind: false,
22781
22782		mouseDrag: true,
22783		touchDrag: true,
22784		pullDrag: true,
22785		freeDrag: false,
22786
22787		margin: 0,
22788		stagePadding: 0,
22789
22790		merge: false,
22791		mergeFit: true,
22792		autoWidth: false,
22793
22794		startPosition: 0,
22795		rtl: false,
22796
22797		smartSpeed: 250,
22798		fluidSpeed: false,
22799		dragEndSpeed: false,
22800
22801		responsive: {},
22802		responsiveRefreshRate: 200,
22803		responsiveBaseElement: window,
22804
22805		fallbackEasing: 'swing',
22806
22807		info: false,
22808
22809		nestedItemSelector: false,
22810		itemElement: 'div',
22811		stageElement: 'div',
22812
22813		refreshClass: 'owl-refresh',
22814		loadedClass: 'owl-loaded',
22815		loadingClass: 'owl-loading',
22816		rtlClass: 'owl-rtl',
22817		responsiveClass: 'owl-responsive',
22818		dragClass: 'owl-drag',
22819		itemClass: 'owl-item',
22820		stageClass: 'owl-stage',
22821		stageOuterClass: 'owl-stage-outer',
22822		grabClass: 'owl-grab'
22823	};
22824
22825	/**
22826	 * Enumeration for width.
22827	 * @public
22828	 * @readonly
22829	 * @enum {String}
22830	 */
22831	Owl.Width = {
22832		Default: 'default',
22833		Inner: 'inner',
22834		Outer: 'outer'
22835	};
22836
22837	/**
22838	 * Enumeration for types.
22839	 * @public
22840	 * @readonly
22841	 * @enum {String}
22842	 */
22843	Owl.Type = {
22844		Event: 'event',
22845		State: 'state'
22846	};
22847
22848	/**
22849	 * Contains all registered plugins.
22850	 * @public
22851	 */
22852	Owl.Plugins = {};
22853
22854	/**
22855	 * List of workers involved in the update process.
22856	 */
22857	Owl.Workers = [ {
22858		filter: [ 'width', 'settings' ],
22859		run: function() {
22860			this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width();
22861			//this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12);
22862		}
22863	}, {
22864		filter: [ 'width', 'items', 'settings' ],
22865		run: function(cache) {
22866			cache.current = this._items && this._items[this.relative(this._current)];
22867		}
22868	}, {
22869		filter: [ 'items', 'settings' ],
22870		run: function() {
22871			this.$stage.children('.cloned').remove();
22872		}
22873	}, {
22874		filter: [ 'width', 'items', 'settings' ],
22875		run: function(cache) {
22876			var margin = this.settings.margin || '',
22877				grid = !this.settings.autoWidth,
22878				rtl = this.settings.rtl,
22879				css = {
22880					'width': 'auto',
22881					'margin-left': rtl ? margin : '',
22882					'margin-right': rtl ? '' : margin
22883				};
22884
22885			!grid && this.$stage.children().css(css);
22886
22887			cache.css = css;
22888		}
22889	}, {
22890		filter: [ 'width', 'items', 'settings' ],
22891		run: function(cache) {
22892			//UNCODE edit to fix Chrome stage padding issue
22893			var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin),
22894				merge = null,
22895				iterator = this._items.length,
22896				grid = !this.settings.autoWidth,
22897				widths = [];
22898
22899			cache.items = {
22900				merge: false,
22901				width: width
22902			};
22903
22904			while (iterator--) {
22905				merge = this._mergers[iterator];
22906				merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
22907
22908				cache.items.merge = merge > 1 || cache.items.merge;
22909
22910				widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
22911			}
22912
22913			this._widths = widths;
22914		}
22915	}, {
22916		filter: [ 'items', 'settings' ],
22917		run: function() {
22918			var clones = [],
22919				items = this._items,
22920				settings = this.settings,
22921				view = Math.max(settings.items * 2, 4),
22922				size = Math.ceil(items.length / 2) * 2,
22923				repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
22924				append = '',
22925				prepend = '';
22926
22927			repeat /= 2;
22928
22929			while (repeat--) {
22930				clones.push(this.normalize(clones.length / 2, true));
22931				append = append + items[clones[clones.length - 1]][0].outerHTML;
22932				clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
22933				prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
22934			}
22935
22936			this._clones = clones;
22937
22938			// var appendVideo = $(append).find('.uncode-video-container');
22939			// if (appendVideo.length) {
22940			// 	appendVideo.attr('data-id', Math.round(Math.random() * 100000));
22941			// }
22942			// var prependVideo = $(prepend).find('.uncode-video-container');
22943			// if (prependVideo.length) {
22944			// 	prependVideo.attr('data-id', Math.round(Math.random() * 100000));
22945			// }
22946			$(append).addClass('cloned').appendTo(this.$stage);
22947			$(prepend).addClass('cloned').prependTo(this.$stage);
22948		}
22949	}, {
22950		filter: [ 'width', 'items', 'settings' ],
22951		run: function() {
22952			var rtl = this.settings.rtl ? 1 : -1,
22953				size = this._clones.length + this._items.length,
22954				iterator = -1,
22955				previous = 0,
22956				current = 0,
22957				coordinates = [];
22958
22959			while (++iterator < size) {
22960				previous = coordinates[iterator - 1] || 0;
22961				current = this._widths[this.relative(iterator)] + this.settings.margin;
22962				coordinates.push(previous + current * rtl);
22963			}
22964
22965			this._coordinates = coordinates;
22966		}
22967	}, {
22968		filter: [ 'width', 'items', 'settings' ],
22969		run: function() {
22970			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
22971				padding = stagePadding,
22972				coordinates = this._coordinates,
22973				css = {
22974					'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
22975					'padding-left': padding || '',
22976					'padding-right': padding || ''
22977				};
22978
22979			this.$stage.css(css);
22980		}
22981	}, {
22982		filter: [ 'width', 'items', 'settings' ],
22983		run: function(cache) {
22984			var iterator = this._coordinates.length,
22985				grid = !this.settings.autoWidth,
22986				items = this.$stage.children();
22987
22988			if (grid && cache.items.merge) {
22989				while (iterator--) {
22990					cache.css.width = this._widths[this.relative(iterator)];
22991					items.eq(iterator).css(cache.css);
22992				}
22993			} else if (grid) {
22994				cache.css.width = cache.items.width;
22995				items.css(cache.css);
22996			}
22997		}
22998	}, {
22999		filter: [ 'items' ],
23000		run: function() {
23001			this._coordinates.length < 1 && this.$stage.removeAttr('style');
23002		}
23003	}, {
23004		filter: [ 'width', 'items', 'settings' ],
23005		run: function(cache) {
23006			cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
23007			cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
23008			this.reset(cache.current);
23009		}
23010	}, {
23011		filter: [ 'position' ],
23012		run: function() {
23013			this.animate(this.coordinates(this._current));
23014		}
23015	}, {
23016		filter: [ 'width', 'position', 'items', 'settings' ],
23017		run: function() {
23018			var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200,
23019				rtl = this.settings.rtl ? 1 : -1,
23020				padding = this.settings.stagePadding * 2,
23021				begin = this.coordinates(this.current()) + padding,
23022				end = begin + this.width() * rtl,
23023				inner, outer, matches = [], i, n;
23024
23025			for (i = 0, n = this._coordinates.length; i < n; i++) {
23026				inner = this._coordinates[i - 1] || 0;
23027				outer = Math.abs(this._coordinates[i]) + padding * rtl;
23028
23029				if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
23030					|| (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
23031					matches.push(i);
23032				}
23033			}
23034
23035			this.$stage.children('.active').removeClass('active');
23036			this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
23037
23038			if (this.settings.center) {
23039				this.$stage.children('.center').removeClass('center');
23040				this.$stage.children().eq(this.current()).addClass('center');
23041			}
23042		}
23043	} ];
23044
23045	/**
23046	 * Initializes the carousel.
23047	 * @protected
23048	 */
23049	Owl.prototype.initialize = function() {
23050		this.enter('initializing');
23051		this.trigger('initialize');
23052
23053		this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
23054
23055		if (this.settings.autoWidth && !this.is('pre-loading')) {
23056			var imgs, nestedSelector, width;
23057			imgs = this.$element.find('img');
23058			nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
23059			width = this.$element.children(nestedSelector).width();
23060
23061			if (imgs.length && width <= 0) {
23062				this.preloadAutoWidthImages(imgs);
23063			}
23064		}
23065
23066		this.$element.addClass(this.options.loadingClass);
23067
23068		// create stage
23069		this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
23070			.wrap('<div class="' + this.settings.stageOuterClass + '"/>');
23071
23072		// append stage
23073		this.$element.append(this.$stage.parent());
23074
23075		// append content
23076		this.replace(this.$element.children().not(this.$stage.parent()));
23077
23078		// check visibility
23079		if (this.$element.is(':visible')) {
23080			// update view
23081			this.refresh();
23082		} else {
23083			// invalidate width
23084			this.invalidate('width');
23085		}
23086
23087		this.$element
23088			.removeClass(this.options.loadingClass)
23089			.addClass(this.options.loadedClass);
23090
23091		// register event handlers
23092		this.registerEventHandlers();
23093
23094		this.leave('initializing');
23095		this.trigger('initialized');
23096	};
23097
23098	/**
23099	 * Setups the current settings.
23100	 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
23101	 * @todo Support for media queries by using `matchMedia` would be nice.
23102	 * @public
23103	 */
23104	Owl.prototype.setup = function() {
23105		var viewport = this.viewport(),
23106			overwrites = this.options.responsive,
23107			match = -1,
23108			settings = null;
23109
23110		if (!overwrites) {
23111			settings = $.extend({}, this.options);
23112		} else {
23113			$.each(overwrites, function(breakpoint) {
23114				if (breakpoint <= viewport && breakpoint > match) {
23115					match = Number(breakpoint);
23116				}
23117			});
23118
23119			settings = $.extend({}, this.options, overwrites[match]);
23120			delete settings.responsive;
23121
23122			// responsive class
23123			if (settings.responsiveClass) {
23124				this.$element.attr('class',
23125					this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
23126				);
23127			}
23128		}
23129
23130		if (this.settings === null || this._breakpoint !== match) {
23131			this.trigger('change', { property: { name: 'settings', value: settings } });
23132			this._breakpoint = match;
23133			this.settings = settings;
23134			this.invalidate('settings');
23135			this.trigger('changed', { property: { name: 'settings', value: this.settings } });
23136		}
23137	};
23138
23139	/**
23140	 * Updates option logic if necessery.
23141	 * @protected
23142	 */
23143	Owl.prototype.optionsLogic = function() {
23144		if (this.settings.autoWidth) {
23145			this.settings.stagePadding = false;
23146			this.settings.merge = false;
23147		}
23148	};
23149
23150	/**
23151	 * Prepares an item before add.
23152	 * @todo Rename event parameter `content` to `item`.
23153	 * @protected
23154	 * @returns {jQuery|HTMLElement} - The item container.
23155	 */
23156	Owl.prototype.prepare = function(item, index) {
23157		var event = this.trigger('prepare', { content: item });
23158		if (!event.data) {
23159			event.data = $('<' + this.settings.itemElement + '/>')
23160				.addClass(this.options.itemClass).attr('data-index', index + 1).append(item)
23161		}
23162
23163		this.trigger('prepared', { content: event.data });
23164
23165		return event.data;
23166	};
23167
23168	/**
23169	 * Updates the view.
23170	 * @public
23171	 */
23172	Owl.prototype.update = function() {
23173		var i = 0,
23174			n = this._pipe.length,
23175			filter = $.proxy(function(p) { return this[p] }, this._invalidated),
23176			cache = {};
23177
23178		while (i < n) {
23179			if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
23180				this._pipe[i].run(cache);
23181			}
23182			i++;
23183		}
23184
23185		this._invalidated = {};
23186
23187		!this.is('valid') && this.enter('valid');
23188	};
23189
23190	/**
23191	 * Gets the width of the view.
23192	 * @public
23193	 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
23194	 * @returns {Number} - The width of the view in pixel.
23195	 */
23196	Owl.prototype.width = function(dimension) {
23197		dimension = dimension || Owl.Width.Default;
23198		var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200;
23199		switch (dimension) {
23200			case Owl.Width.Inner:
23201			case Owl.Width.Outer:
23202				return this._width;
23203			default:
23204				return this._width - stagePadding * 2 + this.settings.margin;
23205		}
23206	};
23207
23208	/**
23209	 * Refreshes the carousel primarily for adaptive purposes.
23210	 * @public
23211	 */
23212	Owl.prototype.refresh = function() {
23213		this.enter('refreshing');
23214		this.trigger('refresh');
23215
23216		this.setup();
23217
23218		this.optionsLogic();
23219
23220		this.$element.addClass(this.options.refreshClass);
23221
23222		this.update();
23223
23224		this.$element.removeClass(this.options.refreshClass);
23225
23226		this.leave('refreshing');
23227		this.trigger('refreshed');
23228	};
23229
23230	/**
23231	 * Checks window `resize` event.
23232	 * @protected
23233	 */
23234	Owl.prototype.onThrottledResize = function() {
23235		window.clearTimeout(this.resizeTimer);
23236		this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
23237	};
23238
23239	/**
23240	 * Checks window `resize` event.
23241	 * @protected
23242	 */
23243	Owl.prototype.onResize = function() {
23244		if (!this._items.length) {
23245			return false;
23246		}
23247
23248		if (this._width === this.$element.width()) {
23249			return false;
23250		}
23251
23252		if (!this.$element.is(':visible')) {
23253			return false;
23254		}
23255
23256		this.enter('resizing');
23257
23258		if (this.trigger('resize').isDefaultPrevented()) {
23259			this.leave('resizing');
23260			return false;
23261		}
23262
23263		this.invalidate('width');
23264
23265		this.refresh();
23266
23267		this.leave('resizing');
23268		this.trigger('resized');
23269	};
23270
23271	/**
23272	 * Registers event handlers.
23273	 * @todo Check `msPointerEnabled`
23274	 * @todo #261
23275	 * @protected
23276	 */
23277	Owl.prototype.registerEventHandlers = function() {
23278		if ($.support.transition) {
23279			this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
23280		}
23281
23282		if (this.settings.responsive !== false) {
23283			this.on(window, 'resize', this._handlers.onThrottledResize);
23284		}
23285
23286		if (this.settings.mouseDrag) {
23287			this.$element.addClass(this.options.dragClass);
23288			this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
23289			this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
23290		}
23291
23292		if (this.settings.touchDrag){
23293			this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
23294			this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
23295		}
23296	};
23297
23298	/**
23299	 * Handles `touchstart` and `mousedown` events.
23300	 * @todo Horizontal swipe threshold as option
23301	 * @todo #261
23302	 * @protected
23303	 * @param {Event} event - The event arguments.
23304	 */
23305	Owl.prototype.onDragStart = function(event) {
23306		var stage = null;
23307
23308		if (event.which === 3) {
23309			return;
23310		}
23311
23312		if ($.support.transform) {
23313			stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
23314			stage = {
23315				x: stage[stage.length === 16 ? 12 : 4],
23316				y: stage[stage.length === 16 ? 13 : 5]
23317			};
23318		} else {
23319			stage = this.$stage.position();
23320			stage = {
23321				x: this.settings.rtl ?
23322					stage.left + this.$stage.width() - this.width() + this.settings.margin :
23323					stage.left,
23324				y: stage.top
23325			};
23326		}
23327
23328		if (this.is('animating')) {
23329			$.support.transform ? this.animate(stage.x) : this.$stage.stop()
23330			this.invalidate('position');
23331		}
23332
23333		this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
23334
23335		this.speed(0);
23336
23337		this._drag.time = new Date().getTime();
23338		this._drag.target = $(event.target);
23339		this._drag.stage.start = stage;
23340		this._drag.stage.current = stage;
23341		this._drag.pointer = this.pointer(event);
23342
23343		$(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
23344
23345		$(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
23346			var delta = this.difference(this._drag.pointer, this.pointer(event));
23347
23348			$(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
23349
23350			if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
23351				return;
23352			}
23353
23354			event.preventDefault();
23355
23356			this.enter('dragging');
23357			this.trigger('drag');
23358		}, this));
23359	};
23360
23361	/**
23362	 * Handles the `touchmove` and `mousemove` events.
23363	 * @todo #261
23364	 * @protected
23365	 * @param {Event} event - The event arguments.
23366	 */
23367	Owl.prototype.onDragMove = function(event) {
23368		var minimum = null,
23369			maximum = null,
23370			pull = null,
23371			delta = this.difference(this._drag.pointer, this.pointer(event)),
23372			stage = this.difference(this._drag.stage.start, delta);
23373
23374		if (!this.is('dragging')) {
23375			return;
23376		}
23377
23378		event.preventDefault();
23379
23380		if (this.settings.loop) {
23381			minimum = this.coordinates(this.minimum());
23382			maximum = this.coordinates(this.maximum() + 1) - minimum;
23383			stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
23384		} else {
23385			minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
23386			maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
23387			pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
23388			stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
23389		}
23390
23391		this._drag.stage.current = stage;
23392
23393		this.animate(stage.x);
23394	};
23395
23396	/**
23397	 * Handles the `touchend` and `mouseup` events.
23398	 * @todo #261
23399	 * @todo Threshold for click event
23400	 * @protected
23401	 * @param {Event} event - The event arguments.
23402	 */
23403	Owl.prototype.onDragEnd = function(event) {
23404		var delta = this.difference(this._drag.pointer, this.pointer(event)),
23405			stage = this._drag.stage.current,
23406			direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
23407
23408		$(document).off('.owl.core');
23409
23410		this.$element.removeClass(this.options.grabClass);
23411
23412		if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
23413			this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
23414			this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
23415			this.invalidate('position');
23416			this.update();
23417
23418			this._drag.direction = direction;
23419
23420			if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
23421				this._drag.target.one('click.owl.core', function() { return false; });
23422			}
23423		}
23424
23425		if (!this.is('dragging')) {
23426			return;
23427		}
23428
23429		this.leave('dragging');
23430		this.trigger('dragged');
23431	};
23432
23433	/**
23434	 * Gets absolute position of the closest item for a coordinate.
23435	 * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
23436	 * @protected
23437	 * @param {Number} coordinate - The coordinate in pixel.
23438	 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
23439	 * @return {Number} - The absolute position of the closest item.
23440	 */
23441	Owl.prototype.closest = function(coordinate, direction) {
23442		var position = -1,
23443			pull = 30,
23444			width = this.width(),
23445			coordinates = this.coordinates();
23446
23447		if (!this.settings.freeDrag) {
23448			// check closest item
23449			$.each(coordinates, $.proxy(function(index, value) {
23450				if (coordinate > value - pull && coordinate < value + pull) {
23451					position = index;
23452				} else if (this.op(coordinate, '<', value)
23453					&& this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
23454					position = direction === 'left' ? index + 1 : index;
23455				}
23456				return position === -1;
23457			}, this));
23458		}
23459
23460		if (!this.settings.loop) {
23461			// non loop boundries
23462			if (this.op(coordinate, '>', coordinates[this.minimum()])) {
23463				position = coordinate = this.minimum();
23464			} else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
23465				position = coordinate = this.maximum();
23466			}
23467		}
23468
23469		return position;
23470	};
23471
23472	/**
23473	 * Animates the stage.
23474	 * @todo #270
23475	 * @public
23476	 * @param {Number} coordinate - The coordinate in pixels.
23477	 */
23478	Owl.prototype.animate = function(coordinate) {
23479		var animate = this.speed() > 0;
23480
23481		this.is('animating') && this.onTransitionEnd();
23482
23483		if (animate) {
23484			this.enter('animating');
23485			this.trigger('translate');
23486		}
23487
23488		if ($.support.transform3d && $.support.transition) {
23489			this.$stage.css({
23490				transform: 'translate3d(' + coordinate + 'px,0px,0px)',
23491				transition: (this.speed() / 1000) + 's'
23492			});
23493		} else if (animate) {
23494			this.$stage.animate({
23495				left: coordinate + 'px'
23496			}, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
23497		} else {
23498			this.$stage.css({
23499				left: coordinate + 'px'
23500			});
23501		}
23502	};
23503
23504	/**
23505	 * Checks whether the carousel is in a specific state or not.
23506	 * @param {String} state - The state to check.
23507	 * @returns {Boolean} - The flag which indicates if the carousel is busy.
23508	 */
23509	Owl.prototype.is = function(state) {
23510		return this._states.current[state] && this._states.current[state] > 0;
23511	};
23512
23513	/**
23514	 * Sets the absolute position of the current item.
23515	 * @public
23516	 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
23517	 * @returns {Number} - The absolute position of the current item.
23518	 */
23519	Owl.prototype.current = function(position) {
23520		if (position === undefined) {
23521			return this._current;
23522		}
23523
23524		if (this._items.length === 0) {
23525			return undefined;
23526		}
23527
23528		position = this.normalize(position);
23529
23530		if (this._current !== position) {
23531			var event = this.trigger('change', { property: { name: 'position', value: position } });
23532
23533			if (event.data !== undefined) {
23534				position = this.normalize(event.data);
23535			}
23536
23537			this._current = position;
23538
23539			this.invalidate('position');
23540
23541			this.trigger('changed', { property: { name: 'position', value: this._current } });
23542		}
23543
23544		return this._current;
23545	};
23546
23547	/**
23548	 * Invalidates the given part of the update routine.
23549	 * @param {String} [part] - The part to invalidate.
23550	 * @returns {Array.<String>} - The invalidated parts.
23551	 */
23552	Owl.prototype.invalidate = function(part) {
23553		if ($.type(part) === 'string') {
23554			this._invalidated[part] = true;
23555			this.is('valid') && this.leave('valid');
23556		}
23557		return $.map(this._invalidated, function(v, i) { return i });
23558	};
23559
23560	/**
23561	 * Resets the absolute position of the current item.
23562	 * @public
23563	 * @param {Number} position - The absolute position of the new item.
23564	 */
23565	Owl.prototype.reset = function(position) {
23566		position = this.normalize(position);
23567
23568		if (position === undefined) {
23569			return;
23570		}
23571
23572		this._speed = 0;
23573		this._current = position;
23574
23575		this.suppress([ 'translate', 'translated' ]);
23576
23577		this.animate(this.coordinates(position));
23578
23579		this.release([ 'translate', 'translated' ]);
23580	};
23581
23582	/**
23583	 * Normalizes an absolute or a relative position of an item.
23584	 * @public
23585	 * @param {Number} position - The absolute or relative position to normalize.
23586	 * @param {Boolean} [relative=false] - Whether the given position is relative or not.
23587	 * @returns {Number} - The normalized position.
23588	 */
23589	Owl.prototype.normalize = function(position, relative) {
23590		var n = this._items.length,
23591			m = relative ? 0 : this._clones.length;
23592
23593		if (!$.isNumeric(position) || n < 1) {
23594			position = undefined;
23595		} else if (position < 0 || position >= n + m) {
23596			position = ((position - m / 2) % n + n) % n + m / 2;
23597		}
23598
23599		return position;
23600	};
23601
23602	/**
23603	 * Converts an absolute position of an item into a relative one.
23604	 * @public
23605	 * @param {Number} position - The absolute position to convert.
23606	 * @returns {Number} - The converted position.
23607	 */
23608	Owl.prototype.relative = function(position) {
23609		position -= this._clones.length / 2;
23610		return this.normalize(position, true);
23611	};
23612
23613	/**
23614	 * Gets the maximum position for the current item.
23615	 * @public
23616	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23617	 * @returns {Number}
23618	 */
23619	Owl.prototype.maximum = function(relative) {
23620		var settings = this.settings,
23621			maximum = this._coordinates.length,
23622			boundary = Math.abs(this._coordinates[maximum - 1]) - this._width,
23623			i = -1, j;
23624
23625		if (settings.loop) {
23626			maximum = this._clones.length / 2 + this._items.length - 1;
23627		} else if (settings.autoWidth || settings.merge) {
23628			// binary search
23629			while (maximum - i > 1) {
23630				Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary
23631					? i = j : maximum = j;
23632			}
23633		} else if (settings.center) {
23634			maximum = this._items.length - 1;
23635		} else {
23636			maximum = this._items.length - settings.items;
23637		}
23638
23639		if (relative) {
23640			maximum -= this._clones.length / 2;
23641		}
23642
23643		return Math.max(maximum, 0);
23644	};
23645
23646	/**
23647	 * Gets the minimum position for the current item.
23648	 * @public
23649	 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
23650	 * @returns {Number}
23651	 */
23652	Owl.prototype.minimum = function(relative) {
23653		return relative ? 0 : this._clones.length / 2;
23654	};
23655
23656	/**
23657	 * Gets an item at the specified relative position.
23658	 * @public
23659	 * @param {Number} [position] - The relative position of the item.
23660	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23661	 */
23662	Owl.prototype.items = function(position) {
23663		if (position === undefined) {
23664			return this._items.slice();
23665		}
23666
23667		position = this.normalize(position, true);
23668		return this._items[position];
23669	};
23670
23671	/**
23672	 * Gets an item at the specified relative position.
23673	 * @public
23674	 * @param {Number} [position] - The relative position of the item.
23675	 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given.
23676	 */
23677	Owl.prototype.mergers = function(position) {
23678		if (position === undefined) {
23679			return this._mergers.slice();
23680		}
23681
23682		position = this.normalize(position, true);
23683		return this._mergers[position];
23684	};
23685
23686	/**
23687	 * Gets the absolute positions of clones for an item.
23688	 * @public
23689	 * @param {Number} [position] - The relative position of the item.
23690	 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given.
23691	 */
23692	Owl.prototype.clones = function(position) {
23693		var odd = this._clones.length / 2,
23694			even = odd + this._items.length,
23695			map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
23696
23697		if (position === undefined) {
23698			return $.map(this._clones, function(v, i) { return map(i) });
23699		}
23700
23701		return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
23702	};
23703
23704	/**
23705	 * Sets the current animation speed.
23706	 * @public
23707	 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
23708	 * @returns {Number} - The current animation speed in milliseconds.
23709	 */
23710	Owl.prototype.speed = function(speed) {
23711		if (speed !== undefined) {
23712			this._speed = speed;
23713		}
23714
23715		return this._speed;
23716	};
23717
23718	/**
23719	 * Gets the coordinate of an item.
23720	 * @todo The name of this method is missleanding.
23721	 * @public
23722	 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
23723	 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates.
23724	 */
23725	Owl.prototype.coordinates = function(position) {
23726		var coordinate = null;
23727
23728		if (position === undefined) {
23729			return $.map(this._coordinates, $.proxy(function(coordinate, index) {
23730				return this.coordinates(index);
23731			}, this));
23732		}
23733
23734		if (this.settings.center) {
23735			coordinate = this._coordinates[position];
23736			coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1);
23737		} else {
23738			coordinate = this._coordinates[position - 1] || 0;
23739		}
23740
23741		return coordinate;
23742	};
23743
23744	/**
23745	 * Calculates the speed for a translation.
23746	 * @protected
23747	 * @param {Number} from - The absolute position of the start item.
23748	 * @param {Number} to - The absolute position of the target item.
23749	 * @param {Number} [factor=undefined] - The time factor in milliseconds.
23750	 * @returns {Number} - The time in milliseconds for the translation.
23751	 */
23752	Owl.prototype.duration = function(from, to, factor) {
23753		return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
23754	};
23755
23756	/**
23757	 * Slides to the specified item.
23758	 * @public
23759	 * @param {Number} position - The position of the item.
23760	 * @param {Number} [speed] - The time in milliseconds for the transition.
23761	 */
23762	Owl.prototype.to = function(position, speed) {
23763		var current = this.current(),
23764			revert = null,
23765			distance = position - this.relative(current),
23766			direction = (distance > 0) - (distance < 0),
23767			items = this._items.length,
23768			minimum = this.minimum(),
23769			maximum = this.maximum();
23770
23771		if (this.settings.loop) {
23772			if (!this.settings.rewind && Math.abs(distance) > items / 2) {
23773				distance += direction * -1 * items;
23774			}
23775
23776			position = current + distance;
23777			revert = ((position - minimum) % items + items) % items + minimum;
23778
23779			if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
23780				current = revert - distance;
23781				position = revert;
23782				this.reset(current);
23783			}
23784		} else if (this.settings.rewind) {
23785			maximum += 1;
23786			position = (position % maximum + maximum) % maximum;
23787		} else {
23788			position = Math.max(minimum, Math.min(maximum, position));
23789		}
23790
23791		this.speed(this.duration(current, position, speed));
23792		this.current(position);
23793
23794		if (this.$element.is(':visible')) {
23795			this.update();
23796		}
23797	};
23798
23799	/**
23800	 * Slides to the next item.
23801	 * @public
23802	 * @param {Number}
vendor: 12,284 bytes, lines 23802-24222
23802 [speed] - The time in milliseconds for the transition.
23803	 */
23804	Owl.prototype.next = function(speed) {
23805		speed = speed || false;
23806		this.to(this.relative(this.current()) + 1, speed);
23807	};
23808
23809	/**
23810	 * Slides to the previous item.
23811	 * @public
23812	 * @param {Number} [speed] - The time in milliseconds for the transition.
23813	 */
23814	Owl.prototype.prev = function(speed) {
23815		speed = speed || false;
23816		this.to(this.relative(this.current()) - 1, speed);
23817	};
23818
23819	/**
23820	 * Handles the end of an animation.
23821	 * @protected
23822	 * @param {Event} event - The event arguments.
23823	 */
23824	Owl.prototype.onTransitionEnd = function(event) {
23825
23826		// if css2 animation then event object is undefined
23827		if (event !== undefined) {
23828			event.stopPropagation();
23829
23830			// Catch only owl-stage transitionEnd event
23831			if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
23832				return false;
23833			}
23834		}
23835
23836		this.leave('animating');
23837		this.trigger('translated');
23838	};
23839
23840	/**
23841	 * Gets viewport width.
23842	 * @protected
23843	 * @return {Number} - The width in pixel.
23844	 */
23845	Owl.prototype.viewport = function() {
23846		var width;
23847		if (this.options.responsiveBaseElement !== window) {
23848			width = $(this.options.responsiveBaseElement).width();
23849		} else if (window.innerWidth) {
23850			width = window.innerWidth;
23851		} else if (document.documentElement && document.documentElement.clientWidth) {
23852			width = document.documentElement.clientWidth;
23853		} else {
23854			throw 'Can not detect viewport width.';
23855		}
23856
23857		return width;
23858	};
23859
23860	/**
23861	 * Replaces the current content.
23862	 * @public
23863	 * @param {HTMLElement|jQuery|String} content - The new content.
23864	 */
23865	Owl.prototype.replace = function(content) {
23866		this.$stage.empty();
23867		this._items = [];
23868
23869		if (content) {
23870			content = (content instanceof jQuery) ? content : $(content);
23871		}
23872
23873		if (this.settings.nestedItemSelector) {
23874			content = content.find('.' + this.settings.nestedItemSelector);
23875		}
23876
23877		content.filter(function() {
23878			return this.nodeType === 1;
23879		}).each($.proxy(function(index, item) {
23880			item = this.prepare(item, index);
23881			this.$stage.append(item);
23882			this._items.push(item);
23883			this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
23884		}, this));
23885
23886		this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
23887
23888		this.invalidate('items');
23889	};
23890
23891	/**
23892	 * Adds an item.
23893	 * @todo Use `item` instead of `content` for the event arguments.
23894	 * @public
23895	 * @param {HTMLElement|jQuery|String} content - The item content to add.
23896	 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
23897	 */
23898	Owl.prototype.add = function(content, position) {
23899		var current = this.relative(this._current);
23900
23901		position = position === undefined ? this._items.length : this.normalize(position, true);
23902		content = content instanceof jQuery ? content : $(content);
23903
23904		this.trigger('add', { content: content, position: position });
23905
23906		content = this.prepare(content, this._items[current].index());
23907
23908		if (this._items.length === 0 || position === this._items.length) {
23909			this._items.length === 0 && this.$stage.append(content);
23910			this._items.length !== 0 && this._items[position - 1].after(content);
23911			this._items.push(content);
23912			this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23913		} else {
23914			this._items[position].before(content);
23915			this._items.splice(position, 0, content);
23916			this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1);
23917		}
23918
23919		this._items[current] && this.reset(this._items[current].index());
23920
23921		this.invalidate('items');
23922
23923		this.trigger('added', { content: content, position: position });
23924	};
23925
23926	/**
23927	 * Removes an item by its position.
23928	 * @todo Use `item` instead of `content` for the event arguments.
23929	 * @public
23930	 * @param {Number} position - The relative position of the item to remove.
23931	 */
23932	Owl.prototype.remove = function(position) {
23933		position = this.normalize(position, true);
23934
23935		if (position === undefined) {
23936			return;
23937		}
23938
23939		this.trigger('remove', { content: this._items[position], position: position });
23940
23941		this._items[position].remove();
23942		this._items.splice(position, 1);
23943		this._mergers.splice(position, 1);
23944
23945		this.invalidate('items');
23946
23947		this.trigger('removed', { content: null, position: position });
23948	};
23949
23950	/**
23951	 * Preloads images with auto width.
23952	 * @todo Replace by a more generic approach
23953	 * @protected
23954	 */
23955	Owl.prototype.preloadAutoWidthImages = function(images) {
23956		images.each($.proxy(function(i, element) {
23957			this.enter('pre-loading');
23958			element = $(element);
23959			$(new Image()).one('load', $.proxy(function(e) {
23960				element.attr('src', e.target.src);
23961				element.css('opacity', 1);
23962				this.leave('pre-loading');
23963				!this.is('pre-loading') && !this.is('initializing') && this.refresh();
23964			}, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
23965		}, this));
23966	};
23967
23968	/**
23969	 * Destroys the carousel.
23970	 * @public
23971	 */
23972	Owl.prototype.destroy = function() {
23973
23974		this.$element.off('.owl.core');
23975		this.$stage.off('.owl.core');
23976		$(document).off('.owl.core');
23977
23978		if (this.settings.responsive !== false) {
23979			window.clearTimeout(this.resizeTimer);
23980			this.off(window, 'resize', this._handlers.onThrottledResize);
23981		}
23982
23983		for (var i in this._plugins) {
23984			this._plugins[i].destroy();
23985		}
23986
23987		this.$stage.children('.cloned').remove();
23988
23989		this.$stage.unwrap();
23990		this.$stage.children().contents().unwrap();
23991		this.$stage.children().unwrap();
23992
23993		this.$element
23994			.removeClass(this.options.refreshClass)
23995			.removeClass(this.options.loadingClass)
23996			.removeClass(this.options.loadedClass)
23997			.removeClass(this.options.rtlClass)
23998			.removeClass(this.options.dragClass)
23999			.removeClass(this.options.grabClass)
24000			.attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
24001			.removeData('owl.carousel');
24002	};
24003
24004	/**
24005	 * Operators to calculate right-to-left and left-to-right.
24006	 * @protected
24007	 * @param {Number} [a] - The left side operand.
24008	 * @param {String} [o] - The operator.
24009	 * @param {Number} [b] - The right side operand.
24010	 */
24011	Owl.prototype.op = function(a, o, b) {
24012		var rtl = this.settings.rtl;
24013		switch (o) {
24014			case '<':
24015				return rtl ? a > b : a < b;
24016			case '>':
24017				return rtl ? a < b : a > b;
24018			case '>=':
24019				return rtl ? a <= b : a >= b;
24020			case '<=':
24021				return rtl ? a >= b : a <= b;
24022			default:
24023				break;
24024		}
24025	};
24026
24027	/**
24028	 * Attaches to an internal event.
24029	 * @protected
24030	 * @param {HTMLElement} element - The event source.
24031	 * @param {String} event - The event name.
24032	 * @param {Function} listener - The event handler to attach.
24033	 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
24034	 */
24035	Owl.prototype.on = function(element, event, listener, capture) {
24036		if (element.addEventListener) {
24037			element.addEventListener(event, listener, capture);
24038		} else if (element.attachEvent) {
24039			element.attachEvent('on' + event, listener);
24040		}
24041	};
24042
24043	/**
24044	 * Detaches from an internal event.
24045	 * @protected
24046	 * @param {HTMLElement} element - The event source.
24047	 * @param {String} event - The event name.
24048	 * @param {Function} listener - The attached event handler to detach.
24049	 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
24050	 */
24051	Owl.prototype.off = function(element, event, listener, capture) {
24052		if (element.removeEventListener) {
24053			element.removeEventListener(event, listener, capture);
24054		} else if (element.detachEvent) {
24055			element.detachEvent('on' + event, listener);
24056		}
24057	};
24058
24059	/**
24060	 * Triggers a public event.
24061	 * @todo Remove `status`, `relatedTarget` should be used instead.
24062	 * @protected
24063	 * @param {String} name - The event name.
24064	 * @param {*} [data=null] - The event data.
24065	 * @param {String} [namespace=carousel] - The event namespace.
24066	 * @param {String} [state] - The state which is associated with the event.
24067	 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
24068	 * @returns {Event} - The event arguments.
24069	 */
24070	Owl.prototype.trigger = function(name, data, namespace, state, enter) {
24071		var status = {
24072			item: { count: this._items.length, index: this.current() }
24073		}, handler = $.camelCase(
24074			$.grep([ 'on', name, namespace ], function(v) { return v })
24075				.join('-').toLowerCase()
24076		), event = $.Event(
24077			[ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
24078			$.extend({ relatedTarget: this }, status, data)
24079		);
24080
24081		if (!this._supress[name]) {
24082			$.each(this._plugins, function(name, plugin) {
24083				if (plugin.onTrigger) {
24084					plugin.onTrigger(event);
24085				}
24086			});
24087
24088			this.register({ type: Owl.Type.Event, name: name });
24089			this.$element.trigger(event);
24090
24091			if (this.settings && typeof this.settings[handler] === 'function') {
24092				this.settings[handler].call(this, event);
24093			}
24094		}
24095
24096		return event;
24097	};
24098
24099	/**
24100	 * Enters a state.
24101	 * @param name - The state name.
24102	 */
24103	Owl.prototype.enter = function(name) {
24104		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24105			if (this._states.current[name] === undefined) {
24106				this._states.current[name] = 0;
24107			}
24108
24109			this._states.current[name]++;
24110		}, this));
24111	};
24112
24113	/**
24114	 * Leaves a state.
24115	 * @param name - The state name.
24116	 */
24117	Owl.prototype.leave = function(name) {
24118		$.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
24119			this._states.current[name]--;
24120		}, this));
24121	};
24122
24123	/**
24124	 * Registers an event or state.
24125	 * @public
24126	 * @param {Object} object - The event or state to register.
24127	 */
24128	Owl.prototype.register = function(object) {
24129		if (object.type === Owl.Type.Event) {
24130			if (!$.event.special[object.name]) {
24131				$.event.special[object.name] = {};
24132			}
24133
24134			if (!$.event.special[object.name].owl) {
24135				var _default = $.event.special[object.name]._default;
24136				$.event.special[object.name]._default = function(e) {
24137					if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
24138						return _default.apply(this, arguments);
24139					}
24140					return e.namespace && e.namespace.indexOf('owl') > -1;
24141				};
24142				$.event.special[object.name].owl = true;
24143			}
24144		} else if (object.type === Owl.Type.State) {
24145			if (!this._states.tags[object.name]) {
24146				this._states.tags[object.name] = object.tags;
24147			} else {
24148				this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
24149			}
24150
24151			this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
24152				return $.inArray(tag, this._states.tags[object.name]) === i;
24153			}, this));
24154		}
24155	};
24156
24157	/**
24158	 * Suppresses events.
24159	 * @protected
24160	 * @param {Array.<String>} events - The events to suppress.
24161	 */
24162	Owl.prototype.suppress = function(events) {
24163		$.each(events, $.proxy(function(index, event) {
24164			this._supress[event] = true;
24165		}, this));
24166	};
24167
24168	/**
24169	 * Releases suppressed events.
24170	 * @protected
24171	 * @param {Array.<String>} events - The events to release.
24172	 */
24173	Owl.prototype.release = function(events) {
24174		$.each(events, $.proxy(function(index, event) {
24175			delete this._supress[event];
24176		}, this));
24177	};
24178
24179	/**
24180	 * Gets unified pointer coordinates from event.
24181	 * @todo #261
24182	 * @protected
24183	 * @param {Event} - The `mousedown` or `touchstart` event.
24184	 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
24185	 */
24186	Owl.prototype.pointer = function(event) {
24187		var result = { x: null, y: null };
24188
24189		event = event.originalEvent || event || window.event;
24190
24191		event = event.touches && event.touches.length ?
24192			event.touches[0] : event.changedTouches && event.changedTouches.length ?
24193				event.changedTouches[0] : event;
24194
24195		if (event.pageX) {
24196			result.x = event.pageX;
24197			result.y = event.pageY;
24198		} else {
24199			result.x = event.clientX;
24200			result.y = event.clientY;
24201		}
24202
24203		return result;
24204	};
24205
24206	/**
24207	 * Gets the difference of two vectors.
24208	 * @todo #261
24209	 * @protected
24210	 * @param {Object} - The first vector.
24211	 * @param {Object} - The second vector.
24212	 * @returns {Object} - The difference.
24213	 */
24214	Owl.prototype.difference = function(first, second) {
24215		return {
24216			x: first.x - second.x,
24217			y: first.y - second.y
24218		};
24219	};
24220
24221	/**
24222	 * The jQuery Plugin for the Owl Carousel
vendor: 32,216 bytes, lines 24223-25505
24223	 * @todo Navigation plugin `next` and `prev`
24224	 * @public
24225	 */
24226	$.fn.owlCarousel = function(option) {
24227		var args = Array.prototype.slice.call(arguments, 1);
24228
24229		return this.each(function() {
24230			var $this = $(this),
24231				data = $this.data('owl.carousel');
24232
24233			if (!data) {
24234				data = new Owl(this, typeof option == 'object' && option);
24235				$this.data('owl.carousel', data);
24236
24237				$.each([
24238					'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
24239				], function(i, event) {
24240					data.register({ type: Owl.Type.Event, name: event });
24241					data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
24242						if (e.namespace && e.relatedTarget !== this) {
24243							this.suppress([ event ]);
24244							data[event].apply(this, [].slice.call(arguments, 1));
24245							this.release([ event ]);
24246						}
24247					}, data));
24248				});
24249			}
24250
24251			if (typeof option == 'string' && option.charAt(0) !== '_') {
24252				data[option].apply(data, args);
24253			}
24254		});
24255	};
24256
24257	/**
24258	 * The constructor for the jQuery Plugin
24259	 * @public
24260	 */
24261	$.fn.owlCarousel.Constructor = Owl;
24262
24263})(window.Zepto || window.jQuery, window, document);
24264
24265/**
24266 * AutoRefresh Plugin
24267 * @version 2.0.0-beta.3
24268 * @author Artus Kolanowski
24269 * @license The MIT License (MIT)
24270 */
24271;(function($, window, document, undefined) {
24272
24273	/**
24274	 * Creates the auto refresh plugin.
24275	 * @class The Auto Refresh Plugin
24276	 * @param {Owl} carousel - The Owl Carousel
24277	 */
24278	var AutoRefresh = function(carousel) {
24279		/**
24280		 * Reference to the core.
24281		 * @protected
24282		 * @type {Owl}
24283		 */
24284		this._core = carousel;
24285
24286		/**
24287		 * Refresh interval.
24288		 * @protected
24289		 * @type {number}
24290		 */
24291		this._interval = null;
24292
24293		/**
24294		 * Whether the element is currently visible or not.
24295		 * @protected
24296		 * @type {Boolean}
24297		 */
24298		this._visible = null;
24299
24300		/**
24301		 * All event handlers.
24302		 * @protected
24303		 * @type {Object}
24304		 */
24305		this._handlers = {
24306			'initialized.owl.carousel': $.proxy(function(e) {
24307				if (e.namespace && this._core.settings.autoRefresh) {
24308					this.watch();
24309				}
24310			}, this)
24311		};
24312
24313		// set default options
24314		this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
24315
24316		// register event handlers
24317		this._core.$element.on(this._handlers);
24318	};
24319
24320	/**
24321	 * Default options.
24322	 * @public
24323	 */
24324	AutoRefresh.Defaults = {
24325		autoRefresh: true,
24326		autoRefreshInterval: 500
24327	};
24328
24329	/**
24330	 * Watches the element.
24331	 */
24332	AutoRefresh.prototype.watch = function() {
24333		if (this._interval) {
24334			return;
24335		}
24336
24337		this._visible = this._core.$element.is(':visible');
24338		this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
24339	};
24340
24341	/**
24342	 * Refreshes the element.
24343	 */
24344	AutoRefresh.prototype.refresh = function() {
24345		if (this._core.$element.is(':visible') === this._visible) {
24346			return;
24347		}
24348
24349		this._visible = !this._visible;
24350
24351		this._core.$element.toggleClass('owl-hidden', !this._visible);
24352
24353		this._visible && (this._core.invalidate('width') && this._core.refresh());
24354	};
24355
24356	/**
24357	 * Destroys the plugin.
24358	 */
24359	AutoRefresh.prototype.destroy = function() {
24360		var handler, property;
24361
24362		window.clearInterval(this._interval);
24363
24364		for (handler in this._handlers) {
24365			this._core.$element.off(handler, this._handlers[handler]);
24366		}
24367		for (property in Object.getOwnPropertyNames(this)) {
24368			typeof this[property] != 'function' && (this[property] = null);
24369		}
24370	};
24371
24372	$.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
24373
24374})(window.Zepto || window.jQuery, window, document);
24375
24376/**
24377 * Lazy Plugin
24378 * @version 2.0.0-beta.3
24379 * @author Bartosz Wojciechowski
24380 * @license The MIT License (MIT)
24381 */
24382;(function($, window, document, undefined) {
24383
24384	/**
24385	 * Creates the lazy plugin.
24386	 * @class The Lazy Plugin
24387	 * @param {Owl} carousel - The Owl Carousel
24388	 */
24389	var Lazy = function(carousel) {
24390
24391		/**
24392		 * Reference to the core.
24393		 * @protected
24394		 * @type {Owl}
24395		 */
24396		this._core = carousel;
24397
24398		/**
24399		 * Already loaded items.
24400		 * @protected
24401		 * @type {Array.<jQuery>}
24402		 */
24403		this._loaded = [];
24404
24405		/**
24406		 * Event handlers.
24407		 * @protected
24408		 * @type {Object}
24409		 */
24410		this._handlers = {
24411			'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) {
24412				if (!e.namespace) {
24413					return;
24414				}
24415
24416				if (!this._core.settings || !this._core.settings.lazyLoad) {
24417					return;
24418				}
24419
24420				if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
24421					var settings = this._core.settings,
24422						n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
24423						i = ((settings.center && n * -1) || 0),
24424						position = ((e.property && e.property.value) || this._core.current()) + i,
24425						clones = this._core.clones().length,
24426						load = $.proxy(function(i, v) { this.load(v) }, this);
24427
24428					while (i++ < n) {
24429						this.load(clones / 2 + this._core.relative(position));
24430						clones && $.each(this._core.clones(this._core.relative(position)), load);
24431						position++;
24432					}
24433				}
24434			}, this)
24435		};
24436
24437		// set the default options
24438		this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
24439
24440		// register event handler
24441		this._core.$element.on(this._handlers);
24442	}
24443
24444	/**
24445	 * Default options.
24446	 * @public
24447	 */
24448	Lazy.Defaults = {
24449		lazyLoad: false
24450	}
24451
24452	/**
24453	 * Loads all resources of an item at the specified position.
24454	 * @param {Number} position - The absolute position of the item.
24455	 * @protected
24456	 */
24457	Lazy.prototype.load = function(position) {
24458		var $item = this._core.$stage.children().eq(position),
24459			$elements = $item && $item.find('.owl-lazy');
24460
24461		if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
24462			return;
24463		}
24464
24465		$elements.each($.proxy(function(index, element) {
24466			var $element = $(element), image,
24467				url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
24468
24469			this._core.trigger('load', { element: $element, url: url }, 'lazy');
24470
24471			if ($element.is('img')) {
24472				$element.one('load.owl.lazy', $.proxy(function() {
24473					$element.css('opacity', 1);
24474					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24475				}, this)).attr('src', url);
24476			} else {
24477				image = new Image();
24478				image.onload = $.proxy(function() {
24479					$element.css({
24480						'background-image': 'url(' + url + ')',
24481						'opacity': '1'
24482					});
24483					this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
24484				}, this);
24485				image.src = url;
24486			}
24487		}, this));
24488
24489		this._loaded.push($item.get(0));
24490	}
24491
24492	/**
24493	 * Destroys the plugin.
24494	 * @public
24495	 */
24496	Lazy.prototype.destroy = function() {
24497		var handler, property;
24498
24499		for (handler in this.handlers) {
24500			this._core.$element.off(handler, this.handlers[handler]);
24501		}
24502		for (property in Object.getOwnPropertyNames(this)) {
24503			typeof this[property] != 'function' && (this[property] = null);
24504		}
24505	};
24506
24507	$.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
24508
24509})(window.Zepto || window.jQuery, window, document);
24510
24511/**
24512 * AutoHeight Plugin
24513 * @version 2.0.0-beta.3
24514 * @author Bartosz Wojciechowski
24515 * @license The MIT License (MIT)
24516 */
24517;(function($, window, document, undefined) {
24518
24519	/**
24520	 * Creates the auto height plugin.
24521	 * @class The Auto Height Plugin
24522	 * @param {Owl} carousel - The Owl Carousel
24523	 */
24524	var AutoHeight = function(carousel) {
24525		/**
24526		 * Reference to the core.
24527		 * @protected
24528		 * @type {Owl}
24529		 */
24530		this._core = carousel;
24531
24532		/**
24533		 * All event handlers.
24534		 * @protected
24535		 * @type {Object}
24536		 */
24537		this._handlers = {
24538			'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
24539				if (e.namespace && this._core.settings.autoHeight) {
24540					this.update();
24541				}
24542			}, this),
24543			'changed.owl.carousel': $.proxy(function(e) {
24544				if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
24545					this.update();
24546				}
24547			}, this),
24548			'loaded.owl.lazy': $.proxy(function(e) {
24549				if (e.namespace && this._core.settings.autoHeight
24550					&& e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
24551					this.update();
24552				}
24553			}, this)
24554		};
24555
24556		// set default options
24557		this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
24558
24559		// register event handlers
24560		this._core.$element.on(this._handlers);
24561	};
24562
24563	/**
24564	 * Default options.
24565	 * @public
24566	 */
24567	AutoHeight.Defaults = {
24568		autoHeight: false,
24569		autoHeightClass: 'owl-height'
24570	};
24571
24572	/**
24573	 * Updates the view.
24574	 */
24575	AutoHeight.prototype.update = function() {
24576		var start = this._core._current,
24577			end = start + this._core.settings.items,
24578			visible = this._core.$stage.children().toArray().slice(start, end);
24579			heights = [],
24580			maxheight = 0;
24581
24582		$.each(visible, function(index, item) {
24583			heights.push($(item).height());
24584		});
24585
24586		maxheight = Math.max.apply(null, heights);
24587
24588		this._core.$stage.parent()
24589			.height(maxheight)
24590			.addClass(this._core.settings.autoHeightClass);
24591	};
24592
24593	AutoHeight.prototype.destroy = function() {
24594		var handler, property;
24595
24596		for (handler in this._handlers) {
24597			this._core.$element.off(handler, this._handlers[handler]);
24598		}
24599		for (property in Object.getOwnPropertyNames(this)) {
24600			typeof this[property] != 'function' && (this[property] = null);
24601		}
24602	};
24603
24604	$.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
24605
24606})(window.Zepto || window.jQuery, window, document);
24607
24608/**
24609 * Video Plugin
24610 * @version 2.0.0-beta.3
24611 * @author Bartosz Wojciechowski
24612 * @license The MIT License (MIT)
24613 */
24614;(function($, window, document, undefined) {
24615
24616	/**
24617	 * Creates the video plugin.
24618	 * @class The Video Plugin
24619	 * @param {Owl} carousel - The Owl Carousel
24620	 */
24621	var Video = function(carousel) {
24622		/**
24623		 * Reference to the core.
24624		 * @protected
24625		 * @type {Owl}
24626		 */
24627		this._core = carousel;
24628
24629		/**
24630		 * Cache all video URLs.
24631		 * @protected
24632		 * @type {Object}
24633		 */
24634		this._videos = {};
24635
24636		/**
24637		 * Current playing item.
24638		 * @protected
24639		 * @type {jQuery}
24640		 */
24641		this._playing = null;
24642
24643		/**
24644		 * All event handlers.
24645		 * @todo The cloned content removale is too late
24646		 * @protected
24647		 * @type {Object}
24648		 */
24649		this._handlers = {
24650			'initialized.owl.carousel': $.proxy(function(e) {
24651				if (e.namespace) {
24652					this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
24653				}
24654			}, this),
24655			'resize.owl.carousel': $.proxy(function(e) {
24656				if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
24657					e.preventDefault();
24658				}
24659			}, this),
24660			'refreshed.owl.carousel': $.proxy(function(e) {
24661				if (e.namespace && this._core.is('resizing')) {
24662					this._core.$stage.find('.cloned .owl-video-frame').remove();
24663				}
24664			}, this),
24665			'changed.owl.carousel': $.proxy(function(e) {
24666				if (e.namespace && e.property.name === 'position' && this._playing) {
24667					this.stop();
24668				}
24669			}, this),
24670			'prepared.owl.carousel': $.proxy(function(e) {
24671				if (!e.namespace) {
24672					return;
24673				}
24674
24675				var $element = $(e.content).find('.owl-video');
24676
24677				if ($element.length) {
24678					$element.css('display', 'none');
24679					this.fetch($element, $(e.content));
24680				}
24681			}, this)
24682		};
24683
24684		// set default options
24685		this._core.options = $.extend({}, Video.Defaults, this._core.options);
24686
24687		// register event handlers
24688		this._core.$element.on(this._handlers);
24689
24690		this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
24691			this.play(e);
24692		}, this));
24693	};
24694
24695	/**
24696	 * Default options.
24697	 * @public
24698	 */
24699	Video.Defaults = {
24700		video: false,
24701		videoHeight: false,
24702		videoWidth: false
24703	};
24704
24705	/**
24706	 * Gets the video ID and the type (YouTube/Vimeo only).
24707	 * @protected
24708	 * @param {jQuery} target - The target containing the video data.
24709	 * @param {jQuery} item - The item containing the video.
24710	 */
24711	Video.prototype.fetch = function(target, item) {
24712		var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube',
24713			id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'),
24714			width = target.attr('data-width') || this._core.settings.videoWidth,
24715			height = target.attr('data-height') || this._core.settings.videoHeight,
24716			url = target.attr('href');
24717
24718		if (url) {
24719			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+)?/);
24720
24721			if (id[3].indexOf('youtu') > -1) {
24722				type = 'youtube';
24723			} else if (id[3].indexOf('vimeo') > -1) {
24724				type = 'vimeo';
24725			} else {
24726				throw new Error('Video URL not supported.');
24727			}
24728			id = id[6];
24729		} else {
24730			throw new Error('Missing video URL.');
24731		}
24732
24733		this._videos[url] = {
24734			type: type,
24735			id: id,
24736			width: width,
24737			height: height
24738		};
24739
24740		item.attr('data-video', url);
24741
24742		this.thumbnail(target, this._videos[url]);
24743	};
24744
24745	/**
24746	 * Creates video thumbnail.
24747	 * @protected
24748	 * @param {jQuery} target - The target containing the video data.
24749	 * @param {Object} info - The video info object.
24750	 * @see `fetch`
24751	 */
24752	Video.prototype.thumbnail = function(target, video) {
24753		var tnLink,
24754			icon,
24755			path,
24756			dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
24757			customTn = target.find('img'),
24758			srcType = 'src',
24759			lazyClass = '',
24760			settings = this._core.settings,
24761			create = function(path) {
24762				icon = '<div class="owl-video-play-icon"></div>';
24763
24764				if (settings.lazyLoad) {
24765					tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>';
24766				} else {
24767					tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>';
24768				}
24769				target.after(tnLink);
24770				target.after(icon);
24771			};
24772
24773		// wrap video content into owl-video-wrapper div
24774		target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>');
24775
24776		if (this._core.settings.lazyLoad) {
24777			srcType = 'data-src';
24778			lazyClass = 'owl-lazy';
24779		}
24780
24781		// custom thumbnail
24782		if (customTn.length) {
24783			create(customTn.attr(srcType));
24784			customTn.remove();
24785			return false;
24786		}
24787
24788		if (video.type === 'youtube') {
24789			path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
24790			create(path);
24791		} else if (video.type === 'vimeo') {
24792			$.ajax({
24793				type: 'GET',
24794				url: '//vimeo.com/api/v2/video/' + video.id + '.json',
24795				jsonp: 'callback',
24796				dataType: 'jsonp',
24797				success: function(data) {
24798					path = data[0].thumbnail_large;
24799					create(path);
24800				}
24801			});
24802		}
24803	};
24804
24805	/**
24806	 * Stops the current video.
24807	 * @public
24808	 */
24809	Video.prototype.stop = function() {
24810		this._core.trigger('stop', null, 'video');
24811		this._playing.find('.owl-video-frame').remove();
24812		this._playing.removeClass('owl-video-playing');
24813		this._playing = null;
24814		this._core.leave('playing');
24815		this._core.trigger('stopped', null, 'video');
24816	};
24817
24818	/**
24819	 * Starts the current video.
24820	 * @public
24821	 * @param {Event} event - The event arguments.
24822	 */
24823	Video.prototype.play = function(event) {
24824		var target = $(event.target),
24825			item = target.closest('.' + this._core.settings.itemClass),
24826			video = this._videos[item.attr('data-video')],
24827			width = video.width || '100%',
24828			height = video.height || this._core.$stage.height(),
24829			html;
24830
24831		if (this._playing) {
24832			return;
24833		}
24834
24835		this._core.enter('playing');
24836		this._core.trigger('play', null, 'video');
24837
24838		item = this._core.items(this._core.relative(item.index()));
24839
24840		this._core.reset(item.index());
24841
24842		if (video.type === 'youtube') {
24843			html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' +
24844				video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>';
24845		} else if (video.type === 'vimeo') {
24846			html = '<iframe src="//player.vimeo.com/video/' + video.id +
24847				'?autoplay=1" width="' + width + '" height="' + height +
24848				'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>';
24849		}
24850
24851		$('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video'));
24852
24853		this._playing = item.addClass('owl-video-playing');
24854	};
24855
24856	/**
24857	 * Checks whether an video is currently in full screen mode or not.
24858	 * @todo Bad style because looks like a readonly method but changes members.
24859	 * @protected
24860	 * @returns {Boolean}
24861	 */
24862	Video.prototype.isInFullScreen = function() {
24863		var element = document.fullscreenElement || document.mozFullScreenElement ||
24864				document.webkitFullscreenElement;
24865
24866		return element && $(element).parent().hasClass('owl-video-frame');
24867	};
24868
24869	/**
24870	 * Destroys the plugin.
24871	 */
24872	Video.prototype.destroy = function() {
24873		var handler, property;
24874
24875		this._core.$element.off('click.owl.video');
24876
24877		for (handler in this._handlers) {
24878			this._core.$element.off(handler, this._handlers[handler]);
24879		}
24880		for (property in Object.getOwnPropertyNames(this)) {
24881			typeof this[property] != 'function' && (this[property] = null);
24882		}
24883	};
24884
24885	$.fn.owlCarousel.Constructor.Plugins.Video = Video;
24886
24887})(window.Zepto || window.jQuery, window, document);
24888
24889/**
24890 * Animate Plugin
24891 * @version 2.0.0-beta.3
24892 * @author Bartosz Wojciechowski
24893 * @license The MIT License (MIT)
24894 */
24895;(function($, window, document, undefined) {
24896
24897	/**
24898	 * Creates the animate plugin.
24899	 * @class The Navigation Plugin
24900	 * @param {Owl} scope - The Owl Carousel
24901	 */
24902	var Animate = function(scope) {
24903		this.core = scope;
24904		this.core.options = $.extend({}, Animate.Defaults, this.core.options);
24905		this.swapping = true;
24906		this.previous = undefined;
24907		this.next = undefined;
24908
24909		this.handlers = {
24910			'change.owl.carousel': $.proxy(function(e) {
24911				if (e.namespace && e.property.name == 'position') {
24912					this.previous = this.core.current();
24913					this.next = e.property.value;
24914				}
24915			}, this),
24916			'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
24917				if (e.namespace) {
24918					this.swapping = e.type == 'translated';
24919				}
24920			}, this),
24921			'translate.owl.carousel': $.proxy(function(e) {
24922				if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
24923					this.swap();
24924				}
24925			}, this)
24926		};
24927
24928		this.core.$element.on(this.handlers);
24929	};
24930
24931	/**
24932	 * Default options.
24933	 * @public
24934	 */
24935	Animate.Defaults = {
24936		animateOut: false,
24937		animateIn: false
24938	};
24939
24940	/**
24941	 * Toggles the animation classes whenever an translations starts.
24942	 * @protected
24943	 * @returns {Boolean|undefined}
24944	 */
24945	Animate.prototype.swap = function() {
24946
24947		if (this.core.settings.items !== 1) {
24948			return;
24949		}
24950
24951		if (!$.support.animation || !$.support.transition) {
24952			return;
24953		}
24954
24955		this.core.speed(0);
24956
24957		var left,
24958			clear = $.proxy(this.clear, this),
24959			previous = this.core.$stage.children().eq(this.previous),
24960			next = this.core.$stage.children().eq(this.next),
24961			incoming = this.core.settings.animateIn,
24962			outgoing = this.core.settings.animateOut;
24963
24964		if (this.core.current() === this.previous) {
24965			return;
24966		}
24967
24968		if (outgoing) {
24969			left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
24970			previous.css( { 'left': left + 'px' } )
24971				.addClass('animated owl-animated-out')
24972				.addClass(outgoing)
24973				.on($.support.animation.end, clear);
24974		}
24975
24976		if (incoming) {
24977			next.addClass('animated owl-animated-in')
24978				.addClass(incoming)
24979				.on($.support.animation.end, clear);
24980		}
24981	};
24982
24983	Animate.prototype.clear = function(e) {
24984		if ($(e.target).hasClass('animated')) {
24985			$(e.target).css( { 'left': '' } )
24986				.removeClass('animated owl-animated-out owl-animated-in')
24987				.removeClass(this.core.settings.animateIn)
24988				.removeClass(this.core.settings.animateOut);
24989			this.core.onTransitionEnd();
24990		}
24991	};
24992
24993	/**
24994	 * Destroys the plugin.
24995	 * @public
24996	 */
24997	Animate.prototype.destroy = function() {
24998		var handler, property;
24999
25000		for (handler in this.handlers) {
25001			this.core.$element.off(handler, this.handlers[handler]);
25002		}
25003		for (property in Object.getOwnPropertyNames(this)) {
25004			typeof this[property] != 'function' && (this[property] = null);
25005		}
25006	};
25007
25008	$.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
25009
25010})(window.Zepto || window.jQuery, window, document);
25011
25012/**
25013 * Autoplay Plugin
25014 * @version 2.0.0-beta.3
25015 * @author Bartosz Wojciechowski
25016 * @author Artus Kolanowski
25017 * @license The MIT License (MIT)
25018 */
25019;(function($, window, document, undefined) {
25020
25021	/**
25022	 * Creates the autoplay plugin.
25023	 * @class The Autoplay Plugin
25024	 * @param {Owl} scope - The Owl Carousel
25025	 */
25026	var Autoplay = function(carousel) {
25027		/**
25028		 * Reference to the core.
25029		 * @protected
25030		 * @type {Owl}
25031		 */
25032		this._core = carousel;
25033
25034		/**
25035		 * The autoplay interval.
25036		 * @type {Number}
25037		 */
25038		this._interval = null;
25039
25040		/**
25041		 * Indicates whenever the autoplay is paused.
25042		 * @type {Boolean}
25043		 */
25044		this._paused = false;
25045
25046		/**
25047		 * All event handlers.
25048		 * @protected
25049		 * @type {Object}
25050		 */
25051		this._handlers = {
25052			'changed.owl.carousel': $.proxy(function(e) {
25053				if (e.namespace && e.property.name === 'settings') {
25054					if (this._core.settings.autoplay) {
25055						this.play();
25056					} else {
25057						this.stop();
25058					}
25059				}
25060			}, this),
25061			'initialized.owl.carousel': $.proxy(function(e) {
25062				if (e.namespace && this._core.settings.autoplay) {
25063					this.play();
25064				}
25065			}, this),
25066			'play.owl.autoplay': $.proxy(function(e, t, s) {
25067				if (e.namespace) {
25068					this.play(t, s);
25069				}
25070			}, this),
25071			'stop.owl.autoplay': $.proxy(function(e) {
25072				if (e.namespace) {
25073					this.stop();
25074				}
25075			}, this),
25076			'mouseover.owl.autoplay': $.proxy(function() {
25077				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25078					this.pause();
25079				}
25080			}, this),
25081			'mouseleave.owl.autoplay': $.proxy(function() {
25082				if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
25083					this.play();
25084				}
25085			}, this)
25086		};
25087
25088		// register event handlers
25089		this._core.$element.on(this._handlers);
25090
25091		// set default options
25092		this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
25093	};
25094
25095	/**
25096	 * Default options.
25097	 * @public
25098	 */
25099	Autoplay.Defaults = {
25100		autoplay: false,
25101		autoplayTimeout: 5000,
25102		autoplayHoverPause: false,
25103		autoplaySpeed: false
25104	};
25105
25106	/**
25107	 * Starts the autoplay.
25108	 * @public
25109	 * @param {Number} [timeout] - The interval before the next animation starts.
25110	 * @param {Number} [speed] - The animation speed for the animations.
25111	 */
25112	Autoplay.prototype.play = function(timeout, speed) {
25113		this._paused = false;
25114
25115		if (this._core.is('rotating')) {
25116			return;
25117		}
25118
25119		this._core.enter('rotating');
25120
25121		this._interval = window.setInterval($.proxy(function() {
25122			if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) {
25123				return;
25124			}
25125			this._core.next(speed || this._core.settings.autoplaySpeed);
25126		}, this), timeout || this._core.settings.autoplayTimeout);
25127	};
25128
25129	/**
25130	 * Stops the autoplay.
25131	 * @public
25132	 */
25133	Autoplay.prototype.stop = function() {
25134		if (!this._core.is('rotating')) {
25135			return;
25136		}
25137
25138		window.clearInterval(this._interval);
25139		this._core.leave('rotating');
25140	};
25141
25142	/**
25143	 * Stops the autoplay.
25144	 * @public
25145	 */
25146	Autoplay.prototype.pause = function() {
25147		if (!this._core.is('rotating')) {
25148			return;
25149		}
25150
25151		this._paused = true;
25152	};
25153
25154	/**
25155	 * Destroys the plugin.
25156	 */
25157	Autoplay.prototype.destroy = function() {
25158		var handler, property;
25159
25160		this.stop();
25161
25162		for (handler in this._handlers) {
25163			this._core.$element.off(handler, this._handlers[handler]);
25164		}
25165		for (property in Object.getOwnPropertyNames(this)) {
25166			typeof this[property] != 'function' && (this[property] = null);
25167		}
25168	};
25169
25170	$.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
25171
25172})(window.Zepto || window.jQuery, window, document);
25173
25174/**
25175 * Navigation Plugin
25176 * @version 2.0.0-beta.3
25177 * @author Artus Kolanowski
25178 * @license The MIT License (MIT)
25179 */
25180;(function($, window, document, undefined) {
25181	'use strict';
25182
25183	/**
25184	 * Creates the navigation plugin.
25185	 * @class The Navigation Plugin
25186	 * @param {Owl} carousel - The Owl Carousel.
25187	 */
25188	var Navigation = function(carousel) {
25189		/**
25190		 * Reference to the core.
25191		 * @protected
25192		 * @type {Owl}
25193		 */
25194		this._core = carousel;
25195
25196		/**
25197		 * Indicates whether the plugin is initialized or not.
25198		 * @protected
25199		 * @type {Boolean}
25200		 */
25201		this._initialized = false;
25202
25203		/**
25204		 * The current paging indexes.
25205		 * @protected
25206		 * @type {Array}
25207		 */
25208		this._pages = [];
25209
25210		/**
25211		 * All DOM elements of the user interface.
25212		 * @protected
25213		 * @type {Object}
25214		 */
25215		this._controls = {};
25216
25217		/**
25218		 * Markup for an indicator.
25219		 * @protected
25220		 * @type {Array.<String>}
25221		 */
25222		this._templates = [];
25223
25224		/**
25225		 * The carousel element.
25226		 * @type {jQuery}
25227		 */
25228		this.$element = this._core.$element;
25229
25230		/**
25231		 * Overridden methods of the carousel.
25232		 * @protected
25233		 * @type {Object}
25234		 */
25235		this._overrides = {
25236			next: this._core.next,
25237			prev: this._core.prev,
25238			to: this._core.to
25239		};
25240
25241		/**
25242		 * All event handlers.
25243		 * @protected
25244		 * @type {Object}
25245		 */
25246		this._handlers = {
25247			'prepared.owl.carousel': $.proxy(function(e) {
25248				if (e.namespace && this._core.settings.dotsData) {
25249					this._templates.push('<div class="' + this._core.settings.dotClass + '">' +
25250						$(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>');
25251				}
25252			}, this),
25253			'added.owl.carousel': $.proxy(function(e) {
25254				if (e.namespace && this._core.settings.dotsData) {
25255					this._templates.splice(e.position, 0, this._templates.pop());
25256				}
25257			}, this),
25258			'remove.owl.carousel': $.proxy(function(e) {
25259				if (e.namespace && this._core.settings.dotsData) {
25260					this._templates.splice(e.position, 1);
25261				}
25262			}, this),
25263			'changed.owl.carousel': $.proxy(function(e) {
25264				if (e.namespace && e.property.name == 'position') {
25265					this.draw();
25266				}
25267			}, this),
25268			'initialized.owl.carousel': $.proxy(function(e) {
25269				if (e.namespace && !this._initialized) {
25270					this._core.trigger('initialize', null, 'navigation');
25271					this.initialize();
25272					this.update();
25273					this.draw();
25274					this._initialized = true;
25275					this._core.trigger('initialized', null, 'navigation');
25276				}
25277			}, this),
25278			'refreshed.owl.carousel': $.proxy(function(e) {
25279				if (e.namespace && this._initialized) {
25280					this._core.trigger('refresh', null, 'navigation');
25281					this.update();
25282					this.draw();
25283					this._core.trigger('refreshed', null, 'navigation');
25284				}
25285			}, this)
25286		};
25287
25288		// set default options
25289		this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
25290
25291		// register event handlers
25292		this.$element.on(this._handlers);
25293	};
25294
25295	/**
25296	 * Default options.
25297	 * @public
25298	 * @todo Rename `slideBy` to `navBy`
25299	 */
25300	Navigation.Defaults = {
25301		nav: false,
25302		navText: [ 'prev', 'next' ],
25303		navSpeed: false,
25304		navElement: 'div',
25305		navContainer: false,
25306		navContainerClass: 'owl-nav',
25307		navClass: [ 'owl-prev', 'owl-next' ],
25308		slideBy: 1,
25309		dotClass: 'owl-dot',
25310		dotsClass: 'owl-dots',
25311		dots: true,
25312		dotsEach: false,
25313		dotsData: false,
25314		dotsSpeed: false,
25315		dotsContainer: false
25316	};
25317
25318	/**
25319	 * Initializes the layout of the plugin and extends the carousel.
25320	 * @protected
25321	 */
25322	Navigation.prototype.initialize = function() {
25323		var override,
25324			settings = this._core.settings;
25325
25326		// create DOM structure for relative navigation
25327		this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
25328			: $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
25329
25330		this._controls.$previous = $('<' + settings.navElement + '>')
25331			.addClass(settings.navClass[0])
25332			.html(settings.navText[0])
25333			.prependTo(this._controls.$relative)
25334			.on('click', $.proxy(function(e) {
25335				this.prev(settings.navSpeed);
25336			}, this));
25337		this._controls.$next = $('<' + settings.navElement + '>')
25338			.addClass(settings.navClass[1])
25339			.html(settings.navText[1])
25340			.appendTo(this._controls.$relative)
25341			.on('click', $.proxy(function(e) {
25342				this.next(settings.navSpeed);
25343			}, this));
25344
25345		// create DOM structure for absolute navigation
25346		if (!settings.dotsData) {
25347			this._templates = [ $('<div>')
25348				.addClass(settings.dotClass)
25349				.append($('<span>'))
25350				.prop('outerHTML') ];
25351		}
25352
25353		this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer)
25354			: $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled');
25355
25356		this._controls.$absolute.on('click', 'div', $.proxy(function(e) {
25357			var index = $(e.target).parent().is(this._controls.$absolute)
25358				? $(e.target).index() : $(e.target).parent().index();
25359
25360			e.preventDefault();
25361
25362			this.to(index, settings.dotsSpeed);
25363		}, this));
25364
25365		// override public methods of the carousel
25366		for (override in this._overrides) {
25367			this._core[override] = $.proxy(this[override], this);
25368		}
25369	};
25370
25371	/**
25372	 * Destroys the plugin.
25373	 * @protected
25374	 */
25375	Navigation.prototype.destroy = function() {
25376		var handler, control, property, override;
25377
25378		for (handler in this._handlers) {
25379			this.$element.off(handler, this._handlers[handler]);
25380		}
25381		for (control in this._controls) {
25382			this._controls[control].remove();
25383		}
25384		for (override in this.overides) {
25385			this._core[override] = this._overrides[override];
25386		}
25387		for (property in Object.getOwnPropertyNames(this)) {
25388			typeof this[property] != 'function' && (this[property] = null);
25389		}
25390	};
25391
25392	/**
25393	 * Updates the internal state.
25394	 * @protected
25395	 */
25396	Navigation.prototype.update = function() {
25397		var i, j, k,
25398			lower = this._core.clones().length / 2,
25399			upper = lower + this._core.items().length,
25400			maximum = this._core.maximum(true),
25401			settings = this._core.settings,
25402			size = settings.center || settings.autoWidth || settings.dotsData
25403				? 1 : settings.dotsEach || settings.items;
25404
25405		if (settings.slideBy !== 'page') {
25406			settings.slideBy = Math.min(settings.slideBy, settings.items);
25407		}
25408
25409		if (settings.dots || settings.slideBy == 'page') {
25410			this._pages = [];
25411
25412			for (i = lower, j = 0, k = 0; i < upper; i++) {
25413				if (j >= size || j === 0) {
25414					this._pages.push({
25415						start: Math.min(maximum, i - lower),
25416						end: i - lower + size - 1
25417					});
25418					if (Math.min(maximum, i - lower) === maximum) {
25419						break;
25420					}
25421					j = 0, ++k;
25422				}
25423				j += this._core.mergers(this._core.relative(i));
25424			}
25425		}
25426	};
25427
25428	/**
25429	 * Draws the user interface.
25430	 * @todo The option `dotsData` wont work.
25431	 * @protected
25432	 */
25433	Navigation.prototype.draw = function() {
25434		var difference,
25435			settings = this._core.settings,
25436			disabled = this._core.items().length <= settings.items,
25437			index = this._core.relative(this._core.current()),
25438			loop = settings.loop || settings.rewind;
25439
25440		this._controls.$relative.toggleClass('disabled', !settings.nav || disabled);
25441
25442		if (settings.nav) {
25443			this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true));
25444			this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true));
25445		}
25446
25447		this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled);
25448
25449		if (settings.dots) {
25450			difference = this._pages.length - this._controls.$absolute.children().length;
25451
25452			if (settings.dotsData && difference !== 0) {
25453				this._controls.$absolute.html(this._templates.join(''));
25454			} else if (difference > 0) {
25455				this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0]));
25456			} else if (difference < 0) {
25457				this._controls.$absolute.children().slice(difference).remove();
25458			}
25459
25460			this._controls.$absolute.find('.active').removeClass('active');
25461			this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active');
25462		}
25463	};
25464
25465	/**
25466	 * Extends event data.
25467	 * @protected
25468	 * @param {Event} event - The event object which gets thrown.
25469	 */
25470	Navigation.prototype.onTrigger = function(event) {
25471		var settings = this._core.settings;
25472
25473		event.page = {
25474			index: $.inArray(this.current(), this._pages),
25475			count: this._pages.length,
25476			size: settings && (settings.center || settings.autoWidth || settings.dotsData
25477				? 1 : settings.dotsEach || settings.items)
25478		};
25479	};
25480
25481	/**
25482	 * Gets the current page position of the carousel.
25483	 * @protected
25484	 * @returns {Number}
25485	 */
25486	Navigation.prototype.current = function() {
25487		var current = this._core.relative(this._core.current());
25488		return $.grep(this._pages, $.proxy(function(page, index) {
25489			return page.start <= current && page.end >= current;
25490		}, this)).pop();
25491	};
25492
25493	/**
25494	 * Gets the current succesor/predecessor position.
25495	 * @protected
25496	 * @returns {Number}
25497	 */
25498	Navigation.prototype.getPosition = function(successor) {
25499		var position, length,
25500			settings = this._core.settings;
25501
25502		if (settings.slideBy == 'page') {
25503			position = $.inArray(this.current(), this._pages);
25504			length = this._pages.length;
25505			successor ? ++position : --position;
vendor: 5,674 bytes, lines 25506-25730
25506			position = this._pages[((position % length) + length) % length].start;
25507		} else {
25508			position = this._core.relative(this._core.current());
25509			length = this._core.items().length;
25510			successor ? position += settings.slideBy : position -= settings.slideBy;
25511		}
25512
25513		return position;
25514	};
25515
25516	/**
25517	 * Slides to the next item or page.
25518	 * @public
25519	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25520	 */
25521	Navigation.prototype.next = function(speed) {
25522		$.proxy(this._overrides.to, this._core)(this.getPosition(true), speed);
25523	};
25524
25525	/**
25526	 * Slides to the previous item or page.
25527	 * @public
25528	 * @param {Number} [speed=false] - The time in milliseconds for the transition.
25529	 */
25530	Navigation.prototype.prev = function(speed) {
25531		$.proxy(this._overrides.to, this._core)(this.getPosition(false), speed);
25532	};
25533
25534	/**
25535	 * Slides to the specified item or page.
25536	 * @public
25537	 * @param {Number} position - The position of the item or page.
25538	 * @param {Number} [speed] - The time in milliseconds for the transition.
25539	 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not.
25540	 */
25541	Navigation.prototype.to = function(position, speed, standard) {
25542		var length;
25543
25544		if (!standard) {
25545			length = this._pages.length;
25546			$.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed);
25547		} else {
25548			$.proxy(this._overrides.to, this._core)(position, speed);
25549		}
25550	};
25551
25552	$.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation;
25553
25554})(window.Zepto || window.jQuery, window, document);
25555
25556/**
25557 * Hash Plugin
25558 * @version 2.0.0-beta.3
25559 * @author Artus Kolanowski
25560 * @license The MIT License (MIT)
25561 */
25562;(function($, window, document, undefined) {
25563	'use strict';
25564
25565	/**
25566	 * Creates the hash plugin.
25567	 * @class The Hash Plugin
25568	 * @param {Owl} carousel - The Owl Carousel
25569	 */
25570	var Hash = function(carousel) {
25571		/**
25572		 * Reference to the core.
25573		 * @protected
25574		 * @type {Owl}
25575		 */
25576		this._core = carousel;
25577
25578		/**
25579		 * Hash index for the items.
25580		 * @protected
25581		 * @type {Object}
25582		 */
25583		this._hashes = {};
25584
25585		/**
25586		 * The carousel element.
25587		 * @type {jQuery}
25588		 */
25589		this.$element = this._core.$element;
25590
25591		/**
25592		 * All event handlers.
25593		 * @protected
25594		 * @type {Object}
25595		 */
25596		this._handlers = {
25597			'initialized.owl.carousel': $.proxy(function(e) {
25598				if (e.namespace && this._core.settings.startPosition === 'URLHash') {
25599					$(window).trigger('hashchange.owl.navigation');
25600				}
25601			}, this),
25602			'prepared.owl.carousel': $.proxy(function(e) {
25603				if (e.namespace) {
25604					var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash');
25605
25606					if (!hash) {
25607						return;
25608					}
25609
25610					this._hashes[hash] = e.content;
25611				}
25612			}, this),
25613			'changed.owl.carousel': $.proxy(function(e) {
25614				if (e.namespace && e.property.name === 'position') {
25615					var current = this._core.items(this._core.relative(this._core.current())),
25616						hash = $.map(this._hashes, function(item, hash) {
25617							return item === current ? hash : null;
25618						}).join();
25619
25620					if (!hash || window.location.hash.slice(1) === hash) {
25621						return;
25622					}
25623
25624					window.location.hash = hash;
25625				}
25626			}, this)
25627		};
25628
25629		// set default options
25630		this._core.options = $.extend({}, Hash.Defaults, this._core.options);
25631
25632		// register the event handlers
25633		this.$element.on(this._handlers);
25634
25635		// register event listener for hash navigation
25636		/*$(window).on('hashchange.owl.navigation', $.proxy(function(e) {
25637			var hash = window.location.hash.substring(1),
25638				items = this._core.$stage.children(),
25639				position = this._hashes[hash] && items.index(this._hashes[hash]);
25640
25641			if (position === undefined || position === this._core.current()) {
25642				return;
25643			}
25644
25645			this._core.to(this._core.relative(position), false, true);
25646		}, this));*/
25647	};
25648
25649	/**
25650	 * Default options.
25651	 * @public
25652	 */
25653	Hash.Defaults = {
25654		URLhashListener: false
25655	};
25656
25657	/**
25658	 * Destroys the plugin.
25659	 * @public
25660	 */
25661	Hash.prototype.destroy = function() {
25662		var handler, property;
25663
25664		$(window).off('hashchange.owl.navigation');
25665
25666		for (handler in this._handlers) {
25667			this._core.$element.off(handler, this._handlers[handler]);
25668		}
25669		for (property in Object.getOwnPropertyNames(this)) {
25670			typeof this[property] != 'function' && (this[property] = null);
25671		}
25672	};
25673
25674	$.fn.owlCarousel.Constructor.Plugins.Hash = Hash;
25675
25676})(window.Zepto || window.jQuery, window, document);
25677
25678/**
25679 * Support Plugin
25680 *
25681 * @version 2.0.0-beta.3
25682 * @author Vivid Planet Software GmbH
25683 * @author Artus Kolanowski
25684 * @license The MIT License (MIT)
25685 */
25686;(function($, window, document, undefined) {
25687
25688	var style = $('<support>').get(0).style,
25689		prefixes = 'Webkit Moz O ms'.split(' '),
25690		events = {
25691			transition: {
25692				end: {
25693					WebkitTransition: 'webkitTransitionEnd',
25694					MozTransition: 'transitionend',
25695					OTransition: 'oTransitionEnd',
25696					transition: 'transitionend'
25697				}
25698			},
25699			animation: {
25700				end: {
25701					WebkitAnimation: 'webkitAnimationEnd',
25702					MozAnimation: 'animationend',
25703					OAnimation: 'oAnimationEnd',
25704					animation: 'animationend'
25705				}
25706			}
25707		},
25708		tests = {
25709			csstransforms: function() {
25710				return !!test('transform');
25711			},
25712			csstransforms3d: function() {
25713				return !!test('perspective');
25714			},
25715			csstransitions: function() {
25716				return !!test('transition');
25717			},
25718			cssanimations: function() {
25719				return !!test('animation');
25720			}
25721		};
25722
25723	function test(property, prefixed) {
25724		var result = false,
25725			upper = property.charAt(0).toUpperCase() + property.slice(1);
25726
25727		$.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) {
25728			if (style[property] !== undefined) {
25729				result = prefixed ? property : true;
25730				return false;
25731			}
25732		});
25733
25734		return result;
25735	}
25736
25737	function prefixed(property) {
25738		return test(property, true);
25739	}
25740
25741	if (tests.csstransitions()) {
25742		/* jshint -W053 */
25743		$.support.transition = new String(prefixed('transition'))
25744		$.support.transition.end = events.transition.end[ $.support.transition ];
25745	}
25746
25747	if (tests.cssanimations()) {
25748		/* jshint -W053 */
25749		$.support.animation = new String(prefixed('animation'))
25750		$.support.animation.end = events.animation.end[ $.support.animation ];
25751	}
25752
25753	if (tests.csstransforms()) {
25754		/* jshint -W053 */
25755		$.support.transform = new String(prefixed('transform'));
25756		$.support.transform3d = tests.csstransforms3d();
25757	}
25758
25759})(window.Zepto || window.jQuery, window, document);
25760
25761(function(window, document, undefined) {
25762
25763	/**
25764	 * Find the absolute position of an element
25765	 */
25766	var absPos = function(element) {
25767		var offsetLeft, offsetTop;
25768		offsetLeft = offsetTop = 0;
25769		if (element.offsetParent) {
25770			do {
25771				offsetLeft += element.offsetLeft;
25772				offsetTop += element.offsetTop;
25773			} while (element = element.offsetParent);
25774		}
25775		return [offsetLeft, offsetTop];
25776	};
25777
25778	/**
25779	 * @constructor Progress Circle class
25780	 * @param params.canvas Canvas on which the circles will be drawn.
25781	 * @param params.minRadius Inner radius of the innermost circle, in px.
25782	 * @param params.arcWidth Width of each circle(to be more accurate, ring).
25783	 * @param params.gapWidth Space between each circle.
25784	 * @param params.centerX X coordinate of the center of circles.
25785	 * @param params.centerY Y coordinate of the center of circles.
25786	 * @param params.infoLineBaseAngle Base angle of the info line.
25787	 * @param params.infoLineAngleInterval Angles between the info lines.
25788	 */
25789	var ProgressCircle = function(params) {
25790		this.canvas = params.canvas;
25791		this.minRadius = params.minRadius || 15;
25792		this.arcWidth = params.arcWidth || 5;
25793		this.gapWidth = params.gapWidth || 3;
25794		this.centerX = params.centerX || this.canvas.width / 2;
25795		this.centerY = params.centerY || this.canvas.height / 2;
25796		this.infoLineLength = params.infoLineLength || 60;
25797		this.horizLineLength = params.horizLineLength || 10;
25798		this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8;
25799		this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6;
25800
25801		this.context = this.canvas.getContext('2d');
25802
25803		this.width = this.canvas.width;
25804		this.height = this.canvas.height;
25805
25806		this.circles = [];
25807		this.runningCount = 0;
25808	};
25809
25810	ProgressCircle.prototype = {
25811		constructor: ProgressCircle,
25812
25813		/**
25814		 * @method Adds an progress monitor entry.
25815		 * @param params.fillColor Color to fill in the circle.
25816		 * @param params.outlineColor Color to outline the circle.
25817		 * @param params.progressListener Callback function to fetch the progress.
25818		 * @param params.infoListener Callback function to fetch the info.
25819		 * @returns this
25820		 */
25821		addEntry: function(params) {
25822			this.circles.push(new Circle({
25823				canvas: this.canvas,
25824				context: this.context,
25825				centerX: this.centerX,
25826				centerY: this.centerY,
25827				innerRadius: this.minRadius + this.circles.length *
25828					(this.gapWidth + this.arcWidth),
25829				arcWidth: this.arcWidth,
25830				infoLineLength: this.infoLineLength,
25831				horizLineLength: this.horizLineLength,
25832
25833				id: this.circles.length,
25834				fillColor: params.fillColor,
25835				outlineColor: params.outlineColor,
25836				progressListener: params.progressListener,
25837				infoListener: params.infoListener,
25838				infoLineAngle: this.infoLineBaseAngle +
25839					this.circles.length * this.infoLineAngleInterval,
25840			}));
25841
25842			return this;
25843		},
25844
25845		/**
25846		 * @method Starts the monitor and updates with the given interval.
25847		 * @param interval Interval between updates, in millisecond.
25848		 * @returns this
25849		 */
25850		start: function(interval) {
25851			var self = this;
25852			this.timer = setInterval(function() {
25853				self._update();
25854			}, interval || 33);
25855
25856			return this;
25857		},
25858
25859		/**
25860		 * @method Stop the animation.
25861		 */
25862		stop: function() {
25863			clearTimeout(this.timer);
25864		},
25865
25866		/**
25867		 * @private
25868		 * @method Call update on each circle and redraw them.
25869		 * @returns this
25870		 */
25871		_update: function() {
25872			this._clear();
25873			this.circles.forEach(function(circle, idx, array) {
25874				circle.update();
25875			});
25876
25877			return this;
25878		},
25879
25880		/**
25881		 * @private
25882		 * @method Clear the canvas.
25883		 * @returns this
25884		 */
25885		_clear: function() {
25886			this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
25887
25888			return this;
25889		},
25890
25891	};
25892
25893	/**
25894	 * @private
25895	 * @class Individual progress circle.
25896	 * @param params.canvas Canvas on which the circle will be drawn.
25897	 * @param params.context Context of the canvas.
25898	 * @param params.innerRadius Inner radius of the circle, in px.
25899	 * @param params.arcWidth Width of each arc(circle).
25900	 * @param params.gapWidth Distance between each arc.
25901	 * @param params.centerX X coordinate of the center of circles.
25902	 * @param params.centerY Y coordinate of the center of circles.
25903	 * @param params.fillColor Color to fill in the circle.
25904	 * @param params.outlineColor Color to outline the circle.
25905	 * @param params.progressListener Callback function to fetch the progress.
25906	 * @param params.infoListener Callback function to fetch the info.
25907	 * @param params.infoLineAngle Angle of info line.
25908	 */
25909	var Circle = function(params) {
25910		this.id = params.id;
25911		this.canvas = params.canvas;
25912		this.context = params.context;
25913		this.centerX = params.centerX;
25914		this.centerY = params.centerY;
25915		this.arcWidth = params.arcWidth;
25916		this.innerRadius = params.innerRadius || 0;
25917		this.fillColor = params.fillColor || '#fff';
25918		this.outlineColor = params.outlineColor || this.fillColor;
25919		this.progressListener = params.progressListener;
25920		this.infoLineLength = params.infoLineLength || 250;
25921		this.horizLineLength = params.horizLineLength || 50;
25922		this.infoListener = params.infoListener;
25923		this.infoLineAngle = params.infoLineAngle;
25924
25925		this.outerRadius = this.innerRadius + this.arcWidth;
25926
25927		// If the info listener is not registered, then don't calculate
25928		// the related coordinates
25929		if (!this.infoListener) return;
25930
25931		// calculate the info-line turning points
25932		var angle = this.infoLineAngle,
25933			arcDistance = (this.innerRadius + this.outerRadius) / 2,
25934
25935			sinA = Math.sin(angle),
25936			cosA = Math.cos(angle);
25937
25938		this.infoLineStartX = this.centerX + sinA * arcDistance;
25939		this.infoLineStartY = this.centerY - cosA * arcDistance;
25940
25941		this.infoLineMidX = this.centerX + sinA * this.infoLineLength;
25942		this.infoLineMidY = this.centerY - cosA * this.infoLineLength;
25943
25944		this.infoLineEndX = this.infoLineMidX +
25945			 (sinA < 0 ? -this.horizLineLength : this.horizLineLength);
25946		this.infoLineEndY = this.infoLineMidY;
25947
25948		var infoText = document.createElement('div'),
25949			style = infoText.style;
25950
25951		style.color = this.fillColor;
25952		style.position = 'absolute';
25953		style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px';
25954		// style.top will be calculated in the `drawInfo` method. Since
25955		// user may want to change the size of the font, so the top offset
25956		// must be updated in each loop.
25957		infoText.className = 'ProgressCircleInfo'; // For css styling
25958		infoText.id = 'progress_circle_info_' + this.id;
25959		document.body.appendChild(infoText);
25960		this.infoText = infoText;
25961	};
25962
25963	Circle.prototype = {
25964		constructor: Circle,
25965
25966		update: function() {
25967			this.progress = this.progressListener();
25968			this._draw();
25969
25970			if (this.infoListener) {
25971				this.info = this.infoListener();
25972				this._drawInfo();
25973			}
25974		},
25975
25976		/**
25977		 * @private
25978		 * @method Draw the circle on the canvas.
25979		 * @returns this
25980		 */
25981		_draw: function() {
25982			var ctx = this.context,
25983
25984				ANGLE_OFFSET = -Math.PI / 2,
25985
25986				startAngle = 0 + ANGLE_OFFSET,
25987				endAngle= startAngle + this.progress * Math.PI * 2,
25988
25989				x = this.centerX,
25990				y = this.centerY,
25991
25992				innerRadius = this.innerRadius - this.arcWidth - 1,
25993				outerRadius = this.outerRadius - this.arcWidth - 1;
25994
25995			if ( innerRadius < 0 )
25996				return;
25997
25998			ctx.fillStyle = this.fillColor;
25999			ctx.strokeStyle = this.outlineColor;
26000
26001			ctx.beginPath();
26002			ctx.arc(x, y, innerRadius, startAngle, endAngle, false);
26003			ctx.arc(x, y, outerRadius, endAngle, startAngle, true);
26004			ctx.closePath();
26005			ctx.stroke();
26006			ctx.fill();
26007
26008			return this;
26009		},
26010
26011		/**
26012		 * @private
26013		 * @method Draw the info lines and info text.
26014		 * @returns this
26015		 */
26016		_drawInfo: function() {
26017
26018			var pointList, lineHeight;
26019
26020			pointList = [
26021				[this.infoLineStartX, this.infoLineStartY],
26022				[this.infoLineMidX, this.infoLineMidY],
26023				[this.infoLineEndX, this.infoLineEndY],
26024			];
26025			this._drawSegments(pointList, false);
26026
26027			this.infoText.innerHTML = this.info;
26028
26029			lineHeight = this.infoText.offsetHeight;
26030			this.infoText.style.top = this.infoLineEndY +
26031				absPos(this.canvas)[1] - lineHeight / 2 + 'px';
26032
26033			return this;
26034		},
26035
26036		/**
26037		 * @private
26038		 * @method Helper function to draw the segments
26039		 * @param pointList An array of points in the form of [x, y].
26040		 * @param close Whether to connect the first and last point.
26041		 */
26042		_drawSegments: function(pointList, close) {
26043			var ctx = this.context;
26044
26045			ctx.beginPath();
26046			ctx.moveTo(pointList[0][0], pointList[0][1]);
26047			for (var i = 1; i < pointList.length; ++i) {
26048				ctx.lineTo(pointList[i][0], pointList[i][1]);
26049			}
26050
26051			if (close) {
26052				ctx.closePath();
26053			}
26054			ctx.stroke();
26055		},
26056	};
26057
26058	window.ProgressCircle = ProgressCircle;
26059
26060})(window, document);
26061
26062
26063
26064
26065/* =========================================================
26066 * jquery.vc_chart.js v1.0
26067 * =========================================================
26068 * Copyright 2013 Wpbakery
26069 *
26070 * Jquery chart plugin for the Visual Composer.
26071 * ========================================================= */
26072(function($){
26073	/**
26074	 * Pie chart animated.
26075	 * @param element - DOM element
26076	 * @param options - settings object.
26077	 * @constructor
26078	 */
26079	var VcChart = function(element, options) {
26080		this.el = element;
26081		this.$el = $(this.el);
26082		var $this = this;
26083		$this.options = $.extend({
26084			color: 'wpb_button',
26085			units: '',
26086			width: '',
26087			label_selector: '.vc_pie_chart_value',
26088			back_selector: '.vc_pie_chart_back',
26089			responsive: true
26090		}, options);
26091		$this.init();
26092	};
26093	VcChart.prototype = {
26094		constructor: VcChart,
26095		_progress_v: 0,
26096		animated: false,
26097		colors: {
26098			'wpb_button': 'rgba(247, 247, 247, 1)',
26099			'btn-primary': 'rgba(0, 136, 204, 1)',
26100			'btn-info': 'rgba(88, 185, 218, 1)',
26101			'btn-success': 'rgba(106, 177, 101, 1)',
26102			'btn-warning': 'rgba(255, 153, 0, 1)',
26103			'btn-danger': 'rgba(255, 103, 91, 1)',
26104			'btn-inverse': 'rgba(85, 85, 85, 1)'
26105		},
26106		init: function() {
26107			this.setupColor();
26108			this.value = this.$el.data('pie-value')/100;
26109			this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value');
26110			this.$wrapper = $('.vc_pie_wrapper', this.$el);
26111			this.$label = $(this.options.label_selector, this.$el);
26112			this.$back = $(this.options.back_selector, this.$el);
26113			this.$canvas = this.$el.find('canvas');
26114			this.arcWidth = this.$el.data('pie-width') * 2;
26115			this.draw();
26116			this.setWayPoint();
26117			if(this.options.responsive === true) this.setResponsive();
26118			if (UNCODE.isMobile) this._progress_v = this.value;
26119		},
26120		setupColor: function() {
26121			// if(typeof this.colors[this.options.color] !== 'undefined') {
26122			//     this.color = this.colors[this.options.color];
26123			// } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) {
26124			//     this.color = this.options.color;
26125			// } else {
26126			//     this.color = 'rgba(247, 247, 247, 0.2)';
26127			// }
26128			if(typeof this.options.color !== 'undefined') {
26129				this.color = this.options.color;
26130			} else this.color = 'rgba(247, 247, 247, 0.2)';
26131
26132		},
26133		setResponsive: function() {
26134			var that = this;
26135			if (!UNCODE.isMobile) {
26136				$(window).resize(function(){
26137					if(that.animated === true) that.circle.stop();
26138					that.draw(true);
26139				});
26140			}
26141		},
26142		draw: function(redraw) {
26143			var w = this.$el.addClass('vc_ready').width() * 2,
26144				border_w = this.arcWidth,
26145				radius;
26146			if(!w) w = this.$el.parents(':visible').first().width()-2;
26147			//w = Math.round(w/100*80);
26148			//if (w < 250) w = 250;
26149			radius = w/2;
26150			this.$wrapper.css({"width" : (w / 2) + "px"});
26151			this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"});
26152			this.$back.css({"width" : (w / 2), "height" : (w / 2)});
26153			this.$canvas.attr({"width" : w + "px", "height" : w + "px"});
26154			this.$el.addClass('vc_ready');
26155			this.circle = new ProgressCircle({
26156				canvas: this.$canvas.get(0),
26157				minRadius: radius,
26158				arcWidth: border_w
26159			});
26160			if(redraw === true && this.animated === true) {
26161				this._progress_v = this.value;
26162				this.circle.addEntry({
26163					fillColor: this.color,
26164					progressListener: $.proxy(this.setProgress, this)
26165				}).start();
26166			}
26167		},
26168		setProgress: function() {
26169			if (this._progress_v >= this.value) {
26170				this.circle.stop();
26171				this.animated = true;
26172				this.$label.html(this.label_value + this.options.units);
26173				return this._progress_v;
26174			}
26175			this._progress_v += 0.01;
26176			if (!isNaN(this.label_value)) {
26177				var label_value = this._progress_v/this.value*this.label_value;
26178				var val = Math.round(label_value) + this.options.units;
26179				this.$label.html(val);
26180			} else this.$label.html(this.label_value + this.options.units);
26181			return this._progress_v;
26182		},
26183		animate: function() {
26184			if(this.animated !== true) {
26185				this.circle.addEntry({
26186					fillColor: this.color,
26187					progressListener: $.proxy(this.setProgress, this)
26188				}).start(10);
26189			}
26190		},
26191		setWayPoint: function() {
26192			if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) {
26193				this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' });
26194			} else {
26195				this.animate();
26196			}
26197		}
26198	};
26199	/**
26200	 * jQuery plugin
26201	 * @param option - object with settings
26202	 * @return {*}
26203	 */
26204	$.fn.vcChat = function(option, value) {
26205		return this.each(function () {
26206			var $this = $(this),
26207				data = $this.data('vc_chart'),
26208				options = typeof option === 'object' ? option : {
26209					color: $this.data('pie-color'),
26210					units: $this.data('pie-units')
26211				};
26212			if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options)));
26213			if (typeof option == 'string') data[option](value);
26214		});
26215	};
26216	/**
26217	 * Allows users to rewrite function inside theme.
26218	 */
26219	if ( typeof window['vc_pieChart'] !== 'function' ) {
26220		window.vc_pieChart = function() {
26221			$('.vc_pie_chart:visible:not(.vc_ready)').vcChat();
26222		}
26223	}
26224	$(document).ready(function(){
26225		!window.vc_iframe && vc_pieChart();
26226
26227		/**
26228		* Tab and collapse integration.
26229		*/
26230		$('.nav-tabs a').on('shown.bs.tab', function(e){
26231			var $cont = $(e.target).closest('.tab-container'),
26232				$active = $('.tab-pane.active', $cont);
26233			$('.vc_pie_chart:not(.vc_ready)', $active).vcChat();
26234		});
26235
26236		$('.panel-collapse').on('shown.bs.collapse', function (e) {
26237			$('.vc_pie_chart:not(.vc_ready)', e.target).vcChat();
26238		})
26239	});
26240
26241})(window.jQuery);
26242
26243/* Progress bar
26244 ---------------------------------------------------------- */
26245function uncode_progress_bar() {
26246	jQuery.each(jQuery('.vc_progress_bar'), function(index, val) {
26247		if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) {
26248			return;
26249		}
26250		if (!UNCODE.isMobile) {
26251			new Waypoint({
26252				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26253				element: val,
26254				handler: function() {
26255					var element = jQuery(this.element);
26256					element.find('.vc_single_bar').each(function(index) {
26257						var $this = jQuery(this),
26258							bar = $this.find('.vc_bar'),
26259							val = bar.data('percentage-value');
26260						setTimeout(function() {
26261							bar.css({
26262								"width": val + '%'
26263							});
26264						}, index * 200);
26265					});
26266				},
26267				offset: '80%'
26268			});
26269		} else {
26270			var element = jQuery(val);
26271			element.find('.vc_single_bar').each(function(index) {
26272				var $this = jQuery(this),
26273					bar = $this.find('.vc_bar'),
26274					val = bar.data('percentage-value');
26275				setTimeout(function() {
26276					bar.css({
26277						"width": val + '%'
26278					});
26279				}, index * 200);
26280			});
26281		}
26282	});
26283};
26284uncode_progress_bar();
26285
26286/*!
26287 * jquery.counterup.js 1.0
26288 *
26289 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal
26290 * Released under the GPL v2 License
26291 *
26292 * Date: Nov 26, 2013
26293 */
26294(function($) {
26295	"use strict";
26296	$.fn.counterUp = function(options) {
26297		// Defaults
26298		var settings = $.extend({
26299			'time': 400,
26300			'delay': 10
26301		}, options);
26302		return this.each(function() {
26303			// Store the object
26304			var $this = $(this);
26305			var $settings = settings;
26306			var counterUpper = function() {
26307				var nums = [];
26308				var divisions = $settings.time / $settings.delay;
26309				var numReal = $this.attr('data-val'),
26310				num = numReal;
26311				var isComma = /[0-9]+,[0-9]+/.test(num);
26312				num = num.replace(/,/g, '');
26313				var isInt = /^[0-9]+$/.test(num);
26314				var isFloat = /^[0-9]+\.[0-9]+$/.test(num);
26315				var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0;
26316				// Generate list of incremental numbers to display
26317				for (var i = divisions; i >= 1; i--) {
26318					// Preserve as int if input was int
26319					var newNum = parseInt(num / divisions * i);
26320					// Preserve float if input was float
26321					if (isFloat) {
26322						newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces);
26323					}
26324					// Preserve commas if input had commas
26325					if (isComma) {
26326						while (/(\d+)(\d{3})/.test(newNum.toString())) {
26327							newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2');
26328						}
26329					}
26330					nums.unshift(newNum);
26331				}
26332				nums.push(numReal);
26333				$this.data('counterup-nums', nums);
26334				$this.text('0');
26335				// Updates the number until we're done
26336				var f = function() {
26337					if ($this.data('counterup-nums') != null) {
26338						$this.text($this.data('counterup-nums').shift());
26339						if ($this.data('counterup-nums').length) {
26340							setTimeout($this.data('counterup-func'), $settings.delay);
26341						} else {
26342							delete $this.data('counterup-nums');
26343							$this.data('counterup-nums', null);
26344							$this.data('counterup-func', null);
26345						}
26346					}
26347				};
26348				$this.data('counterup-func', f);
26349				// Start the count up
26350				setTimeout($this.data('counterup-func'), $settings.delay);
26351			};
26352			// Perform counts when the element gets into view
26353			new Waypoint({
26354				context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window,
26355				element: this,
26356				handler: function() {
26357					counterUpper();
26358					if (!UNCODE.isUnmodalOpen) {
26359						this.destroy();
26360					}
26361				},
26362				offset: '100%'
26363			});
26364		});
26365	};
26366})(jQuery);
26367
26368/*!
26369 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/)
26370 * Copyright (c) 2016 Edson Hilios
26371 *
26372 * Permission is hereby granted, free of charge, to any person obtaining a copy of
26373 * this software and associated documentation files (the "Software"), to deal in
26374 * the Software without restriction, including without limitation the rights to
26375 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
26376 * the Software, and to permit persons to whom the Software is furnished to do so,
26377 * subject to the following conditions:
26378 *
26379 * The above copyright notice and this permission notice shall be included in all
26380 * copies or substantial portions of the Software.
26381 *
26382 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26383 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
26384 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
26385 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
26386 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26387 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26388 */
26389(function(factory) {
26390	"use strict";
26391	if (typeof define === "function" && define.amd) {
26392		define([ "jquery" ], factory);
26393	} else {
26394		factory(jQuery);
26395	}
26396})(function($) {
26397	"use strict";
26398	var instances = [], matchers = [], defaultOptions = {
26399		precision: 100,
26400		elapse: false,
26401		defer: false
26402	};
26403	matchers.push(/^[0-9]*$/.source);
26404	matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26405	matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source);
26406	matchers = new RegExp(matchers.join("|"));
26407	function parseDateString(dateString) {
26408		if (dateString instanceof Date) {
26409			return dateString;
26410		}
26411		if (String(dateString).match(matchers)) {
26412			if (String(dateString).match(/^[0-9]*$/)) {
26413				dateString = Number(dateString);
26414			}
26415			if (String(dateString).match(/\-/)) {
26416				dateString = String(dateString).replace(/\-/g, "/");
26417			}
26418			return new Date(dateString);
26419		} else {
26420			throw new Error("Couldn't cast `" + dateString + "` to a date object.");
26421		}
26422	}
26423	var DIRECTIVE_KEY_MAP = {
26424		Y: "years",
26425		m: "months",
26426		n: "daysToMonth",
26427		d: "daysToWeek",
26428		w: "weeks",
26429		W: "weeksToMonth",
26430		H: "hours",
26431		M: "minutes",
26432		S: "seconds",
26433		D: "totalDays",
26434		I: "totalHours",
26435		N: "totalMinutes",
26436		T: "totalSeconds"
26437	};
26438	function escapedRegExp(str) {
26439		var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
26440		return new RegExp(sanitize);
26441	}
26442	function strftime(offsetObject) {
26443		return function(format) {
26444			var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi);
26445			if (directives) {
26446				for (var i = 0, len = directives.length; i < len; ++i) {
26447					var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null;
26448					directive = directive[2];
26449					if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) {
26450						value = DIRECTIVE_KEY_MAP[directive];
26451						value = Number(offsetObject[value]);
26452					}
26453					if (value !== null) {
26454						if (modifier === "!") {
26455							value = pluralize(plural, value);
26456						}
26457						if (modifier === "") {
26458							if (value < 10) {
26459								value = "0" + value.toString();
26460							}
26461						}
26462						format = format.replace(regexp, value.toString());
26463					}
26464				}
26465			}
26466			format = format.replace(/%%/, "%");
26467			return format;
26468		};
26469	}
26470	function pluralize(format, count) {
26471		var plural = "s", singular = "";
26472		if (format) {
26473			format = format.rep
vendor: 8,618 bytes, lines 26473-26617
26473lace(/(:|;|\s)/gi, "").split(/\,/);
26474			if (format.length === 1) {
26475				plural = format[0];
26476			} else {
26477				singular = format[0];
26478				plural = format[1];
26479			}
26480		}
26481		if (Math.abs(count) > 1) {
26482			return plural;
26483		} else {
26484			return singular;
26485		}
26486	}
26487	var Countdown = function(el, finalDate, options) {
26488		this.el = el;
26489		this.$el = $(el);
26490		this.interval = null;
26491		this.offset = {};
26492		this.options = $.extend({}, defaultOptions);
26493		this.instanceNumber = instances.length;
26494		instances.push(this);
26495		this.$el.data("countdown-instance", this.instanceNumber);
26496		if (options) {
26497			if (typeof options === "function") {
26498				this.$el.on("update.countdown", options);
26499				this.$el.on("stoped.countdown", options);
26500				this.$el.on("finish.countdown", options);
26501			} else {
26502				this.options = $.extend({}, defaultOptions, options);
26503			}
26504		}
26505		this.setFinalDate(finalDate);
26506		if (this.options.defer === false) {
26507			this.start();
26508		}
26509	};
26510	$.extend(Countdown.prototype, {
26511		start: function() {
26512			if (this.interval !== null) {
26513				clearInterval(this.interval);
26514			}
26515			var self = this;
26516			this.update();
26517			this.interval = setInterval(function() {
26518				self.update.call(self);
26519			}, this.options.precision);
26520		},
26521		stop: function() {
26522			clearInterval(this.interval);
26523			this.interval = null;
26524			this.dispatchEvent("stoped");
26525		},
26526		toggle: function() {
26527			if (this.interval) {
26528				this.stop();
26529			} else {
26530				this.start();
26531			}
26532		},
26533		pause: function() {
26534			this.stop();
26535		},
26536		resume: function() {
26537			this.start();
26538		},
26539		remove: function() {
26540			this.stop.call(this);
26541			instances[this.instanceNumber] = null;
26542			delete this.$el.data().countdownInstance;
26543		},
26544		setFinalDate: function(value) {
26545			this.finalDate = parseDateString(value);
26546		},
26547		update: function() {
26548			if (this.$el.closest("html").length === 0) {
26549				this.remove();
26550				return;
26551			}
26552			var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft;
26553			newTotalSecsLeft = this.finalDate.getTime() - now.getTime();
26554			newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3);
26555			newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft);
26556			if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) {
26557				return;
26558			} else {
26559				this.totalSecsLeft = newTotalSecsLeft;
26560			}
26561			this.elapsed = now >= this.finalDate;
26562			this.offset = {
26563				seconds: this.totalSecsLeft % 60,
26564				minutes: Math.floor(this.totalSecsLeft / 60) % 60,
26565				hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24,
26566				days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26567				daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7,
26568				daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368),
26569				weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7),
26570				weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4,
26571				months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368),
26572				years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()),
26573				totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24),
26574				totalHours: Math.floor(this.totalSecsLeft / 60 / 60),
26575				totalMinutes: Math.floor(this.totalSecsLeft / 60),
26576				totalSeconds: this.totalSecsLeft
26577			};
26578			if (!this.options.elapse && this.totalSecsLeft === 0) {
26579				this.stop();
26580				this.dispatchEvent("finish");
26581			} else {
26582				this.dispatchEvent("update");
26583			}
26584		},
26585		dispatchEvent: function(eventName) {
26586			var event = $.Event(eventName + ".countdown");
26587			event.finalDate = this.finalDate;
26588			event.elapsed = this.elapsed;
26589			event.offset = $.extend({}, this.offset);
26590			event.strftime = strftime(this.offset);
26591			this.$el.trigger(event);
26592		}
26593	});
26594	$.fn.countdown = function() {
26595		var argumentsArray = Array.prototype.slice.call(arguments, 0);
26596		return this.each(function() {
26597			var instanceNumber = $(this).data("countdown-instance");
26598			if (instanceNumber !== undefined) {
26599				var instance = instances[instanceNumber], method = argumentsArray[0];
26600				if (Countdown.prototype.hasOwnProperty(method)) {
26601					instance[method].apply(instance, argumentsArray.slice(1));
26602				} else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) {
26603					instance.setFinalDate.call(instance, method);
26604					instance.start();
26605				} else {
26606					$.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method));
26607				}
26608			} else {
26609				new Countdown(this, argumentsArray[0], argumentsArray[1]);
26610			}
26611		});
26612	};
26613});
26614
26615!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;
26616function getStyles(config){
26617  // 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;
26617left: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+"}"
26618};
26619  var ShareUtils;
26620
26621if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") {
26622  Object.defineProperty(HTMLElement.prototype, "classList", {
26623    get: function() {
26624      var ret, self, update;
26625      update = function(fn) {
26626        return function(value) {
26627          var classes, index;
26628          classes = self.className.split(/\s+/);
26629          index = classes.indexOf(value);
26630          fn(classes, index, value);
26631          self.className = classes.join(" ");
26632        };
26633      };
26634      self = this;
26635      ret = {
26636        add: update(function(classes, index, value) {
26637          ~index || classes.push(value);
26638        }),
26639        remove: update(function(classes, index) {
26640          ~index && classes.splice(index, 1);
26641        }),
26642        toggle: update(function(classes, index, value) {
26643          if (~index) {
26644            classes.splice(index, 1);
26645          } else {
26646            classes.push(value);
26647          }
26648        }),
26649        contains: function(value) {
26650          return !!~self.className.split(/\s+/).indexOf(value);
26651        },
26652        item: function(i) {
26653          return self.className.split(/\s+/)[i] || null;
26654        }
26655      };
26656      Object.defineProperty(ret, "length", {
26657        get: function() {
26658          return self.className.split(/\s+/).length;
26659        }
26660      });
26661      return ret;
26662    }
26663  });
26664}
26665
26666String.prototype.to_rfc3986 = function() {
26667  var tmp;
26668  tmp = encodeURIComponent(this);
26669  return tmp.replace(/[!'()*]/g, function(c) {
26670    return "%" + c.charCodeAt(0).toString(16);
26671  });
26672};
26673
26674ShareUtils = (function() {
26675  function ShareUtils() {}
26676
26677  ShareUtils.prototype.extend = function(to, from, overwrite) {
26678    var hasProp, prop;
26679    for (prop in from) {
26680      hasProp = to[prop] !== undefined;
26681      if (hasProp && typeof from[prop] === "object") {
26682        this.extend(to[prop], from[prop], overwrite);
26683      } else {
26684        if (overwrite || !hasProp) {
26685          to[prop] = from[prop];
26686        }
26687      }
26688    }
26689  };
26690
26691  ShareUtils.prototype.hide = function(el) {
26692    return el.style.display = "none";
26693  };
26694
26695  ShareUtils.prototype.show = function(el) {
26696    return el.style.display = "block";
26697  };
26698
26699  ShareUtils.prototype.has_class = function(el, class_name) {
26700    return el.classList.contains(class_name);
26701  };
26702
26703  ShareUtils.prototype.add_class = function(el, class_name) {
26704    return el.classList.add(class_name);
26705  };
26706
26707  ShareUtils.prototype.remove_class = function(el, class_name) {
26708    return el.classList.remove(class_name);
26709  };
26710
26711  ShareUtils.prototype.is_encoded = function(str) {
26712    str = str.to_rfc3986();
26713    return decodeURIComponent(str) !== str;
26714  };
26715
26716  ShareUtils.prototype.encode = function(str) {
26717    if (typeof str === "undefined" || this.is_encoded(str)) {
26718      return str;
26719    } else {
26720      return str.to_rfc3986();
26721    }
26722  };
26723
26724  ShareUtils.prototype.popup = function(url, params) {
26725    var k, popup, qs, v;
26726    if (params == null) {
26727      params = {};
26728    }
26729    popup = {
26730      width: 500,
26731      height: 350
26732    };
26733    popup.top = (screen.height / 2) - (popup.height / 2);
26734    popup.left = (screen.width / 2) - (popup.width / 2);
26735    qs = ((function() {
26736      var _results;
26737      _results = [];
26738      for (k in params) {
26739        v = params[k];
26740        _results.push("" + k + "=" + (this.encode(v)));
26741      }
26742      return _results;
26743    }).call(this)).join('&');
26744    if (qs) {
26745      qs = "?" + qs;
26746    }
26747    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=" 
26747+ popup.width + ",height=" + popup.height);
26748  };
26749
26750  return ShareUtils;
26751
26752})();
26753var Share,
26754  __hasProp = {}.hasOwnProperty,
26755  __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; };
26756
26757Share = (function(_super) {
26758  __extends(Share, _super);
26759
26760  function Share(element, options) {
26761    this.element = element;
26762    this.el = {
26763      head: document.getElementsByTagName('head')[0],
26764      body: document.getElementsByTagName('body')[0]
26765    };
26766    this.config = {
26767      enabled_networks: 0,
26768      protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//',
26769      url: window.location.href.replace("&", "%26"),
26770      caption: null,
26771      title: this.default_title(),
26772      image: this.default_image(),
26773      description: this.default_description(),
26774      ui: {
26775        flyout: 'top center',
26776        button_text: 'Share',
26777        button_font: true,
26778        icon_font: true
26779      },
26780      networks: {
26781        twitter: {
26782          enabled: true,
26783          url: null,
26784          title: null,
26785          description: null
26786        },
26787        facebook: {
26788          enabled: true,
26789          load_sdk: true,
26790          url: null,
26791          app_id: null,
26792          title: null,
26793          caption: null,
26794          description: null,
26795          image: null
26796        },
26797        pinterest: {
26798          enabled: true,
26799          url: null,
26800          image: null,
26801          description: null
26802        },
26803        reddit: {
26804          enabled: true,
26805          url: null,
26806          title: null
26807        },
26808        linkedin: {
26809          enabled: true,
26810          url: null,
26811          title: null,
26812          description: null
26813        },
26814        xing: {
26815          enabled: true,
26816          url: null,
26817          title: null,
26818          image: null,
26819          description: null
26820        },
26821        whatsapp: {
26822          enabled: true,
26823          title: null,
26824          url: null
26825        },
26826        email: {
26827          enabled: true,
26828          title: null,
26829          description: null,
26830          url: null
26831        }
26832      }
26833    };
26834    this.setup(element, options);
26835    return this;
26836  }
26837
26838  Share.prototype.setup = function(element, opts) {
26839    var index, instance, instances, _i, _len;
26840    instances = document.querySelectorAll(element);
26841    this.extend(this.config, opts, true);
26842    this.set_global_configuration();
26843    this.normalize_network_configuration();
26844    if (this.config.ui.icon_font) {
26845      this.inject_icons();
26846    }
26847    if (this.config.ui.button_font) {
26848      this.inject_fonts();
26849    }
26850    if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) {
26851      this.inject_facebook_sdk();
26852    }
26853    for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) {
26854      instance = instances[index];
26855      this.setup_instance(element, index);
26856    }
26857  };
26858
26859  Share.prototype.setup_instance = function(element, index) {
26860    var button, instance, label, network, networks, _i, _len, _results,
26861      _this = this;
26862    instance = document.querySelectorAll(element)[index];
26863    this.hide(instance);
26864    this.add_class(instance, "sharer-" + index);
26865    instance = document.querySelectorAll(element)[index];
26866    this.inject_css(instance);
26867    this.inject_html(instance);
26868    this.show(instance);
26869    label = instance.getElementsByTagName("label")[0];
26870    button = instance.getElementsByClassName("social")[0];
26871    networks = instance.getElementsByTagName('li');
26872    this.add_class(button, "networks-" + this.config.enabled_networks);
26873    label.addEventListener("click", function() {
26874      return _this.event_toggle(button);
26875    });
26876    _this = this;
26877    _results = [];
26878    for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) {
26879      network = networks[index];
26880      _results.push(network.addEventListener("click", function() {
26881        _this.event_network(instance, this);
26882        return _this.event_close(button);
26883      }));
26884    }
26885    return _results;
26886  };
26887
26888  Share.prototype.event_toggle = function(button) {
26889    if (this.has_class(button, "active")) {
26890      return this.event_close(button);
26891    } else {
26892      return this.event_open(button);
26893    }
26894  };
26895
26896  Share.prototype.event_open = function(button) {
26897    if (this.has_class(button, "load")) {
26898      this.remove_class(button, "load");
26899    }
26900    return this.add_class(button, "active");
26901  };
26902
26903  Share.prototype.event_close = function(button) {
26904    return this.remove_class(button, "active");
26905  };
26906
26907  Share.prototype.event_network = function(instance, network) {
26908    var name;
26909    name = network.getAttribute("data-network");
26910    this.hook("before", name, instance);
26911    this["network_" + name]();
26912    return this.hook("after", name, instance);
26913  };
26914
26915  Share.prototype.open = function() {
26916    return this["public"]("open");
26917  };
26918
26919  Share.prototype.close = function() {
26920    return this["public"]("close");
26921  };
26922
26923  Share.prototype.toggle = function() {
26924    return this["public"]("toggle");
26925  };
26926
26927  Share.prototype["public"] = function(action) {
26928    var button, index, instance, _i, _len, _ref, _results;
26929    _ref = document.querySelectorAll(this.element);
26930    _results = [];
26931    for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) {
26932      instance = _ref[index];
26933      button = instance.getElementsByClassName("social")[0];
26934      _results.push(this["event_" + action](button));
26935    }
26936    return _results;
26937  };
26938
26939  Share.prototype.network_facebook = function() {
26940    if (this.config.networks.facebook.load_sdk) {
26941      if (!window.FB) {
26942        return console.error("The Facebook JS SDK hasn't loaded yet.");
26943      }
26944      return FB.ui({
26945        method: 'feed',
26946        name: this.config.networks.facebook.title,
26947        link: this.config.networks.facebook.url,
26948        picture: this.config.networks.facebook.image,
26949        caption: this.config.networks.facebook.caption,
26950        description: this.config.networks.facebook.description
26951      });
26952    } else {
26953      return this.popup('https://www.facebook.com/sharer/sharer.php', {
26954        u: this.config.networks.facebook.url
26955      });
26956    }
26957  };
26958
26959  Share.prototype.network_twitter = function() {
26960    return this.popup('https://twitter.com/intent/tweet', {
26961      text: this.config.networks.twitter.title,
26962      url: this.config.networks.twitter.url
26963    });
26964  };
26965
26966  Share.prototype.network_pinterest = function() {
26967    return this.popup('https://www.pinterest.com/pin/create/button', {
26968      url: this.config.networks.pinterest.url,
26969      media: this.config.networks.pinterest.image,
26970      description: this.config.networks.pinterest.description
26971    });
26972  };
26973
26974  Share.prototype.network_linkedin = function() {
26975    return this.popup('https://www.linkedin.com/shareArticle', {
26976      url: this.config.networks.linkedin.url,
26977      title: this.config.networks.linkedin.title,
26978      summary: this.config.networks.linkedin.description
26979    });
26980  }
26981
26982  Share.prototype.network_xing = function() {
26983    return this.popup('https://www.xing.com/spi/shares/new', {
26984      url: this.config.networks.xing.url,
26985      image: this.config.networks.xing.image,
26986      title: this.config.networks.xing.title,
26987      summary: this.config.networks.xing.description
26988    });
26989  }
26990
26991  Share.prototype.network_whatsapp = function() {
26992    return this.popup('https://api.whatsapp.com/send', {
26993      text: this.config.networks.whatsapp.title + '%20' + this.config.networks.whatsapp.url,
26994    });
26995  }
26996
26997  Share.prototype.network_email = function() {
26998    return this.popup('mailto:', {
26999      subject: this.config.networks.email.title,
27000      body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description,
27001    });
27002  };
27003
27004  Share.prototype.inject_icons = function() {
27005  //  return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css");
27006  };
27007
27008  Share.prototype.inject_fonts = function() {
27009   // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text);
27010  };
27011
27012  Share.prototype.inject_stylesheet = function(url) {
27013    var link;
27014    if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) {
27015      link = document.createElement("link");
27016      link.setAttribute("rel", "stylesheet");
27017      link.setAttribute("href", url);
27018      return this.el.head.appendChild(link);
27019    }
27020  };
27021
27022  Share.prototype.inject_css = function(instance) {
27023    var css, meta, selector, style;
27024    selector = "." + (instance.getAttribute('class').split(" ").join("."));
27025    if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) {
27026      this.config.selector = selector;
27027      css = getStyles(this.config);
27028      style = document.createElement("style");
27029      style.type = "text/css";
27030      if (style.styleSheet) {
27031        style.styleSheet.cssText = css;
27032      } else {
27033        style.appendChild(document.createTextNode(css));
27034      }
27035      this.el.head.appendChild(style);
27036      delete this.config.selector;
27037      meta = document.createElement("meta");
27038      meta.setAttribute("name", "sharer" + selector);
27039      return this.el.head.appendChild(meta);
27040    }
27041  };
27042
27043  Share.prototype.inject_html = function(instance) {
27044    //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>";
27045    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>";
27046  };
27047
27048  Share.prototype.inject_facebook_sdk = function() {
27049    var fb_root, script;
27050    if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) {
27051      script = document.createElement("script");
27052      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')";
27053      fb_root = document.createElement("div");
27054      fb_root.id = "fb-root";
27055      this.el.body.appendChild(fb_root);
27056      return this.el.body.appendChild(script);
27057    }
27058  };
27059
27060  Share.prototype.hook = function(type, network, instance) {
27061    var fn, opts;
27062    fn = this.config.networks[network][type];
27063    if (typeof fn === "function") {
27064      opts = fn.call(this.config.networks[network], instance);
27065      if (opts !== void 0) {
27066        opts = this.normalize_filter_config_updates(opts);
27067        this.extend(this.config.networks[network], opts, true);
27068        this.normalize_network_configuration();
27069      }
27070    }
27071  };
27072
27073  Share.prototype.default_title = function() {
27074    var content;
27075    if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) {
27076      return encodeURIComponent(content.getAttribute('content'));
27077    } else if (content = document.querySelector('title')) {
27078      return encodeURIComponent(content.innerText);
27079    }
27080  };
27081
27082  Share.prototype.default_image = function() {
27083    var content;
27084    if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) {
27085      return content.getAttribute('content');
27086    }
27087  };
27088
27089  Share.prototype.default_description = function() {
27090    var content;
27091    if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) {
27092      return encodeURIComponent(content.getAttribute('content'));
27093    } else {
27094      return '';
27095    }
27096  };
27097
27098  Share.prototype.set_global_configuration = function() {
27099    var display, network, option, options, _ref, _results;
27100    _ref = this.config.networks;
27101    _results = [];
27102    for (network in _ref) {
27103      options = _ref[network];
27104      for (option in options) {
27105        if (this.config.networks[network][option] == null) {
27106          this.config.networks[network][option] = this.config[option];
27107        }
27108      }
27109      if (this.config.networks[network].enabled) {
27110        display = 'block';
27111        this.config.enabled_networks += 1;
27112      } else {
27113        display = 'none';
27114      }
27115      _results.push(this.config.networks[network].display = display);
27116    }
27117    return _results;
27118  };
27119
27120  Share.prototype.normalize_network_configuration = function() {
27121    if (!this.config.networks.facebook.app_id) {
27122      this.config.networks.facebook.load_sdk = false;
27123    }
27124    if (!this.is_encoded(this.config.networks.twitter.description)) {
27125      this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description);
27126    }
27127    if (typeof this.config.networks.facebook.app_id === 'number') {
27128      return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString();
27129    }
27130  };
27131
27132  Share.prototype.normalize_filter_config_updates = function(opts) {
27133    if (this.config.networks.facebook.app_id !== opts.app_id) {
27134      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.");
27135      delete opts.app_id;
27136    }
27137    if (this.config.networks.facebook.load_sdk !== opts.load_sdk) {
27138      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.");
27139      delete opts.app_id;
27140    }
27141    return opts;
27142  };
27143
27144  return Share;
27145
27146})(ShareUtils);
27147 return Share;
27148});
27149
27150// Generated by CoffeeScript 1.9.2
27151
27152// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
27153
27154(function() {
27155  var $, win;
27156
27157  $ = this.jQuery || window.jQuery;
27158
27159  win = $(window);
27160
27161  $.fn.stick_in_parent = function(opts) {
27162    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
27163    if (opts == null) {
27164      opts = {};
27165    }
27166    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;
27167    if (offset_top == null) {
27168      offset_top = 0;
27169    }
27170    if (parent_selector == null) {
27171      parent_selector = void 0;
27172    }
27173    if (inner_scrolling == null) {
27174      inner_scrolling = true;
27175    }
27176    if (sticky_class == null) {
27177      sticky_class = "is_stuck";
27178    }
27179    doc = $(document);
27180    if (enable_bottoming == null) {
27181      enable_bottoming = true;
27182    }
27183    outer_width = function(el) {
27184      var _el, computed, w;
27185      if (window.getComputedStyle) {
27186        _el = el[0];
27187        computed = window.getComputedStyle(el[0]);
27188        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
27189        if (computed.getPropertyValue("box-sizing") !== "border-box") {
27190          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
27191        }
27192        return w;
27193      } else {
27194        return el.outerWidth(true);
27195      }
27196    };
27197    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
27198      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
27199      if (elm.data("sticky_kit")) {
27200        return;
27201      }
27202      elm.data("sticky_kit", true);
27203      last_scroll_height = doc.height();
27204      parent = elm.parent();
27205      if (parent_selector != null) {
27206        parent = parent.closest(parent_selector);
27207      }
27208      if (!parent.length) {
27209        throw "failed to find stick parent";
27210      }
27211      fixed = false;
27212      bottomed = false;
27213      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
27214      if (spacer) {
27215        spacer.css('position', elm.css('position'));
27216      }
27217      recalc = function() {
27218        var border_top, padding_top, restore;
27219        if (detached) {
27220          return;
27221        }
27222        last_scroll_height = doc.height();
27223        border_top = parseInt(parent.css("border-top-width"), 10);
27224        padding_top = parseInt(parent.css("padding-top"), 10);
27225        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
27226        parent_top = parent.offset().top + border_top + padding_top;
27227        parent_height = parent.height();
27228        if (fixed) {
27229          fixed = false;
vendor: 6,068 bytes, lines 27230-27424
27230          bottomed = false;
27231          if (manual_spacer == null) {
27232            elm.insertAfter(spacer);
27233            spacer.detach();
27234          }
27235          elm.css({
27236            position: "",
27237            top: "",
27238            width: "",
27239            bottom: ""
27240          }).removeClass(sticky_class);
27241          restore = true;
27242        }
27243        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
27244        height = elm.outerHeight(true);
27245        el_float = elm.css("float");
27246        if (spacer) {
27247          spacer.css({
27248            width: outer_width(elm),
27249            height: height,
27250            display: elm.css("display"),
27251            "vertical-align": elm.css("vertical-align"),
27252            "float": el_float
27253          });
27254        }
27255        if (restore) {
27256          return tick();
27257        }
27258      };
27259      recalc();
27260      if (height === parent_height) {
27261        return;
27262      }
27263      last_pos = void 0;
27264      offset = offset_top;
27265      recalc_counter = recalc_every;
27266      tick = function() {
27267        var css, delta, recalced, scroll, will_bottom, win_height;
27268        if (detached) {
27269          return;
27270        }
27271        recalced = false;
27272        if (recalc_counter != null) {
27273          recalc_counter -= 1;
27274          if (recalc_counter <= 0) {
27275            recalc_counter = recalc_every;
27276            recalc();
27277            recalced = true;
27278          }
27279        }
27280        if (!recalced && doc.height() !== last_scroll_height) {
27281          recalc();
27282          recalced = true;
27283        }
27284        scroll = win.scrollTop();
27285        if (last_pos != null) {
27286          delta = scroll - last_pos;
27287        }
27288        last_pos = scroll;
27289        if (fixed) {
27290          if (enable_bottoming) {
27291            will_bottom = scroll + height + offset > parent_height + parent_top;
27292            if (bottomed && !will_bottom) {
27293              bottomed = false;
27294              elm.css({
27295                position: "fixed",
27296                bottom: "",
27297                top: offset
27298              }).trigger("sticky_kit:unbottom");
27299            }
27300          }
27301          if (scroll < top) {
27302            fixed = false;
27303            offset = offset_top;
27304            if (manual_spacer == null) {
27305              if (el_float === "left" || el_float === "right") {
27306                elm.insertAfter(spacer);
27307              }
27308              spacer.detach();
27309            }
27310            css = {
27311              position: "",
27312              width: "",
27313              top: ""
27314            };
27315            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
27316          }
27317          if (inner_scrolling) {
27318            win_height = win.height();
27319            if (height + offset_top > win_height) {
27320              if (!bottomed) {
27321                offset -= delta;
27322                offset = Math.max(win_height - height, offset);
27323                offset = Math.min(offset_top, offset);
27324                if (fixed) {
27325                  elm.css({
27326                    top: offset + "px"
27327                  });
27328                }
27329              }
27330            }
27331          }
27332        } else {
27333          if (scroll > top) {
27334            fixed = true;
27335            css = {
27336              position: "fixed",
27337              top: offset
27338            };
27339            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
27340            elm.css(css).addClass(sticky_class);
27341            if (manual_spacer == null) {
27342              elm.after(spacer);
27343              if (el_float === "left" || el_float === "right") {
27344                spacer.append(elm);
27345              }
27346            }
27347            elm.trigger("sticky_kit:stick");
27348          }
27349        }
27350        if (fixed && enable_bottoming) {
27351          if (will_bottom == null) {
27352            will_bottom = scroll + height + offset > parent_height + parent_top;
27353          }
27354          if (!bottomed && will_bottom) {
27355            bottomed = true;
27356            if (parent.css("position") === "static") {
27357              parent.css({
27358                position: "relative"
27359              });
27360            }
27361            return elm.css({
27362              position: "absolute",
27363              bottom: padding_bottom,
27364              top: "auto"
27365            }).trigger("sticky_kit:bottom");
27366          }
27367        }
27368      };
27369      recalc_and_tick = function() {
27370        recalc();
27371        return tick();
27372      };
27373      detach = function() {
27374        detached = true;
27375        win.off("touchmove", tick);
27376        win.off("scroll", tick);
27377        win.off("resize", recalc_and_tick);
27378        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
27379        elm.off("sticky_kit:detach", detach);
27380        elm.removeData("sticky_kit");
27381        elm.css({
27382          position: "",
27383          bottom: "",
27384          top: "",
27385          width: ""
27386        });
27387        parent.position("position", "");
27388        if (fixed) {
27389          if (manual_spacer == null) {
27390            if (el_float === "left" || el_float === "right") {
27391              elm.insertAfter(spacer);
27392            }
27393            spacer.remove();
27394          }
27395          return elm.removeClass(sticky_class);
27396        }
27397      };
27398      win.on("touchmove", tick);
27399      win.on("scroll", tick);
27400      win.on("resize", recalc_and_tick);
27401      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
27402      elm.on("sticky_kit:detach", detach);
27403      return setTimeout(tick, 0);
27404    };
27405    for (i = 0, len = this.length; i < len; i++) {
27406      elm = this[i];
27407      fn($(elm));
27408    }
27409    return this;
27410  };
27411
27412}).call(this);
27413/* ==========================================================================
27414 * bootstrap-tab-history.js
27415 * Author: Michael Narayan <[email protected]>
27416 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/
27417 * ==========================================================================
27418 * Licensed under the Apache License, Version 2.0 (the "License"); you may
27419 * not use this file except in compliance with the License. You may obtain a
27420 * copy of the License at
27421 *
27422 * http://www.apache.org/licenses/LICENSE-2.0
27423 *
27424 * Unless required by applicable law or agreed to in writing, softw
27424are
27425 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
27426 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
27427 * License for the specific language governing permissions and limitations
27428 * under the License.
27429 * ========================================================================== */
27430
27431/* ========================================================================== */
27432/* JSHint directives                                                          */
27433/*                                                                            */
27434/* global BootstrapTabHistory: true                                           */
27435/*                                                                            */
27436/* global document                                                            */
27437/* global jQuery                                                              */
27438/* global history                                                             */
27439/* global window                                                              */
27440/* ========================================================================== */
27441
27442/**
27443 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
27444 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set
27445 * the `data-tab-history` attribute to true (or a string denoting a tab grouping).
27446 *
27447 * See the README for additional information.
27448 *
27449 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes.
27450 */
27451
27452BootstrapTabHistory = {
27453  options: {
27454    /**
27455     * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the
27456     * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true.
27457     *
27458     * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`.
27459     *
27460     * @public
27461     * @type {?number}
27462     */
27463    defaultAnchorYOffset: 0,
27464    /**
27465     * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp.
27466     *
27467     * May be overriden on a per-element basis by the attribute `data-tab-history-changer`.
27468     *
27469     * @public
27470     * @type {string}
27471     */
27472    defaultChanger: 'replace',
27473    /**
27474     * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise,
27475     * `null` is passed as the third parameter to these calls.
27476     *
27477     * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`.
27478     *
27479     * @public
27480     * @type {boolean}
27481     */
27482    defaultUpdateURL: false,
27483    /**
27484     * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page
27485     * load.
27486     *
27487     * @public
27488     * @type {boolean}
27489     */
27490    showTabsBasedOnAnchor: true
27491  }
27492};
27493
27494(function () {
27495  'use strict';
27496
27497  jQuery(function () {
27498    if(history && history.pushState && history.replaceState) {
27499      var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27500
27501      if(bootstrapTabHistory) {
27502        showTabsBasedOnState(bootstrapTabHistory);
27503      } else {
27504        showTabsBasedOnAnchor();
27505      }
27506
27507      backfillHistoryState();
27508
27509      jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab);
27510      jQuery(window).on('popstate', onPopState);
27511    } else {
27512      showTabsBasedOnAnchor();
27513    }
27514  });
27515
27516  /**
27517   * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState.
27518   *
27519   * @type {boolean}
27520   */
27521  var showingTabsBasedOnState = false;
27522
27523  /**
27524   * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper
27525   * `history.back` handling when `data-tab-history-update-url` is true.
27526   */
27527  function backfillHistoryState() {
27528    var newState = null;
27529
27530    jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode
27531      var $activeTabElement = jQuery(this);
27532      var selector = getTabSelector($activeTabElement);
27533
27534      if(selector) {
27535        var tabGroup = getTabGroup($activeTabElement);
27536
27537        if(tabGroup) {
27538          newState = createNewHistoryState(newState || history.state, tabGroup, selector);
27539        }
27540      }
27541    });
27542
27543    if(newState) {
27544      history.replaceState(newState, '', null);
27545    }
27546  }
27547
27548  /**
27549   * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to
27550   * said bootstrapTabHistory attribute.
27551   *
27552   * @param {?object} existingState
27553   * @param {!string} tabGroup
27554   * @param {!string} selector
27555   * @returns {!object}
27556   */
27557  function createNewHistoryState(existingState, tabGroup, selector) {
27558    // Clone history.state and ensure it has a bootstrapTabHistory entry.
27559    var newState = jQuery.extend(true, {}, existingState, {
27560      bootstrapTabHistory: {}
27561    });
27562
27563    newState.bootstrapTabHistory[tabGroup] = selector;
27564
27565    return newState;
27566  }
27567
27568  /**
27569   * @param {jQuery} $tab
27570   * @returns {?string}
27571   */
27572  function getTabGroup($tab) {
27573    return parseTruthyAttributeValue($tab.data('tab-history'));
27574  }
27575
27576  /**
27577   * @param {jQuery} $tab
27578   * @returns {?string}
27579   */
27580  function getTabSelector($tab) {
27581    return $tab.data('target') || $tab.attr('href');
27582  }
27583
27584  /**
27585   * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate.
27586   *
27587   * @param {jQuery.Event} shownEvt
27588   */
27589  function onShownTab(shownEvt) {
27590    if(!showingTabsBasedOnState) {
27591      var $activatedTab = jQuery(shownEvt.target);
27592      if ( $activatedTab.hasClass('panel-collapse') )
27593        $activatedTab = $activatedTab.closest('.panel').find('a');
27594      var selector = getTabSelector($activatedTab);
27595
27596      if(selector) {
27597        var tabGroup = getTabGroup($activatedTab);
27598
27599        if(tabGroup) {
27600          var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger;
27601          var newState = createNewHistoryState(history.state, tabGroup, selector);
27602          var updateURL = (function ($activatedTab) {
27603            if(selector[0] === '#') {
27604              var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url'));
27605
27606              if(elementUpdateURLOption === undefined) {
27607                return BootstrapTabHistory.options.defaultUpdateURL;
27608              } else {
27609                return elementUpdateURLOption;
27610              }
27611            } else {
27612              return false;
27613            }
27614          })($activatedTab);
27615
27616          switch(historyChanger) {
27617            case 'push':
27618              history.pushState(newState, '', updateURL ? selector : null);
27619              break;
27620            case 'replace':
27621              history.replaceState(newState, '', updateURL ? selector : null);
27622              break;
27623            default:
27624              throw new Error('Unknown tab-history-changer: ' + historyChanger);
27625          }
27626        }
27627      }
27628    }
27629  }
27630
27631  /**
27632   * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate.
27633   */
27634  function onPopState() {
27635    var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory;
27636
27637    if(bootstrapTabHistory) {
27638      showTabsBasedOnState(bootstrapTabHistory);
27639    }
27640  }
27641
27642  /**
27643   * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned.
27644   *
27645   * Rationale: HAML data attributes which are set to `true` are rendered as a blank string.
27646   *
27647   * @param {*} value
27648   * @returns {*}
27649   */
27650  function parseTruthyAttributeValue(value) {
27651    if(value) {
27652      return value;
27653    } else if(value === '') {
27654      return true;
27655    } else {
27656      return value;
27657    }
27658  }
27659
27660  /**
27661   * Show tabs based upon the anchor component of `window.location`.
27662   */
27663  function showTabsBasedOnAnchor() {
27664    if(BootstrapTabHistory.options.showTabsBasedOnAnchor) {
27665      var anchor = window.location && window.location.hash;
27666
27667      if(anchor) {
27668        var $tabElement = showTabForSelector(anchor);
27669
27670        if($tabElement && window.addEventListener && window.removeEventListener) {
27671          var anchorYOffset = (function ($tabElement) {
27672            var elementSetting = $tabElement.data('tab-history-anchor-y-offset');
27673
27674            if(elementSetting === undefined) {
27675              return BootstrapTabHistory.options.defaultAnchorYOffset;
27676            } else {
27677              return elementSetting;
27678            }
27679          })($tabElement);
27680
27681          // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get
27682          //   here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the
27683          //   `history.state` object should have been used (unless the browser did not support the modern History API).
27684          if(anchorYOffset || anchorYOffset === 0) {
27685            var scrollListener = function resetAnchorScroll () {
27686              window.removeEventListener('scroll', scrollListener);
27687              window.scrollTo(0, anchorYOffset);
27688            };
27689
27690            window.addEventListener('scroll', scrollListener);
27691          }
27692        }
27693      }
27694    }
27695  }
27696
27697  /**
27698   * Show a tab which corresponds to the provided selector.
27699   *
27700   * @param {string} selector - A CSS selector.
27701   * @returns {?jQuery} - The tab which was found to show (even if said tab was already active).
27702   */
27703  function showTabForSelector(selector) {
27704    var $tabElement = (function (selector) {
27705      var $ret = null;
27706
27707      jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () {
27708        var $potentialTab = jQuery(this);
27709
27710        if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) {
27711          $ret = $potentialTab;
27712          return false;
vendor: 43,483 bytes, lines 27713-28929
27713        } else {
27714         return null;
27715        }
27716      });
27717
27718      return $ret;
27719    })(selector);
27720
27721    if($tabElement) {
27722      if ( !$tabElement.parent().hasClass('active') ) {
27723        $tabElement.trigger('click');
27724      }
27725      //$tabElement.tab('show');
27726    }
27727
27728    return $tabElement;
27729  }
27730
27731  /**
27732   * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors.
27733   *
27734   * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant.
27735   */
27736  function showTabsBasedOnState(bootstrapTabHistory) {
27737    showingTabsBasedOnState = true;
27738
27739    try {
27740      for(var k in bootstrapTabHistory) {
27741        if(bootstrapTabHistory.hasOwnProperty(k)) {
27742          showTabForSelector(bootstrapTabHistory[k]);
27743        }
27744      }
27745    } finally {
27746      showingTabsBasedOnState = false;
27747    }
27748  }
27749})();
27750
27751/*!
27752 * justifiedGallery - v3.8.1
27753 * http://miromannino.github.io/Justified-Gallery/
27754 * Copyright (c) 2020 Miro Mannino
27755 * Licensed under the MIT license.
27756 */
27757(function (factory) {
27758  if (typeof define === 'function' && define.amd) {
27759    // AMD. Register as an anonymous module.
27760    define(['jquery'], factory);
27761  } else if (typeof module === 'object' && module.exports) {
27762    // Node/CommonJS
27763    module.exports = function (root, jQuery) {
27764      if (jQuery === undefined) {
27765        // require('jQuery') returns a factory that requires window to
27766        // build a jQuery instance, we normalize how we use modules
27767        // that require this pattern but the window provided is a noop
27768        // if it's defined (how jquery works)
27769        if (typeof window !== 'undefined') {
27770          jQuery = require('jquery');
27771        }
27772        else {
27773          jQuery = require('jquery')(root);
27774        }
27775      }
27776      factory(jQuery);
27777      return jQuery;
27778    };
27779  } else {
27780    // Browser globals
27781    factory(jQuery);
27782  }
27783}(function ($) {
27784
27785  /**
27786   * Justified Gallery controller constructor
27787   *
27788   * @param $gallery the gallery to build
27789   * @param settings the settings (the defaults are in JustifiedGallery.defaults)
27790   * @constructor
27791   */
27792  var JustifiedGallery = function ($gallery, settings) {
27793
27794    this.settings = settings;
27795    this.checkSettings();
27796
27797    this.imgAnalyzerTimeout = null;
27798    this.entries = null;
27799    this.buildingRow = {
27800      entriesBuff: [],
27801      width: 0,
27802      height: 0,
27803      aspectRatio: 0
27804    };
27805    this.lastFetchedEntry = null;
27806    this.lastAnalyzedIndex = -1;
27807    this.yield = {
27808      every: 2, // do a flush every n flushes (must be greater than 1)
27809      flushed: 0 // flushed rows without a yield
27810    };
27811    this.border = settings.border >= 0 ? settings.border : settings.margins;
27812    this.maxRowHeight = this.retrieveMaxRowHeight();
27813    this.suffixRanges = this.retrieveSuffixRanges();
27814    this.offY = this.border;
27815    this.rows = 0;
27816    this.spinner = {
27817      phase: 0,
27818      timeSlot: 150,
27819      $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'),
27820      intervalId: null
27821    };
27822    this.scrollBarOn = false;
27823    this.checkWidthIntervalId = null;
27824    this.galleryWidth = $gallery.width();
27825    this.$gallery = $gallery;
27826
27827  };
27828
27829  /** @returns {String} the best suffix given the width and the height */
27830  JustifiedGallery.prototype.getSuffix = function (width, height) {
27831    var longestSide, i;
27832    longestSide = (width > height) ? width : height;
27833    for (i = 0; i < this.suffixRanges.length; i++) {
27834      if (longestSide <= this.suffixRanges[i]) {
27835        return this.settings.sizeRangeSuffixes[this.suffixRanges[i]];
27836      }
27837    }
27838    return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]];
27839  };
27840
27841  /**
27842   * Remove the suffix from the string
27843   *
27844   * @returns {string} a new string without the suffix
27845   */
27846  JustifiedGallery.prototype.removeSuffix = function (str, suffix) {
27847    return str.substring(0, str.length - suffix.length);
27848  };
27849
27850  /**
27851   * @returns {boolean} a boolean to say if the suffix is contained in the str or not
27852   */
27853  JustifiedGallery.prototype.endsWith = function (str, suffix) {
27854    return str.indexOf(suffix, str.length - suffix.length) !== -1;
27855  };
27856
27857  /**
27858   * Get the used suffix of a particular url
27859   *
27860   * @param str
27861   * @returns {String} return the used suffix
27862   */
27863  JustifiedGallery.prototype.getUsedSuffix = function (str) {
27864    for (var si in this.settings.sizeRangeSuffixes) {
27865      if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) {
27866        if (this.settings.sizeRangeSuffixes[si].length === 0) continue;
27867        if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si];
27868      }
27869    }
27870    return '';
27871  };
27872
27873  /**
27874   * Given an image src, with the width and the height, returns the new image src with the
27875   * best suffix to show the best quality thumbnail.
27876   *
27877   * @returns {String} the suffix to use
27878   */
27879  JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) {
27880    var newImageSrc;
27881
27882    if (this.settings.thumbnailPath) {
27883      newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image);
27884    } else {
27885      var matchRes = imageSrc.match(this.settings.extension);
27886      var ext = (matchRes !== null) ? matchRes[0] : '';
27887      newImageSrc = imageSrc.replace(this.settings.extension, '');
27888      newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc));
27889      newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext;
27890    }
27891
27892    return newImageSrc;
27893  };
27894
27895  /**
27896   * Shows the images that is in the given entry
27897   *
27898   * @param $entry the entry
27899   * @param callback the callback that is called when the show animation is finished
27900   */
27901  JustifiedGallery.prototype.showImg = function ($entry, callback) {
27902    if (this.settings.cssAnimation) {
27903      $entry.addClass('jg-entry-visible');
27904      if (callback) callback();
27905    } else {
27906      $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27907      $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback);
27908    }
27909  };
27910
27911  /**
27912   * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the
27913   * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src.
27914   *
27915   * @param $image the image to analyze
27916   * @returns {String} the extracted src
27917   */
27918  JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) {
27919    var imageSrc = $image.data('safe-src');
27920    var imageSrcLoc = 'data-safe-src';
27921    // Begin Uncode edit
27922    if (typeof imageSrc === 'undefined') {
27923    	var imageCurrentSrc = $image[0].currentSrc;
27924    	if (imageCurrentSrc) {
27925    		imageSrc = imageCurrentSrc;
27926    	} else {
27927    		imageSrc = $image.attr('src');
27928    	}
27929		imageSrcLoc = 'src';
27930    }
27931    // End Uncode edit
27932    $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method
27933    $image.data('jg.src', imageSrc); // this will change overtime
27934    $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method
27935    return imageSrc;
27936  };
27937
27938  /** @returns {jQuery} the image in the given entry */
27939  JustifiedGallery.prototype.imgFromEntry = function ($entry) {
27940    var $img = $entry.find(this.settings.imgSelector);
27941    if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode
27942    return $img.length === 0 ? null : $img;
27943  };
27944
27945  /** @returns {jQuery} the caption in the given entry */
27946  JustifiedGallery.prototype.captionFromEntry = function ($entry) {
27947    var $caption = $entry.find('> .jg-caption');
27948    return $caption.length === 0 ? null : $caption;
27949  };
27950
27951  /**
27952   * Display the entry
27953   *
27954   * @param {jQuery} $entry the entry to display
27955   * @param {int} x the x position where the entry must be positioned
27956   * @param y the y position where the entry must be positioned
27957   * @param imgWidth the image width
27958   * @param imgHeight the image height
27959   * @param rowHeight the row height of the row that owns the entry
27960   */
27961  JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) {
27962    $entry.width(imgWidth);
27963    $entry.height(Math.floor(rowHeight));//hacked by Uncode
27964    $entry.css('top', Math.floor(y));//hacked by Uncode
27965    $entry.css('left', x);
27966
27967    var $image = this.imgFromEntry($entry);
27968    if ($image !== null) {
27969      $image.css('width', imgWidth);
27970      $image.css('height', imgHeight);
27971      $image.css('margin-left', - imgWidth / 2);
27972      $image.css('margin-top', - imgHeight / 2);
27973
27974      // Image reloading for an high quality of thumbnails
27975      var imageSrc = $image.data('jg.src');
27976      if (imageSrc) {
27977        imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]);
27978
27979        $image.one('error', function () {
27980           this.resetImgSrc($image); //revert to the original thumbnail
27981        });
27982
27983        var loadNewImage = function () {
27984          // if (imageSrc !== newImageSrc) {
27985            $image.attr('src', imageSrc);
27986          // }
27987        };
27988
27989        if ($entry.data('jg.loaded') === 'skipped' && imageSrc) {
27990          this.onImageEvent(imageSrc, (function() {
27991            this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27992            $entry.data('jg.loaded', true);
27993          }).bind(this));
27994        } else {
27995          this.showImg($entry, loadNewImage); //load the new image after the fadeIn
27996        }
27997
27998      }
27999
28000    } else {
28001      this.showImg($entry);
28002    }
28003
28004    this.displayEntryCaption($entry);
28005  };
28006
28007  /**
28008   * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt'
28009   * or the 'title' attributes.
28010   *
28011   * @param {jQuery} $entry the entry to process
28012   */
28013  JustifiedGallery.prototype.displayEntryCaption = function ($entry) {
28014    var $image = this.imgFromEntry($entry);
28015    if ($image !== null && this.settings.captions) {
28016      var $imgCaption = this.captionFromEntry($entry);
28017
28018      // Create it if it doesn't exists
28019      if ($imgCaption === null) {
28020        var caption = $image.attr('alt');
28021        if (!this.isValidCaption(caption)) caption = $entry.attr('title');
28022        if (this.isValidCaption(caption)) { // Create only we found something
28023          $imgCaption = $('<div class="jg-caption">' + caption + '</div>');
28024          $entry.append($imgCaption);
28025          $entry.data('jg.createdCaption', true);
28026        }
28027      }
28028
28029      // Create events (we check again the $imgCaption because it can be still inexistent)
28030      if ($imgCaption !== null) {
28031        if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity);
28032        this.addCaptionEventsHandlers($entry);
28033      }
28034    } else {
28035      this.removeCaptionEventsHandlers($entry);
28036    }
28037  };
28038
28039  /**
28040   * Validates the caption
28041   *
28042   * @param caption The caption that should be validated
28043   * @return {boolean} Validation result
28044   */
28045  JustifiedGallery.prototype.isValidCaption = function (caption) {
28046    return (typeof caption !== 'undefined' && caption.length > 0);
28047  };
28048
28049  /**
28050   * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry.
28051   * It shows the caption using jQuery (or using CSS if it is configured so)
28052   *
28053   * @param {Event} eventObject the event object
28054   */
28055  JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) {
28056    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28057    if (this.settings.cssAnimation) {
28058      $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden');
28059    } else {
28060      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28061        this.settings.captionSettings.visibleOpacity);
28062    }
28063  };
28064
28065  /**
28066   * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry.
28067   * It hides the caption using jQuery (or using CSS if it is configured so)
28068   *
28069   * @param {Event} eventObject the event object
28070   */
28071  JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) {
28072    var $caption = this.captionFromEntry($(eventObject.currentTarget));
28073    if (this.settings.cssAnimation) {
28074      $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden');
28075    } else {
28076      $caption.stop().fadeTo(this.settings.captionSettings.animationDuration,
28077        this.settings.captionSettings.nonVisibleOpacity);
28078    }
28079  };
28080
28081  /**
28082   * Add the handlers of the entry for the caption
28083   *
28084   * @param $entry the entry to modify
28085   */
28086  JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) {
28087    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28088    if (typeof captionMouseEvents === 'undefined') {
28089      captionMouseEvents = {
28090        mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this),
28091        mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this)
28092      };
28093      $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter);
28094      $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave);
28095      $entry.data('jg.captionMouseEvents', captionMouseEvents);
28096    }
28097  };
28098
28099  /**
28100   * Remove the handlers of the entry for the caption
28101   *
28102   * @param $entry the entry to modify
28103   */
28104  JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) {
28105    var captionMouseEvents = $entry.data('jg.captionMouseEvents');
28106    if (typeof captionMouseEvents !== 'undefined') {
28107      $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter);
28108      $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave);
28109      $entry.removeData('jg.captionMouseEvents');
28110    }
28111  };
28112
28113  /**
28114   * Clear the building row data to be used for a new row
28115   */
28116  JustifiedGallery.prototype.clearBuildingRow = function () {
28117    this.buildingRow.entriesBuff = [];
28118    this.buildingRow.aspectRatio = 0;
28119    this.buildingRow.width = 0;
28120  };
28121
28122  /**
28123   * Justify the building row, preparing it to
28124   *
28125   * @param isLastRow
28126   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28127   * @returns a boolean to know if the row has been justified or not
28128   */
28129  JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) {
28130    var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true;
28131    var minHeight = 0;
28132    var availableWidth = this.galleryWidth - 2 * this.border - (
28133      (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28134    var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode
28135    var defaultRowHeight = this.settings.rowHeight;
28136    var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold;
28137
28138    //Skip the last row if we can't justify it and the lastRow == 'hide'
28139    if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) {
28140      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28141        $entry = this.buildingRow.entriesBuff[i];
28142        if (this.settings.cssAnimation)
28143          $entry.removeClass('jg-entry-visible');
28144        else {
28145          $entry.stop().fadeTo(0, 0.1);
28146          $entry.find('> img, > a > img').fadeTo(0, 0);
28147        }
28148      }
28149      return -1;
28150    }
28151
28152    // With lastRow = nojustify, justify if is justificable (the images will not become too big)
28153    if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') {
28154      justify = false;
28155
28156      if (this.rows > 0) {
28157        defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows;
28158        justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold;
28159      }
28160    }
28161
28162    for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28163      $entry = this.buildingRow.entriesBuff[i];
28164      imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28165
28166      if (justify) {
28167        newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio;
28168        newImgH = rowHeight;
28169      } else {
28170        newImgW = defaultRowHeight * imgAspectRatio;
28171        newImgH = defaultRowHeight;
28172      }
28173
28174      availableWidth -= Math.round(newImgW);
28175      $entry.data('jg.jwidth', Math.round(newImgW));
28176      $entry.data('jg.jheight', Math.ceil(newImgH));
28177      if (i === 0 || minHeight > newImgH) minHeight = newImgH;
28178    }
28179
28180    this.buildingRow.height = minHeight;
28181    return justify;
28182  };
28183
28184  /**
28185   * Flush a row: justify it, modify the gallery height accordingly to the row height
28186   *
28187   * @param isLastRow
28188   * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row.
28189   */
28190  JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) {
28191    var settings = this.settings;
28192    var $entry, buildingRowRes, offX = this.border, i;
28193
28194    buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow);
28195    if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) {
28196      this.clearBuildingRow();
28197      return;
28198    }
28199
28200    if (this.maxRowHeight) {
28201      if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight;
28202    }
28203
28204    //Align last (unjustified) row
28205    if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) {
28206      var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins;
28207
28208      for (i = 0; i < this.buildingRow.entriesBuff.length; i++) {
28209        $entry = this.buildingRow.entriesBuff[i];
28210        availableWidth -= $entry.data('jg.jwidth');
28211      }
28212
28213      if (settings.lastRow === 'center')
28214        offX += Math.round(availableWidth / 2);
28215      else if (settings.lastRow === 'right')
28216        offX += availableWidth;
28217    }
28218
28219    var lastEntryIdx = this.buildingRow.entriesBuff.length - 1;
28220    for (i = 0; i <= lastEntryIdx; i++) {
28221      $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i];
28222      this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height);
28223      offX += $entry.data('jg.jwidth') + settings.margins;
28224    }
28225
28226    //Gallery Height
28227    this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border;
28228    this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight());
28229
28230    if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) {
28231      //Ready for a new row
28232      this.offY += this.buildingRow.height + settings.margins;
28233      this.rows += 1;
28234      this.clearBuildingRow();
28235      this.settings.triggerEvent.call(this, 'jg.rowflush');
28236    }
28237  };
28238
28239
28240  // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221
28241  var galleryPrevStaticHeight = 0;
28242
28243  JustifiedGallery.prototype.rememberGalleryHeight = function () {
28244    galleryPrevStaticHeight = this.$gallery.height();
28245    this.$gallery.height(galleryPrevStaticHeight);
28246  };
28247
28248  // grow only
28249  JustifiedGallery.prototype.setGalleryTempHeight = function (height) {
28250    galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight);
28251    this.$gallery.height(galleryPrevStaticHeight);
28252  };
28253
28254  JustifiedGallery.prototype.setGalleryFinalHeight = function (height) {
28255    galleryPrevStaticHeight = height;
28256    this.$gallery.height(height);
28257  };
28258
28259  /**
28260   * Checks the width of the gallery container, to know if a new justification is needed
28261   */
28262  JustifiedGallery.prototype.checkWidth = function () {
28263    this.checkWidthIntervalId = setInterval($.proxy(function () {
28264
28265      // if the gallery is not currently visible, abort.
28266      if (!this.$gallery.is(":visible")) return;
28267
28268      var galleryWidth = parseFloat(this.$gallery.width());
28269      if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) {
28270        this.galleryWidth = galleryWidth;
28271        this.rewind();
28272
28273        this.rememberGalleryHeight();
28274
28275        // Restart to analyze
28276        this.startImgAnalyzer(true);
28277      }
28278    }, this), this.settings.refreshTime);
28279  };
28280
28281  /**
28282   * @returns {boolean} a boolean saying if the spinner is active or not
28283   */
28284  JustifiedGallery.prototype.isSpinnerActive = function () {
28285    return this.spinner.intervalId !== null;
28286  };
28287
28288  /**
28289   * @returns {int} the spinner height
28290   */
28291  JustifiedGallery.prototype.getSpinnerHeight = function () {
28292    return this.spinner.$el.innerHeight();
28293  };
28294
28295  /**
28296   * Stops the spinner animation and modify the gallery height to exclude the spinner
28297   */
28298  JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () {
28299    clearInterval(this.spinner.intervalId);
28300    this.spinner.intervalId = null;
28301    this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight());
28302    this.spinner.$el.detach();
28303  };
28304
28305  /**
28306   * Starts the spinner animation
28307   */
28308  JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () {
28309    var spinnerContext = this.spinner;
28310    var $spinnerPoints = spinnerContext.$el.find('span');
28311    clearInterval(spinnerContext.intervalId);
28312    this.$gallery.append(spinnerContext.$el);
28313    this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight());
28314    spinnerContext.intervalId = setInterval(function () {
28315      if (spinnerContext.phase < $spinnerPoints.length) {
28316        $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1);
28317      } else {
28318        $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0);
28319      }
28320      spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2);
28321    }, spinnerContext.timeSlot);
28322  };
28323
28324  /**
28325   * Rewind the image analysis to start from the first entry.
28326   */
28327  JustifiedGallery.prototype.rewind = function () {
28328    this.lastFetchedEntry = null;
28329    this.lastAnalyzedIndex = -1;
28330    this.offY = this.border;
28331    this.rows = 0;
28332    this.clearBuildingRow();
28333  };
28334
28335  /**
28336   * @returns {String} `settings.selector` rejecting spinner element
28337   */
28338  JustifiedGallery.prototype.getSelectorWithoutSpinner = function () {
28339    return this.settings.selector + ', div:not(.jg-spinner)';
28340  };
28341
28342  /**
28343   * @returns {Array} all entries matched by `settings.selector`
28344   */
28345  JustifiedGallery.prototype.getAllEntries = function () {
28346    var selector = this.getSelectorWithoutSpinner();
28347    return this.$gallery.children(selector).toArray();
28348  };
28349
28350  /**
28351   * Update the entries searching it from the justified gallery HTML element
28352   *
28353   * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered)
28354   * @returns {boolean} true if some entries has been founded
28355   */
28356  JustifiedGallery.prototype.updateEntries = function (norewind) {
28357    var newEntries;
28358
28359    if (norewind && this.lastFetchedEntry != null) {
28360      var selector = this.getSelectorWithoutSpinner();
28361      newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray();
28362    } else {
28363      this.entries = [];
28364      newEntries = this.getAllEntries();
28365    }
28366
28367    if (newEntries.length > 0) {
28368
28369      // Sort or randomize
28370      if ($.isFunction(this.settings.sort)) {
28371        newEntries = this.sortArray(newEntries);
28372      } else if (this.settings.randomize) {
28373        newEntries = this.shuffleArray(newEntries);
28374      }
28375      this.lastFetchedEntry = newEntries[newEntries.length - 1];
28376
28377      // Filter
28378      if (this.settings.filter) {
28379        newEntries = this.filterArray(newEntries);
28380      } else {
28381        this.resetFilters(newEntries);
28382      }
28383
28384    }
28385
28386    this.entries = this.entries.concat(newEntries);
28387    return true;
28388  };
28389
28390  /**
28391   * Apply the entries order to the DOM, iterating the entries and appending the images
28392   *
28393   * @param entries the entries that has been modified and that must be re-ordered in the DOM
28394   */
28395  JustifiedGallery.prototype.insertToGallery = function (entries) {
28396    var that = this;
28397    $.each(entries, function () {
28398      $(this).appendTo(that.$gallery);
28399    });
28400  };
28401
28402  /**
28403   * Shuffle the array using the Fisher-Yates shuffle algorithm
28404   *
28405   * @param a the array to shuffle
28406   * @return the shuffled array
28407   */
28408  JustifiedGallery.prototype.shuffleArray = function (a) {
28409    var i, j, temp;
28410    for (i = a.length - 1; i > 0; i--) {
28411      j = Math.floor(Math.random() * (i + 1));
28412      temp = a[i];
28413      a[i] = a[j];
28414      a[j] = temp;
28415    }
28416    this.insertToGallery(a);
28417    return a;
28418  };
28419
28420  /**
28421   * Sort the array using settings.comparator as comparator
28422   *
28423   * @param a the array to sort (it is sorted)
28424   * @return the sorted array
28425   */
28426  JustifiedGallery.prototype.sortArray = function (a) {
28427    a.sort(this.settings.sort);
28428    this.insertToGallery(a);
28429    return a;
28430  };
28431
28432  /**
28433   * Reset the filters removing the 'jg-filtered' class from all the entries
28434   *
28435   * @param a the array to reset
28436   */
28437  JustifiedGallery.prototype.resetFilters = function (a) {
28438    for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered');
28439  };
28440
28441  /**
28442   * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering.
28443   *
28444   * @param a the array to filter
28445   * @return the filtered array
28446   */
28447  JustifiedGallery.prototype.filterArray = function (a) {
28448    var settings = this.settings;
28449    if ($.type(settings.filter) === 'string') {
28450      // Filter only keeping the entries passed in the string
28451      return a.filter(function (el) {
28452        var $el = $(el);
28453        if ($el.is(settings.filter)) {
28454          $el.removeClass('jg-filtered');
28455          return true;
28456        } else {
28457          $el.addClass('jg-filtered').removeClass('jg-visible');
28458          return false;
28459        }
28460      });
28461    } else if ($.isFunction(settings.filter)) {
28462      // Filter using the passed function
28463      var filteredArr = a.filter(settings.filter);
28464      for (var i = 0; i < a.length; i++) {
28465        if (filteredArr.indexOf(a[i]) === -1) {
28466          $(a[i]).addClass('jg-filtered').removeClass('jg-visible');
28467        } else {
28468          $(a[i]).removeClass('jg-filtered');
28469        }
28470      }
28471      return filteredArr;
28472    }
28473  };
28474
28475  /**
28476   * Revert the image src to the default value.
28477   */
28478  JustifiedGallery.prototype.resetImgSrc = function ($img) {
28479    if ($img.data('jg.originalSrcLoc') === 'src') {
28480      $img.attr('src', $img.data('jg.originalSrc'));
28481    } else {
28482      $img.attr('src', '');
28483    }
28484  };
28485
28486  /**
28487   * Destroy the Justified Gallery instance.
28488   *
28489   * It clears all the css properties added in the style attributes. We doesn't backup the original
28490   * values for those css attributes, because it costs (performance) and because in general one
28491   * shouldn't use the style attribute for an uniform set of images (where we suppose the use of
28492   * classes). Creating a backup is also difficult because JG could be called multiple times and
28493   * with different style attributes.
28494   */
28495  JustifiedGallery.prototype.destroy = function () {
28496    clearInterval(this.checkWidthIntervalId);
28497    this.stopImgAnalyzerStarter();
28498
28499    // Get fresh entries list since filtered entries are absent in `this.entries`
28500    $.each(this.getAllEntries(), $.proxy(function (_, entry) {
28501      var $entry = $(entry);
28502
28503      // Reset entry style
28504      $entry.css('width', '');
28505      $entry.css('height', '');
28506      $entry.css('top', '');
28507      $entry.css('left', '');
28508      $entry.data('jg.loaded', undefined);
28509      $entry.removeClass('jg-entry jg-filtered jg-entry-visible');
28510
28511      // Reset image style
28512      var $img = this.imgFromEntry($entry);
28513      if ($img) {
28514        $img.css('width', '');
28515        $img.css('height', '');
28516        $img.css('margin-left', '');
28517        $img.css('margin-top', '');
28518        this.resetImgSrc($img);
28519        $img.data('jg.originalSrc', undefined);
28520        $img.data('jg.originalSrcLoc', undefined);
28521        $img.data('jg.src', undefined);
28522      }
28523
28524      // Remove caption
28525      this.removeCaptionEventsHandlers($entry);
28526      var $caption = this.captionFromEntry($entry);
28527      if ($entry.data('jg.createdCaption')) {
28528        // remove also the caption element (if created by jg)
28529        $entry.data('jg.createdCaption', undefined);
28530        if ($caption !== null) $caption.remove();
28531      } else {
28532        if ($caption !== null) $caption.fadeTo(0, 1);
28533      }
28534
28535    }, this));
28536
28537    this.$gallery.css('height', '');
28538    this.$gallery.removeClass('justified-gallery');
28539    this.$gallery.data('jg.controller', undefined);
28540    this.settings.triggerEvent.call(this, 'jg.destroy');
28541  };
28542
28543  /**
28544   * Analyze the images and builds the rows. It returns if it found an image that is not loaded.
28545   *
28546   * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end
28547   */
28548  JustifiedGallery.prototype.analyzeImages = function (isForResize) {
28549    for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) {
28550      var $entry = $(this.entries[i]);
28551      if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') {
28552        var availableWidth = this.galleryWidth - 2 * this.border - (
28553          (this.buildingRow.entriesBuff.length - 1) * this.settings.margins);
28554        var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height');
28555
28556        this.buildingRow.entriesBuff.push($entry);
28557        this.buildingRow.aspectRatio += imgAspectRatio;
28558        this.buildingRow.width += imgAspectRatio * this.settings.rowHeight;
28559        this.lastAnalyzedIndex = i;
28560
28561        if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) {
28562          this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28563
28564          if (++this.yield.flushed >= this.yield.every) {
28565            this.startImgAnalyzer(isForResize);
28566            return;
28567          }
28568        }
28569      } else if ($entry.data('jg.loaded') !== 'error') {
28570        return;
28571      }
28572    }
28573
28574    // Last row flush (the row is not full)
28575    if (this.buildingRow.entriesBuff.length > 0) {
28576      this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount);
28577    }
28578
28579    if (this.isSpinnerActive()) {
28580      this.stopLoadingSpinnerAnimation();
28581    }
28582
28583    /* Stop, if there is, the timeout to start the analyzeImages.
28584     This is because an image can be set loaded, and the timeout can be set,
28585     but this image can be analyzed yet.
28586     */
28587    this.stopImgAnalyzerStarter();
28588
28589    this.setGalleryFinalHeight(this.galleryHeightToSet);
28590
28591    //On complete callback
28592    this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete');
28593  };
28594
28595  /**
28596   * Stops any ImgAnalyzer starter (that has an assigned timeout)
28597   */
28598  JustifiedGallery.prototype.stopImgAnalyzerStarter = function () {
28599    this.yield.flushed = 0;
28600    if (this.imgAnalyzerTimeout !== null) {
28601      clearTimeout(this.imgAnalyzerTimeout);
28602      this.imgAnalyzerTimeout = null;
28603    }
28604  };
28605
28606  /**
28607   * Starts the image analyzer. It is not immediately called to let the browser to update the view
28608   *
28609   * @param isForResize specifies if the image analyzer must be called for resizing or not
28610   */
28611  JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) {
28612    var that = this;
28613    this.stopImgAnalyzerStarter();
28614    this.imgAnalyzerTimeout = setTimeout(function () {
28615      that.analyzeImages(isForResize);
28616    }, 0.001); // we can't start it immediately due to a IE different behaviour
28617  };
28618
28619  /**
28620   * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property,
28621   * because some browsers, with a 404 set complete = true.
28622   *
28623   * @param imageSrc the image src to load
28624   * @param onLoad callback that is called when the image has been loaded
28625   * @param onError callback that is called in case of an error
28626   */
28627  JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) {
28628    if (!onLoad && !onError) return;
28629
28630    var memImage = new Image();
28631    var $memImage = $(memImage);
28632    if (onLoad) {
28633      $memImage.one('load', function () {
28634        $memImage.off('load error');
28635        onLoad(memImage);
28636      });
28637    }
28638    if (onError) {
28639      $memImage.one('error', function () {
28640        $memImage.off('load error');
28641        onError(memImage);
28642      });
28643    }
28644    memImage.src = imageSrc;
28645  };
28646
28647  /**
28648   * Init of Justified Gallery controlled
28649   * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images)
28650   */
28651  JustifiedGallery.prototype.init = function () {
28652    var imagesToLoad = false, skippedImages = false, that = this;
28653    $.each(this.entries, function (index, entry) {
28654      var $entry = $(entry);
28655      var $image = that.imgFromEntry($entry);
28656
28657      $entry.addClass('jg-entry');
28658
28659      if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') {
28660
28661        // Link Rel global overwrite
28662        if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel);
28663
28664        // Link Target global overwrite
28665        if (that.settings.target !== null) $entry.attr('target', that.settings.target);
28666
28667        if ($image !== null) {
28668
28669          // Image src
28670          var imageSrc = that.extractImgSrcFromImage($image);
28671
28672          /* If we have the height and the width, we don't wait that the image is loaded,
28673             but we start directly with the justification */
28674          if (that.settings.waitThumbnailsLoad === false || !imageSrc) {
28675            var width = parseFloat($image.attr('width'));
28676            var height = parseFloat($image.attr('height'));
28677            if ($image.prop('tagName') === 'svg') {
28678              width = parseFloat($image[0].getBBox().width);
28679              height = parseFloat($image[0].getBBox().height);
28680            }
28681            if (!isNaN(width) && !isNaN(height)) {
28682              $entry.data('jg.width', width);
28683              $entry.data('jg.height', height);
28684              $entry.data('jg.loaded', 'skipped');
28685              skippedImages = true;
28686              that.startImgAnalyzer(false);
28687              return true; // continue
28688            }
28689          }
28690
28691          $entry.data('jg.loaded', false);
28692          imagesToLoad = true;
28693
28694          // Spinner start
28695          if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation();
28696
28697          that.onImageEvent(imageSrc, function (loadImg) { // image loaded
28698            $entry.data('jg.width', loadImg.width);
28699            $entry.data('jg.height', loadImg.height);
28700            $entry.data('jg.loaded', true);
28701            that.startImgAnalyzer(false);
28702          }, function () { // image load error
28703            $entry.data('jg.loaded', 'error');
28704            that.startImgAnalyzer(false);
28705          });
28706
28707        } else {
28708          $entry.data('jg.loaded', true);
28709          $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1);
28710          $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1);
28711        }
28712
28713      }
28714
28715    });
28716
28717    if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false);
28718    this.checkWidth();
28719  };
28720
28721  /**
28722   * Checks that it is a valid number. If a string is passed it is converted to a number
28723   *
28724   * @param settingContainer the object that contains the setting (to allow the conversion)
28725   * @param settingName the setting name
28726   */
28727  JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) {
28728    if ($.type(settingContainer[settingName]) === 'string') {
28729      settingContainer[settingName] = parseFloat(settingContainer[settingName]);
28730    }
28731
28732    if ($.type(settingContainer[settingName]) === 'number') {
28733      if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName;
28734    } else {
28735      throw settingName + ' must be a number';
28736    }
28737  };
28738
28739  /**
28740   * Checks the sizeRangeSuffixes and, if necessary, converts
28741   * its keys from string (e.g. old settings with 'lt100') to int.
28742   */
28743  JustifiedGallery.prototype.checkSizeRangesSuffixes = function () {
28744    if ($.type(this.settings.sizeRangeSuffixes) !== 'object') {
28745      throw 'sizeRangeSuffixes must be defined and must be an object';
28746    }
28747
28748    var suffixRanges = [];
28749    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28750      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx);
28751    }
28752
28753    var newSizeRngSuffixes = { 0: '' };
28754    for (var i = 0; i < suffixRanges.length; i++) {
28755      if ($.type(suffixRanges[i]) === 'string') {
28756        try {
28757          var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10);
28758          newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28759        } catch (e) {
28760          throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')';
28761        }
28762      } else {
28763        newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]];
28764      }
28765    }
28766
28767    this.settings.sizeRangeSuffixes = newSizeRngSuffixes;
28768  };
28769
28770  /**
28771   * check and convert the maxRowHeight setting
28772   * requires rowHeight to be already set
28773   * TODO: should be always called when only rowHeight is changed
28774   * @return number or null
28775   */
28776  JustifiedGallery.prototype.retrieveMaxRowHeight = function () {
28777    var newMaxRowHeight = null;
28778    var rowHeight = this.settings.rowHeight;
28779
28780    if ($.type(this.settings.maxRowHeight) === 'string') {
28781      if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) {
28782        newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100;
28783      } else {
28784        newMaxRowHeight = parseFloat(this.settings.maxRowHeight);
28785      }
28786    } else if ($.type(this.settings.maxRowHeight) === 'number') {
28787      newMaxRowHeight = this.settings.maxRowHeight;
28788    } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) {
28789      return null;
28790    } else {
28791      throw 'maxRowHeight must be a number or a percentage';
28792    }
28793
28794    // check if the converted value is not a number
28795    if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight';
28796
28797    // check values, maxRowHeight must be >= rowHeight
28798    if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight;
28799
28800    return newMaxRowHeight;
28801  };
28802
28803  /**
28804   * Checks the settings
28805   */
28806  JustifiedGallery.prototype.checkSettings = function () {
28807    this.checkSizeRangesSuffixes();
28808
28809    this.checkOrConvertNumber(this.settings, 'rowHeight');
28810    this.checkOrConvertNumber(this.settings, 'margins');
28811    this.checkOrConvertNumber(this.settings, 'border');
28812    this.checkOrConvertNumber(this.settings, 'maxRowsCount');
28813
28814    var lastRowModes = [
28815      'justify',
28816      'nojustify',
28817      'left',
28818      'center',
28819      'right',
28820      'hide'
28821    ];
28822    if (lastRowModes.indexOf(this.settings.lastRow) === -1) {
28823      throw 'lastRow must be one of: ' + lastRowModes.join(', ');
28824    }
28825
28826    this.checkOrConvertNumber(this.settings, 'justifyThreshold');
28827    if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) {
28828      throw 'justifyThreshold must be in the interval [0,1]';
28829    }
28830    if ($.type(this.settings.cssAnimation) !== 'boolean') {
28831      throw 'cssAnimation must be a boolean';
28832    }
28833
28834    if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean';
28835    this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration');
28836
28837    this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity');
28838    if (this.settings.captionSettings.visibleOpacity < 0 ||
28839      this.settings.captionSettings.visibleOpacity > 1) {
28840      throw 'captionSettings.visibleOpacity must be in the interval [0, 1]';
28841    }
28842
28843    this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity');
28844    if (this.settings.captionSettings.nonVisibleOpacity < 0 ||
28845      this.settings.captionSettings.nonVisibleOpacity > 1) {
28846      throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]';
28847    }
28848
28849    this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration');
28850    this.checkOrConvertNumber(this.settings, 'refreshTime');
28851    this.checkOrConvertNumber(this.settings, 'refreshSensitivity');
28852    if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean';
28853    if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string';
28854
28855    if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) {
28856      throw 'sort must be false or a comparison function';
28857    }
28858
28859    if (this.settings.filter !== false && !$.isFunction(this.settings.filter) &&
28860      $.type(this.settings.filter) !== 'string') {
28861      throw 'filter must be false, a string or a filter function';
28862    }
28863  };
28864
28865  /**
28866   * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned.
28867   * @returns {Array} sorted suffix ranges
28868   */
28869  JustifiedGallery.prototype.retrieveSuffixRanges = function () {
28870    var suffixRanges = [];
28871    for (var rangeIdx in this.settings.sizeRangeSuffixes) {
28872      if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10));
28873    }
28874    suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; });
28875    return suffixRanges;
28876  };
28877
28878  /**
28879   * Update the existing settings only changing some of them
28880   *
28881   * @param newSettings the new settings (or a subgroup of them)
28882   */
28883  JustifiedGallery.prototype.updateSettings = function (newSettings) {
28884    // In this case Justified Gallery has been called again changing only some options
28885    this.settings = $.extend({}, this.settings, newSettings);
28886    this.checkSettings();
28887
28888    // As reported in the settings: negative value = same as margins, 0 = disabled
28889    this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins;
28890
28891    this.maxRowHeight = this.retrieveMaxRowHeight();
28892    this.suffixRanges = this.retrieveSuffixRanges();
28893  };
28894
28895  JustifiedGallery.prototype.defaults = {
28896    sizeRangeSuffixes: {}, /* e.g. Flickr configuration
28897        {
28898          100: '_t',  // used when longest is less than 100px
28899          240: '_m',  // used when longest is between 101px and 240px
28900          320: '_n',  // ...
28901          500: '',
28902          640: '_z',
28903          1024: '_b'  // used as else case because it is the last
28904        }
28905    */
28906    thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the
28907    path relative to a specific thumbnail size. The function should accept respectively three arguments:
28908    current path, width and height */
28909    rowHeight: 120, // required? required to be > 0?
28910    maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels,
28911    // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height
28912    // can't exceed 3 * rowHeight)
28913    maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled)
28914    margins: 1,
28915    border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border
28916
28917    lastRow: 'nojustify', // … which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide'
28918
28919    justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified
28920                             * (i.e. lastRow setting is not considered) */
28921    waitThumbnailsLoad: true,
28922    captions: true,
28923    cssAnimation: true,
28924    imagesAnimationDuration: 500, // ignored with css animations
28925    captionSettings: { // ignored with css animations
28926      animationDuration: 500,
28927      visibleOpacity: 0.7,
28928      nonVisibleOpacity: 0.0
28929    },
28930    rel: null, // rewrite the rel of each analyzed links
28931    target: null, // rewrite the target of all links
28932    extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image
28933    refreshTime: 200, // time interval (in ms) to check if the page changes its width
28934    refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery
28935    randomize: false,
28936    rtl: false, // right-to-left mode
28937    sort: false, /*
28938      - false: to do not sort
28939      - function: to sort them using the function as comparator (see Array.prototype.sort())
28940    */
28941    filter: false, /*
28942      - false, null or undefined: for a disabled filter
28943      - a string: an entry is kept if entry.is(filter string) returns true
28944                  see jQuery's .is() function for further information
28945      - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise.
28946                    It follows the specifications of the Array.prototype.filter() function of JavaScript.
28947    */
28948    selector: 'a', // The selector that is used to know what are the entries of the gallery
28949    imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry
28950    triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger
28951      this.$gallery.trigger(event);  // Consider that 'this' is this set to the JustifiedGallery object, so it can
28952    }                                // access to fields such as $gallery, useful to trigger events with jQuery.
28953  };
28954
28955
28956  /**
28957   * Justified Gallery plugin for jQuery
28958   *
28959   * Events
28960   *  - jg.complete : called when all the gallery has been created
28961   *  - jg.resize : called when the gallery has been resized
28962   *  - jg.rowflush : when a new row appears
28963   *
28964   * @param arg the action (or the settings) passed when the plugin is called
28965   * @returns {*} the object itself
28966   */
28967  $.fn.justifiedGallery = function (arg) {
28968    return this.each(function (index, gallery) {
28969
28970      var $gallery = $(gallery);
28971      $gallery.addClass('justified-gallery');
28972
28973      var controller = $gallery.data('jg.controller');
28974      if (typeof controller === 'undefined') {
28975        // Create controller and assign it to the object data
28976        if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') {
28977          if (arg === 'destroy') return; // Just a call to an unexisting object
28978          throw 'The argument must be an object';
28979        }
28980        controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg));
28981        $gallery.data('jg.controller', controller);
28982      } else if (arg === 'norewind') {
28983        // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row
28984        // ... left to be more readable
28985      } else if (arg === 'destroy') {
28986        controller.destroy();
28987        return;
28988      } else {
28989        // In this case Justified Gallery has been called again changing only some options
28990        controller.updateSettings(arg);
28991        controller.rewind();
28992      }
28993
28994      // Update the entries list
28995      if (!controller.updateEntries(arg === 'norewind')) return;
28996
28997      // Init justified gallery
28998      controller.init();
28999
29000    });
29001  };
29002
29003}));
29004
29005/*!
29006* Customized version of iScroll.js 0.0.1
29007* It fixes bugs affecting its integration with fullpage.js
29008*/
29009/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */
29010(function (window, document, Math) {
29011var rAF = window.requestAnimationFrame  ||
29012    window.webkitRequestAnimationFrame  ||
29013    window.mozRequestAnimationFrame     ||
29014    window.oRequestAnimationFrame       ||
29015    window.msRequestAnimationFrame      ||
29016    function (callback) { window.setTimeout(callback, 1000 / 60); };
29017
29018var utils = (function () {
29019    var me = {};
29020
29021    var _elementStyle = document.createElement('div').style;
29022    var _vendor = (function () {
29023        var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
29024            transform,
29025            i = 0,
29026            l = vendors.length;
29027
29028        for ( ; i < l; i++ ) {
29029            transform = vendors[i] + 'ransform';
29030            if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
29031        }
29032
29033        return false;
vendor: 5,154 bytes, lines 29034-29186
29034    })();
29035
29036    function _prefixStyle (style) {
29037        if ( _vendor === false ) return false;
29038        if ( _vendor === '' ) return style;
29039        return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
29040    }
29041
29042    me.getTime = Date.now || function getTime () { return new Date().getTime(); };
29043
29044    me.extend = function (target, obj) {
29045        for ( var i in obj ) {
29046            target[i] = obj[i];
29047        }
29048    };
29049
29050    me.addEvent = function (el, type, fn, capture) {
29051        el.addEventListener(type, fn, !!capture);
29052    };
29053
29054    me.removeEvent = function (el, type, fn, capture) {
29055        el.removeEventListener(type, fn, !!capture);
29056    };
29057
29058    me.prefixPointerEvent = function (pointerEvent) {
29059        return window.MSPointerEvent ?
29060            'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):
29061            pointerEvent;
29062    };
29063
29064    me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
29065        var distance = current - start,
29066            speed = Math.abs(distance) / time,
29067            destination,
29068            duration;
29069
29070        deceleration = deceleration === undefined ? 0.0006 : deceleration;
29071
29072        destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
29073        duration = speed / deceleration;
29074
29075        if ( destination < lowerMargin ) {
29076            destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
29077            distance = Math.abs(destination - current);
29078            duration = distance / speed;
29079        } else if ( destination > 0 ) {
29080            destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
29081            distance = Math.abs(current) + destination;
29082            duration = distance / speed;
29083        }
29084
29085        return {
29086            destination: Math.round(destination),
29087            duration: duration
29088        };
29089    };
29090
29091    var _transform = _prefixStyle('transform');
29092
29093    me.extend(me, {
29094        hasTransform: _transform !== false,
29095        hasPerspective: _prefixStyle('perspective') in _elementStyle,
29096        hasTouch: 'ontouchstart' in window,
29097        hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed
29098        hasTransition: _prefixStyle('transition') in _elementStyle
29099    });
29100
29101    /*
29102    This should find all Android browsers lower than build 535.19 (both stock browser and webview)
29103    - galaxy S2 is ok
29104    - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`
29105    - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29106   - galaxy S3 is badAndroid (stock brower, webview)
29107     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29108   - galaxy S4 is badAndroid (stock brower, webview)
29109     `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`
29110   - galaxy S5 is OK
29111     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29112   - galaxy S6 is OK
29113     `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`
29114  */
29115    me.isBadAndroid = (function() {
29116        var appVersion = window.navigator.appVersion;
29117        // Android browser is not a chrome browser.
29118        if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) {
29119            var safariVersion = appVersion.match(/Safari\/(\d+.\d)/);
29120            if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) {
29121                return parseFloat(safariVersion[1]) < 535.19;
29122            } else {
29123                return true;
29124            }
29125        } else {
29126            return false;
29127        }
29128    })();
29129
29130    me.extend(me.style = {}, {
29131        transform: _transform,
29132        transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
29133        transitionDuration: _prefixStyle('transitionDuration'),
29134        transitionDelay: _prefixStyle('transitionDelay'),
29135        transformOrigin: _prefixStyle('transformOrigin')
29136    });
29137
29138    me.hasClass = function (e, c) {
29139        var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
29140        return re.test(e.className);
29141    };
29142
29143    me.addClass = function (e, c) {
29144        if ( me.hasClass(e, c) ) {
29145            return;
29146        }
29147
29148        var newclass = e.className.split(' ');
29149        newclass.push(c);
29150        e.className = newclass.join(' ');
29151    };
29152
29153    me.removeClass = function (e, c) {
29154        if ( !me.hasClass(e, c) ) {
29155            return;
29156        }
29157
29158        var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
29159        e.className = e.className.replace(re, ' ');
29160    };
29161
29162    me.offset = function (el) {
29163        var left = -el.offsetLeft,
29164            top = -el.offsetTop;
29165
29166        // jshint -W084
29167        while (el = el.offsetParent) {
29168            left -= el.offsetLeft;
29169            top -= el.offsetTop;
29170        }
29171        // jshint +W084
29172
29173        return {
29174            left: left,
29175            top: top
29176        };
29177    };
29178
29179    me.preventDefaultException = function (el, exceptions) {
29180        for ( var i in exceptions ) {
29181            if ( exceptions[i].test(el[i]) ) {
29182                return true;
29183            }
29184        }
29185
29186        return false;
vendor: 5,660 bytes, lines 29187-29352
29187    };
29188
29189    me.extend(me.eventType = {}, {
29190        touchstart: 1,
29191        touchmove: 1,
29192        touchend: 1,
29193
29194        mousedown: 2,
29195        mousemove: 2,
29196        mouseup: 2,
29197
29198        pointerdown: 3,
29199        pointermove: 3,
29200        pointerup: 3,
29201
29202        MSPointerDown: 3,
29203        MSPointerMove: 3,
29204        MSPointerUp: 3
29205    });
29206
29207    me.extend(me.ease = {}, {
29208        quadratic: {
29209            style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
29210            fn: function (k) {
29211                return k * ( 2 - k );
29212            }
29213        },
29214        circular: {
29215            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)
29216            fn: function (k) {
29217                return Math.sqrt( 1 - ( --k * k ) );
29218            }
29219        },
29220        back: {
29221            style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
29222            fn: function (k) {
29223                var b = 4;
29224                return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
29225            }
29226        },
29227        bounce: {
29228            style: '',
29229            fn: function (k) {
29230                if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
29231                    return 7.5625 * k * k;
29232                } else if ( k < ( 2 / 2.75 ) ) {
29233                    return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
29234                } else if ( k < ( 2.5 / 2.75 ) ) {
29235                    return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
29236                } else {
29237                    return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
29238                }
29239            }
29240        },
29241        elastic: {
29242            style: '',
29243            fn: function (k) {
29244                var f = 0.22,
29245                    e = 0.4;
29246
29247                if ( k === 0 ) { return 0; }
29248                if ( k == 1 ) { return 1; }
29249
29250                return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
29251            }
29252        }
29253    });
29254
29255    me.tap = function (e, eventName) {
29256        var ev = document.createEvent('Event');
29257        ev.initEvent(eventName, true, true);
29258        ev.pageX = e.pageX;
29259        ev.pageY = e.pageY;
29260        e.target.dispatchEvent(ev);
29261    };
29262
29263    me.click = function (e) {
29264        var target = e.target,
29265            ev;
29266
29267        if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
29268            // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent
29269            // initMouseEvent is deprecated.
29270            ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event');
29271            ev.initEvent('click', true, true);
29272            ev.view = e.view || window;
29273            ev.detail = 1;
29274            ev.screenX = target.screenX || 0;
29275            ev.screenY = target.screenY || 0;
29276            ev.clientX = target.clientX || 0;
29277            ev.clientY = target.clientY || 0;
29278            ev.ctrlKey = !!e.ctrlKey;
29279            ev.altKey = !!e.altKey;
29280            ev.shiftKey = !!e.shiftKey;
29281            ev.metaKey = !!e.metaKey;
29282            ev.button = 0;
29283            ev.relatedTarget = null;
29284            ev._constructed = true;
29285            target.dispatchEvent(ev);
29286        }
29287    };
29288
29289    return me;
29290})();
29291function IScroll (el, options) {
29292    this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
29293    this.scroller = this.wrapper.children[0];
29294    this.scrollerStyle = this.scroller.style;       // cache style for better performance
29295
29296    this.options = {
29297
29298        resizeScrollbars: true,
29299
29300        mouseWheelSpeed: 20,
29301
29302        snapThreshold: 0.334,
29303
29304// INSERT POINT: OPTIONS
29305        disablePointer : !utils.hasPointer,
29306        disableTouch : utils.hasPointer || !utils.hasTouch,
29307        disableMouse : utils.hasPointer || utils.hasTouch,
29308        startX: 0,
29309        startY: 0,
29310        scrollY: true,
29311        directionLockThreshold: 5,
29312        momentum: true,
29313
29314        bounce: true,
29315        bounceTime: 600,
29316        bounceEasing: '',
29317
29318        preventDefault: true,
29319        preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ },
29320
29321        HWCompositing: true,
29322        useTransition: true,
29323        useTransform: true,
29324        bindToWrapper: typeof window.onmousedown === "undefined"
29325    };
29326
29327    for ( var i in options ) {
29328        this.options[i] = options[i];
29329    }
29330
29331    // Normalize options
29332    this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
29333
29334    this.options.useTransition = utils.hasTransition && this.options.useTransition;
29335    this.options.useTransform = utils.hasTransform && this.options.useTransform;
29336
29337    this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
29338    this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
29339
29340    // If you want eventPassthrough I have to lock one of the axes
29341    this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
29342    this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
29343
29344    // With eventPassthrough we also need lockDirection mechanism
29345    this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
29346    this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
29347
29348    this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
29349
29350    this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
29351
29352    if ( this.options.tap === true ) {
vendor: 4,893 bytes, lines 29353-29524
29353        this.options.tap = 'tap';
29354    }
29355
29356    // https://github.com/cubiq/iscroll/issues/1029
29357    if (!this.options.useTransition && !this.options.useTransform) {
29358        if(!(/relative|absolute/i).test(this.scrollerStyle.position)) {
29359            this.scrollerStyle.position = "relative";
29360        }
29361    }
29362
29363    if ( this.options.shrinkScrollbars == 'scale' ) {
29364        this.options.useTransition = false;
29365    }
29366
29367    this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
29368
29369// INSERT POINT: NORMALIZATION
29370
29371    // Some defaults
29372    this.x = 0;
29373    this.y = 0;
29374    this.directionX = 0;
29375    this.directionY = 0;
29376    this._events = {};
29377
29378// INSERT POINT: DEFAULTS
29379
29380    this._init();
29381    this.refresh();
29382
29383    this.scrollTo(this.options.startX, this.options.startY);
29384    this.enable();
29385}
29386
29387IScroll.prototype = {
29388    version: '5.2.0',
29389
29390    _init: function () {
29391        this._initEvents();
29392
29393        if ( this.options.scrollbars || this.options.indicators ) {
29394            this._initIndicators();
29395        }
29396
29397        if ( this.options.mouseWheel ) {
29398            this._initWheel();
29399        }
29400
29401        if ( this.options.snap ) {
29402            this._initSnap();
29403        }
29404
29405        if ( this.options.keyBindings ) {
29406            this._initKeys();
29407        }
29408
29409// INSERT POINT: _init
29410
29411    },
29412
29413    destroy: function () {
29414        this._initEvents(true);
29415        clearTimeout(this.resizeTimeout);
29416        this.resizeTimeout = null;
29417        this._execEvent('destroy');
29418    },
29419
29420    _transitionEnd: function (e) {
29421        if ( e.target != this.scroller || !this.isInTransition ) {
29422            return;
29423        }
29424
29425        this._transitionTime();
29426        if ( !this.resetPosition(this.options.bounceTime) ) {
29427            this.isInTransition = false;
29428            this._execEvent('scrollEnd');
29429        }
29430    },
29431
29432    _start: function (e) {
29433        // React to left mouse button only
29434        if ( utils.eventType[e.type] != 1 ) {
29435          // for button property
29436          // http://unixpapa.com/js/mouse.html
29437          var button;
29438        if (!e.which) {
29439          /* IE case */
29440          button = (e.button < 2) ? 0 :
29441                   ((e.button == 4) ? 1 : 2);
29442        } else {
29443          /* All others */
29444          button = e.button;
29445        }
29446            if ( button !== 0 ) {
29447                return;
29448            }
29449        }
29450
29451        if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
29452            return;
29453        }
29454
29455        if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29456            e.preventDefault();
29457        }
29458
29459        var point = e.touches ? e.touches[0] : e,
29460            pos;
29461
29462        this.initiated  = utils.eventType[e.type];
29463        this.moved      = false;
29464        this.distX      = 0;
29465        this.distY      = 0;
29466        this.directionX = 0;
29467        this.directionY = 0;
29468        this.directionLocked = 0;
29469
29470        this.startTime = utils.getTime();
29471
29472        if ( this.options.useTransition && this.isInTransition ) {
29473            this._transitionTime();
29474            this.isInTransition = false;
29475            pos = this.getComputedPosition();
29476            this._translate(Math.round(pos.x), Math.round(pos.y));
29477            this._execEvent('scrollEnd');
29478        } else if ( !this.options.useTransition && this.isAnimating ) {
29479            this.isAnimating = false;
29480            this._execEvent('scrollEnd');
29481        }
29482
29483        this.startX    = this.x;
29484        this.startY    = this.y;
29485        this.absStartX = this.x;
29486        this.absStartY = this.y;
29487        this.pointX    = point.pageX;
29488        this.pointY    = point.pageY;
29489
29490        this._execEvent('beforeScrollStart');
29491    },
29492
29493    _move: function (e) {
29494        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29495            return;
29496        }
29497
29498        if ( this.options.preventDefault ) {    // increases performance on Android? TODO: check!
29499            e.preventDefault();
29500        }
29501
29502        var point       = e.touches ? e.touches[0] : e,
29503            deltaX      = point.pageX - this.pointX,
29504            deltaY      = point.pageY - this.pointY,
29505            timestamp   = utils.getTime(),
29506            newX, newY,
29507            absDistX, absDistY;
29508
29509        this.pointX     = point.pageX;
29510        this.pointY     = point.pageY;
29511
29512        this.distX      += deltaX;
29513        this.distY      += deltaY;
29514        absDistX        = Math.abs(this.distX);
29515        absDistY        = Math.abs(this.distY);
29516
29517        // We need to move at least 10 pixels for the scrolling to initiate
29518        if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
29519            return;
29520        }
29521
29522        // If you are scrolling in one direction lock the other
29523        if ( !this.directionLocked && !this.options.freeScroll ) {
29524            if ( absDistX > absDistY + this.options.directionLockThreshold ) {
vendor: 6,057 bytes, lines 29525-29711
29525                this.directionLocked = 'h';     // lock horizontally
29526            } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
29527                this.directionLocked = 'v';     // lock vertically
29528            } else {
29529                this.directionLocked = 'n';     // no lock
29530            }
29531        }
29532
29533        if ( this.directionLocked == 'h' ) {
29534            if ( this.options.eventPassthrough == 'vertical' ) {
29535                e.preventDefault();
29536            } else if ( this.options.eventPassthrough == 'horizontal' ) {
29537                this.initiated = false;
29538                return;
29539            }
29540
29541            deltaY = 0;
29542        } else if ( this.directionLocked == 'v' ) {
29543            if ( this.options.eventPassthrough == 'horizontal' ) {
29544                e.preventDefault();
29545            } else if ( this.options.eventPassthrough == 'vertical' ) {
29546                this.initiated = false;
29547                return;
29548            }
29549
29550            deltaX = 0;
29551        }
29552
29553        deltaX = this.hasHorizontalScroll ? deltaX : 0;
29554        deltaY = this.hasVerticalScroll ? deltaY : 0;
29555
29556        newX = this.x + deltaX;
29557        newY = this.y + deltaY;
29558
29559        // Slow down if outside of the boundaries
29560        if ( newX > 0 || newX < this.maxScrollX ) {
29561            newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
29562        }
29563        if ( newY > 0 || newY < this.maxScrollY ) {
29564            newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
29565        }
29566
29567        this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
29568        this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
29569
29570        if ( !this.moved ) {
29571            this._execEvent('scrollStart');
29572        }
29573
29574        this.moved = true;
29575
29576        this._translate(newX, newY);
29577
29578/* REPLACE START: _move */
29579
29580        if ( timestamp - this.startTime > 300 ) {
29581            this.startTime = timestamp;
29582            this.startX = this.x;
29583            this.startY = this.y;
29584        }
29585
29586/* REPLACE END: _move */
29587
29588    },
29589
29590    _end: function (e) {
29591        if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
29592            return;
29593        }
29594
29595        if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
29596            e.preventDefault();
29597        }
29598
29599        var point = e.changedTouches ? e.changedTouches[0] : e,
29600            momentumX,
29601            momentumY,
29602            duration = utils.getTime() - this.startTime,
29603            newX = Math.round(this.x),
29604            newY = Math.round(this.y),
29605            distanceX = Math.abs(newX - this.startX),
29606            distanceY = Math.abs(newY - this.startY),
29607            time = 0,
29608            easing = '';
29609
29610        this.isInTransition = 0;
29611        this.initiated = 0;
29612        this.endTime = utils.getTime();
29613
29614        // reset if we are outside of the boundaries
29615        if ( this.resetPosition(this.options.bounceTime) ) {
29616            return;
29617        }
29618
29619        this.scrollTo(newX, newY);  // ensures that the last position is rounded
29620
29621        // we scrolled less than 10 pixels
29622        if ( !this.moved ) {
29623            if ( this.options.tap ) {
29624                utils.tap(e, this.options.tap);
29625            }
29626
29627            if ( this.options.click ) {
29628                utils.click(e);
29629            }
29630
29631            this._execEvent('scrollCancel');
29632            return;
29633        }
29634
29635        if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
29636            this._execEvent('flick');
29637            return;
29638        }
29639
29640        // start momentum animation if needed
29641        if ( this.options.momentum && duration < 300 ) {
29642            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 };
29643            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 };
29644            newX = momentumX.destination;
29645            newY = momentumY.destination;
29646            time = Math.max(momentumX.duration, momentumY.duration);
29647            this.isInTransition = 1;
29648        }
29649
29650
29651        if ( this.options.snap ) {
29652            var snap = this._nearestSnap(newX, newY);
29653            this.currentPage = snap;
29654            time = this.options.snapSpeed || Math.max(
29655                    Math.max(
29656                        Math.min(Math.abs(newX - snap.x), 1000),
29657                        Math.min(Math.abs(newY - snap.y), 1000)
29658                    ), 300);
29659            newX = snap.x;
29660            newY = snap.y;
29661
29662            this.directionX = 0;
29663            this.directionY = 0;
29664            easing = this.options.bounceEasing;
29665        }
29666
29667// INSERT POINT: _end
29668
29669        if ( newX != this.x || newY != this.y ) {
29670            // change easing function when scroller goes out of the boundaries
29671            if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
29672                easing = utils.ease.quadratic;
29673            }
29674
29675            this.scrollTo(newX, newY, time, easing);
29676            return;
29677        }
29678
29679        this._execEvent('scrollEnd');
29680    },
29681
29682    _resize: function () {
29683        var that = this;
29684
29685        clearTimeout(this.resizeTimeout);
29686
29687        this.resizeTimeout = setTimeout(function () {
29688            that.refresh();
29689        }, this.options.resizePolling);
29690    },
29691
29692    resetPosition: function (time) {
29693        var x = this.x,
29694            y = this.y;
29695
29696        time = time || 0;
29697
29698        if ( !this.hasHorizontalScroll || this.x > 0 ) {
29699            x = 0;
29700        } else if ( this.x < this.maxScrollX ) {
29701            x = this.maxScrollX;
29702        }
29703
29704        if ( !this.hasVerticalScroll || this.y > 0 ) {
29705            y = 0;
29706        } else if ( this.y < this.maxScrollY ) {
29707            y = this.maxScrollY;
29708        }
29709
29710        if ( x == this.x && y == this.y ) {
29711            return false;
vendor: 5,509 bytes, lines 29712-29916
29712        }
29713
29714        this.scrollTo(x, y, time, this.options.bounceEasing);
29715
29716        return true;
29717    },
29718
29719    disable: function () {
29720        this.enabled = false;
29721    },
29722
29723    enable: function () {
29724        this.enabled = true;
29725    },
29726
29727    refresh: function () {
29728        var rf = this.wrapper.offsetHeight;     // Force reflow
29729
29730        this.wrapperWidth   = this.wrapper.clientWidth;
29731        this.wrapperHeight  = this.wrapper.clientHeight;
29732
29733/* REPLACE START: refresh */
29734
29735        this.scrollerWidth  = this.scroller.offsetWidth;
29736        this.scrollerHeight = this.scroller.offsetHeight;
29737
29738        this.maxScrollX     = this.wrapperWidth - this.scrollerWidth;
29739        this.maxScrollY     = this.wrapperHeight - this.scrollerHeight;
29740
29741/* REPLACE END: refresh */
29742
29743        this.hasHorizontalScroll    = this.options.scrollX && this.maxScrollX < 0;
29744        this.hasVerticalScroll      = this.options.scrollY && this.maxScrollY < 0;
29745
29746        if ( !this.hasHorizontalScroll ) {
29747            this.maxScrollX = 0;
29748            this.scrollerWidth = this.wrapperWidth;
29749        }
29750
29751        if ( !this.hasVerticalScroll ) {
29752            this.maxScrollY = 0;
29753            this.scrollerHeight = this.wrapperHeight;
29754        }
29755
29756        this.endTime = 0;
29757        this.directionX = 0;
29758        this.directionY = 0;
29759
29760        this.wrapperOffset = utils.offset(this.wrapper);
29761
29762        this._execEvent('refresh');
29763
29764        this.resetPosition();
29765
29766// INSERT POINT: _refresh
29767
29768    },
29769
29770
29771    on: function (type, fn) {
29772        if ( !this._events[type] ) {
29773            this._events[type] = [];
29774        }
29775
29776        this._events[type].push(fn);
29777    },
29778
29779    off: function (type, fn) {
29780        if ( !this._events[type] ) {
29781            return;
29782        }
29783
29784        var index = this._events[type].indexOf(fn);
29785
29786        if ( index > -1 ) {
29787            this._events[type].splice(index, 1);
29788        }
29789    },
29790
29791    _execEvent: function (type) {
29792        if ( !this._events[type] ) {
29793            return;
29794        }
29795
29796        var i = 0,
29797            l = this._events[type].length;
29798
29799        if ( !l ) {
29800            return;
29801        }
29802
29803        for ( ; i < l; i++ ) {
29804            this._events[type][i].apply(this, [].slice.call(arguments, 1));
29805        }
29806    },
29807
29808    scrollBy: function (x, y, time, easing) {
29809        x = this.x + x;
29810        y = this.y + y;
29811        time = time || 0;
29812
29813        this.scrollTo(x, y, time, easing);
29814    },
29815
29816    scrollTo: function (x, y, time, easing) {
29817        easing = easing || utils.ease.circular;
29818
29819        this.isInTransition = this.options.useTransition && time > 0;
29820        var transitionType = this.options.useTransition && easing.style;
29821        if ( !time || transitionType ) {
29822                if(transitionType) {
29823                    this._transitionTimingFunction(easing.style);
29824                    this._transitionTime(time);
29825                }
29826            this._translate(x, y);
29827        } else {
29828            this._animate(x, y, time, easing.fn);
29829        }
29830    },
29831
29832    scrollToElement: function (el, time, offsetX, offsetY, easing) {
29833        el = el.nodeType ? el : this.scroller.querySelector(el);
29834
29835        if ( !el ) {
29836            return;
29837        }
29838
29839        var pos = utils.offset(el);
29840
29841        pos.left -= this.wrapperOffset.left;
29842        pos.top  -= this.wrapperOffset.top;
29843
29844        // if offsetX/Y are true we center the element to the screen
29845        if ( offsetX === true ) {
29846            offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
29847        }
29848        if ( offsetY === true ) {
29849            offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
29850        }
29851
29852        pos.left -= offsetX || 0;
29853        pos.top  -= offsetY || 0;
29854
29855        pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
29856        pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
29857
29858        time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
29859
29860        this.scrollTo(pos.left, pos.top, time, easing);
29861    },
29862
29863    _transitionTime: function (time) {
29864        if (!this.options.useTransition) {
29865            return;
29866        }
29867        time = time || 0;
29868        var durationProp = utils.style.transitionDuration;
29869        if(!durationProp) {
29870            return;
29871        }
29872
29873        this.scrollerStyle[durationProp] = time + 'ms';
29874
29875        if ( !time && utils.isBadAndroid ) {
29876            this.scrollerStyle[durationProp] = '0.0001ms';
29877            // remove 0.0001ms
29878            var self = this;
29879            rAF(function() {
29880                if(self.scrollerStyle[durationProp] === '0.0001ms') {
29881                    self.scrollerStyle[durationProp] = '0s';
29882                }
29883            });
29884        }
29885
29886
29887        if ( this.indicators ) {
29888            for ( var i = this.indicators.length; i--; ) {
29889                this.indicators[i].transitionTime(time);
29890            }
29891        }
29892
29893
29894// INSERT POINT: _transitionTime
29895
29896    },
29897
29898    _transitionTimingFunction: function (easing) {
29899        this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
29900
29901
29902        if ( this.indicators ) {
29903            for ( var i = this.indicators.length; i--; ) {
29904                this.indicators[i].transitionTimingFunction(easing);
29905            }
29906        }
29907
29908
29909// INSERT POINT: _transitionTimingFunction
29910
29911    },
29912
29913    _translate: function (x, y) {
29914        //Uncode addition
29915        if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 )
29916            return false;
vendor: 9,939 bytes, lines 29917-30228
29917
29918        if ( this.options.useTransform ) {
29919
29920/* REPLACE START: _translate */
29921
29922            this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
29923
29924/* REPLACE END: _translate */
29925
29926        } else {
29927            x = Math.round(x);
29928            y = Math.round(y);
29929            this.scrollerStyle.left = x + 'px';
29930            this.scrollerStyle.top = y + 'px';
29931        }
29932
29933        this.x = x;
29934        this.y = y;
29935
29936
29937        if ( this.indicators ) {
29938            for ( var i = this.indicators.length; i--; ) {
29939                this.indicators[i].updatePosition();
29940            }
29941        }
29942
29943        //Uncode addition
29944        var uncodevent = new CustomEvent('fp-slide-scroll');
29945        window.dispatchEvent(uncodevent);
29946
29947// INSERT POINT: _translate
29948
29949    },
29950
29951    _initEvents: function (remove) {
29952        var eventType = remove ? utils.removeEvent : utils.addEvent,
29953            target = this.options.bindToWrapper ? this.wrapper : window;
29954
29955        eventType(window, 'orientationchange', this);
29956        eventType(window, 'resize', this);
29957
29958        if ( this.options.click ) {
29959            eventType(this.wrapper, 'click', this, true);
29960        }
29961
29962        if ( !this.options.disableMouse ) {
29963            eventType(this.wrapper, 'mousedown', this);
29964            eventType(target, 'mousemove', this);
29965            eventType(target, 'mousecancel', this);
29966            eventType(target, 'mouseup', this);
29967        }
29968
29969        if ( utils.hasPointer && !this.options.disablePointer ) {
29970            eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
29971            eventType(target, utils.prefixPointerEvent('pointermove'), this);
29972            eventType(target, utils.prefixPointerEvent('pointercancel'), this);
29973            eventType(target, utils.prefixPointerEvent('pointerup'), this);
29974        }
29975
29976        if ( utils.hasTouch && !this.options.disableTouch ) {
29977            eventType(this.wrapper, 'touchstart', this);
29978            eventType(target, 'touchmove', this);
29979            eventType(target, 'touchcancel', this);
29980            eventType(target, 'touchend', this);
29981        }
29982
29983        eventType(this.scroller, 'transitionend', this);
29984        eventType(this.scroller, 'webkitTransitionEnd', this);
29985        eventType(this.scroller, 'oTransitionEnd', this);
29986        eventType(this.scroller, 'MSTransitionEnd', this);
29987    },
29988
29989    getComputedPosition: function () {
29990        var matrix = window.getComputedStyle(this.scroller, null),
29991            x, y;
29992
29993        if ( this.options.useTransform ) {
29994            matrix = matrix[utils.style.transform].split(')')[0].split(', ');
29995            x = +(matrix[12] || matrix[4]);
29996            y = +(matrix[13] || matrix[5]);
29997        } else {
29998            x = +matrix.left.replace(/[^-\d.]/g, '');
29999            y = +matrix.top.replace(/[^-\d.]/g, '');
30000        }
30001
30002        return { x: x, y: y };
30003    },
30004    _initIndicators: function () {
30005        var interactive = this.options.interactiveScrollbars,
30006            customStyle = typeof this.options.scrollbars != 'string',
30007            indicators = [],
30008            indicator;
30009
30010        var that = this;
30011
30012        this.indicators = [];
30013
30014        if ( this.options.scrollbars ) {
30015            // Vertical scrollbar
30016            if ( this.options.scrollY ) {
30017                indicator = {
30018                    el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
30019                    interactive: interactive,
30020                    defaultScrollbars: true,
30021                    customStyle: customStyle,
30022                    resize: this.options.resizeScrollbars,
30023                    shrink: this.options.shrinkScrollbars,
30024                    fade: this.options.fadeScrollbars,
30025                    listenX: false
30026                };
30027
30028                this.wrapper.appendChild(indicator.el);
30029                indicators.push(indicator);
30030            }
30031
30032            // Horizontal scrollbar
30033            if ( this.options.scrollX ) {
30034                indicator = {
30035                    el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
30036                    interactive: interactive,
30037                    defaultScrollbars: true,
30038                    customStyle: customStyle,
30039                    resize: this.options.resizeScrollbars,
30040                    shrink: this.options.shrinkScrollbars,
30041                    fade: this.options.fadeScrollbars,
30042                    listenY: false
30043                };
30044
30045                this.wrapper.appendChild(indicator.el);
30046                indicators.push(indicator);
30047            }
30048        }
30049
30050        if ( this.options.indicators ) {
30051            // TODO: check concat compatibility
30052            indicators = indicators.concat(this.options.indicators);
30053        }
30054
30055        for ( var i = indicators.length; i--; ) {
30056            this.indicators.push( new Indicator(this, indicators[i]) );
30057        }
30058
30059        // TODO: check if we can use array.map (wide compatibility and performance issues)
30060        function _indicatorsMap (fn) {
30061            if (that.indicators) {
30062                for ( var i = that.indicators.length; i--; ) {
30063                    fn.call(that.indicators[i]);
30064                }
30065            }
30066        }
30067
30068        if ( this.options.fadeScrollbars ) {
30069            this.on('scrollEnd', function () {
30070                _indicatorsMap(function () {
30071                    this.fade();
30072                });
30073            });
30074
30075            this.on('scrollCancel', function () {
30076                _indicatorsMap(function () {
30077                    this.fade();
30078                });
30079            });
30080
30081            this.on('scrollStart', function () {
30082                _indicatorsMap(function () {
30083                    this.fade(1);
30084                });
30085            });
30086
30087            this.on('beforeScrollStart', function () {
30088                _indicatorsMap(function () {
30089                    this.fade(1, true);
30090                });
30091            });
30092        }
30093
30094
30095        this.on('refresh', function () {
30096            _indicatorsMap(function () {
30097                this.refresh();
30098            });
30099        });
30100
30101        this.on('destroy', function () {
30102            _indicatorsMap(function () {
30103                this.destroy();
30104            });
30105
30106            delete this.indicators;
30107        });
30108    },
30109
30110    _initWheel: function () {
30111        utils.addEvent(this.wrapper, 'wheel', this);
30112        utils.addEvent(this.wrapper, 'mousewheel', this);
30113        utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
30114
30115        this.on('destroy', function () {
30116            clearTimeout(this.wheelTimeout);
30117            this.wheelTimeout = null;
30118            utils.removeEvent(this.wrapper, 'wheel', this);
30119            utils.removeEvent(this.wrapper, 'mousewheel', this);
30120            utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
30121        });
30122    },
30123
30124    _wheel: function (e) {
30125        if ( !this.enabled ) {
30126            return;
30127        }
30128
30129        var wheelDeltaX, wheelDeltaY,
30130            newX, newY,
30131            that = this;
30132
30133        if ( this.wheelTimeout === undefined ) {
30134            that._execEvent('scrollStart');
30135        }
30136
30137        // Execute the scrollEnd event after 400ms the wheel stopped scrolling
30138        clearTimeout(this.wheelTimeout);
30139        this.wheelTimeout = setTimeout(function () {
30140            if(!that.options.snap) {
30141                that._execEvent('scrollEnd');
30142            }
30143            that.wheelTimeout = undefined;
30144        }, 400);
30145
30146        if ( 'deltaX' in e ) {
30147            if (e.deltaMode === 1) {
30148                wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
30149                wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
30150            } else {
30151                wheelDeltaX = -e.deltaX;
30152                wheelDeltaY = -e.deltaY;
30153            }
30154        } else if ( 'wheelDeltaX' in e ) {
30155            wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
30156            wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
30157        } else if ( 'wheelDelta' in e ) {
30158            wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
30159        } else if ( 'detail' in e ) {
30160            wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
30161        } else {
30162            return;
30163        }
30164
30165        wheelDeltaX *= this.options.invertWheelDirection;
30166        wheelDeltaY *= this.options.invertWheelDirection;
30167
30168        if ( !this.hasVerticalScroll ) {
30169            wheelDeltaX = wheelDeltaY;
30170            wheelDeltaY = 0;
30171        }
30172
30173        if ( this.options.snap ) {
30174            newX = this.currentPage.pageX;
30175            newY = this.currentPage.pageY;
30176
30177            if ( wheelDeltaX > 0 ) {
30178                newX--;
30179            } else if ( wheelDeltaX < 0 ) {
30180                newX++;
30181            }
30182
30183            if ( wheelDeltaY > 0 ) {
30184                newY--;
30185            } else if ( wheelDeltaY < 0 ) {
30186                newY++;
30187            }
30188
30189            this.goToPage(newX, newY);
30190
30191            return;
30192        }
30193
30194        newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
30195        newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
30196
30197        this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;
30198        this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;
30199
30200        if ( newX > 0 ) {
30201            newX = 0;
30202        } else if ( newX < this.maxScrollX ) {
30203            newX = this.maxScrollX;
30204        }
30205
30206        if ( newY > 0 ) {
30207            newY = 0;
30208        } else if ( newY < this.maxScrollY ) {
30209            newY = this.maxScrollY;
30210        }
30211
30212        this.scrollTo(newX, newY, 0);
30213
30214// INSERT POINT: _wheel
30215    },
30216
30217    _initSnap: function () {
30218        this.currentPage = {};
30219
30220        if ( typeof this.options.snap == 'string' ) {
30221            this.options.snap = this.scroller.querySelectorAll(this.options.snap);
30222        }
30223
30224        this.on('refresh', function () {
30225            var i = 0, l,
30226                m = 0, n,
30227                cx, cy,
30228                x = 0, y,
vendor: 7,339 bytes, lines 30229-30482
30229                stepX = this.options.snapStepX || this.wrapperWidth,
30230                stepY = this.options.snapStepY || this.wrapperHeight,
30231                el;
30232
30233            this.pages = [];
30234
30235            if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
30236                return;
30237            }
30238
30239            if ( this.options.snap === true ) {
30240                cx = Math.round( stepX / 2 );
30241                cy = Math.round( stepY / 2 );
30242
30243                while ( x > -this.scrollerWidth ) {
30244                    this.pages[i] = [];
30245                    l = 0;
30246                    y = 0;
30247
30248                    while ( y > -this.scrollerHeight ) {
30249                        this.pages[i][l] = {
30250                            x: Math.max(x, this.maxScrollX),
30251                            y: Math.max(y, this.maxScrollY),
30252                            width: stepX,
30253                            height: stepY,
30254                            cx: x - cx,
30255                            cy: y - cy
30256                        };
30257
30258                        y -= stepY;
30259                        l++;
30260                    }
30261
30262                    x -= stepX;
30263                    i++;
30264                }
30265            } else {
30266                el = this.options.snap;
30267                l = el.length;
30268                n = -1;
30269
30270                for ( ; i < l; i++ ) {
30271                    if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
30272                        m = 0;
30273                        n++;
30274                    }
30275
30276                    if ( !this.pages[m] ) {
30277                        this.pages[m] = [];
30278                    }
30279
30280                    x = Math.max(-el[i].offsetLeft, this.maxScrollX);
30281                    y = Math.max(-el[i].offsetTop, this.maxScrollY);
30282                    cx = x - Math.round(el[i].offsetWidth / 2);
30283                    cy = y - Math.round(el[i].offsetHeight / 2);
30284
30285                    this.pages[m][n] = {
30286                        x: x,
30287                        y: y,
30288                        width: el[i].offsetWidth,
30289                        height: el[i].offsetHeight,
30290                        cx: cx,
30291                        cy: cy
30292                    };
30293
30294                    if ( x > this.maxScrollX ) {
30295                        m++;
30296                    }
30297                }
30298            }
30299
30300            this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
30301
30302            // Update snap threshold if needed
30303            if ( this.options.snapThreshold % 1 === 0 ) {
30304                this.snapThresholdX = this.options.snapThreshold;
30305                this.snapThresholdY = this.options.snapThreshold;
30306            } else {
30307                this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
30308                this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
30309            }
30310        });
30311
30312        this.on('flick', function () {
30313            var time = this.options.snapSpeed || Math.max(
30314                    Math.max(
30315                        Math.min(Math.abs(this.x - this.startX), 1000),
30316                        Math.min(Math.abs(this.y - this.startY), 1000)
30317                    ), 300);
30318
30319            this.goToPage(
30320                this.currentPage.pageX + this.directionX,
30321                this.currentPage.pageY + this.directionY,
30322                time
30323            );
30324        });
30325    },
30326
30327    _nearestSnap: function (x, y) {
30328        if ( !this.pages.length ) {
30329            return { x: 0, y: 0, pageX: 0, pageY: 0 };
30330        }
30331
30332        var i = 0,
30333            l = this.pages.length,
30334            m = 0;
30335
30336        // Check if we exceeded the snap threshold
30337        if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
30338            Math.abs(y - this.absStartY) < this.snapThresholdY ) {
30339            return this.currentPage;
30340        }
30341
30342        if ( x > 0 ) {
30343            x = 0;
30344        } else if ( x < this.maxScrollX ) {
30345            x = this.maxScrollX;
30346        }
30347
30348        if ( y > 0 ) {
30349            y = 0;
30350        } else if ( y < this.maxScrollY ) {
30351            y = this.maxScrollY;
30352        }
30353
30354        for ( ; i < l; i++ ) {
30355            if ( x >= this.pages[i][0].cx ) {
30356                x = this.pages[i][0].x;
30357                break;
30358            }
30359        }
30360
30361        l = this.pages[i].length;
30362
30363        for ( ; m < l; m++ ) {
30364            if ( y >= this.pages[0][m].cy ) {
30365                y = this.pages[0][m].y;
30366                break;
30367            }
30368        }
30369
30370        if ( i == this.currentPage.pageX ) {
30371            i += this.directionX;
30372
30373            if ( i < 0 ) {
30374                i = 0;
30375            } else if ( i >= this.pages.length ) {
30376                i = this.pages.length - 1;
30377            }
30378
30379            x = this.pages[i][0].x;
30380        }
30381
30382        if ( m == this.currentPage.pageY ) {
30383            m += this.directionY;
30384
30385            if ( m < 0 ) {
30386                m = 0;
30387            } else if ( m >= this.pages[0].length ) {
30388                m = this.pages[0].length - 1;
30389            }
30390
30391            y = this.pages[0][m].y;
30392        }
30393
30394        return {
30395            x: x,
30396            y: y,
30397            pageX: i,
30398            pageY: m
30399        };
30400    },
30401
30402    goToPage: function (x, y, time, easing) {
30403        easing = easing || this.options.bounceEasing;
30404
30405        if ( x >= this.pages.length ) {
30406            x = this.pages.length - 1;
30407        } else if ( x < 0 ) {
30408            x = 0;
30409        }
30410
30411        if ( y >= this.pages[x].length ) {
30412            y = this.pages[x].length - 1;
30413        } else if ( y < 0 ) {
30414            y = 0;
30415        }
30416
30417        var posX = this.pages[x][y].x,
30418            posY = this.pages[x][y].y;
30419
30420        time = time === undefined ? this.options.snapSpeed || Math.max(
30421            Math.max(
30422                Math.min(Math.abs(posX - this.x), 1000),
30423                Math.min(Math.abs(posY - this.y), 1000)
30424            ), 300) : time;
30425
30426        this.currentPage = {
30427            x: posX,
30428            y: posY,
30429            pageX: x,
30430            pageY: y
30431        };
30432
30433        this.scrollTo(posX, posY, time, easing);
30434    },
30435
30436    next: function (time, easing) {
30437        var x = this.currentPage.pageX,
30438            y = this.currentPage.pageY;
30439
30440        x++;
30441
30442        if ( x >= this.pages.length && this.hasVerticalScroll ) {
30443            x = 0;
30444            y++;
30445        }
30446
30447        this.goToPage(x, y, time, easing);
30448    },
30449
30450    prev: function (time, easing) {
30451        var x = this.currentPage.pageX,
30452            y = this.currentPage.pageY;
30453
30454        x--;
30455
30456        if ( x < 0 && this.hasVerticalScroll ) {
30457            x = 0;
30458            y--;
30459        }
30460
30461        this.goToPage(x, y, time, easing);
30462    },
30463
30464    _initKeys: function (e) {
30465        // default key bindings
30466        var keys = {
30467            pageUp: 33,
30468            pageDown: 34,
30469            end: 35,
30470            home: 36,
30471            left: 37,
30472            up: 38,
30473            right: 39,
30474            down: 40
30475        };
30476        var i;
30477
30478        // if you give me characters I give you keycode
30479        if ( typeof this.options.keyBindings == 'object' ) {
30480            for ( i in this.options.keyBindings ) {
30481                if ( typeof this.options.keyBindings[i] == 'string' ) {
30482                    this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
vendor: 11,097 bytes, lines 30482-30835
30482deAt(0);
30483                }
30484            }
30485        } else {
30486            this.options.keyBindings = {};
30487        }
30488
30489        for ( i in keys ) {
30490            this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
30491        }
30492
30493        utils.addEvent(window, 'keydown', this);
30494
30495        this.on('destroy', function () {
30496            utils.removeEvent(window, 'keydown', this);
30497        });
30498    },
30499
30500    _key: function (e) {
30501        if ( !this.enabled ) {
30502            return;
30503        }
30504
30505        var snap = this.options.snap,   // we are using this alot, better to cache it
30506            newX = snap ? this.currentPage.pageX : this.x,
30507            newY = snap ? this.currentPage.pageY : this.y,
30508            now = utils.getTime(),
30509            prevTime = this.keyTime || 0,
30510            acceleration = 0.250,
30511            pos;
30512
30513        if ( this.options.useTransition && this.isInTransition ) {
30514            pos = this.getComputedPosition();
30515
30516            this._translate(Math.round(pos.x), Math.round(pos.y));
30517            this.isInTransition = false;
30518        }
30519
30520        this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
30521
30522        switch ( e.keyCode ) {
30523            case this.options.keyBindings.pageUp:
30524                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30525                    newX += snap ? 1 : this.wrapperWidth;
30526                } else {
30527                    newY += snap ? 1 : this.wrapperHeight;
30528                }
30529                break;
30530            case this.options.keyBindings.pageDown:
30531                if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
30532                    newX -= snap ? 1 : this.wrapperWidth;
30533                } else {
30534                    newY -= snap ? 1 : this.wrapperHeight;
30535                }
30536                break;
30537            case this.options.keyBindings.end:
30538                newX = snap ? this.pages.length-1 : this.maxScrollX;
30539                newY = snap ? this.pages[0].length-1 : this.maxScrollY;
30540                break;
30541            case this.options.keyBindings.home:
30542                newX = 0;
30543                newY = 0;
30544                break;
30545            case this.options.keyBindings.left:
30546                newX += snap ? -1 : 5 + this.keyAcceleration>>0;
30547                break;
30548            case this.options.keyBindings.up:
30549                newY += snap ? 1 : 5 + this.keyAcceleration>>0;
30550                break;
30551            case this.options.keyBindings.right:
30552                newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
30553                break;
30554            case this.options.keyBindings.down:
30555                newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
30556                break;
30557            default:
30558                return;
30559        }
30560
30561        if ( snap ) {
30562            this.goToPage(newX, newY);
30563            return;
30564        }
30565
30566        if ( newX > 0 ) {
30567            newX = 0;
30568            this.keyAcceleration = 0;
30569        } else if ( newX < this.maxScrollX ) {
30570            newX = this.maxScrollX;
30571            this.keyAcceleration = 0;
30572        }
30573
30574        if ( newY > 0 ) {
30575            newY = 0;
30576            this.keyAcceleration = 0;
30577        } else if ( newY < this.maxScrollY ) {
30578            newY = this.maxScrollY;
30579            this.keyAcceleration = 0;
30580        }
30581
30582        this.scrollTo(newX, newY, 0);
30583
30584        this.keyTime = now;
30585    },
30586
30587    _animate: function (destX, destY, duration, easingFn) {
30588        var that = this,
30589            startX = this.x,
30590            startY = this.y,
30591            startTime = utils.getTime(),
30592            destTime = startTime + duration;
30593
30594        function step () {
30595            var now = utils.getTime(),
30596                newX, newY,
30597                easing;
30598
30599            if ( now >= destTime ) {
30600                that.isAnimating = false;
30601                that._translate(destX, destY);
30602
30603                if ( !that.resetPosition(that.options.bounceTime) ) {
30604                    that._execEvent('scrollEnd');
30605                }
30606
30607                return;
30608            }
30609
30610            now = ( now - startTime ) / duration;
30611            easing = easingFn(now);
30612            newX = ( destX - startX ) * easing + startX;
30613            newY = ( destY - startY ) * easing + startY;
30614            that._translate(newX, newY);
30615
30616            if ( that.isAnimating ) {
30617                rAF(step);
30618            }
30619        }
30620
30621        this.isAnimating = true;
30622        step();
30623    },
30624    handleEvent: function (e) {
30625        switch ( e.type ) {
30626            case 'touchstart':
30627            case 'pointerdown':
30628            case 'MSPointerDown':
30629            case 'mousedown':
30630                this._start(e);
30631                break;
30632            case 'touchmove':
30633            case 'pointermove':
30634            case 'MSPointerMove':
30635            case 'mousemove':
30636                this._move(e);
30637                break;
30638            case 'touchend':
30639            case 'pointerup':
30640            case 'MSPointerUp':
30641            case 'mouseup':
30642            case 'touchcancel':
30643            case 'pointercancel':
30644            case 'MSPointerCancel':
30645            case 'mousecancel':
30646                this._end(e);
30647                break;
30648            case 'orientationchange':
30649            case 'resize':
30650                this._resize();
30651                break;
30652            case 'transitionend':
30653            case 'webkitTransitionEnd':
30654            case 'oTransitionEnd':
30655            case 'MSTransitionEnd':
30656                this._transitionEnd(e);
30657                break;
30658            case 'wheel':
30659            case 'DOMMouseScroll':
30660            case 'mousewheel':
30661                this._wheel(e);
30662                break;
30663            case 'keydown':
30664                this._key(e);
30665                break;
30666            case 'click':
30667                if ( this.enabled && !e._constructed ) {
30668                    e.preventDefault();
30669                    e.stopPropagation();
30670                }
30671                break;
30672        }
30673    }
30674};
30675function createDefaultScrollbar (direction, interactive, type) {
30676    var scrollbar = document.createElement('div'),
30677        indicator = document.createElement('div');
30678
30679    if ( type === true ) {
30680        scrollbar.style.cssText = 'position:absolute;z-index:9999';
30681        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';
30682    }
30683
30684    indicator.className = 'iScrollIndicator';
30685
30686    if ( direction == 'h' ) {
30687        if ( type === true ) {
30688            scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
30689            indicator.style.height = '100%';
30690        }
30691        scrollbar.className = 'iScrollHorizontalScrollbar';
30692    } else {
30693        if ( type === true ) {
30694            scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
30695            indicator.style.width = '100%';
30696        }
30697        scrollbar.className = 'iScrollVerticalScrollbar';
30698    }
30699
30700    scrollbar.style.cssText += ';overflow:hidden';
30701
30702    if ( !interactive ) {
30703        scrollbar.style.pointerEvents = 'none';
30704    }
30705
30706    scrollbar.appendChild(indicator);
30707
30708    return scrollbar;
30709}
30710
30711function Indicator (scroller, options) {
30712    this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
30713    this.wrapperStyle = this.wrapper.style;
30714    this.indicator = this.wrapper.children[0];
30715    this.indicatorStyle = this.indicator.style;
30716    this.scroller = scroller;
30717
30718    this.options = {
30719        listenX: true,
30720        listenY: true,
30721        interactive: false,
30722        resize: true,
30723        defaultScrollbars: false,
30724        shrink: false,
30725        fade: false,
30726        speedRatioX: 0,
30727        speedRatioY: 0
30728    };
30729
30730    for ( var i in options ) {
30731        this.options[i] = options[i];
30732    }
30733
30734    this.sizeRatioX = 1;
30735    this.sizeRatioY = 1;
30736    this.maxPosX = 0;
30737    this.maxPosY = 0;
30738
30739    if ( this.options.interactive ) {
30740        if ( !this.options.disableTouch ) {
30741            utils.addEvent(this.indicator, 'touchstart', this);
30742            utils.addEvent(window, 'touchend', this);
30743        }
30744        if ( !this.options.disablePointer ) {
30745            utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30746            utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
30747        }
30748        if ( !this.options.disableMouse ) {
30749            utils.addEvent(this.indicator, 'mousedown', this);
30750            utils.addEvent(window, 'mouseup', this);
30751        }
30752    }
30753
30754    if ( this.options.fade ) {
30755        this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
30756        var durationProp = utils.style.transitionDuration;
30757        if(!durationProp) {
30758            return;
30759        }
30760        this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';
30761        // remove 0.0001ms
30762        var self = this;
30763        if(utils.isBadAndroid) {
30764            rAF(function() {
30765                if(self.wrapperStyle[durationProp] === '0.0001ms') {
30766                    self.wrapperStyle[durationProp] = '0s';
30767                }
30768            });
30769        }
30770        this.wrapperStyle.opacity = '0';
30771    }
30772}
30773
30774Indicator.prototype = {
30775    handleEvent: function (e) {
30776        switch ( e.type ) {
30777            case 'touchstart':
30778            case 'pointerdown':
30779            case 'MSPointerDown':
30780            case 'mousedown':
30781                this._start(e);
30782                break;
30783            case 'touchmove':
30784            case 'pointermove':
30785            case 'MSPointerMove':
30786            case 'mousemove':
30787                this._move(e);
30788                break;
30789            case 'touchend':
30790            case 'pointerup':
30791            case 'MSPointerUp':
30792            case 'mouseup':
30793            case 'touchcancel':
30794            case 'pointercancel':
30795            case 'MSPointerCancel':
30796            case 'mousecancel':
30797                this._end(e);
30798                break;
30799        }
30800    },
30801
30802    destroy: function () {
30803        if ( this.options.fadeScrollbars ) {
30804            clearTimeout(this.fadeTimeout);
30805            this.fadeTimeout = null;
30806        }
30807        if ( this.options.interactive ) {
30808            utils.removeEvent(this.indicator, 'touchstart', this);
30809            utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
30810            utils.removeEvent(this.indicator, 'mousedown', this);
30811
30812            utils.removeEvent(window, 'touchmove', this);
30813            utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30814            utils.removeEvent(window, 'mousemove', this);
30815
30816            utils.removeEvent(window, 'touchend', this);
30817            utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
30818            utils.removeEvent(window, 'mouseup', this);
30819        }
30820
30821        if ( this.options.defaultScrollbars ) {
30822            this.wrapper.parentNode.removeChild(this.wrapper);
30823        }
30824    },
30825
30826    _start: function (e) {
30827        var point = e.touches ? e.touches[0] : e;
30828
30829        e.preventDefault();
30830        e.stopPropagation();
30831
30832        this.transitionTime();
30833
30834        this.initiated = true;
30835        this.moved = false;
vendor: 9,615 bytes, lines 30836-31094
30836        this.lastPointX = point.pageX;
30837        this.lastPointY = point.pageY;
30838
30839        this.startTime  = utils.getTime();
30840
30841        if ( !this.options.disableTouch ) {
30842            utils.addEvent(window, 'touchmove', this);
30843        }
30844        if ( !this.options.disablePointer ) {
30845            utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
30846        }
30847        if ( !this.options.disableMouse ) {
30848            utils.addEvent(window, 'mousemove', this);
30849        }
30850
30851        this.scroller._execEvent('beforeScrollStart');
30852    },
30853
30854    _move: function (e) {
30855        var point = e.touches ? e.touches[0] : e,
30856            deltaX, deltaY,
30857            newX, newY,
30858            timestamp = utils.getTime();
30859
30860        if ( !this.moved ) {
30861            this.scroller._execEvent('scrollStart');
30862        }
30863
30864        this.moved = true;
30865
30866        deltaX = point.pageX - this.lastPointX;
30867        this.lastPointX = point.pageX;
30868
30869        deltaY = point.pageY - this.lastPointY;
30870        this.lastPointY = point.pageY;
30871
30872        newX = this.x + deltaX;
30873        newY = this.y + deltaY;
30874
30875        this._pos(newX, newY);
30876
30877// INSERT POINT: indicator._move
30878
30879        e.preventDefault();
30880        e.stopPropagation();
30881    },
30882
30883    _end: function (e) {
30884        if ( !this.initiated ) {
30885            return;
30886        }
30887
30888        this.initiated = false;
30889
30890        e.preventDefault();
30891        e.stopPropagation();
30892
30893        utils.removeEvent(window, 'touchmove', this);
30894        utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
30895        utils.removeEvent(window, 'mousemove', this);
30896
30897        if ( this.scroller.options.snap ) {
30898            var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
30899
30900            var time = this.options.snapSpeed || Math.max(
30901                    Math.max(
30902                        Math.min(Math.abs(this.scroller.x - snap.x), 1000),
30903                        Math.min(Math.abs(this.scroller.y - snap.y), 1000)
30904                    ), 300);
30905
30906            if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
30907                this.scroller.directionX = 0;
30908                this.scroller.directionY = 0;
30909                this.scroller.currentPage = snap;
30910                this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
30911            }
30912        }
30913
30914        if ( this.moved ) {
30915            this.scroller._execEvent('scrollEnd');
30916        }
30917    },
30918
30919    transitionTime: function (time) {
30920        time = time || 0;
30921        var durationProp = utils.style.transitionDuration;
30922        if(!durationProp) {
30923            return;
30924        }
30925
30926        this.indicatorStyle[durationProp] = time + 'ms';
30927
30928        if ( !time && utils.isBadAndroid ) {
30929            this.indicatorStyle[durationProp] = '0.0001ms';
30930            // remove 0.0001ms
30931            var self = this;
30932            rAF(function() {
30933                if(self.indicatorStyle[durationProp] === '0.0001ms') {
30934                    self.indicatorStyle[durationProp] = '0s';
30935                }
30936            });
30937        }
30938    },
30939
30940    transitionTimingFunction: function (easing) {
30941        this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
30942    },
30943
30944    refresh: function () {
30945        this.transitionTime();
30946
30947        if ( this.options.listenX && !this.options.listenY ) {
30948            this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
30949        } else if ( this.options.listenY && !this.options.listenX ) {
30950            this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
30951        } else {
30952            this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
30953        }
30954
30955        if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
30956            utils.addClass(this.wrapper, 'iScrollBothScrollbars');
30957            utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
30958
30959            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30960                if ( this.options.listenX ) {
30961                    this.wrapper.style.right = '8px';
30962                } else {
30963                    this.wrapper.style.bottom = '8px';
30964                }
30965            }
30966        } else {
30967            utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
30968            utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
30969
30970            if ( this.options.defaultScrollbars && this.options.customStyle ) {
30971                if ( this.options.listenX ) {
30972                    this.wrapper.style.right = '2px';
30973                } else {
30974                    this.wrapper.style.bottom = '2px';
30975                }
30976            }
30977        }
30978
30979        var r = this.wrapper.offsetHeight;  // force refresh
30980
30981        if ( this.options.listenX ) {
30982            this.wrapperWidth = this.wrapper.clientWidth;
30983            if ( this.options.resize ) {
30984                this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
30985                this.indicatorStyle.width = this.indicatorWidth + 'px';
30986            } else {
30987                this.indicatorWidth = this.indicator.clientWidth;
30988            }
30989
30990            this.maxPosX = this.wrapperWidth - this.indicatorWidth;
30991
30992            if ( this.options.shrink == 'clip' ) {
30993                this.minBoundaryX = -this.indicatorWidth + 8;
30994                this.maxBoundaryX = this.wrapperWidth - 8;
30995            } else {
30996                this.minBoundaryX = 0;
30997                this.maxBoundaryX = this.maxPosX;
30998            }
30999
31000            this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));
31001        }
31002
31003        if ( this.options.listenY ) {
31004            this.wrapperHeight = this.wrapper.clientHeight;
31005            if ( this.options.resize ) {
31006                this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
31007                this.indicatorStyle.height = this.indicatorHeight + 'px';
31008            } else {
31009                this.indicatorHeight = this.indicator.clientHeight;
31010            }
31011
31012            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31013
31014            if ( this.options.shrink == 'clip' ) {
31015                this.minBoundaryY = -this.indicatorHeight + 8;
31016                this.maxBoundaryY = this.wrapperHeight - 8;
31017            } else {
31018                this.minBoundaryY = 0;
31019                this.maxBoundaryY = this.maxPosY;
31020            }
31021
31022            this.maxPosY = this.wrapperHeight - this.indicatorHeight;
31023            this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
31024        }
31025
31026        this.updatePosition();
31027    },
31028
31029    updatePosition: function () {
31030        var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
31031            y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
31032
31033        if ( !this.options.ignoreBoundaries ) {
31034            if ( x < this.minBoundaryX ) {
31035                if ( this.options.shrink == 'scale' ) {
31036                    this.width = Math.max(this.indicatorWidth + x, 8);
31037                    this.indicatorStyle.width = this.width + 'px';
31038                }
31039                x = this.minBoundaryX;
31040            } else if ( x > this.maxBoundaryX ) {
31041                if ( this.options.shrink == 'scale' ) {
31042                    this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
31043                    this.indicatorStyle.width = this.width + 'px';
31044                    x = this.maxPosX + this.indicatorWidth - this.width;
31045                } else {
31046                    x = this.maxBoundaryX;
31047                }
31048            } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
31049                this.width = this.indicatorWidth;
31050                this.indicatorStyle.width = this.width + 'px';
31051            }
31052
31053            if ( y < this.minBoundaryY ) {
31054                if ( this.options.shrink == 'scale' ) {
31055                    this.height = Math.max(this.indicatorHeight + y * 3, 8);
31056                    this.indicatorStyle.height = this.height + 'px';
31057                }
31058                y = this.minBoundaryY;
31059            } else if ( y > this.maxBoundaryY ) {
31060                if ( this.options.shrink == 'scale' ) {
31061                    this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
31062                    this.indicatorStyle.height = this.height + 'px';
31063                    y = this.maxPosY + this.indicatorHeight - this.height;
31064                } else {
31065                    y = this.maxBoundaryY;
31066                }
31067            } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
31068                this.height = this.indicatorHeight;
31069                this.indicatorStyle.height = this.height + 'px';
31070            }
31071        }
31072
31073        this.x = x;
31074        this.y = y;
31075
31076        if ( this.scroller.options.useTransform ) {
31077            this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
31078        } else {
31079            this.indicatorStyle.left = x + 'px';
31080            this.indicatorStyle.top = y + 'px';
31081        }
31082    },
31083
31084    _pos: function (x, y) {
31085        if ( x < 0 ) {
31086            x = 0;
31087        } else if ( x > this.maxPosX ) {
31088            x = this.maxPosX;
31089        }
31090
31091        if ( y < 0 ) {
31092            y = 0;
31093        } else if ( y > this.maxPosY ) {
31094            y = this.maxPosY;
31095        }
31096
31097        x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
31098        y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
31099
31100        this.scroller.scrollTo(x, y);
31101    },
31102
31103    fade: function (val, hold) {
31104        if ( hold && !this.visible ) {
31105            return;
31106        }
31107
31108        clearTimeout(this.fadeTimeout);
31109        this.fadeTimeout = null;
31110
31111        var time = val ? 250 : 500,
31112            delay = val ? 0 : 300;
31113
31114        val = val ? '1' : '0';
31115
31116        this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
31117
31118        this.fadeTimeout = setTimeout((function (val) {
31119            this.wrapperStyle.opacity = val;
31120            this.visible = +val;
31121        }).bind(this, val), delay);
31122    }
31123};
31124
31125IScroll.utils = utils;
31126
31127if ( typeof module != 'undefined' && module.exports ) {
31128    module.exports = IScroll;
31129} else if ( typeof define == 'function' && define.amd ) {
31130        define( function () { return IScroll; } );
31131} else {
31132    window.IScroll = IScroll;
31133}
31134
31135})(window, document, Math);
31136/*!
31137 * fullPage 2.9.4
31138 * https://github.com/alvarotrigo/fullPage.js
31139 * @license MIT licensed
31140 *
31141 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo
31142 */
31143(function(global, factory) {
31144    'use strict';
31145    if (typeof define === 'function' && define.amd) {
31146        define(['jquery'], function($) {
31147          return factory($, global, global.document, global.Math);
31148        });
31149    } else if (typeof exports === "object" && exports) {
31150        module.exports = factory(require('jquery'), global, global.document, global.Math);
31151    } else {
31152        factory(jQuery, global, global.document, global.Math);
31153    }
31154})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) {
31155    'use strict';
31156
31157    // keeping central set of classnames and selectors
31158    var WRAPPER =               'fullpage-wrapper';
31159    var WRAPPER_SEL =           '.' + WRAPPER;
31160
31161    // slimscroll
31162    var SCROLLABLE =            'fp-scrollable';
31163    var SCROLLABLE_SEL =        '.' + SCROLLABLE;
31164
31165    // util
31166    var RESPONSIVE =            'fp-responsive';
31167    var NO_TRANSITION =         'fp-notransition';
31168    var DESTROYED =             'fp-destroyed';
31169    var ENABLED =               'fp-enabled';
31170    var VIEWING_PREFIX =        'fp-viewing';
31171    var ACTIVE =                'active';
31172    var ACTIVE_SEL =            '.' + ACTIVE;
31173    var COMPLETELY =            'fp-completely';
31174    var COMPLETELY_SEL =        '.' + COMPLETELY;
31175
31176    // section
31177    var SECTION_DEFAULT_SEL =   '.section';
31178    var SECTION =               'fp-section';
31179    var SECTION_SEL =           '.' + SECTION;
31180    var SECTION_ACTIVE_SEL =    SECTION_SEL + ACTIVE_SEL;
31181    var SECTION_FIRST_SEL =     SECTION_SEL + ':first';
31182    var SECTION_LAST_SEL =      SECTION_SEL + ':last';
31183    var TABLE_CELL =            'fp-tableCell';
31184    var TABLE_CELL_SEL =        '.' + TABLE_CELL;
31185    var AUTO_HEIGHT =           'fp-auto-height';
31186    var AUTO_HEIGHT_SEL =       '.fp-auto-height';
31187    var NORMAL_SCROLL =         'fp-normal-scroll';
31188    var NORMAL_SCROLL_SEL =     '.fp-normal-scroll';
31189
31190    // section nav
31191    var SECTION_NAV =           'fp-nav';
31192    var SECTION_NAV_SEL =       '#' + SECTION_NAV;
31193    var SECTION_NAV_TOOLTIP =   'fp-tooltip';
31194    var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP;
31195    var SHOW_ACTIVE_TOOLTIP =   'fp-show-active';
31196
31197    // slide
31198    var SLIDE_DEFAULT_SEL =     '.slide';
31199    var SLIDE =                 'fp-slide';
31200    var SLIDE_SEL =             '.' + SLIDE;
31201    var SLIDE_ACTIVE_SEL =      SLIDE_SEL + ACTIVE_SEL;
31202    var SLIDES_WRAPPER =        'fp-slides';
31203    var SLIDES_WRAPPER_SEL =    '.' + SLIDES_WRAPPER;
31204    var SLIDES_CONTAINER =      'fp-slidesContainer';
31205    var SLIDES_CONTAINER_SEL =  '.' + SLIDES_CONTAINER;
31206    var TABLE =                 'fp-table';
31207
31208    // slide nav
31209    var SLIDES_NAV =            'fp-slidesNav';
31210    var SLIDES_NAV_SEL =        '.' + SLIDES_NAV;
31211    var SLIDES_NAV_LINK_SEL =   SLIDES_NAV_SEL + ' a';
31212    var SLIDES_ARROW =          'fp-controlArrow';
31213    var SLIDES_ARROW_SEL =      '.' + SLIDES_ARROW;
31214    var SLIDES_PREV =           'fp-prev';
31215    var SLIDES_PREV_SEL =       '.' + SLIDES_PREV;
31216    var SLIDES_ARROW_PREV =     SLIDES_ARROW + ' ' + SLIDES_PREV;
31217    var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL;
31218    var SLIDES_NEXT =           'fp-next';
31219    var SLIDES_NEXT_SEL =       '.' + SLIDES_NEXT;
31220    var SLIDES_ARROW_NEXT =     SLIDES_ARROW + ' ' + SLIDES_NEXT;
31221    var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL;
31222
31223    var $window = $(window);
31224    var $document = $(document);
31225
31226    // Default options for iScroll.js used when using scrollOverflow
31227    var iscrollOptions = {
31228        scrollbars: true,
31229        mouseWheel: true,
31230        hideScrollbars: false,
31231        fadeScrollbars: false,
31232        disableMouse: true,
31233        interactiveScrollbars: true,
31234        bounce: false,
31235    };
31236
31237    $.fn.fullpage = function(options) {
31238        //only once my friend!
31239        if($('html').hasClass(ENABLED)){ displayWarnings(); return; }
31240
31241        // common jQuery objects
31242        var $htmlBody = $('html, body');
31243        var $body = $('body');
31244
31245        var FP = $.fn.fullpage;
31246
31247        // Creating some defaults, extending them with any options that were provided
31248        options = $.extend({
31249            //navigation
31250            menu: false,
31251            anchors:[],
31252            lockAnchors: false,
31253            navigation: false,
31254            navigationPosition: 'right',
31255            navigationTooltips: [],
31256            showActiveTooltip: false,
31257            slidesNavigation: false,
31258            slidesNavPosition: 'bottom',
31259            scrollBar: false,
31260            hybrid: false,
31261
31262            //scrolling
31263            css3: true,
31264            scrollingSpeed: 700,
31265            autoScrolling: true,
31266            fitToSection: true,
31267            fitToSectionDelay: 1000,
31268            easing: 'easeInOutCubic',
31269            easingcss3: 'ease',
31270            loopBottom: false,
31271            loopTop: false,
31272            loopHorizontal: true,
31273            continuousVertical: false,
31274            continuousHorizontal: false,
31275            scrollHorizontally: false,
31276            interlockedSlides: false,
31277            dragAndMove: false,
31278            offsetSections: false,
31279            resetSliders: false,
31280            fadingEffect: false,
31281            normalScrollElements: null,
31282            scrollOverflow: false,
31283            scrollOverflowReset: false,
31284            scrollOverflowHandler: iscrollHandler,
31285            scrollOverflowOptions: null,
31286            touchSensitivity: 5,
31287            normalScrollElementTouchThreshold: 5,
31288            bigSectionsDestination: null,
31289
31290            //Accessibility
31291            keyboardScrolling: true,
31292            animateAnchor: true,
31293            recordHistory: true,
31294
31295            //design
31296            controlArrows: true,
31297            controlArrowColor: '#fff',
31298            verticalCentered: true,
31299            sectionsColor : [],
31300            paddingTop: 0,
31301            paddingBottom: 0,
31302            fixedElements: null,
31303            responsive: 0, //backwards compabitility with responsiveWiddth
31304            responsiveWidth: 0,
31305            responsiveHeight: 0,
31306            responsiveSlides: false,
31307            parallax: false,
31308            parallaxOptions: {
31309                type: 'reveal',
31310                percentage: 62,
31311                property: 'translate'
31312            },
31313
31314            //Custom selectors
31315            sectionSelector: SECTION_DEFAULT_SEL,
31316            slideSelector: SLIDE_DEFAULT_SEL,
31317
31318            //events
31319            afterLoad: null,
31320            onLeave: null,
31321            afterRender: null,
31322            afterResize: null,
31323            afterReBuild: null,
31324            afterSlideLoad: null,
31325            onSlideLeave: null,
31326            afterResponsive: null,
31327
31328            lazyLoading: true
31329        }, options);
31330
31331        //flag to avoid very fast sliding for landscape sliders
31332        var slideMoving = false;
31333
31334        var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/);
31335        var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
31336        var container = $(this);
31337        var windowsHeight = $window.height();
31338        var isResizing = false;
31339        var isWindowFocused = true;
31340        var lastScrolledDestiny;
31341        var lastScrolledSlide;
31342        var canScroll = true;
31343        var scrollings = [];
31344        var controlPressed;
31345        var startingSection;
31346        var isScrollAllowed = {};
31347        isScrollAllowed.m = {  'up':true, 'down':true, 'left':true, 'right':true };
31348        isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m);
31349        var MSPointer = getMSPointer();
31350        var events = {
31351            touchmove: 'ontouchmove' in window ? 'touchmove' :  MSPointer.move,
31352            touchstart: 'ontouchstart' in window ? 'touchstart' :  MSPointer.down
31353        };
31354
31355        //cheks for passive event support
31356        //added by Uncode from new fullPage updates
31357        var g_supportsPassive = false;
31358        try {
31359          var opts = Object.defineProperty({}, 'passive', {
31360            get: function() {
31361              g_supportsPassive = true;
31362            }
31363          });
31364          window.addEventListener("testPassive", null, opts);
31365          window.removeEventListener("testPassive", null, opts);
31366        } catch (e) {}
31367
31368        //timeouts
31369        var resizeId;
31370        var afterSectionLoadsId;
31371        var afterSlideLoadsId;
31372        var scrollId;
31373        var scrollId2;
31374        var keydownId;
31375        var originals = $.extend(true, {}, options); //deep copy
31376
31377        //Uncode addition
31378        var $masthead = $('#masthead');
31379        var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false;
31380        var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight;
31381        var bodyBorder = UNCODE.bodyBorder;
31382        var adminBarHeight = UNCODE.adminBarHeight;
31383
31384        displayWarnings();
31385
31386        //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783
31387        iscrollOptions.click = isTouch; // see #2035
31388
31389        //extending iScroll options with the user custom ones
31390        iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions);
31391
31392        //easeInOutCubic animation included in the plugin
31393        $.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;}});
31394
31395        /**
31396        * Sets the autoScroll option.
31397        * It changes the scroll bar visibility and the history of the site as a result.
31398        */
31399        function setAutoScrolling(value, type){
31400            //removing the transformation
31401            if(!value){
31402                silentScroll(0);
31403            }
31404
31405            setVariableState('autoScrolling', value, type);
31406
31407            var element = $(SECTION_ACTIVE_SEL);
31408
31409            if(options.autoScrolling && !options.scrollBar){
31410                $htmlBody.css({
31411                    'overflow' : 'hidden !important',
31412                    'height' : '100%'
31413                });
31414
31415                //Uncode addition
31416                //setRecordHistory(originals.recordHistory, 'internal');
31417
31418                //for IE touch devices
31419                container.css({
31420                    '-ms-touch-action': 'none',
31421                    'touch-action': 'none'
31422                });
31423
31424                if(element.length){
31425                    //moving the container up
31426                    silentScroll(element.position().top);
31427                }
31428
31429            }else{
31430                $htmlBody.css({
31431                    'overflow' : 'visible !important',
31432                    'height' : 'initial'
31433                });
31434
31435                //Uncode addition
31436                //setRecordHistory(false, 'internal');
31437
31438                //for IE touch devices
31439                container.css({
31440                    '-ms-touch-action': '',
31441                    'touch-action': ''
31442                });
31443
31444                //scrolling the page to the section with no animation
31445                if (element.length) {
31446                    $htmlBody.scrollTop(element.position().top);
31447                }
31448            }
31449        }
31450
31451        /**
31452        * Defines wheter to record the history for each hash change in the URL.
31453        */
31454        function setRecordHistory(value, type){
31455            setVariableState('recordHistory', value, type);
31456        }
31457
31458        /**
31459        * Defines the scrolling speed
31460        */
31461        function setScrollingSpeed(value, type){
31462            setVariableState('scrollingSpeed', value, type);
31463        }
31464
31465        /**
31466        * Sets fitToSection
31467        */
31468        function setFitToSection(value, type){
31469            setVariableState('fitToSection', value, type);
31470        }
31471
31472        /**
31473        * Sets lockAnchors
31474        */
31475        function setLockAnchors(value){
31476            options.lockAnchors = value;
31477        }
31478
31479        /**
31480        * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
31481        */
31482        function setMouseWheelScrolling(value){
31483            if(value){
31484                addMouseWheelHandler();
31485                addMiddleWheelHandler();
31486            }else{
31487                removeMouseWheelHandler();
31488                removeMiddleWheelHandler();
31489            }
31490        }
31491
31492        /**
31493        * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
31494        * Optionally a second parameter can be used to specify the direction for which the action will be applied.
31495        *
31496        * @param directions string containing the direction or directions separated by comma.
31497        */
31498        function setAllowScrolling(value, directions){
31499            if(typeof directions !== 'undefined'){
31500                directions = directions.replace(/ /g,'').split(',');
31501
31502                $.each(directions, function (index, direction){
31503                    setIsScrollAllowed(value, direction, 'm');
31504                });
31505            }
31506            else if(value){
31507                setMouseWheelScrolling(true);
31508                addTouchHandler();
31509            }else{
31510                setMouseWheelScrolling(false);
31511                removeTouchHandler();
31512            }
31513        }
31514
31515        /**
31516        * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys
31517        */
31518        function setKeyboardScrolling(value, directions){
31519            if(typeof directions !== 'undefined'){
31520                directions = directions.replace(/ /g,'').split(',');
31521
31522                $.each(directions, function (index, direction){
31523                    setIsScrollAllowed(value, direction, 'k');
31524                });
31525            }else{
31526                options.keyboardScrolling = value;
31527            }
31528        }
31529
31530        /**
31531        * Moves the page up one section.
31532        */
31533        function moveSectionUp(){
31534            var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL);
31535
31536            //looping to the bottom if there's no more sections above
31537            if (!prev.length && (options.loopTop || options.continuousVertical)) {
31538                prev = $(SECTION_SEL).last();
31539            }
31540
31541            if (prev.length) {
31542                scrollPage(prev, null, true);
31543            }
31544        }
31545
31546        /**
31547        * Moves the page down one section.
31548        */
31549        function moveSectionDown(){
31550            var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL);
31551
31552            //looping to the top if there's no more sections below
31553            if(!next.length &&
31554                (options.loopBottom || options.continuousVertical)){
31555                next = $(SECTION_SEL).first();
31556            }
31557
31558            if(next.length){
31559                scrollPage(next, null, false);
31560            }
31561        }
31562
31563        /**
31564        * Moves the page to the given section and slide with no animation.
31565        * Anchors or index positions can be used as params.
31566        */
31567        function silentMoveTo(sectionAnchor, slideAnchor){
31568            setScrollingSpeed (0, 'internal');
31569            moveTo(sectionAnchor, slideAnchor);
31570            setScrollingSpeed (originals.scrollingSpeed, 'internal');
31571        }
31572
31573        /**
31574        * Moves the page to the given section and slide.
31575        * Anchors or index positions can be used as params.
31576        */
31577        function moveTo(sectionAnchor, slideAnchor){
31578            var destiny = getSectionByAnchor(sectionAnchor);
31579
31580            if (typeof slideAnchor !== 'undefined'){
31581                scrollPageAndSlide(sectionAnchor, slideAnchor);
31582            }else if(destiny.length > 0){
31583                scrollPage(destiny);
31584            }
31585        }
31586
31587        /**
31588        * Slides right the slider of the active section.
31589        * Optional `section` param.
31590        */
31591        function moveSlideRight(section){
31592            moveSlide('right', section);
31593        }
31594
31595        /**
31596        * Slides left the slider of the active section.
31597        * Optional `section` param.
31598        */
31599        function moveSlideLeft(section){
31600            moveSlide('left', section);
31601        }
31602
31603        /**
31604         * When resizing is finished, we adjust the slides sizes and positions
31605         */
31606        function reBuild(resizing){
31607            if(container.hasClass(DESTROYED)){ return; }  //nothing to do if the plugin was destroyed
31608
31609            isResizing = true;
31610
31611            windowsHeight = $window.height();  //updating global var
31612
31613            $(SECTION_SEL).each(function(){
31614                var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL);
31615                var slides = $(this).find(SLIDE_SEL);
31616
31617                //adjusting the height of the table-cell for IE and Firefox
31618                if(options.verticalCentered){
31619                    $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px');
31620                }
31621
31622                $(this).css('height', windowsHeight + 'px');
31623
31624                //resizing the scrolling divs
31625                if(options.scrollOverflow){
31626                    if(slides.length){
31627                        slides.each(function(){
31628                            createScrollBar($(this));
31629                        });
31630                    }else{
31631                        createScrollBar($(this));
31632                    }
31633                }
31634
31635                //adjusting the position fo the FULL WIDTH slides...
31636                if (slides.length > 1) {
31637                    landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL));
31638                }
31639            });
31640
31641            var activeSection = $(SECTION_ACTIVE_SEL);
31642            var sectionIndex = activeSection.index(SECTION_SEL);
31643
31644            //isn't it the first section?
31645            if(sectionIndex){
31646                //adjusting the position for the current section
31647                silentMoveTo(sectionIndex + 1);
31648            }
31649
31650            isResizing = false;
31651            // Uncode change
31652            // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container);
31653            $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight());
31654            $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container);
31655        }
31656
31657        /**
31658        * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height`
31659        * are smaller than the set limit values.
31660        */
31661        function setResponsive(active){
31662            var isResponsive = $body.hasClass(RESPONSIVE);
31663
31664            if(active){
31665                if(!isResponsive){
31666                    setAutoScrolling(false, 'internal');
31667                    setFitToSection(false, 'internal');
31668                    $(SECTION_NAV_SEL).hide();
31669                    $body.addClass(RESPONSIVE);
31670                    $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31671                }
31672            }
31673            else if(isResponsive){
31674                setAutoScrolling(originals.autoScrolling, 'internal');
31675                setFitToSection(originals.autoScrolling, 'internal');
31676                $(SECTION_NAV_SEL).show();
31677                $body.removeClass(RESPONSIVE);
31678                $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active);
31679            }
31680        }
31681
31682        if($(this).length){
31683            //public functions
31684            FP.setAutoScrolling = setAutoScrolling;
31685            FP.setRecordHistory = setRecordHistory;
31686            FP.setScrollingSpeed = setScrollingSpeed;
31687            FP.setFitToSection = setFitToSection;
31688            FP.setLockAnchors = setLockAnchors;
31689            FP.setMouseWheelScrolling = setMouseWheelScrolling;
31690            FP.setAllowScrolling = setAllowScrolling;
31691            FP.setKeyboardScrolling = setKeyboardScrolling;
31692            FP.moveSectionUp = moveSectionUp;
31693            FP.moveSectionDown = moveSectionDown;
31694            FP.silentMoveTo = silentMoveTo;
31695            FP.moveTo = moveTo;
31696            FP.moveSlideRight = moveSlideRight;
31697            FP.moveSlideLeft = moveSlideLeft;
31698            FP.fitToSection = fitToSection;
31699            FP.reBuild = reBuild;
31700            FP.setResponsive = setResponsive;
31701            FP.destroy = destroy;
31702
31703            init();
31704
31705            bindEvents();
31706        }
31707
31708        function init(){
31709            //if css3 is not supported, it will use jQuery animations
31710            if(options.css3){
31711                options.css3 = support3d();
31712            }
31713
31714            options.scrollBar = options.scrollBar || options.hybrid;
31715
31716            setOptionsFromDOM();
31717            prepareDom();
31718            setAllowScrolling(true);
31719            setAutoScrolling(options.autoScrolling, 'internal');
31720            responsive();
31721
31722            //setting the class for the body element
31723            setBodyClass();
31724
31725            //Uncode addition
31726            // if(document.readyState === 'complete'){
31727            //     scrollToAnchor();
31728            // }
31729            // $window.on('load', scrollToAnchor);
31730        }
31731
31732        function bindEvents(){
31733            $window
31734                //when scrolling...
31735                //.on('scroll', scrollHandler)
31736
31737                //detecting any change on the URL to scroll to the given anchor link
31738                //(a way to detect back history button as we play with the hashes on the URL)
31739                .on('hashchange', hashChangeHandler)
31740
31741                //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
31742                .blur(blurHandler)
31743
31744                //when resizing the site, we adjust the heights of the sections, slimScroll...
31745                .resize(resizeHandler);
31746
31747            $document
31748                //Sliding with arrow keys, both, vertical and horizontal
31749                .keydown(keydownHandler)
31750
31751                //to prevent scrolling while zooming
31752                .keyup(keyUpHandler)
31753
31754                //Scrolls to the section when clicking the navigation bullet
31755                .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler)
31756
31757                //Scrolls the slider to the given slide destination for the given section
31758                .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler)
31759
31760                .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler);
31761
31762            //Scrolling horizontally when clicking on the slider controls.
31763            $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler);
31764
31765            /**
31766            * Applying normalScroll elements.
31767            * Ignoring the scrolls over the specified selectors.
31768            */
31769            if(options.normalScrollElements){
31770                $document.on('mouseenter', options.normalScrollElements, function () {
31771                    setMouseWheelScrolling(false);
31772                });
31773
31774                $document.on('mouseleave', options.normalScrollElements, function(){
31775                    setMouseWheelScrolling(true);
31776                });
31777            }
31778        }
31779
31780        /**
31781        * Setting options from DOM elements if they are not provided.
31782        */
31783        function setOptionsFromDOM(){
31784            var sections = container.find(options.sectionSelector);
31785
31786            //no anchors option? Checking for them in the DOM attributes
31787            if(!options.anchors.length){
31788                options.anchors = sections.filter('[data-anchor]').map(function(){
31789                    return $(this).data('anchor').toString();
31790                }).get();
31791            }
31792
31793            //no tooltips option? Checking for them in the DOM attributes
31794            if(!options.navigationTooltips.length){
31795                options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){
31796                    return $(this).data('tooltip').toString();
31797                }).get();
31798            }
31799        }
31800
31801        /**
31802        * Works over the DOM structure to set it up for the current fullpage options.
31803        */
31804        function prepareDom(){
31805            container.css({
31806                'height': '100%',
31807                'position': 'relative'
31808            });
31809
31810            //adding a class to recognize the container internally in the code
31811            container.addClass(WRAPPER);
31812            $('html').addClass(ENABLED);
31813
31814            windowsHeight = $window.height();
31815
31816            container.removeClass(DESTROYED); //in case it was destroyed before initializing it again
31817
31818            addInternalSelectors();
31819
31820             //styling the sections / slides / menu
31821            $(SECTION_SEL).each(function(index){
31822                var section = $(this);
31823                var slides = section.find(SLIDE_SEL);
31824                var numSlides = slides.length;
31825
31826                styleSection(section, index);
31827                styleMenu(section, index);
31828
31829                // if there's any slide
31830                if (numSlides > 0) {
31831                    styleSlides(section, slides, numSlides);
31832                }else{
31833                    if(options.verticalCentered){
31834                        addTableClass(section);
31835                    }
31836                }
31837            });
31838
31839            //fixed elements need to be moved out of the plugin container due to problems with CSS3.
31840            if(options.fixedElements && options.css3){
31841                $(options.fixedElements).appendTo($body);
31842            }
31843
31844            //vertical centered of the navigation + active bullet
31845            if(options.navigation){
31846                addVerticalNavigation();
31847            }
31848
31849            enableYoutubeAPI();
31850
31851            if(options.scrollOverflow){
31852                if(document.readyState === 'complete'){
31853                    createScrollBarHandler();
31854                }
31855                //after DOM and images are loaded
31856                $window.on('load', createScrollBarHandler);
31857            }else{
31858                afterRenderActions();
31859            }
31860        }
31861
31862        /**
31863        * Styles the horizontal slides for a section.
31864        */
31865        function styleSlides(section, slides, numSlides){
31866            var sliderWidth = numSlides * 100;
31867            var slideWidth = 100 / numSlides;
31868
31869            slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />');
31870            slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />');
31871
31872            section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%');
31873
31874            if(numSlides > 1){
31875                if(options.controlArrows){
31876                    createSlideArrows(section);
31877                }
31878
31879                if(options.slidesNavigation){
31880                    addSlidesNavigation(section, numSlides);
31881                }
31882            }
31883
31884            slides.each(function(index) {
31885                $(this).css('width', slideWidth + '%');
31886
31887                if(options.verticalCentered){
31888                    addTableClass($(this));
31889                }
31890            });
31891
31892            var startingSlide = section.find(SLIDE_ACTIVE_SEL);
31893
31894            //if the slide won't be an starting point, the default will be the first one
31895            //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
31895ide by default.
31896            if( startingSlide.length &&  ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){
31897                silentLandscapeScroll(startingSlide, 'internal');
31898            }else{
31899                slides.eq(0).addClass(ACTIVE);
31900            }
31901        }
31902
31903        /**
31904        * Styling vertical sections
31905        */
31906        function styleSection(section, index){
31907            //if no active section is defined, the 1st one will be the default one
31908            if(!index && $(SECTION_ACTIVE_SEL).length === 0) {
31909                section.addClass(ACTIVE);
31910            }
31911            startingSection = $(SECTION_ACTIVE_SEL);
31912
31913            section.css('height', windowsHeight + 'px');
31914
31915            if(options.paddingTop){
31916                section.css('padding-top', options.paddingTop);
31917            }
31918
31919            if(options.paddingBottom){
31920                section.css('padding-bottom', options.paddingBottom);
31921            }
31922
31923            if (typeof options.sectionsColor[index] !==  'undefined') {
31924                section.css('background-color', options.sectionsColor[index]);
31925            }
31926
31927            if (typeof options.anchors[index] !== 'undefined') {
31928                section.attr('data-anchor', options.anchors[index]);
31929            }
31930        }
31931
31932        /**
31933        * Sets the data-anchor attributes to the menu elements and activates the current one.
31934        */
31935        function styleMenu(section, index){
31936            if (typeof options.anchors[index] !== 'undefined') {
31937                //activating the menu / nav element on load
31938                if(section.hasClass(ACTIVE)){
31939                    activateMenuAndNav(options.anchors[index], index);
31940                }
31941            }
31942
31943            //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
31944            if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){
31945                $(options.menu).appendTo($body);
31946            }
31947        }
31948
31949        /**
31950        * Adds internal classes to be able to provide customizable selectors
31951        * keeping the link with the style sheet.
31952        */
31953        function addInternalSelectors(){
31954            container.find(options.sectionSelector).addClass(SECTION);
31955            container.find(options.slideSelector).addClass(SLIDE);
31956        }
31957
31958        /**
31959        * Creates the control arrows for the given section
31960        */
31961        function createSlideArrows(section){
31962            section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>');
31963
31964            if(options.controlArrowColor!='#fff'){
31965                section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
31966                section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
31967            }
31968
31969            if(!options.loopHorizontal){
31970                section.find(SLIDES_ARROW_PREV_SEL).hide();
31971            }
31972        }
31973
31974        /**
31975        * Creates a vertical navigation bar.
31976        */
31977        function addVerticalNavigation(){
31978            $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>');
31979            var nav = $(SECTION_NAV_SEL);
31980
31981            nav.addClass(function() {
31982                return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition;
31983            });
31984
31985            for (var i = 0; i < $(SECTION_SEL).length; i++) {
31986                var link = '';
31987                if (options.anchors.length) {
31988                    link = options.anchors[i];
31989                }
31990
31991                var li = '<li><a href="#' + link + '"><span></span></a>';
31992
31993                // Only add tooltip if needed (defined by user)
31994                var tooltip = options.navigationTooltips[i];
31995
31996                if (typeof tooltip !== 'undefined' && tooltip !== '') {
31997                    li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>';
31998                }
31999
32000                li += '</li>';
32001
32002                nav.find('ul').append(li);
32003            }
32004
32005            //centering it vertically
32006            $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px');
32007
32008            //activating the current active section
32009            $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE);
32010        }
32011
32012        /**
32013        * Creates the slim scroll scrollbar for the sections and slides inside them.
32014        */
32015        function createScrollBarHandler(){
32016            $(SECTION_SEL).each(function(){
32017                var slides = $(this).find(SLIDE_SEL);
32018
32019                if(slides.length){
32020                    slides.each(function(){
32021                        createScrollBar($(this));
32022                    });
32023                }else{
32024                    createScrollBar($(this));
32025                }
32026
32027            });
32028            afterRenderActions();
32029        }
32030
32031        /*
32032        * Enables the Youtube videos API so we can control their flow if necessary.
32033        */
32034        function enableYoutubeAPI(){
32035            container.find('iframe[src*="youtube.com/embed/"]').each(function(){
32036                addURLParam($(this), 'enablejsapi=1');
32037            });
32038        }
32039
32040        /**
32041        * Adds a new parameter and its value to the `src` of a given element
32042        */
32043        function addURLParam(element, newParam){
32044            var originalSrc = element.attr('src');
32045            element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam);
32046        }
32047
32048        /*
32049        * Returns the prefix sign to use for a new parameter in an existen URL.
32050        *
32051        * @return {String}  ? | &
32052        */
32053        function getUrlParamSign(url){
32054            return ( !/\?/.test( url ) ) ? '?' : '&';
32055        }
32056
32057        /**
32058        * Actions and callbacks to fire afterRender
32059        */
32060        function afterRenderActions(){
32061            var section = $(SECTION_ACTIVE_SEL);
32062
32063            section.addClass(COMPLETELY);
32064
32065            if(options.scrollOverflowHandler.afterRender){
32066                options.scrollOverflowHandler.afterRender(section);
32067            }
32068            lazyLoad(section);
32069            playMedia(section);
32070            options.scrollOverflowHandler.afterLoad();
32071
32072            if(isDestinyTheStartingSection()){
32073                $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1));
32074            }
32075
32076            // Uncode change
32077            // $.isFunction( options.afterRender ) && options.afterRender.call(container);
32078            $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight());
32079        }
32080
32081        /**
32082        * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization)
32083        */
32084        function isDestinyTheStartingSection(){
32085            var anchors =  window.location.hash.replace('#', '').split('/');
32086            var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0]));
32087
32088            return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index();
32089        }
32090
32091
32092        var isScrolling = false;
32093        var lastScroll = 0;
32094
32095        //when scrolling...
32096        function scrollHandler(){
32097            var currentSection;
32098
32099            if(!options.autoScrolling || options.scrollBar){
32100                var currentScroll = $window.scrollTop();
32101                var scrollDirection = getScrollDirection(currentScroll);
32102                var visibleSectionIndex = 0;
32103                var screen_mid = currentScroll + ($window.height() / 2.0);
32104                var isAtBottom = $body.height() - $window.height() === currentScroll;
32105                var sections =  document.querySelectorAll(SECTION_SEL);
32106
32107                //when using `auto-height` for a small last section it won't be centered in the viewport
32108                if(isAtBottom){
32109                    visibleSectionIndex = sections.length - 1;
32110                }
32111                //is at top? when using `auto-height` for a small first section it won't be centered in the viewport
32112                else if(!currentScroll){
32113                    visibleSectionIndex = 0;
32114                }
32115
32116                //taking the section which is showing more content in the viewport
32117                else{
32118                    for (var i = 0; i < sections.length; ++i) {
32119                        var section = sections[i];
32120
32121                        // Pick the the last section which passes the middle line of the screen.
32122                        if (section.offsetTop <= screen_mid)
32123                        {
32124                            visibleSectionIndex = i;
32125                        }
32126                    }
32127                }
32128
32129                if(isCompletelyInViewPort(scrollDirection)){
32130                    if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){
32131                        $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32132                    }
32133                }
32134
32135                //geting the last one, the current one on the screen
32136                currentSection = $(sections).eq(visibleSectionIndex);
32137
32138                //setting the visible section as active when manually scrolling
32139                //executing only once the first time we reach the section
32140                if(!currentSection.hasClass(ACTIVE)){
32141                    isScrolling = true;
32142                    var leavingSection = $(SECTION_ACTIVE_SEL);
32143                    var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1;
32144                    var yMovement = getYmovement(currentSection);
32145                    var anchorLink  = currentSection.data('anchor');
32146                    var sectionIndex = currentSection.index(SECTION_SEL) + 1;
32147                    var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL);
32148                    var slideIndex;
32149                    var slideAnchorLink;
32150
32151                    if(activeSlide.length){
32152                        slideAnchorLink = activeSlide.data('anchor');
32153                        slideIndex = activeSlide.index();
32154                    }
32155
32156                    if(canScroll){
32157                        currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32158
32159                        $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement);
32160                        $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex);
32161
32162                        stopMedia(leavingSection);
32163                        lazyLoad(currentSection);
32164                        playMedia(currentSection);
32165
32166                        activateMenuAndNav(anchorLink, sectionIndex - 1);
32167
32168                        if(options.anchors.length){
32169                            //needed to enter in hashChange event when using the menu with anchor links
32170                            lastScrolledDestiny = anchorLink;
32171                        }
32172                        setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
32173                    }
32174
32175                    //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
32176                    clearTimeout(scrollId);
32177                    scrollId = setTimeout(function(){
32178                        isScrolling = false;
32179                    }, 100);
32180                }
32181
32182                if(options.fitToSection){
32183                    //for the auto adjust of the viewport to fit a whole section
32184                    clearTimeout(scrollId2);
32185
32186                    scrollId2 = setTimeout(function(){
32187                        //checking it again in case it changed during the delay
32188                        if(options.fitToSection){
32189                            fitToSection();
32190                        }
32191                    }, options.fitToSectionDelay);
32192                }
32193            }
32194        }
32195
32196        /**
32197        * Fits the site to the nearest active section
32198        */
32199        function fitToSection(){
32200            //checking fitToSection again in case it was set to false before the timeout delay
32201            if(canScroll){
32202                //allows to scroll to an active section and
32203                //if the section is already active, we prevent firing callbacks
32204                isResizing = true;
32205
32206                scrollPage($(SECTION_ACTIVE_SEL));
32207                isResizing = false;
32208            }
32209        }
32210
32211        /**
32212        * Determines whether the active section has seen in its whole or not.
32213        */
32214        function isCompletelyInViewPort(movement){
32215            var top = $(SECTION_ACTIVE_SEL).position().top;
32216            var bottom = top + $window.height();
32217
32218            if(movement == 'up'){
32219                return bottom >= ($window.scrollTop() + $window.height());
32220            }
32221            return top <= $window.scrollTop();
32222        }
32223
32224        /**
32225        * Gets the directon of the the scrolling fired by the scroll event.
32226        */
32227        function getScrollDirection(currentScroll){
32228            var direction = currentScroll > lastScroll ? 'down' : 'up';
32229
32230            lastScroll = currentScroll;
32231
32232            //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination
32233            previousDestTop = currentScroll;
32234
32235            return direction;
32236        }
32237
32238        /**
32239        * Determines the way of scrolling up or down:
32240        * by 'automatically' scrolling a section or by using the default and normal scrolling.
32241        */
32242        function scrolling(type, scrollable){
32243            if (!isScrollAllowed.m[type]){
32244                return;
32245            }
32246            var check = (type === 'down') ? 'bottom' : 'top';
32247            var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp;
32248
32249            if(scrollable.length > 0 ){
32250                //is the scrollbar at the start/end of the scroll?
32251                if(options.scrollOverflowHandler.isScrolled(check, scrollable)){
32252                    scrollSection();
32253                }else{
32254                    return true;
32255                }
32256            }else{
32257                // moved up/down
32258                scrollSection();
32259            }
32260        }
32261
32262        /*
32263        * Preventing bouncing in iOS #2285
32264        */
32265        function preventBouncing(event){
32266            var e = event.originalEvent;
32267            if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){
32268                //preventing the easing on iOS devices
32269                event.preventDefault();
32270            }
32271        }
32272
32273        var touchStartY = 0;
32274        var touchStartX = 0;
32275        var touchEndY = 0;
32276        var touchEndX = 0;
32277
32278        /* Detecting touch events
32279
32280        * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
32281        * This way, the touchstart and the touch moves shows an small difference between them which is the
32282        * used one to determine the direction.
32283        */
32284        function touchMoveHandler(event){
32285            var e = event.originalEvent;
32286            var activeSection = $(e.target).closest(SECTION_SEL);
32287
32288            // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
32289            if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) {
32290
32291                if(options.autoScrolling){
32292                    //preventing the easing on iOS devices
32293                    event.preventDefault();
32294                }
32295
32296                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32297                var touchEvents = getEventsPage(e);
32298
32299                touchEndY = touchEvents.y;
32300                touchEndX = touchEvents.x;
32301
32302                //if movement in the X axys is greater than in the Y and the currect section has slides...
32303                if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
32304
32305                    //is the movement greater than the minimum resistance to scroll?
32306                    if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) {
32307                        if (touchStartX > touchEndX) {
32308                            if(isScrollAllowed.m.right){
32309                                moveSlideRight(activeSection); //next
32310                            }
32311                        } else {
32312                            if(isScrollAllowed.m.left){
32313                                moveSlideLeft(activeSection); //prev
32314                            }
32315                        }
32316                    }
32317                }
32318
32319                //vertical scrolling (only when autoScrolling is enabled)
32320                else if(options.autoScrolling && canScroll){
32321
32322                    //is the movement greater than the minimum resistance to scroll?
32323                    if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) {
32324                        if (touchStartY > touchEndY) {
32325                            scrolling('down', scrollable);
32326                        } else if (touchEndY > touchStartY) {
32327                            scrolling('up', scrollable);
32328                        }
32329                    }
32330                }
32331            }
32332        }
32333
32334        /**
32335         * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
32336         * Currently works well for iOS - Android might need some testing
32337         * @param  {Element} el  target element / jquery selector (in subsequent nodes)
32338         * @param  {int}     hop current hop compared to options.normalScrollElementTouchThreshold
32339         * @return {boolean} true if there is a match to options.normalScrollElements
32340         */
32341        function checkParentForNormalScrollElement (el, hop) {
32342            hop = hop || 0;
32343            var parent = $(el).parent();
32344
32345            if (hop < options.normalScrollElementTouchThreshold &&
32346                parent.is(options.normalScrollElements) ) {
32347                return true;
32348            } else if (hop == options.normalScrollElementTouchThreshold) {
32349                return false;
32350            } else {
32351                return checkParentForNormalScrollElement(parent, ++hop);
32352            }
32353        }
32354
32355        /**
32356        * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen
32357        * this way we make sure that is really a touch event what IE is detecting.
32358        */
32359        function isReallyTouch(e){
32360            //if is not IE   ||  IE is detecting `touch` or `pen`
32361            return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse';
32362        }
32363
32364        /**
32365        * Handler for the touch start event.
32366        */
32367        function touchStartHandler(event){
32368            var e = event.originalEvent;
32369
32370            //stopping the auto scroll to adjust to a section
32371            if(options.fitToSection){
32372                $htmlBody.stop();
32373            }
32374
32375            if(isReallyTouch(e)){
32376                var touchEvents = getEventsPage(e);
32377                touchStartY = touchEvents.y;
32378                touchStartX = touchEvents.x;
32379            }
32380        }
32381
32382        /**
32383        * Gets the average of the last `number` elements of the given array.
32384        */
32385        function getAverage(elements, number){
32386            var sum = 0;
32387
32388            //taking `number` elements from the end to make the average, if there are not enought, 1
32389            var lastElements = elements.slice(Math.max(elements.length - number, 1));
32390
32391            for(var i = 0; i < lastElements.length; i++){
32392                sum = sum + lastElements[i];
32393            }
32394
32395            return Math.ceil(sum/number);
32396        }
32397
32398        /**
32399         * Detecting mousewheel scrolling
32400         *
32401         * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
32402         * http://www.sitepoint.com/html5-javascript-mouse-wheel/
32403         */
32404        var prevTime = new Date().getTime();
32405
32406        function MouseWheelHandler(e) {
32407            var curTime = new Date().getTime();
32408            var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL);
32409
32410            //autoscrolling and not zooming?
32411            if(options.autoScrolling && !controlPressed && !isNormalScroll){
32412                // cross-browser wheel delta
32413                e = e || window.event;
32414                var value = e.wheelDelta || -e.deltaY || -e.detail;
32415                var delta = Math.max(-1, Math.min(1, value));
32416
32417                var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined';
32418                var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection);
32419
32420                //Limiting the array to 150 (lets not waste memory!)
32421                if(scrollings.length > 149){
32422                    scrollings.shift();
32423                }
32424
32425                //keeping record of the previous scrollings
32426                scrollings.push(Math.abs(value));
32427
32428                //preventing to scroll the site on mouse wheel when scrollbar is present
32429                if(options.scrollBar){
32430                    e.preventDefault ? e.preventDefault() : e.returnValue = false;
32431                }
32432
32433                var activeSection = $(SECTION_ACTIVE_SEL);
32434                var scrollable = options.scrollOverflowHandler.scrollable(activeSection);
32435
32436                //time difference between the last scroll and the current one
32437                var timeDiff = curTime-prevTime;
32438                prevTime = curTime;
32439
32440                //haven't they scrolled in a while?
32441                //(enough to be consider a different scrolling action to scroll another section)
32442                if(timeDiff > 200){
32443                    //emptying the array, we dont care about old scrollings for our averages
32444                    scrollings = [];
32445                }
32446
32447                if(canScroll){
32448                    var averageEnd = getAverage(scrollings, 10);
32449                    var averageMiddle = getAverage(scrollings, 70);
32450                    var isAccelerating = averageEnd >= averageMiddle;
32451
32452                    //to avoid double swipes...
32453                    if(isAccelerating && isScrollingVertically){
32454                        //scrolling down?
32455                        if (delta < 0) {
32456                            scrolling('down', scrollable);
32457
32458                        //scrolling up?
32459                        }else {
32460                            scrolling('up', scrollable);
32461                        }
32462                    }
32463                }
32464
32465                return false;
32466            }
32467
32468            if(options.fitToSection){
32469                //stopping the auto scroll to adjust to a section
32470                $htmlBody.stop();
32471            }
32472        }
32473
32474        /**
32475        * Slides a slider to the given direction.
32476        * Optional `section` param.
32477        */
32478        function moveSlide(direction, section){
32479            var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section;
32480            var slides = activeSection.find(SLIDES_WRAPPER_SEL);
32481            var numSlides = slides.find(SLIDE_SEL).length;
32482
32483            // more than one slide needed and nothing should be sliding
32484            if (!slides.length || slideMoving || numSlides < 2) {
32485                return;
32486            }
32487
32488            var currentSlide = slides.find(SLIDE_ACTIVE_SEL);
32489            var destiny = null;
32490
32491            if(direction === 'left'){
32492                destiny = currentSlide.prev(SLIDE_SEL);
32493            }else{
32494                destiny = currentSlide.next(SLIDE_SEL);
32495            }
32496
32497            //isn't there a next slide in the secuence?
32498            if(!destiny.length){
32499                //respect loopHorizontal settin
32500                if (!options.loopHorizontal) return;
32501
32502                if(direction === 'left'){
32503                    destiny = currentSlide.siblings(':last');
32504                }else{
32505                    destiny = currentSlide.siblings(':first');
32506                }
32507            }
32508
32509            slideMoving = true;
32510
32511            landscapeScroll(slides, destiny, direction);
32512        }
32513
32514        /**
32515        * Maintains the active slides in the viewport
32516        * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical)
32517        */
32518        function keepSlidesPosition(){
32519            $(SLIDE_ACTIVE_SEL).each(function(){
32520                silentLandscapeScroll($(this), 'internal');
32521            });
32522        }
32523
32524        var previousDestTop = 0;
32525        /**
32526        * Returns the destination Y position based on the scrolling direction and
32527        * the height of the section.
32528        */
32529        function getDestinationPosition(element){
32530            var elemPosition = element.position();
32531
32532            //top of the desination will be at the top of the viewport
32533            var position = elemPosition.top;
32534            var isScrollingDown =  elemPosition.top > previousDestTop;
32535            var sectionBottom = position - windowsHeight + element.outerHeight();
32536            var bigSectionsDestination = options.bigSectionsDestination;
32537
32538            //Uncode addition
32539            var containerH = container.outerHeight();
32540            var containerPosition = container.offset();
32541
32542            //########### Commented by Uncode - START ###########
32543            //is the destination element bigger than the viewport?
32544            // if(element.outerHeight() > windowsHeight){
32545            //     //scrolling up?
32546            //     if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){
32547            //         position = sectionBottom;
32548            //     }
32549            // }
32550
32551            // //sections equal or smaller than the viewport height && scrolling down? ||  is resizing and its in the last section
32552            // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){
32553            //     //The bottom of the destination will be at the bottom of the viewport
32554            //     position = sectionBottom;
32555            // }
32556            //########### Commented by Uncode - END ###########
32557
32558            //Uncode addition
32559            if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') )
32560                position += 18;
32561            if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) {
32562                position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight;
32563            }
32564
32565            /*
32566            Keeping record of the last scrolled position to determine the scrolling direction.
32567            No conventional methods can be used as the scroll bar might not be present
32568            AND the section might not be active if it is auto-height and didnt reach the middle
32569            of the viewport.
32570            */
32571            previousDestTop = position;
32572            return position;
32573        }
32574
32575        /**
32576        * Scrolls the site to the given element and scrolls to the slide if a callback is given.
32577        */
32578        function scrollPage(element, callback, isMovementUp){
32579            if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function
32580
32581            var dtop = getDestinationPosition(element);
32582            var slideAnchorLink;
32583            var slideIndex;
32584
32585            //local variables
32586            var v = {
32587                element: element,
32588                callback: callback,
32589                isMovementUp: isMovementUp,
32590                dtop: dtop,
32591                yMovement: getYmovement(element),
32592                anchorLink: element.data('anchor'),
32593                sectionIndex: element.index(SECTION_SEL),
32594                activeSlide: element.find(SLIDE_ACTIVE_SEL),
32595                activeSection: $(SECTION_ACTIVE_SEL),
32596                leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1,
32597
32598                //caching the value of isResizing at the momment the function is called
32599                //because it will be checked later inside a setTimeout and the value might change
32600                localIsResizing: isResizing
32601            };
32602
32603            //quiting when destination scroll is the same as the current one
32604            if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; }
32605
32606            if(v.activeSlide.length){
32607                slideAnchorLink = v.activeSlide.data('anchor');
32608                slideIndex = v.activeSlide.index();
32609            }
32610
32611            // If continuousVertical && we need to wrap around
32612            if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
32613                ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
32614                (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
32615
32616                v = createInfiniteSections(v);
32617            }
32618
32619            //callback (onLeave) if the site is not just resizing and readjusting the slides
32620            if($.isFunction(options.onLeave) && !v.localIsResizing){
32621                if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){
32622                    return;
32623                }
32624            }
32625
32626            //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one)
32627            if(!v.localIsResizing){
32628                stopMedia(v.activeSection);
32629            }
32630
32631            options.scrollOverflowHandler.beforeLeave();
32632            element.addClass(ACTIVE).siblings().removeClass(ACTIVE);
32633            lazyLoad(element);
32634            options.scrollOverflowHandler.onLeave();
32635
32636
32637            //preventing from activating the MouseWheelHandler event
32638            //more than once if the page is scrolling
32639            canScroll = false;
32640
32641            setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
32642
32643            performMovement(v);
32644
32645            //flag to avoid callingn `scrollPage()` twice in case of using anchor links
32646            lastScrolledDestiny = v.anchorLink;
32647
32648            //avoid firing it twice (as it does also on scroll)
32649            activateMenuAndNav(v.anchorLink, v.sectionIndex);
32650        }
32651
32652        /**
32653        * Performs the vertical movement (by CSS3 or by jQuery)
32654        */
32655        function performMovement(v){
32656            // using CSS3 translate functionality
32657            if (options.css3 && options.autoScrolling && !options.scrollBar) {
32658
32659                // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
32660                // that's why we round it to 0.
32661                var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)';
32662                transformContainer(translate3d, true);
32663
32664                //even when the scrollingSpeed is 0 there's a little delay, which might cause the
32665                //scrollingSpeed to change in case of using silentMoveTo();
32666                if(options.scrollingSpeed){
32667                    clearTimeout(afterSectionLoadsId);
32668                    afterSectionLoadsId = setTimeout(function () {
32669                        afterSectionLoads(v);
32670                    }, options.scrollingSpeed);
32671                }else{
32672                    afterSectionLoads(v);
32673                }
32674            }
32675
32676            // using jQuery animate
32677            else{
32678                var scrollSettings = getScrollSettings(v);
32679
32680                $(scrollSettings.element).animate(
32681                    scrollSettings.options,
32682                options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating  `html, body`
32683                    if(options.scrollBar){
32684
32685                        /* Hack!
32686                        The timeout prevents setting the most dominant section in the viewport as "active" when the user
32687                        scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar.
32688
32689                        When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished.
32690                        */
32691                        setTimeout(function(){
32692                            afterSectionLoads(v);
32693                        },30);
32694                    }else{
32695                        afterSectionLoads(v);
32696                    }
32697                });
32698            }
32699        }
32700
32701        /**
32702        * Gets the scrolling settings depending on the plugin autoScrolling option
32703        */
32704        function getScrollSettings(v){
32705            var scroll = {};
32706
32707            if(options.autoScrolling && !options.scrollBar){
32708                scroll.options = { 'top': -v.dtop};
32709                scroll.element = WRAPPER_SEL;
32710            }else{
32711                scroll.options = { 'scrollTop': v.dtop};
32712                scroll.element = 'html, body';
32713            }
32714
32715            return scroll;
32716        }
32717
32718        /**
32719        * Adds sections before or after the current one to create the infinite effect.
32720        */
32721        function createInfiniteSections(v){
32722            // Scrolling down
32723            if (!v.isMovementUp) {
32724                // Move all previous sections to after the active section
32725                $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse());
32726            }
32727            else { // Scrolling up
32728                // Move all next sections to before the active section
32729                $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL));
32730            }
32731
32732            // Maintain the displayed position (now that we changed the element order)
32733            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32734
32735            // Maintain the active slides visible in the viewport
32736            keepSlidesPosition();
32737
32738            // save for later the elements that still need to be reordered
32739            v.wrapAroundElements = v.activeSection;
32740
32741            // Recalculate animation variables
32742            v.dtop = v.element.position().top;
32743            v.yMovement = getYmovement(v.element);
32744
32745            return v;
32746        }
32747
32748        /**
32749        * Fix section order after continuousVertical changes have been animated
32750        */
32751        function continuousVerticalFixSectionOrder (v) {
32752            // If continuousVertical is in effect (and autoScrolling would also be in effect then),
32753            // finish moving the elements around so the direct navigation will function more simply
32754            if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
32755                return;
32756            }
32757
32758            if (v.isMovementUp) {
32759                $(SECTION_FIRST_SEL).before(v.wrapAroundElements);
32760            }
32761            else {
32762                $(SECTION_LAST_SEL).after(v.wrapAroundElements);
32763            }
32764
32765            silentScroll($(SECTION_ACTIVE_SEL).position().top);
32766
32767            // Maintain the active slides visible in the viewport
32768            keepSlidesPosition();
32769        }
32770
32771
32772        /**
32773        * Actions to do once the section is loaded.
32774        */
32775        function afterSectionLoads (v){
32776            continuousVerticalFixSectionOrder(v);
32777
32778            //callback (afterLoad) if the site is not just resizing and readjusting the slides
32779            $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1));
32780            options.scrollOverflowHandler.afterLoad();
32781
32782            if(!v.localIsResizing){
32783                playMedia(v.element);
32784            }
32785
32786            v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY);
32787
32788            canScroll = true;
32789
32790            $.isFunction(v.callback) && v.callback.call(this);
32791        }
32792
32793        /**
32794        * Sets the value for the given attribute from the `data-` attribute with the same suffix
32795        * ie: data-srcset ==> srcset  |  data-src ==> src
32796        */
32797        function setSrc(element, attribute){
32798            element
32799                .attr(attribute, element.data(attribute))
32800                .removeAttr('data-' + attribute);
32801        }
32802
32803        /**
32804        * Lazy loads image, video and audio elements.
32805        */
32806        function lazyLoad(destiny){
32807            if (!options.lazyLoading){
32808                return;
32809            }
32810
32811            var panel = getSlideOrSection(destiny);
32812            var element;
32813
32814            panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){
32815                element = $(this);
32816
32817                $.each(['src', 'srcset'], function(index, type){
32818                    var attribute = element.attr('data-' + type);
32819                    if(typeof attribute !== 'undefined' && attribute){
32820                        setSrc(element, type);
32821                    }
32822                });
32823
32824                if(element.is('source')){
32825                    element.closest('video').get(0).load();
32826                }
32827            });
32828        }
32829
32830        /**
32831        * Plays video and audio elements.
32832        */
32833        function playMedia(destiny){
32834            var panel = getSlideOrSection(destiny);
32835
32836            //playing HTML5 media elements
32837            panel.find('video, audio').each(function(){
32838                var element = $(this).get(0);
32839
32840                if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) {
32841                    element.play();
32842                }
32843            });
32844
32845            //youtube videos
32846            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32847                var element = $(this).get(0);
32848
32849                if ( element.hasAttribute('data-autoplay') ){
32850                    playYoutube(element);
32851                }
32852
32853                //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load.
32854                element.onload = function() {
32855                    if ( element.hasAttribute('data-autoplay') ){
32856                        playYoutube(element);
32857                    }
32858                };
32859            });
32860        }
32861
32862        /**
32863        * Plays a youtube video
32864        */
32865        function playYoutube(element){
32866            element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
32867        }
32868
32869        /**
32870        * Stops video and audio elements.
32871        */
32872        function stopMedia(destiny){
32873            var panel = getSlideOrSection(destiny);
32874
32875            //stopping HTML5 media elements
32876            panel.find('video, audio').each(function(){
32877                var element = $(this).get(0);
32878
32879                if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) {
32880                    element.pause();
32881                }
32882            });
32883
32884            //youtube videos
32885            panel.find('iframe[src*="youtube.com/embed/"]').each(function(){
32886                var element = $(this).get(0);
32887
32888                if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){
32889                    $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*');
32890                }
32891            });
32892        }
32893
32894        /**
32895        * Gets the active slide (or section) for the given section
32896        */
32897        function getSlideOrSection(destiny){
32898            var slide = destiny.find(SLIDE_ACTIVE_SEL);
32899            if( slide.length ) {
32900                destiny = $(slide);
32901            }
32902
32903            return destiny;
32904        }
32905
32906        /**
32907        * Scrolls to the anchor in the URL when loading the site
32908        */
32909        function scrollToAnchor(){
32910            //getting the anchor link in the URL and deleting the `#`
32911            var value =  window.location.hash.replace('#', '').split('/');
32912            var sectionAnchor = decodeURIComponent(value[0]);
32913            var slideAnchor = decodeURIComponent(value[1]);
32914
32915            if(sectionAnchor){  //if theres any #
32916                if(options.animateAnchor){
32917                    scrollPageAndSlide(sectionAnchor, slideAnchor);
32918                }else{
32919                    silentMoveTo(sectionAnchor, slideAnchor);
32920                }
32921            }
32922        }
32923
32924        /**
32925        * Detecting any change on the URL to scroll to the given anchor link
32926        * (a way to detect back history button as we play with the hashes on the URL)
32927        */
32928        function hashChangeHandler(){
32929            if(!isScrolling && !options.lockAnchors){
32930                var value =  window.location.hash.replace('#', '').split('/');
32931                var sectionAnchor = decodeURIComponent(value[0]);
32932                var slideAnchor = decodeURIComponent(value[1]);
32933
32934                    //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
32935                    var isFirstSlideMove =  (typeof lastScrolledDestiny === 'undefined');
32936                    var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving);
32937
32938
32939                if(sectionAnchor.length){
32940                    /*in order to call scrollpage() only once for each destination at a time
32941                    It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
32942                    event is fired on every scroll too.*/
32943                    if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor ))  {
32944                        scrollPageAndSlide(sectionAnchor, slideAnchor);
32945                    }
32946                }
32947            }
32948        }
32949
32950        //Sliding with arrow keys, both, vertical and horizontal
32951        function keydownHandler(e) {
32952
32953            clearTimeout(keydownId);
32954
32955            var activeElement = $(':focus');
32956
32957            if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') &&
32958                activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' &&
32959                options.keyboardScrolling && options.autoScrolling){
32960                var keyCode = e.which;
32961
32962                //preventing the scroll with arrow keys & spacebar & Page Up & Down keys
32963                var keyControls = [40, 38, 32, 33, 34];
32964                if($.inArray(keyCode, keyControls) > -1){
32965                    e.preventDefault();
32966                }
32967
32968                controlPressed = e.ctrlKey;
32969
32970                keydownId = setTimeout(function(){
32971                    onkeydown(e);
32972                },150);
32973            }
32974        }
32975
32976        function tooltipTextHandler(){
32977            $(this).prev().trigger('click');
32978        }
32979
32980        //to prevent scrolling while zooming
32981        function keyUpHandler(e){
32982            if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox
32983                controlPressed = e.ctrlKey;
32984            }
32985        }
32986
32987        //binding the mousemove when the mouse's middle button is released
32988        function mouseDownHandler(e){
32989            //middle button
32990            if (e.which == 2){
32991                oldPageY = e.pageY;
32992                container.on('mousemove', mouseMoveHandler);
32993            }
32994        }
32995
32996        //unbinding the mousemove when the mouse's middle button is released
32997        function mouseUpHandler(e){
32998            //middle button
32999            if (e.which == 2){
33000                container.off('mousemove');
33001            }
33002        }
33003
33004        //Scrolling horizontally when clicking on the slider controls.
33005        function slideArrowHandler(){
33006            var section = $(this).closest(SECTION_SEL);
33007
33008            if ($(this).hasClass(SLIDES_PREV)) {
33009                if(isScrollAllowed.m.left){
33010                    moveSlideLeft(section);
33011                }
33012            } else {
33013                if(isScrollAllowed.m.right){
33014                    moveSlideRight(section);
33015                }
33016            }
33017        }
33018
33019        //when opening a new tab (ctrl + t), `control` won't be pressed when coming back.
33020        function blurHandler(){
33021            isWindowFocused = false;
33022            controlPressed = false;
33023        }
33024
33025        //Scrolls to the section when clicking the navigation bullet
33026        function sectionBulletHandler(e){
33027            e.preventDefault();
33028            var index = $(this).parent().index();
33029            scrollPage($(SECTION_SEL).eq(index));
33030        }
33031
33032        //Scrolls the slider to the given slide destination for the given section
33033        function slideBulletHandler(e){
33034            e.preventDefault();
33035            var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL);
33036            var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index());
33037
33038            landscapeScroll(slides, destiny);
33039        }
33040
33041        /**
33042        * Keydown event
33043        */
33044        function onkeydown(e){
33045            var shiftPressed = e.shiftKey;
33046
33047            //do nothing if we can not scroll or we are not using horizotnal key arrows.
33048            if(!canScroll && [37,39].indexOf(e.which) < 0){
33049                return;
33050            }
33051
33052            switch (e.which) {
33053                //up
33054                case 38:
33055                case 33:
33056                    if(isScrollAllowed.k.up){
33057                        moveSectionUp();
33058                    }
33059                    break;
33060
33061                //down
33062                case 32: //spacebar
33063                    if(shiftPressed && isScrollAllowed.k.up){
33064                        moveSectionUp();
33065                        break;
33066                    }
33067                /* falls through */
33068                case 40:
33069                case 34:
33070                    if(isScrollAllowed.k.down){
33071                        moveSectionDown();
33072                    }
33073                    break;
33074
33075                //Home
33076                case 36:
33077                    if(isScrollAllowed.k.up){
33078                        moveTo(1);
33079                    }
33080                    break;
33081
33082                //End
33083                case 35:
33084                     if(isScrollAllowed.k.down){
33085                        moveTo( $(SECTION_SEL).length );
33086                    }
33087                    break;
33088
33089                //left
33090                case 37:
33091                    if(isScrollAllowed.k.left){
33092                        moveSlideLeft();
33093                    }
33094                    break;
33095
33096                //right
33097                case 39:
33098                    if(isScrollAllowed.k.right){
33099                        moveSlideRight();
33100                    }
33101                    break;
33102
33103                default:
33104                    return; // exit this handler for other keys
33105            }
33106        }
33107
33108        /**
33109        * Detecting the direction of the mouse movement.
33110        * Used only for the middle button of the mouse.
33111        */
33112        var oldPageY = 0;
33113        function mouseMoveHandler(e){
33114            if(canScroll){
33115                // moving up
33116                if (e.pageY < oldPageY && isScrollAllowed.m.up){
33117                    moveSectionUp();
33118                }
33119
33120                // moving down
33121                else if(e.pageY > oldPageY && isScrollAllowed.m.down){
33122                    moveSectionDown();
33123                }
33124            }
33125            oldPageY = e.pageY;
33126        }
33127
33128        /**
33129        * Scrolls horizontal sliders.
33130        */
33131        function landscapeScroll(slides, destiny, direction){
33132            var section = slides.closest(SECTION_SEL);
33133            var v = {
33134                slides: slides,
33135                destiny: destiny,
33136                direction: direction,
33137                destinyPos: destiny.position(),
33138                slideIndex: destiny.index(),
33139                section: section,
33140                sectionIndex: section.index(SECTION_SEL),
33141                anchorLink: section.data('anchor'),
33142                slidesNav: section.find(SLIDES_NAV_SEL),
33143                slideAnchor:  getAnchor(destiny),
33144                prevSlide: section.find(SLIDE_ACTIVE_SEL),
33145                prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(),
33146
33147                //caching the value of isResizing at the momment the function is called
33148                //because it will be checked later inside a setTimeout and the value might change
33149                localIsResizing: isResizing
33150            };
33151            v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex);
33152            v.direction = v.direction ? v.direction : v.xMovement;
33153
33154            //important!! Only do it when not resizing
33155            if(!v.localIsResizing){
33156                //preventing from scrolling to the next/prev section when using scrollHorizontally
33157                canScroll = false;
33158            }
33159
33160            if(options.onSlideLeave){
33161
33162                //if the site is not just resizing and readjusting the slides
33163                if(!v.localIsResizing && v.xMovement!=='none'){
33164                    if($.isFunction( options.onSlideLeave )){
33165                        if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){
33166                            slideMoving = false;
33167                            return;
33168                        }
33169                    }
33170                }
33171            }
33172
33173            destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE);
33174
33175            if(!v.localIsResizing){
33176                stopMedia(v.prevSlide);
33177                lazyLoad(destiny);
33178            }
33179
33180            if(!options.loopHorizontal && options.controlArrows){
33181                //hidding it for the fist slide, showing for the rest
33182                section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0);
33183
33184                //hidding it for the last slide, showing for the rest
33185                section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child'));
33186            }
33187
33188            //only changing the URL if the slides are in the current section (not for resize re-adjusting)
33189            if(section.hasClass(ACTIVE) && !v.localIsResizing){
33190                setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex);
33191            }
33192
33193            performHorizontalMove(slides, v, true);
33194        }
33195
33196
33197        function afterSlideLoads(v){
33198            activeSlidesNavigation(v.slidesNav, v.slideIndex);
33199
33200            //if the site is not just resizing and readjusting the slides
33201            if(!v.localIsResizing){
33202                $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex);
33203
33204                //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally
33205                //and to prevent double scroll right after a windows resize
33206                canScroll = true;
33207
33208                playMedia(v.destiny);
33209            }
33210
33211            //letting them slide again
33212            slideMoving = false;
33213        }
33214
33215        /**
33216        * Performs the horizontal movement. (CSS3 or jQuery)
33217        *
33218        * @param fireCallback {Bool} - determines whether or not to fire the callback
33219        */
33220        function performHorizontalMove(slides, v, fireCallback){
33221            var destinyPos = v.destinyPos;
33222
33223            if(options.css3){
33224                var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)';
33225
33226                addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v);
33227
33228                afterSlideLoadsId = setTimeout(function(){
33229                    fireCallback && afterSlideLoads(v);
33230                }, options.scrollingSpeed, options.easing);
33231            }else{
33232                slides.animate({
33233                    scrollLeft : Math.round(destinyPos.left)
33234                }, options.scrollingSpeed, options.easing, function() {
33235
33236                    fireCallback && afterSlideLoads(v);
33237                });
33238            }
33239        }
33240
33241        /**
33242        * Sets the state for the horizontal bullet navigations.
33243        */
33244        function activeSlidesNavigation(slidesNav, slideIndex){
33245            slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE);
33246            slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE);
33247        }
33248
33249        var previousHeight = windowsHeight;
33250
33251        //when resizing the site, we adjust the heights of the sections, slimScroll...
33252        function resizeHandler(){
33253            //checking if it needs to get responsive
33254            responsive();
33255
33256            // rebuild immediately on touch devices
33257            if (isTouchDevice) {
33258                var activeElement = $(document.activeElement);
33259
33260                //if the keyboard is NOT visible
33261                if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) {
33262                    var currentHeight = $window.height();
33263
33264                    //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)
33265                    if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
33266                        reBuild(true);
33267                        previousHeight = currentHeight;
33268                    }
33269                }
33270            }else{
33271                //in order to call the functions only when the resize is finished
33272                //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
33273                clearTimeout(resizeId);
33274
33275                resizeId = setTimeout(function(){
33276                    reBuild(true);
33277                }, 350);
33278            }
33279        }
33280
33281        /**
33282        * Checks if the site needs to get responsive and disables autoScrolling if so.
33283        * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
33284        */
33285        function responsive(){
33286            var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity
33287            var heightLimit = options.responsiveHeight;
33288
33289            //only calculating what we need. Remember its called on the resize event.
33290            var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit;
33291            var isBreakingPointHeight = heightLimit && $window.height() < heightLimit;
33292
33293            if(widthLimit && heightLimit){
33294                setResponsive(isBreakingPointWidth || isBreakingPointHeight);
33295            }
33296            else if(widthLimit){
33297                setResponsive(isBreakingPointWidth);
33298            }
33299            else if(heightLimit){
33300                setResponsive(isBreakingPointHeight);
33301            }
33302        }
33303
33304        /**
33305        * Adds transition animations for the given element
33306        */
33307        function addAnimation(container, element){
33308            var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
33309
33310            container.removeClass(NO_TRANSITION);
33311            return container.css({
33312                '-webkit-transition': transition,
33313                'transition': transition
33314            });
33315        }
33316
33317        /**
33318        * Remove transition animations for the given element
33319        */
33320        function removeAnimation(element){
33321            return element.addClass(NO_TRANSITION);
33322        }
33323
33324        /**
33325        * Activating the vertical navigation bullets according to the given slide name.
33326        */
33327        function activateNavDots(name, sectionIndex){
33328            if(options.navigation){
33329                $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE);
33330                if(name){
33331                    $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE);
33332                }else{
33333                    $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE);
33334                }
33335            }
33336        }
33337
33338        /**
33339        * Activating the website main menu elements according to the given slide name.
33340        */
33341        function activateMenuElement(name){
33342            if(options.menu){
33343                $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE);
33344                $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE);
33345            }
33346        }
33347
33348        /**
33349        * Sets to active the current menu and vertical nav items.
33350        */
33351        function activateMenuAndNav(anchor, index){
33352            activateMenuElement(anchor);
33353            activateNavDots(anchor, index);
33354        }
33355
33356        /**
33357        * Retuns `up` or `down` depending on the scrolling movement to reach its destination
33358        * from the current section.
33359        */
33360        function getYmovement(destiny){
33361            var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL);
33362            var toIndex = destiny.index(SECTION_SEL);
33363            if( fromIndex == toIndex){
33364                return 'none';
33365            }
33366            if(fromIndex > toIndex){
33367                return 'up';
33368            }
33369            return 'down';
33370        }
33371
33372        /**
33373        * Retuns `right` or `left` depending on the scrolling movement to reach its destination
33374        * from the current slide.
33375        */
33376        function getXmovement(fromIndex, toIndex){
33377            if( fromIndex == toIndex){
33378                return 'none';
33379            }
33380            if(fromIndex > toIndex){
33381                return 'left';
33382            }
33383            return 'right';
33384        }
33385
33386        /**
33387        * Checks if the element needs scrollbar and if the user wants to apply it.
33388        * If so it creates it.
33389        *
33390        * @param {Object} element   jQuery object of the section or slide
33391        */
33392        function createScrollBar(element){
33393            //User doesn't want scrollbar here? Sayonara baby!
33394            if(element.hasClass('fp-noscroll')) return;
33395
33396            //needed to make `scrollHeight` work under Opera 12
33397            element.css('overflow', 'hidden');
33398
33399            var scrollOverflowHandler = options.scrollOverflowHandler;
33400            var wrap = scrollOverflowHandler.wrapContent();
33401            //in case element is a slide
33402            var section = element.closest(SECTION_SEL);
33403            var scrollable = scrollOverflowHandler.scrollable(element);
33404            var contentHeight;
33405
33406            //if there was scroll, the contentHeight will be the one in the scrollable section
33407            if(scrollable.length){
33408                contentHeight = scrollOverflowHandler.scrollHeight(element);
33409            }else{
33410                contentHeight = element.get(0).scrollHeight;
33411                if(options.verticalCentered){
33412                    contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight;
33413                }
33414            }
33415
33416            var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
33417
33418            //needs scroll?
33419            if ( contentHeight > scrollHeight) {
33420                //did we already have an scrollbar ? Updating it
33421                if(scrollable.length){
33422                    scrollOverflowHandler.update(element, scrollHeight);
33423                }
33424                //creating the scrolling
33425                else{
33426                    if(options.verticalCentered){
33427                        element.find(TABLE_CELL_SEL).wrapInner(wrap);
33428                    }else{
33429                        element.wrapInner(wrap);
33430                    }
33431                    scrollOverflowHandler.create(element, scrollHeight);
33432                }
33433            }
33434            //removing the scrolling when it is not necessary anymore
33435            else{
33436                scrollOverflowHandler.remove(element);
33437            }
33438
33439            //undo
33440            element.css('overflow', '');
33441        }
33442
33443        function addTableClass(element){
33444            //In case we are styling for the 2nd time as in with reponsiveSlides
33445            if(!element.hasClass(TABLE)){
33446                element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />');
33447            }
33448        }
33449
33450        function getTableHeight(element){
33451            var sectionHeight = windowsHeight;
33452
33453            if(options.paddingTop || options.paddingBottom){
33454                var section = element;
33455                if(!section.hasClass(SECTION)){
33456                    section = element.closest(SECTION_SEL);
33457                }
33458
33459                var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
33460                sectionHeight = (windowsHeight - paddings);
33461            }
33462
33463            return sectionHeight;
33464        }
33465
33466        /**
33467        * Adds a css3 transform property to the container class with or without animation depending on the animated param.
33468        */
33469        function transformContainer(translate3d, animated){
33470            if(animated){
33471                addAnimation(container);
33472            }else{
33473                removeAnimation(container);
33474            }
33475
33476            container.css(getTransforms(translate3d));
33477
33478            //syncronously removing the class after the animation has been applied.
33479            setTimeout(function(){
33480                container.removeClass(NO_TRANSITION);
33481            },10);
33482        }
33483
33484        /**
33485        * Gets a section by its anchor / index
33486        */
33487        function getSectionByAnchor(sectionAnchor){
33488            if(!sectionAnchor) return [];
33489
33490            var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]');
33491            if(!section.length){
33492                section = $(SECTION_SEL).eq( sectionAnchor -1);
33493            }
33494
33495            return section;
33496        }
33497
33498        /**
33499        * Gets a slide inside a given section by its anchor / index
33500        */
33501        function getSlideByAnchor(slideAnchor, section){
33502            var slides = section.find(SLIDES_WRAPPER_SEL);
33503            var slide =  slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]');
33504
33505            if(!slide.length){
33506                slide = slides.find(SLIDE_SEL).eq(slideAnchor);
33507            }
33508
33509            return slide;
33510        }
33511
33512        /**
33513        * Scrolls to the given section and slide anchors
33514        */
33515        function scrollPageAndSlide(destiny, slide){
33516            var section = getSectionByAnchor(destiny);
33517
33518            //do nothing if there's no section with the given anchor name
33519            if(!section.length) return;
33520
33521            //default slide
33522            if (typeof slide === 'undefined') {
33523                slide = 0;
33524            }
33525
33526            //we need to scroll to the section and then to the slide
33527            if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){
33528                scrollPage(section, function(){
33529                    scrollSlider(section, slide);
33530                });
33531            }
33532            //if we were already in the section
33533            else{
33534                scrollSlider(section, slide);
33535            }
33536        }
33537
33538        /**
33539        * Scrolls the slider to the given slide destination for the given section
33540        */
33541        function scrollSlider(section, slideAnchor){
33542            if(typeof slideAnchor !== 'undefined'){
33543                var slides = section.find(SLIDES_WRAPPER_SEL);
33544                var destiny =  getSlideByAnchor(slideAnchor, section);
33545
33546                if(destiny.length){
33547                    landscapeScroll(slides, destiny);
33548                }
33549            }
33550        }
33551
33552        /**
33553        * Creates a landscape navigation bar with dots for horizontal sliders.
33554        */
33555        function addSlidesNavigation(section, numSlides){
33556            section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>');
33557            var nav = section.find(SLIDES_NAV_SEL);
33558
33559            //top or bottom
33560            nav.addClass(options.slidesNavPosition);
33561
33562            for(var i=0; i< numSlides; i++){
33563                nav.find('ul').append('<li><a href="#"><span></span></a></li>');
33564            }
33565
33566            //centering it
33567            nav.css('margin-left', '-' + (nav.width()/2) + 'px');
33568
33569            nav.find('li').first().find('a').addClass(ACTIVE);
33570        }
33571
33572
33573        /**
33574        * Sets the state of the website depending on the active section/slide.
33575        * It changes the URL hash when needed and updates the body class.
33576        */
33577        function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
33578            var sectionHash = '';
33579
33580            if(options.anchors.length && !options.lockAnchors){
33581
33582                //isn't it the first slide?
33583                if(slideIndex){
33584                    if(typeof anchorLink !== 'undefined'){
33585                        sectionHash = anchorLink;
33586                    }
33587
33588                    //slide without anchor link? We take the index instead.
33589                    if(typeof slideAnchor === 'undefined'){
33590                        slideAnchor = slideIndex;
33591                    }
33592
33593                    lastScrolledSlide = slideAnchor;
33594                    setUrlHash(sectionHash + '/' + slideAnchor);
33595
33596                //first slide won't have slide anchor, just the section one
33597                }else if(typeof slideIndex !== 'undefined'){
33598                    lastScrolledSlide = slideAnchor;
33599                    setUrlHash(anchorLink);
33600                }
33601
33602                //section without slides
33603                else{
33604                    setUrlHash(anchorLink);
33605                }
33606            }
33607
33608            setBodyClass();
33609        }
33610
33611        /**
33612        * Sets the URL hash.
33613        */
33614        function setUrlHash(url){
33615            //Uncode addition
33616            if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer )
33617                return false;
33618
33619            if(options.recordHistory){
33620                location.hash = url;
33621            }else{
33622                //Uncode addition
33623                //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
33624                // if(isTouchDevice || isTouch){
33625                //     window.history.replaceState(undefined, undefined, '#' + url);
33626                // }else{
33627                //     var baseUrl = window.location.href.split('#')[0];
33628                //     window.location.replace( baseUrl + '#' + url );
33629                // }
33630                return false;
33631            }
33632        }
33633
33634        /**
33635        * Gets the anchor for the given slide / section. Its index will be used if there's none.
33636        */
33637        function getAnchor(element){
33638            var anchor = element.data('anchor');
33639            var index = element.index();
33640
33641            //Slide without anchor link? We take the index instead.
33642            if(typeof anchor === 'undefined'){
33643                anchor = index;
33644            }
33645
33646            return anchor;
33647        }
33648
33649        /**
33650        * Sets a class for the body of the page depending on the active section / slide
33651        */
33652        function setBodyClass(){
33653            var section = $(SECTION_ACTIVE_SEL);
33654            var slide = section.find(SLIDE_ACTIVE_SEL);
33655
33656            var sectionAnchor = getAnchor(section);
33657            var slideAnchor = getAnchor(slide);
33658
33659            var text = String(sectionAnchor);
33660
33661            if(slide.length){
33662                text = text + '-' + slideAnchor;
33663            }
33664
33665            //changing slash for dash to make it a valid CSS style
33666            text = text.replace('/', '-').replace('#','');
33667
33668            //removing previous anchor classes
33669            var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g");
33670            $body[0].className = $body[0].className.replace(classRe, '');
33671
33672            //adding the current anchor
33673            $body.addClass(VIEWING_PREFIX + '-' + text);
33674        }
33675
33676        /**
33677        * Checks for translate3d support
33678        * @return boolean
33679        * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
33680        */
33681        function support3d() {
33682            var el = document.createElement('p'),
33683                has3d,
33684                transforms = {
33685                    'webkitTransform':'-webkit-transform',
33686                    'OTransform':'-o-transform',
33687                    'msTransform':'-ms-transform',
33688                    'MozTransform':'-moz-transform',
33689                    'transform':'transform'
33690                };
33691
33692            // Add it to the body to get the computed style.
33693            document.body.insertBefore(el, null);
33694
33695            for (var t in transforms) {
33696                if (el.style[t] !== undefined) {
33697                    el.style[t] = 'translate3d(1px,1px,1px)';
33698                    has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
33699                }
33700            }
33701
33702            document.body.removeChild(el);
33703
33704            return (has3d !== undefined && has3d.length > 0 && has3d !== 'none');
33705        }
33706
33707        /**
33708        * Removes the auto scrolling action fired by the mouse wheel and trackpad.
33709        * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
33710        */
33711        function removeMouseWheelHandler(){
33712            if (document.addEventListener) {
33713                document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
33714                document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
33715                document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox
33716            } else {
33717                document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8
33718            }
33719        }
33720
33721        /**
33722        * Adds the auto scrolling action for the mouse wheel and trackpad.
33723        * After this function is called, the mousewheel and trackpad movements will scroll through sections
33724        * https://developer.mozilla.org/en-US/docs/Web/Events/wheel
33725        */
33726        function addMouseWheelHandler(){
33727            var prefix = '';
33728            var _addEventListener;
33729
33730            if (window.addEventListener){
33731                _addEventListener = "addEventListener";
33732            }else{
33733                _addEventListener = "attachEvent";
33734                prefix = 'on';
33735            }
33736
33737             // detect available wheel event
33738            var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel"
33739                      document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel"
33740                      'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox
33741            var passiveEvent = g_supportsPassive ? {passive: false }
33741: false;
33742
33743
33744            if(support == 'DOMMouseScroll'){
33745                document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent);
33746            }
33747
33748            //handle MozMousePixelScroll in older Firefox
33749            else{
33750                document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent);
33751            }
33752        }
33753
33754        /**
33755        * Binding the mousemove when the mouse's middle button is pressed
33756        */
33757        function addMiddleWheelHandler(){
33758            container
33759                .on('mousedown', mouseDownHandler)
33760                .on('mouseup', mouseUpHandler);
33761        }
33762
33763        /**
33764        * Unbinding the mousemove when the mouse's middle button is released
33765        */
33766        function removeMiddleWheelHandler(){
33767            container
33768                .off('mousedown', mouseDownHandler)
33769                .off('mouseup', mouseUpHandler);
33770        }
33771
33772        /**
33773        * Adds the possibility to auto scroll through sections on touch devices.
33774        */
33775        function addTouchHandler(){
33776            if(isTouchDevice || isTouch){
33777                if(options.autoScrolling){
33778                    $body.off(events.touchmove).on(events.touchmove, preventBouncing);
33779                }
33780
33781                $(WRAPPER_SEL)
33782                    .off(events.touchstart).on(events.touchstart, touchStartHandler)
33783                    .off(events.touchmove).on(events.touchmove, touchMoveHandler);
33784            }
33785        }
33786
33787        /**
33788        * Removes the auto scrolling for touch devices.
33789        */
33790        function removeTouchHandler(){
33791            if(isTouchDevice || isTouch){
33792                $(WRAPPER_SEL)
33793                    .off(events.touchstart)
33794                    .off(events.touchmove);
33795            }
33796        }
33797
33798        /*
33799        * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
33800        * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
33801        */
33802        function getMSPointer(){
33803            var pointer;
33804
33805            //IE >= 11 & rest of browsers
33806            if(window.PointerEvent){
33807                pointer = { down: 'pointerdown', move: 'pointermove'};
33808            }
33809
33810            //IE < 11
33811            else{
33812                pointer = { down: 'MSPointerDown', move: 'MSPointerMove'};
33813            }
33814
33815            return pointer;
33816        }
33817
33818        /**
33819        * Gets the pageX and pageY properties depending on the browser.
33820        * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
33821        */
33822        function getEventsPage(e){
33823            var events = [];
33824
33825            events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
33826            events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
33827
33828            //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008
33829            if(isTouch && isReallyTouch(e) && options.scrollBar){
33830                events.y = e.touches[0].pageY;
33831                events.x = e.touches[0].pageX;
33832            }
33833
33834            return events;
33835        }
33836
33837        /**
33838        * Slides silently (with no animation) the active slider to the given slide.
33839        * @param noCallback {bool} true or defined -> no callbacks
33840        */
33841        function silentLandscapeScroll(activeSlide, noCallbacks){
33842            setScrollingSpeed (0, 'internal');
33843
33844            if(typeof noCallbacks !== 'undefined'){
33845                //preventing firing callbacks afterSlideLoad etc.
33846                isResizing = true;
33847            }
33848
33849            landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide);
33850
33851            if(typeof noCallbacks !== 'undefined'){
33852                isResizing = false;
33853            }
33854
33855            setScrollingSpeed(originals.scrollingSpeed, 'internal');
33856        }
33857
33858        /**
33859        * Scrolls silently (with no animation) the page to the given Y position.
33860        */
33861        function silentScroll(top){
33862            // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625
33863            // that's why we round it to 0.
33864            var roundedTop = Math.round(top);
33865
33866            if (options.css3 && options.autoScrolling && !options.scrollBar){
33867                var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)';
33868                transformContainer(translate3d, false);
33869            }
33870            else if(options.autoScrolling && !options.scrollBar){
33871                container.css('top', -roundedTop);
33872            }
33873            else{
33874                $htmlBody.scrollTop(roundedTop);
33875            }
33876        }
33877
33878        /**
33879        * Returns the cross-browser transform string.
33880        */
33881        function getTransforms(translate3d){
33882            return {
33883                '-webkit-transform': translate3d,
33884                '-moz-transform': translate3d,
33885                '-ms-transform':translate3d,
33886                'transform': translate3d
33887            };
33888        }
33889
33890        /**
33891        * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard)
33892        * @type  m (mouse) or k (keyboard)
33893        */
33894        function setIsScrollAllowed(value, direction, type){
33895            switch (direction){
33896                case 'up': isScrollAllowed[type].up = value; break;
33897                case 'down': isScrollAllowed[type].down = value; break;
33898                case 'left': isScrollAllowed[type].left = value; break;
33899                case 'right': isScrollAllowed[type].right = value; break;
33900                case 'all':
33901                    if(type == 'm'){
33902                        setAllowScrolling(value);
33903                    }else{
33904                        setKeyboardScrolling(value);
33905                    }
33906            }
33907        }
33908
33909        /*
33910        * Destroys fullpage.js plugin events and optinally its html markup and styles
33911        */
33912        function destroy(all){
33913            setAutoScrolling(false, 'internal');
33914            setAllowScrolling(false);
33915            setKeyboardScrolling(false);
33916            container.addClass(DESTROYED);
33917
33918            clearTimeout(afterSlideLoadsId);
33919            clearTimeout(afterSectionLoadsId);
33920            clearTimeout(resizeId);
33921            clearTimeout(scrollId);
33922            clearTimeout(scrollId2);
33923
33924            $window
33925                .off('scroll', scrollHandler)
33926                .off('hashchange', hashChangeHandler)
33927                .off('resize', resizeHandler);
33928
33929            $document
33930                .off('click touchstart', SECTION_NAV_SEL + ' a')
33931                .off('mouseenter', SECTION_NAV_SEL + ' li')
33932                .off('mouseleave', SECTION_NAV_SEL + ' li')
33933                .off('click touchstart', SLIDES_NAV_LINK_SEL)
33934                .off('mouseover', options.normalScrollElements)
33935                .off('mouseout', options.normalScrollElements);
33936
33937            $(SECTION_SEL)
33938                .off('click touchstart', SLIDES_ARROW_SEL);
33939
33940            clearTimeout(afterSlideLoadsId);
33941            clearTimeout(afterSectionLoadsId);
33942
33943            //lets make a mess!
33944            if(all){
33945                destroyStructure();
33946            }
33947        }
33948
33949        /*
33950        * Removes inline styles added by fullpage.js
33951        */
33952        function destroyStructure(){
33953            //reseting the `top` or `translate` properties to 0
33954            silentScroll(0);
33955
33956            //loading all the lazy load content
33957            container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){
33958                setSrc($(this), 'src');
33959            });
33960
33961            container.find('img[data-srcset]').each(function(){
33962                setSrc($(this), 'srcset');
33963            });
33964
33965            $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL +  ', ' + SLIDES_ARROW_SEL).remove();
33966
33967            //removing inline styles
33968            $(SECTION_SEL).css( {
33969                'height': '',
33970                'background-color' : '',
33971                'padding': ''
33972            });
33973
33974            $(SLIDE_SEL).css( {
33975                'width': ''
33976            });
33977
33978            container.css({
33979                'height': '',
33980                'position': '',
33981                '-ms-touch-action': '',
33982                'touch-action': ''
33983            });
33984
33985            $htmlBody.css({
33986                'overflow': '',
33987                'height': ''
33988            });
33989
33990            // remove .fp-enabled class
33991            $('html').removeClass(ENABLED);
33992
33993            // remove .fp-responsive class
33994            $body.removeClass(RESPONSIVE);
33995
33996            // remove all of the .fp-viewing- classes
33997            $.each($body.get(0).className.split(/\s+/), function (index, className) {
33998                if (className.indexOf(VIEWING_PREFIX) === 0) {
33999                    $body.removeClass(className);
34000                }
34001            });
34002
34003            //removing added classes
34004            $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){
34005                options.scrollOverflowHandler.remove($(this));
34006                $(this).removeClass(TABLE + ' ' + ACTIVE);
34007            });
34008
34009            removeAnimation(container);
34010
34011            //Unwrapping content
34012            container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){
34013                //unwrap not being use in case there's no child element inside and its just text
34014                $(this).replaceWith(this.childNodes);
34015            });
34016
34017            //removing the applied transition from the fullpage wrapper
34018            container.css({
34019                '-webkit-transition': 'none',
34020                'transition': 'none'
34021            });
34022
34023            //scrolling the page to the top with no animation
34024            $htmlBody.scrollTop(0);
34025
34026            //removing selectors
34027            var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER];
34028            $.each(usedSelectors, function(index, value){
34029                $('.' + value).removeClass(value);
34030            });
34031        }
34032
34033        /*
34034        * Sets the state for a variable with multiple states (original, and temporal)
34035        * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
34036        * This function is used to keep track of both states, the original and the temporal one.
34037        * If type is not 'internal', then we assume the user is globally changing the variable.
34038        */
34039        function setVariableState(variable, value, type){
34040            options[variable] = value;
34041            if(type !== 'internal'){
34042                originals[variable] = value;
34043            }
34044        }
34045
34046        /**
34047        * Displays warnings
34048        */
34049        function displayWarnings(){
34050            var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax'];
34051            //UNCODE.addition
34052            // if($('html').hasClass(ENABLED)){
34053            //     showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!');
34054            //     return;
34055            // }
34056
34057            // Disable mutually exclusive settings
34058            //UNCODE.addition
34059            // if (options.continuousVertical &&
34060            //     (options.loopTop || options.loopBottom)) {
34061            //     options.continuousVertical = false;
34062            //     showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34063            // }
34064
34065            // if(options.scrollBar && options.scrollOverflow){
34066            //     showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox');
34067            // }
34068
34069            // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){
34070            //     options.continuousVertical = false;
34071            //     showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled');
34072            // }
34073
34074            //using extensions? Wrong file!
34075            $.each(extensions, function(index, extension){
34076                //is the option set to true?
34077                if(options[extension]){
34078                    showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension);
34079                }
34080            });
34081
34082            //anchors can not have the same value as any element ID or NAME
34083            $.each(options.anchors, function(index, name){
34084
34085                //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396)
34086                var nameAttr = $document.find('[name]').filter(function() {
34087                    return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase();
34088                });
34089
34090                var idAttr = $document.find('[id]').filter(function() {
34091                    return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase();
34092                });
34093
34094                if(idAttr.length || nameAttr.length ){
34095                    showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).');
34096                    idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property');
34097                    nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property');
34098                }
34099            });
34100        }
34101
34102        /**
34103        * Shows a message in the console of the given type.
34104        */
34105        function showError(type, text){
34106            console && console[type] && console[type]('fullPage: ' + text);
34107        }
34108
34109    }; //end of $.fn.fullpage
34110
34111    if(typeof IScroll !== 'undefined'){
34112        /*
34113        * Turns iScroll `mousewheel` option off dynamically
34114        * https://github.com/cubiq/iscroll/issues/1036
34115        */
34116        IScroll.prototype.wheelOn = function () {
34117            this.wrapper.addEventListener('wheel', this);
34118            this.wrapper.addEventListener('mousewheel', this);
34119            this.wrapper.addEventListener('DOMMouseScroll', this);
34120        };
34121
34122        /*
34123        * Turns iScroll `mousewheel` option on dynamically
34124        * https://github.com/cubiq/iscroll/issues/1036
34125        */
34126        IScroll.prototype.wheelOff = function () {
34127            this.wrapper.removeEventListener('wheel', this);
34128            this.wrapper.removeEventListener('mousewheel', this);
34129            this.wrapper.removeEventListener('DOMMouseScroll', this);
34130        };
34131    }
34132
34133    /**
34134     * An object to handle overflow scrolling.
34135     * This uses jquery.slimScroll to accomplish overflow scrolling.
34136     * It is possible to pass in an alternate scrollOverflowHandler
34137     * to the fullpage.js option that implements the same functions
34138     * as this handler.
34139     *
34140     * @type {Object}
34141     */
34142    var iscrollHandler = {
34143        refreshId: null,
34144        iScrollInstances: [],
34145
34146        // Enables or disables the mouse wheel for the active section or all slides in it
34147        toggleWheel: function(value){
34148            var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL);
34149            scrollable.each(function(){
34150                var iScrollInstance = $(this).data('iscrollInstance');
34151                if(typeof iScrollInstance !== 'undefined' && iScrollInstance){
34152                    if(value){
34153                        iScrollInstance.wheelOn();
34154                    }
34155                    else{
34156                        iScrollInstance.wheelOff();
34157                    }
34158                }
34159            });
34160        },
34161
34162        /**
34163        * Turns off iScroll for the destination section.
34164        * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
34165        * scroll the destination section/slide before the sections animations ends.
34166        */
34167        onLeave: function(){
34168            iscrollHandler.toggleWheel(false);
34169        },
34170
34171        // Turns off iScroll for the leaving section
34172        beforeLeave: function(){
34173            iscrollHandler.onLeave()
34174        },
34175
34176        // Turns on iScroll on section load
34177        afterLoad: function(){
34178            iscrollHandler.toggleWheel(true);
34179        },
34180
34181        /**
34182         * Called when overflow scrolling is needed for a section.
34183         *
34184         * @param  {Object} element      jQuery object containing current section
34185         * @param  {Number} scrollHeight Current window height in pixels
34186         */
34187        create: function(element, scrollHeight) {
34188            var scrollable = element.find(SCROLLABLE_SEL);
34189
34190            scrollable.height(scrollHeight);
34191            scrollable.each(function() {
34192                var $this = $(this);
34193                var iScrollInstance = $this.data('iscrollInstance');
34194                if (iScrollInstance) {
34195                    $.each(iscrollHandler.iScrollInstances, function(){
34196                        $(this).destroy();
34197                    });
34198                }
34199
34200                iScrollInstance = new IScroll($this.get(0), iscrollOptions);
34201                iscrollHandler.iScrollInstances.push(iScrollInstance);
34202
34203                //off by default until the section gets active
34204                iScrollInstance.wheelOff();
34205
34206                $this.data('iscrollInstance', iScrollInstance);
34207            });
34208        },
34209
34210        /**
34211         * Return a boolean depending on whether the scrollable element is a
34212         * the end or at the start of the scrolling depending on the given type.
34213         *
34214         * @param  {String}  type       Either 'top' or 'bottom'
34215         * @param  {Object}  scrollable jQuery object for the scrollable element
34216         * @return {Boolean}
34217         */
34218        isScrolled: function(type, scrollable) {
34219            var scroller = scrollable.data('iscrollInstance');
34220
34221            //no scroller?
34222            if (!scroller) {
34223                return true;
34224            }
34225
34226            //Uncode addition
34227            var uncode_body_borders = parseFloat($('.body-borders').attr('data-border')) || 0;
34228            //End Uncode addition
34229
34230            if (type === 'top') {
34231                return scroller.y >= 0 && !scrollable.scrollTop();
34232            } else if (type === 'bottom') {
34233                //Uncode change
34234                // return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34235                return (0 - scroller.y) + scrollable.scrollTop() + 1 + ( uncode_body_borders * 2 ) + scrollable.innerHeight() >= scrollable[0].scrollHeight;
34236                //End Uncode change
34237            }
34238        },
34239
34240        /**
34241         * Returns the scrollable element for the given section.
34242         * If there are landscape slides, will only return a scrollable element
34243         * if it is in the active slide.
34244         *
34245         * @param  {Object}  activeSection jQuery object containing current section
34246         * @return {Boolean}
34247         */
34248        scrollable: function(activeSection){
34249            // if there are landscape slides, we check if the scrolling bar is in the current one or not
34250            if (activeSection.find(SLIDES_WRAPPER_SEL).length) {
34251                return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL);
34252            }
34253            return activeSection.find(SCROLLABLE_SEL);
34254        },
34255
34256        /**
34257         * Returns the scroll height of the wrapped content.
34258         * If this is larger than the window height minus section padding,
34259         * overflow scrolling is needed.
34260         *
34261         * @param  {Object} element jQuery object containing current section
34262         * @return {Number}
34263         */
34264        scrollHeight: function(element) {
34265            return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight;
34266        },
34267
34268        /**
34269         * Called when overflow scrolling is no longer needed for a section.
34270         *
34271         * @param  {Object}
34271 element      jQuery object containing current section
34272         */
34273        remove: function(element) {
34274            var scrollable = element.find(SCROLLABLE_SEL);
34275            if (scrollable.length) {
34276                var iScrollInstance = scrollable.data('iscrollInstance');
34277                iScrollInstance.destroy();
34278
34279                scrollable.data('iscrollInstance', null);
34280            }
34281            element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap();
34282        },
34283
34284        /**
34285         * Called when overflow scrolling has already been setup but the
34286         * window height has potentially changed.
34287         *
34288         * @param  {Object} element      jQuery object containing current section
34289         * @param  {Number} scrollHeight Current window height in pixels
34290         */
34291        update: function(element, scrollHeight) {
34292            //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a
34293            //short period of time.
34294            //it also comes on handy because iScroll requires the use of timeout when using `refresh`.
34295            clearTimeout(iscrollHandler.refreshId);
34296            iscrollHandler.refreshId = setTimeout(function(){
34297                $.each(iscrollHandler.iScrollInstances, function(){
34298                    $(this).get(0).refresh();
34299                });
34300            }, 150);
34301
34302            //updating the wrappers height
34303            element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
34304        },
34305
34306        /**
34307         * Called to get any additional elements needed to wrap the section
34308         * content in order to facilitate overflow scrolling.
34309         *
34310         * @return {String|Object} Can be a string containing HTML,
34311         *                         a DOM element, or jQuery object.
34312         */
34313        wrapContent: function() {
34314            return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>';
34315        }
34316    };
34317});
34318
34319(function (global, factory) {
34320	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
34321	typeof define === 'function' && define.amd ? define(['exports'], factory) :
34322	(global = global || self, factory(global.window = global.window || {}));
34323}(this, (function (exports) { 'use strict';
34324
34325	/*!
34326	 * ScrollTrigger 3.8.0
34327	 * https://greensock.com
34328	 *
34329	 * @license Copyright 2008-2021, GreenSock. All rights reserved.
34330	 * Subject to the terms at https://greensock.com/standard-license or for
34331	 * Club GreenSock members, the agreement issued with that membership.
34332	 * @author: Jack Doyle, [email protected]
34333	*/
34334	var gsap,
34335	    _coreInitted,
34336	    _win,
34337	    _doc,
34338	    _docEl,
34339	    _body,
34340	    _root,
34341	    _resizeDelay,
34342	    _raf,
34343	    _request,
34344	    _toArray,
34345	    _clamp,
34346	    _time2,
34347	    _syncInterval,
34348	    _refreshing,
34349	    _pointerIsDown,
34350	    _transformProp,
34351	    _i,
34352	    _prevWidth,
34353	    _prevHeight,
34354	    _autoRefresh,
34355	    _sort,
34356	    _suppressOverwrites,
34357	    _ignoreResize,
34358	    _limitCallbacks,
34359	    _startup = 1,
34360	    _proxies = [],
34361	    _scrollers = [],
34362	    _getTime = Date.now,
34363	    _time1 = _getTime(),
34364	    _lastScrollTime = 0,
34365	    _enabled = 1,
34366	    _passThrough = function _passThrough(v) {
34367	  return v;
34368	},
34369	    _getTarget = function _getTarget(t) {
34370	  return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null);
34371	},
34372	    _round = function _round(value) {
34373	  return Math.round(value * 100000) / 100000 || 0;
34374	},
34375	    _windowExists = function _windowExists() {
34376	  return typeof window !== "undefined";
34377	},
34378	    _getGSAP = function _getGSAP() {
34379	  return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
34380	},
34381	    _isViewport = function _isViewport(e) {
34382	  return !!~_root.indexOf(e);
34383	},
34384	    _getProxyProp = function _getProxyProp(element, property) {
34385	  return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property];
34386	},
34387	    _getScrollFunc = function _getScrollFunc(element, _ref) {
34388	  var s = _ref.s,
34389	      sc = _ref.sc;
34390
34391	  var i = _scrollers.indexOf(element),
34392	      offset = sc === _vertical.sc ? 1 : 2;
34393
34394	  !~i && (i = _scrollers.push(element) - 1);
34395	  return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) {
34396	    return arguments.length ? element[s] = value : element[s];
34397	  }));
34398	},
34399	    _getBoundsFunc = function _getBoundsFunc(element) {
34400	  return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () {
34401	    _winOffsets.width = _win.innerWidth;
34402	    _winOffsets.height = _win.innerHeight;
34403	    return _winOffsets;
34404	  } : function () {
34405	    return _getBounds(element);
34406	  });
34407	},
34408	    _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) {
34409	  var d = _ref2.d,
34410	      d2 = _ref2.d2,
34411	      a = _ref2.a;
34412	  return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () {
34413	    return a()[d];
34414	  } : function () {
34415	    return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0;
34416	  };
34417	},
34418	    _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) {
34419	  return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () {
34420	    return _winOffsets;
34421	  };
34422	},
34423	    _maxScroll = function _maxScroll(element, _ref3) {
34424	  var s = _ref3.s,
34425	      d2 = _ref3.d2,
34426	      d = _ref3.d,
34427	      a = _ref3.a;
34428	  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];
34429	},
34430	    _iterateAutoRefresh = function _iterateAutoRefresh(func, events) {
34431	  for (var i = 0; i < _autoRefresh.length; i += 3) {
vendor: 5,689 bytes, lines 34432-34636
34432	    (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]);
34433	  }
34434	},
34435	    _isString = function _isString(value) {
34436	  return typeof value === "string";
34437	},
34438	    _isFunction = function _isFunction(value) {
34439	  return typeof value === "function";
34440	},
34441	    _isNumber = function _isNumber(value) {
34442	  return typeof value === "number";
34443	},
34444	    _isObject = function _isObject(value) {
34445	  return typeof value === "object";
34446	},
34447	    _callIfFunc = function _callIfFunc(value) {
34448	  return _isFunction(value) && value();
34449	},
34450	    _combineFunc = function _combineFunc(f1, f2) {
34451	  return function () {
34452	    var result1 = _callIfFunc(f1),
34453	        result2 = _callIfFunc(f2);
34454
34455	    return function () {
34456	      _callIfFunc(result1);
34457
34458	      _callIfFunc(result2);
34459	    };
34460	  };
34461	},
34462	    _endAnimation = function _endAnimation(animation, reversed, pause) {
34463	  return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause();
34464	},
34465	    _callback = function _callback(self, func) {
34466	  var result = func(self);
34467	  result && result.totalTime && (self.callbackAnimation = result);
34468	},
34469	    _abs = Math.abs,
34470	    _scrollLeft = "scrollLeft",
34471	    _scrollTop = "scrollTop",
34472	    _left = "left",
34473	    _top = "top",
34474	    _right = "right",
34475	    _bottom = "bottom",
34476	    _width = "width",
34477	    _height = "height",
34478	    _Right = "Right",
34479	    _Left = "Left",
34480	    _Top = "Top",
34481	    _Bottom = "Bottom",
34482	    _padding = "padding",
34483	    _margin = "margin",
34484	    _Width = "Width",
34485	    _Height = "Height",
34486	    _px = "px",
34487	    _horizontal = {
34488	  s: _scrollLeft,
34489	  p: _left,
34490	  p2: _Left,
34491	  os: _right,
34492	  os2: _Right,
34493	  d: _width,
34494	  d2: _Width,
34495	  a: "x",
34496	  sc: function sc(value) {
34497	    return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
34498	  }
34499	},
34500	    _vertical = {
34501	  s: _scrollTop,
34502	  p: _top,
34503	  p2: _Top,
34504	  os: _bottom,
34505	  os2: _Bottom,
34506	  d: _height,
34507	  d2: _Height,
34508	  a: "y",
34509	  op: _horizontal,
34510	  sc: function sc(value) {
34511	    return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
34512	  }
34513	},
34514	    _getComputedStyle = function _getComputedStyle(element) {
34515	  return _win.getComputedStyle(element);
34516	},
34517	    _makePositionable = function _makePositionable(element) {
34518	  var position = _getComputedStyle(element).position;
34519
34520	  element.style.position = position === "absolute" || position === "fixed" ? position : "relative";
34521	},
34522	    _setDefaults = function _setDefaults(obj, defaults) {
34523	  for (var p in defaults) {
34524	    p in obj || (obj[p] = defaults[p]);
34525	  }
34526
34527	  return obj;
34528	},
34529	    _getBounds = function _getBounds(element, withoutTransforms) {
34530	  var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
34531	    x: 0,
34532	    y: 0,
34533	    xPercent: 0,
34534	    yPercent: 0,
34535	    rotation: 0,
34536	    rotationX: 0,
34537	    rotationY: 0,
34538	    scale: 1,
34539	    skewX: 0,
34540	    skewY: 0
34541	  }).progress(1),
34542	      bounds = element.getBoundingClientRect();
34543	  tween && tween.progress(0).kill();
34544	  return bounds;
34545	},
34546	    _getSize = function _getSize(element, _ref4) {
34547	  var d2 = _ref4.d2;
34548	  return element["offset" + d2] || element["client" + d2] || 0;
34549	},
34550	    _getLabelRatioArray = function _getLabelRatioArray(timeline) {
34551	  var a = [],
34552	      labels = timeline.labels,
34553	      duration = timeline.duration(),
34554	      p;
34555
34556	  for (p in labels) {
34557	    a.push(labels[p] / duration);
34558	  }
34559
34560	  return a;
34561	},
34562	    _getClosestLabel = function _getClosestLabel(animation) {
34563	  return function (value) {
34564	    return gsap.utils.snap(_getLabelRatioArray(animation), value);
34565	  };
34566	},
34567	    _snapDirectional = function _snapDirectional(snapIncrementOrArray) {
34568	  var snap = gsap.utils.snap(snapIncrementOrArray),
34569	      a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) {
34570	    return a - b;
34571	  });
34572	  return a ? function (value, direction) {
34573	    var i;
34574
34575	    if (!direction) {
34576	      return snap(value);
34577	    }
34578
34579	    if (direction > 0) {
34580	      value -= 1e-4;
34581
34582	      for (i = 0; i < a.length; i++) {
34583	        if (a[i] >= value) {
34584	          return a[i];
34585	        }
34586	      }
34587
34588	      return a[i - 1];
34589	    } else {
34590	      i = a.length;
34591	      value += 1e-4;
34592
34593	      while (i--) {
34594	        if (a[i] <= value) {
34595	          return a[i];
34596	        }
34597	      }
34598	    }
34599
34600	    return a[0];
34601	  } : function (value, direction) {
34602	    var snapped = snap(value);
34603	    return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray);
34604	  };
34605	},
34606	    _getLabelAtDirection = function _getLabelAtDirection(timeline) {
34607	  return function (value, st) {
34608	    return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction);
34609	  };
34610	},
34611	    _multiListener = function _multiListener(func, element, types, callback) {
34612	  return types.split(",").forEach(function (type) {
34613	    return func(element, type, callback);
34614	  });
34615	},
34616	    _addListener = function _addListener(element, type, func) {
34617	  return element.addEventListener(type, func, {
34618	    passive: true
34619	  });
34620	},
34621	    _removeListener = function _removeListener(element, type, func) {
34622	  return element.removeEventListener(type, func);
34623	},
34624	    _markerDefaults = {
34625	  startColor: "green",
34626	  endColor: "red",
34627	  indent: 0,
34628	  fontSize: "16px",
34629	  fontWeight: "normal"
34630	},
34631	    _defaults = {
34632	  toggleActions: "play",
34633	  anticipatePin: 0
34634	},
34635	    _keywords = {
34636	  top: 0,
34637	  left: 0,
34638	  center: 0.5,
34639	  bottom: 1,
34640	  right: 1
34641	},
34642	    _offsetToPx = function _offsetToPx(value, size) {
34643	  if (_isString(value)) {
34644	    var eqIndex = value.indexOf("="),
34645	        relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
34646
34647	    if (~eqIndex) {
34648	      value.indexOf("%") > eqIndex && (relative *= size / 100);
34649	      value = value.substr(0, eqIndex - 1);
34650	    }
34651
34652	    value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
34653	  }
34654
34655	  return value;
34656	},
34657	    _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) {
34658	  var startColor = _ref5.startColor,
34659	      endColor = _ref5.endColor,
34660	      fontSize = _ref5.fontSize,
34661	      indent = _ref5.indent,
34662	      fontWeight = _ref5.fontWeight;
34663
34664	  var e = _doc.createElement("div"),
34665	      useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed",
34666	      isScroller = type.indexOf("scroller") !== -1,
34667	      parent = useFixedPosition ? _body : container,
34668	      isStart = type.indexOf("start") !== -1,
34669	      color = isStart ? startColor : endColor,
34670	      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;";
34671
34672	  css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;");
34673	  (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
34674	  matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
34675	  e._isStart = isStart;
34676	  e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : ""));
34677	  e.style.cssText = css;
34678	  e.innerText = name || name === 0 ? type + "-" + name : type;
34679	  parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e);
34680	  e._offset = e["offset" + direction.op.d2];
34681
34682	  _positionMarker(e, 0, direction, isStart);
34683
34684	  return e;
34685	},
34686	    _positionMarker = function _positionMarker(marker, start, direction, flipped) {
34687	  var vars = {
34688	    display: "block"
34689	  },
34690	      side = direction[flipped ? "os2" : "p2"],
34691	      oppositeSide = direction[flipped ? "p2" : "os2"];
34692	  marker._isFlipped = flipped;
34693	  vars[direction.a + "Percent"] = flipped ? -100 : 0;
34694	  vars[direction.a] = flipped ? "1px" : 0;
34695	  vars["border" + side + _Width] = 1;
34696	  vars["border" + oppositeSide + _Width] = 0;
34697	  vars[direction.p] = start + "px";
34698	  gsap.set(marker, vars);
34699	},
34700	    _triggers = [],
34701	    _ids = {},
34702	    _sync = function _sync() {
34703	  return _getTime() - _lastScrollTime > 20 && _updateAll();
34704	},
34705	    _onScroll = function _onScroll() {
34706	  var time = _getTime();
34707
34708	  if (_lastScrollTime !== time) {
34709	    _updateAll();
34710
34711	    _lastScrollTime || _dispatch("scrollStart");
34712	    _lastScrollTime = time;
34713	  } else if (!_request) {
34714	    _request = _raf(_updateAll);
34715	  }
34716	},
34717	    _onResize = function _onResize() {
34718	  return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true);
34719	},
34720	    _listeners = {},
34721	    _emptyArray = [],
34722	    _media = [],
34723	    _creatingMedia,
34724	    _lastMediaTick,
34725	    _onMediaChange = function _onMediaChange(e) {
34726	  var tick = gsap.ticker.frame,
34727	      matches = [],
34728	      i = 0,
34729	      index;
34730
34731	  if (_lastMediaTick !== tick || _startup) {
34732	    _revertAll();
34733
34734	    for (; i < _media.length; i += 4) {
34735	      index = _win.matchMedia(_media[i]).matches;
34736
34737	      if (index !== _media[i + 3]) {
34738	        _media[i + 3] = index;
34739	        index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2]();
34740	      }
34741	    }
34742
34743	    _revertRecorded();
34744
34745	    for (i = 0; i < matches.length; i++) {
34746	      index = matches[i];
34747	      _creatingMedia = _media[index];
34748	      _media[index + 2] = _media[index + 1](e);
34749	    }
34750
34751	    _creatingMedia = 0;
34752	    _coreInitted && _refreshAll(0, 1);
34753	    _lastMediaTick = tick;
34754
34755	    _dispatch("matchMedia");
34756	  }
34757	},
34758	    _softRefresh = function _softRefresh() {
34759	  return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true);
34760	},
34761	    _dispatch = function _dispatch(type) {
34762	  return _listeners[type] && _listeners[type].map(function (f) {
34763	    return f();
34764	  }) || _emptyArray;
34765	},
34766	    _savedStyles = [],
34767	    _revertRecorded = function _revertRecorded(media) {
34768	  for (var i = 0; i < _savedStyles.length; i += 5) {
34769	    if (!media || _savedStyles[i + 4] === media) {
34770	      _savedStyles[i].style.cssText = _savedStyles[i + 1];
34771	      _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || "");
34772	      _savedStyles[i + 3].uncache = 1;
34773	    }
34774	  }
34775	},
34776	    _revertAll = function _revertAll(kill, media) {
34777	  var trigger;
34778
34779	  for (_i = 0; _i < _triggers.length; _i++) {
34780	    trigger = _triggers[_i];
34781
34782	    if (!media || trigger.media === media) {
34783	      if (kill) {
34784	        trigger.kill(1);
34785	      } else {
34786	        trigger.revert();
34787	      }
34788	    }
34789	  }
34790
34791	  media && _revertRecorded(media);
34792	  media || _dispatch("revert");
34793	},
34794	    _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 34795-35129
34795	  return _scrollers.forEach(function (obj) {
34796	    return typeof obj === "function" && (obj.rec = 0);
34797	  });
34798	},
34799	    _refreshingAll,
34800	    _refreshAll = function _refreshAll(force, skipRevert) {
34801	  if (_lastScrollTime && !force) {
34802	    _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
34803
34804	    return;
34805	  }
34806
34807	  _refreshingAll = true;
34808
34809	  var refreshInits = _dispatch("refreshInit");
34810
34811	  _sort && ScrollTrigger.sort();
34812	  skipRevert || _revertAll();
34813
34814	  _triggers.forEach(function (t) {
34815	    return t.refresh();
34816	  });
34817
34818	  refreshInits.forEach(function (result) {
34819	    return result && result.render && result.render(-1);
34820	  });
34821
34822	  _clearScrollMemory();
34823
34824	  _resizeDelay.pause();
34825
34826	  _refreshingAll = false;
34827
34828	  _dispatch("refresh");
34829	},
34830	    _lastScroll = 0,
34831	    _direction = 1,
34832	    _updateAll = function _updateAll() {
34833	  if (!_refreshingAll) {
34834	    var l = _triggers.length,
34835	        time = _getTime(),
34836	        recordVelocity = time - _time1 >= 50,
34837	        scroll = l && _triggers[0].scroll();
34838
34839	    _direction = _lastScroll > scroll ? -1 : 1;
34840	    _lastScroll = scroll;
34841
34842	    if (recordVelocity) {
34843	      if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
34844	        _lastScrollTime = 0;
34845
34846	        _dispatch("scrollEnd");
34847	      }
34848
34849	      _time2 = _time1;
34850	      _time1 = time;
34851	    }
34852
34853	    if (_direction < 0) {
34854	      _i = l;
34855
34856	      while (_i-- > 0) {
34857	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34858	      }
34859
34860	      _direction = 1;
34861	    } else {
34862	      for (_i = 0; _i < l; _i++) {
34863	        _triggers[_i] && _triggers[_i].update(0, recordVelocity);
34864	      }
34865	    }
34866
34867	    _request = 0;
34868	  }
34869	},
34870	    _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"],
34871	    _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
34872	    _swapPinOut = function _swapPinOut(pin, spacer, state) {
34873	  _setState(state);
34874
34875	  var cache = pin._gsap;
34876
34877	  if (cache.spacerIsNative) {
34878	    _setState(cache.spacerState);
34879	  } else if (pin.parentNode === spacer) {
34880	    var parent = spacer.parentNode;
34881
34882	    if (parent) {
34883	      parent.insertBefore(pin, spacer);
34884	      parent.removeChild(spacer);
34885	    }
34886	  }
34887	},
34888	    _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) {
34889	  if (pin.parentNode !== spacer) {
34890	    var i = _propNamesToCopy.length,
34891	        spacerStyle = spacer.style,
34892	        pinStyle = pin.style,
34893	        p;
34894
34895	    while (i--) {
34896	      p = _propNamesToCopy[i];
34897	      spacerStyle[p] = cs[p];
34898	    }
34899
34900	    spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
34901	    cs.display === "inline" && (spacerStyle.display = "inline-block");
34902	    pinStyle[_bottom] = pinStyle[_right] = "auto";
34903	    spacerStyle.overflow = "visible";
34904	    spacerStyle.boxSizing = "border-box";
34905	    spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
34906	    spacerStyle[_height] = _getSize(pin, _vertical) + _px;
34907	    spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
34908
34909	    _setState(spacerState);
34910
34911	    pinStyle[_width] = pinStyle["max" + _Width] = cs[_width];
34912	    pinStyle[_height] = pinStyle["max" + _Height] = cs[_height];
34913	    pinStyle[_padding] = cs[_padding];
34914	    pin.parentNode.insertBefore(spacer, pin);
34915	    spacer.appendChild(pin);
34916	  }
34917	},
34918	    _capsExp = /([A-Z])/g,
34919	    _setState = function _setState(state) {
34920	  if (state) {
34921	    var style = state.t.style,
34922	        l = state.length,
34923	        i = 0,
34924	        p,
34925	        value;
34926	    (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1;
34927
34928	    for (; i < l; i += 2) {
34929	      value = state[i + 1];
34930	      p = state[i];
34931
34932	      if (value) {
34933	        style[p] = value;
34934	      } else if (style[p]) {
34935	        style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
34936	      }
34937	    }
34938	  }
34939	},
34940	    _getState = function _getState(element) {
34941	  var l = _stateProps.length,
34942	      style = element.style,
34943	      state = [],
34944	      i = 0;
34945
34946	  for (; i < l; i++) {
34947	    state.push(_stateProps[i], style[_stateProps[i]]);
34948	  }
34949
34950	  state.t = element;
34951	  return state;
34952	},
34953	    _copyState = function _copyState(state, override, omitOffsets) {
34954	  var result = [],
34955	      l = state.length,
34956	      i = omitOffsets ? 8 : 0,
34957	      p;
34958
34959	  for (; i < l; i += 2) {
34960	    p = state[i];
34961	    result.push(p, p in override ? override[p] : state[i + 1]);
34962	  }
34963
34964	  result.t = state.t;
34965	  return result;
34966	},
34967	    _winOffsets = {
34968	  left: 0,
34969	  top: 0
34970	},
34971	    _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) {
34972	  _isFunction(value) && (value = value(self));
34973
34974	  if (_isString(value) && value.substr(0, 3) === "max") {
34975	    value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
34976	  }
34977
34978	  var time = containerAnimation ? containerAnimation.time() : 0,
34979	      p1,
34980	      p2,
34981	      element;
34982	  containerAnimation && containerAnimation.seek(0);
34983
34984	  if (!_isNumber(value)) {
34985	    _isFunction(trigger) && (trigger = trigger(self));
34986	    var offsets = value.split(" "),
34987	        bounds,
34988	        localOffset,
34989	        globalOffset,
34990	        display;
34991	    element = _getTarget(trigger) || _body;
34992	    bounds = _getBounds(element) || {};
34993
34994	    if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
34995	      display = element.style.display;
34996	      element.style.display = "block";
34997	      bounds = _getBounds(element);
34998	      display ? element.style.display = display : element.style.removeProperty("display");
34999	    }
35000
35001	    localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
35002	    globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
35003	    value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
35004	    markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
35005	    scrollerSize -= scrollerSize - globalOffset;
35006	  } else if (markerScroller) {
35007	    _positionMarker(markerScroller, scrollerSize, direction, true);
35008	  }
35009
35010	  if (marker) {
35011	    var position = value + scrollerSize,
35012	        isStart = marker._isStart;
35013	    p1 = "scroll" + direction.d2;
35014
35015	    _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1);
35016
35017	    if (useFixedPosition) {
35018	      scrollerBounds = _getBounds(markerScroller);
35019	      useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
35020	    }
35021	  }
35022
35023	  if (containerAnimation && element) {
35024	    p1 = _getBounds(element);
35025	    containerAnimation.seek(scrollerMax);
35026	    p2 = _getBounds(element);
35027	    containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p];
35028	    value = value / containerAnimation._caScrollDist * scrollerMax;
35029	  }
35030
35031	  containerAnimation && containerAnimation.seek(time);
35032	  return containerAnimation ? value : Math.round(value);
35033	},
35034	    _prefixExp = /(?:webkit|moz|length|cssText|inset)/i,
35035	    _reparent = function _reparent(element, parent, top, left) {
35036	  if (element.parentNode !== parent) {
35037	    var style = element.style,
35038	        p,
35039	        cs;
35040
35041	    if (parent === _body) {
35042	      element._stOrig = style.cssText;
35043	      cs = _getComputedStyle(element);
35044
35045	      for (p in cs) {
35046	        if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
35047	          style[p] = cs[p];
35048	        }
35049	      }
35050
35051	      style.top = top;
35052	      style.left = left;
35053	    } else {
35054	      style.cssText = element._stOrig;
35055	    }
35056
35057	    gsap.core.getCache(element).uncache = 1;
35058	    parent.appendChild(element);
35059	  }
35060	},
35061	    _getTweenCreator = function _getTweenCreator(scroller, direction) {
35062	  var getScroll = _getScrollFunc(scroller, direction),
35063	      prop = "_scroll" + direction.p2,
35064	      lastScroll1,
35065	      lastScroll2,
35066	      getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
35067	    var tween = getTween.tween,
35068	        onComplete = vars.onComplete,
35069	        modifiers = {};
35070	    tween && tween.kill();
35071	    lastScroll1 = Math.round(initialValue);
35072	    vars[prop] = scrollTo;
35073	    vars.modifiers = modifiers;
35074
35075	    modifiers[prop] = function (value) {
35076	      value = _round(getScroll());
35077
35078	      if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) {
35079	        tween.kill();
35080	        getTween.tween = 0;
35081	      } else {
35082	        value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
35083	      }
35084
35085	      lastScroll2 = lastScroll1;
35086	      return lastScroll1 = _round(value);
35087	    };
35088
35089	    vars.onComplete = function () {
35090	      getTween.tween = 0;
35091	      onComplete && onComplete.call(tween);
35092	    };
35093
35094	    tween = getTween.tween = gsap.to(scroller, vars);
35095	    return tween;
35096	  };
35097
35098	  scroller[prop] = getScroll;
35099	  scroller.addEventListener("wheel", function () {
35100	    return getTween.tween && getTween.tween.kill() && (getTween.tween = 0);
35101	  }, {
35102	    passive: true
35103	  });
35104	  return getTween;
35105	};
35106
35107	_horizontal.op = _vertical;
35108	var ScrollTrigger = function () {
35109	  function ScrollTrigger(vars, animation) {
35110	    _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
35111	    this.init(vars, animation);
35112	  }
35113
35114	  var _proto = ScrollTrigger.prototype;
35115
35116	  _proto.init = function init(vars, animation) {
35117	    this.progress = this.start = 0;
35118	    this.vars && this.kill(1);
35119
35120	    if (!_enabled) {
35121	      this.update = this.refresh = this.kill = _passThrough;
35122	      return;
35123	    }
35124
35125	    vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
35126	      trigger: vars
35127	    } : vars, _defaults);
35128
35129	    var _vars = vars,
35130	        onUpdate = _vars.onUpdate,
35131	        toggleClass = _vars.toggleClass,
35132	        id = _vars.id,
35133	        onToggle = _vars.onToggle,
35134	        onRefresh = _vars.onRefresh,
35135	        scrub = _vars.scrub,
35136	        trigger = _vars.trigger,
35137	        pin = _vars.pin,
35138	        pinSpacing = _vars.pinSpacing,
35139	        invalidateOnRefresh = _vars.invalidateOnRefresh,
35140	        anticipatePin = _vars.anticipatePin,
35141	        onScrubComplete = _vars.onScrubComplete,
35142	        onSnapComplete = _vars.onSnapComplete,
35143	        once = _vars.once,
35144	        snap = _vars.snap,
35145	        pinReparent = _vars.pinReparent,
35146	        pinSpacer = _vars.pinSpacer,
35147	        containerAnimation = _vars.containerAnimation,
35148	        fastScrollEnd = _vars.fastScrollEnd,
35149	        preventOverlaps = _vars.preventOverlaps,
35150	        direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical,
35151	        isToggle = !scrub && scrub !== 0,
35152	        scroller = _getTarget(vars.scroller || _win),
35153	        scrollerCache = gsap.core.getCache(scroller),
35154	        isViewport = _isViewport(scroller),
35155	        useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed",
35156	        callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
35157	        toggleActions = isToggle && vars.toggleActions.split(" "),
35158	        markers = "markers" in vars ? vars.markers : _defaults.markers,
35159	        borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
35160	        self = this,
35161	        onRefreshInit = vars.onRefreshInit && function () {
35162	      return vars.onRefreshInit(self);
35163	    },
35164	        getScrollerSize = _getSizeFunc(scroller, isViewport, direction),
35165	        getScrollerOffsets = _getOffsetsFunc(scroller, isViewport),
35166	        lastSnap = 0,
35167	        scrollFunc = _getScrollFunc(scroller, direction),
35168	        tweenTo,
35169	        pinCache,
35170	        snapFunc,
35171	        scroll1,
35172	        scroll2,
35173	        start,
35174	        end,
35175	        markerStart,
35176	        markerEnd,
35177	        markerStartTrigger,
35178	        markerEndTrigger,
35179	        markerVars,
35180	        change,
35181	        pinOriginalState,
35182	        pinActiveState,
35183	        pinState,
35184	        spacer,
35185	        offset,
35186	        pinGetter,
35187	        pinSetter,
35188	        pinStart,
35189	        pinChange,
35190	        spacingStart,
35191	        spacerState,
35192	        markerStartSetter,
35193	        markerEndSetter,
35194	        cs,
35195	        snap1,
35196	        snap2,
35197	        scrubTween,
35198	        scrubSmooth,
35199	        snapDurClamp,
35200	        snapDelayedCall,
35201	        prevProgress,
35202	        prevScroll,
35203	        prevAnimProgress,
35204	        caMarkerSetter;
35205
35206	    self.media = _creatingMedia;
35207	    anticipatePin *= 45;
35208	    self.scroller = scroller;
35209	    self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc;
35210	    scroll1 = scrollFunc();
35211	    self.vars = vars;
35212	    animation = animation || vars.animation;
35213	    "refreshPriority" in vars && (_sort = 1);
35214	    scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
35215	      top: _getTweenCreator(scroller, _vertical),
35216	      left: _getTweenCreator(scroller, _horizontal)
35217	    };
35218	    self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
35219
35220	    if (animation) {
35221	      animation.vars.lazy = false;
35222	      animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true);
35223	      self.animation = animation.pause();
35224	      animation.scrollTrigger = self;
35225	      scrubSmooth = _isNumber(scrub) && scrub;
35226	      scrubSmooth && (scrubTween = gsap.to(animation, {
35227	        ease: "power3",
35228	        duration: scrubSmooth,
35229	        onComplete: function onComplete() {
35230	          return onScrubComplete && onScrubComplete(self);
35231	        }
35232	      }));
35233	      snap1 = 0;
35234	      id || (id = animation.vars.id);
35235	    }
35236
35237	    _triggers.push(self);
35238
35239	    if (snap) {
35240	      if (!_isObject(snap) || snap.push) {
35241	        snap = {
35242	          snapTo: snap
35243	        };
35244	      }
35245
35246	      "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, {
35247	        scrollBehavior: "auto"
35248	      });
35249	      snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) {
35250	        return _snapDirectional(snap.snapTo)(value, st.direction);
35251	      } : gsap.utils.snap(snap.snapTo);
35252	      snapDurClamp = snap.duration || {
35253	        min: 0.1,
35254	        max: 2
35255	      };
35256	      snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
35257	      snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
35258	        if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) {
35259	          var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
35260	              velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
35261	              change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185),
35262	              naturalEnd = self.progress + (snap.inertia === false ? 0 : change1),
35263	              endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
35264	              scroll = scrollFunc(),
35265	              endScroll = Math.round(start + endValue * change),
35266	              _snap = snap,
35267	              onStart = _snap.onStart,
35268	              _onInterrupt = _snap.onInterrupt,
35269	              _onComplete = _snap.onComplete,
35270	              tween = tweenTo.tween;
35271
35272	          if (scroll <= end && scroll >= start && endScroll !== scroll) {
35273	            if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) {
35274	              return;
35275	            }
35276
35277	            if (snap.inertia === false) {
35278	              change1 = endValue - self.progress;
35279	            }
35280
35281	            tweenTo(endScroll, {
35282	              duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
35283	              ease: snap.ease || "power3",
35284	              data: _abs(endScroll - scroll),
35285	              onInterrupt: function onInterrupt() {
35286	                return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self);
35287	              },
35288	              onComplete: function onComplete() {
35289	                lastSnap = scrollFunc();
35290	                snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
35291	                onSnapComplete && onSnapComplete(self);
35292	                _onComplete && _onComplete(self);
35293	              }
35294	            }, scroll, change1 * change, endScroll - scroll - change1 * change);
35295	            onStart && onStart(self, tweenTo.tween);
35296	          }
35297	        } else if (self.isActive) {
35298	          snapDelayedCall.restart(true);
35299	        }
35300	      }).pause();
35301	    }
35302
35303	    id && (_ids[id] = self);
35304	    trigger = self.trigger = _getTarget(trigger || pin);
35305	    pin = pin === true ? trigger : _getTarget(pin);
35306	    _isString(toggleClass) && (toggleClass = {
35307	      targets: trigger,
35308	      className: toggleClass
35309	    });
35310
35311	    if (pin) {
35312	      pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
35313	      self.pin = pin;
35314	      vars.force3D !== false && gsap.set(pin, {
35315	        force3D: true
35316	      });
35317	      pinCache = gsap.core.getCache(pin);
35318
35319	      if (!pinCache.spacer) {
35320	        if (pinSpacer) {
35321	          pinSpacer = _getTarget(pinSpacer);
35322	          pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement);
35323	          pinCache.spacerIsNative = !!pinSpacer;
35324	          pinSpacer && (pinCache.spacerState = _getState(pinSpacer));
35325	        }
35326
35327	        pinCache.spacer = spacer = pinSpacer || _doc.createElement("div");
35328	        spacer.classList.add("pin-spacer");
35329	        id && spacer.classList.add("pin-spacer-" + id);
35330	        pinCache.pinState = pinOriginalState = _getState(pin);
35331	      } else {
35332	        pinOriginalState = pinCache.pinState;
35333	      }
35334
35335	      self.spacer = spacer = pinCache.spacer;
35336	      cs = _getComputedStyle(pin);
35337	      spacingStart = cs[pinSpacing + direction.os2];
35338	      pinGetter = gsap.getProperty(pin);
35339	      pinSetter = gsap.quickSetter(pin, direction.a, _px);
35340
35341	      _swapPinIn(pin, spacer, cs);
35342
35343	      pinState = _getState(pin);
35344	    }
35345
35346	    if (markers) {
35347	      markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
35348	      markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
35349	      markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
35350	      offset = markerStartTrigger["offset" + direction.op.d2];
35351	      markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35352	      markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation);
35353	      containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px));
35354
35355	      if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) {
35356	        _makePositionable(isViewport ? _body : scroller);
35357
35358	        gsap.set([markerStartTrigger, markerEndTrigger], {
35359	          force3D: true
35360	        });
35361	        markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
35362	        markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
35363	      }
35364	    }
35365
35366	    if (containerAnimation) {
35367	      var oldOnUpdate = containerAnimation.vars.onUpdate,
35368	          oldParams = containerAnimation.vars.onUpdateParams;
35369	      containerAnimation.eventCallback("onUpdate", function () {
35370	        self.update(0, 0, 1);
35371	        oldOnUpdate && oldOnUpdate.apply(oldParams || []);
35372	      });
35373	    }
35374
35375	    self.previous = function () {
35376	      return _triggers[_triggers.indexOf(self) - 1];
35377	    };
35378
35379	    self.next = function () {
35380	      return _triggers[_triggers.indexOf(self) + 1];
35381	    };
35382
35383	    self.revert = function (revert) {
35384	      var r = revert !== false || !self.enabled,
35385	          prevRefreshing = _refreshing;
35386
35387	      if (r !== self.isReverted) {
35388	        if (r) {
35389	          self.scroll.rec || (self.scroll.rec = scrollFunc());
35390	          prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0);
35391	          prevProgress = self.progress;
35392	          prevAnimProgress = animation && animation.progress();
35393	        }
35394
35395	        markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35396	          return m.style.display = r ? "none" : "block";
35397	        });
35398	        r && (_refreshing = 1);
35399	        self.update(r);
35400	        _refreshing = prevRefreshing;
35401	        pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState));
35402	        self.isReverted = r;
35403	      }
35404	    };
35405
35406	    self.refresh = function (soft, force) {
35407	      if ((_refreshing || !self.enabled) && !force) {
35408	        return;
35409	      }
35410
35411	      if (pin && soft && _lastScrollTime) {
35412	        _addListener(ScrollTrigger, "scrollEnd", _softRefresh);
35413
35414	        return;
35415	      }
35416
35417	      _refreshing = 1;
35418	      scrubTween && scrubTween.pause();
35419	      invalidateOnRefresh && animation && animation.progress(0).invalidate();
35420	      self.isReverted || self.revert();
35421
35422	      var size = getScrollerSize(),
35423	          scrollerBounds = getScrollerOffsets(),
35424	          max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction),
35425	          offset = 0,
35426	          otherPinOffset = 0,
35427	          parsedEnd = vars.end,
35428	          parsedEndTrigger = vars.endTrigger || trigger,
35429	          parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"),
35430	          pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer),
35431	          triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0,
35432	          i = triggerIndex,
35433	          cs,
35434	          bounds,
35435	          scroll,
35436	          isVertical,
35437	          override,
35438	          curTrigger,
35439	          curPin,
35440	          oppositeScroll,
35441	          initted,
35442	          revertedPins;
35443
35444	      while (i--) {
35445	        curTrigger = _triggers[i];
35446	        curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1);
35447	        curPin = curTrigger.pin;
35448
35449	        if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) {
35450	          revertedPins || (revertedPins = []);
35451	          revertedPins.unshift(curTrigger);
35452	          curTrigger.revert();
35453	        }
35454	      }
35455
35456	      _isFunction(parsedStart) && (parsedStart = parsedStart(self));
35457	      start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0);
35458	      _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
35459
35460	      if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
35461	        if (~parsedEnd.indexOf(" ")) {
35462	          parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
35463	        } else {
35464	          offset = _offsetToPx(parsedEnd.substr(2), size);
35465	          parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
35466	          parsedEndTrigger = trigger;
35467	        }
35468	      }
35469
35470	      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;
35471	      change = end - start || (start -= 0.01) && 0.001;
35472	      offset = 0;
35473	      i = triggerIndex;
35474
35475	      while (i--) {
35476	        curTrigger = _triggers[i];
35477	        curPin = curTrigger.pin;
35478
35479	        if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) {
35480	          cs = curTrigger.end - curTrigger.start;
35481	          (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs);
35482	          curPin === pin && (otherPinOffset += cs);
35483	        }
35484	      }
35485
35486	      start += offset;
35487	      end += offset;
35488	      self._pinPush = otherPinOffset;
35489
35490	      if (markerStart && offset) {
35491	        cs = {};
35492	        cs[direction.a] = "+=" + offset;
35493	        pinnedContainer && (cs[direction.p] = "-=" + scrollFunc());
35494	        gsap.set([markerStart, markerEnd], cs);
35495	      }
35496
35497	      if (pin) {
35498	        cs = _getComputedStyle(pin);
35499	        isVertical = direction === _vertical;
35500	        scroll = scrollFunc();
35501	        pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
35502	        !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll");
35503
35504	        _swapPinIn(pin, spacer, cs);
35505
35506	        pinState = _getState(pin);
35507	        bounds = _getBounds(pin, true);
35508	        oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)();
35509
35510	        if (pinSpacing) {
35511	          spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px];
35512	          spacerState.t = spacer;
35513	          i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
35514	          i && spacerState.push(direction.d, i + _px);
35515
35516	          _setState(spacerState);
35517
35518	          useFixedPosition && scrollFunc(prevScroll);
35519	        }
35520
35521	        if (useFixedPosition) {
35522	          override = {
35523	            top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px,
35524	            left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px,
35525	            boxSizing: "border-box",
35526	            position: "fixed"
35527	          };
35528	          override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
35529	          override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
35530	          override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
35531	          override[_padding] = cs[_padding];
35532	          override[_padding + _Top] = cs[_padding + _Top];
35533	          override[_padding + _Right] = cs[_padding + _Right];
35534	          override[_padding + _Bottom] = cs[_padding + _Bottom];
35535	          override[_padding + _Left] = cs[_padding + _Left];
35536	          pinActiveState = _copyState(pinOriginalState, override, pinReparent);
35537	        }
35538
35539	        if (animation) {
35540	          initted = animation._initted;
35541
35542	          _suppressOverwrites(1);
35543
35544	          animation.render(animation.duration(), true, true);
35545	          pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
35546	          change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
35547	          animation.render(0, true, true);
35548	          initted || animation.invalidate();
35549
35550	          _suppressOverwrites(0);
35551	        } else {
35552	          pinChange = change;
35553	        }
35554	      } else if (trigger && scrollFunc() && !containerAnimation) {
35555	        bounds = trigger.parentNode;
35556
35557	        while (bounds && bounds !== _body) {
35558	          if (bounds._pinOffset) {
35559	            start -= bounds._pinOffset;
35560	            end -= bounds._pinOffset;
35561	          }
35562
35563	          bounds = bounds.parentNode;
35564	        }
35565	      }
35566
35567	      revertedPins && revertedPins.forEach(function (t) {
35568	        return t.revert(false);
35569	      });
35570	      self.start = start;
35571	      self.end = end;
35572	      scroll1 = scroll2 = scrollFunc();
35573
35574	      if (!containerAnimation) {
35575	        scroll1 < prevScroll && scrollFunc(prevScroll);
35576	        self.scroll.rec = 0;
35577	      }
35578
35579	      self.revert(false);
35580	      _refreshing = 0;
35581	      animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true);
35582
35583	      if (prevProgress !== self.progress) {
35584	        animation && !isToggle && animation.totalProgress(prevProgress, true);
35585	        self.progress = prevProgress;
35586	        self.update(0, 0, 1);
35587	      }
35588
35589	      pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
35590	      onRefresh && onRefresh(self);
35591	    };
35592
35593	    self.getVelocity = function () {
35594	      return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0;
35595	    };
35596
35597	    self.endAnimation = function () {
vendor: 8,601 bytes, lines 35598-35836
35598	      _endAnimation(self.callbackAnimation);
35599
35600	      if (animation) {
35601	        scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1);
35602	      }
35603	    };
35604
35605	    self.getTrailing = function (name) {
35606	      var i = _triggers.indexOf(self),
35607	          a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1);
35608
35609	      return _isString(name) ? a.filter(function (t) {
35610	        return t.vars.preventOverlaps === name;
35611	      }) : a;
35612	    };
35613
35614	    self.update = function (reset, recordVelocity, forceFake) {
35615	      if (containerAnimation && !forceFake && !reset) {
35616	        return;
35617	      }
35618
35619	      var scroll = self.scroll(),
35620	          p = reset ? 0 : (scroll - start) / change,
35621	          clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
35622	          prevProgress = self.progress,
35623	          isActive,
35624	          wasActive,
35625	          toggleState,
35626	          action,
35627	          stateChanged,
35628	          toggled,
35629	          isAtMax,
35630	          isTakingAction;
35631
35632	      if (recordVelocity) {
35633	        scroll2 = scroll1;
35634	        scroll1 = containerAnimation ? scrollFunc() : scroll;
35635
35636	        if (snap) {
35637	          snap2 = snap1;
35638	          snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
35639	        }
35640	      }
35641
35642	      anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
35643
35644	      if (clipped !== prevProgress && self.enabled) {
35645	        isActive = self.isActive = !!clipped && clipped < 1;
35646	        wasActive = !!prevProgress && prevProgress < 1;
35647	        toggled = isActive !== wasActive;
35648	        stateChanged = toggled || !!clipped !== !!prevProgress;
35649	        self.direction = clipped > prevProgress ? 1 : -1;
35650	        self.progress = clipped;
35651
35652	        if (stateChanged && !_refreshing) {
35653	          toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
35654
35655	          if (isToggle) {
35656	            action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
35657	            isTakingAction = animation && (action === "complete" || action === "reset" || action in animation);
35658	          }
35659	        }
35660
35661	        preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) {
35662	          return t.endAnimation();
35663	        }));
35664
35665	        if (!isToggle) {
35666	          if (scrubTween && !_refreshing && !_startup) {
35667	            scrubTween.vars.totalProgress = clipped;
35668	            scrubTween.invalidate().restart();
35669	          } else if (animation) {
35670	            animation.totalProgress(clipped, !!_refreshing);
35671	          }
35672	        }
35673
35674	        if (pin) {
35675	          reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
35676
35677	          if (!useFixedPosition) {
35678	            pinSetter(pinStart + pinChange * clipped);
35679	          } else if (stateChanged) {
35680	            isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
35681
35682	            if (pinReparent) {
35683	              if (!reset && (isActive || isAtMax)) {
35684	                var bounds = _getBounds(pin, true),
35685	                    _offset = scroll - start;
35686
35687	                _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px);
35688	              } else {
35689	                _reparent(pin, spacer);
35690	              }
35691	            }
35692
35693	            _setState(isActive || isAtMax ? pinActiveState : pinState);
35694
35695	            pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0));
35696	          }
35697	        }
35698
35699	        snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true);
35700	        toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) {
35701	          return el.classList[isActive || once ? "add" : "remove"](toggleClass.className);
35702	        });
35703	        onUpdate && !isToggle && !reset && onUpdate(self);
35704
35705	        if (stateChanged && !_refreshing) {
35706	          if (isToggle) {
35707	            if (isTakingAction) {
35708	              if (action === "complete") {
35709	                animation.pause().totalProgress(1);
35710	              } else if (action === "reset") {
35711	                animation.restart(true).pause();
35712	              } else if (action === "restart") {
35713	                animation.restart(true);
35714	              } else {
35715	                animation[action]();
35716	              }
35717	            }
35718
35719	            onUpdate && onUpdate(self);
35720	          }
35721
35722	          if (toggled || !_limitCallbacks) {
35723	            onToggle && toggled && _callback(self, onToggle);
35724	            callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35725	            once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0);
35726
35727	            if (!toggled) {
35728	              toggleState = clipped === 1 ? 1 : 3;
35729	              callbacks[toggleState] && _callback(self, callbacks[toggleState]);
35730	            }
35731	          }
35732
35733	          if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) {
35734	            _endAnimation(self.callbackAnimation);
35735
35736	            scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1);
35737	          }
35738	        } else if (isToggle && onUpdate && !_refreshing) {
35739	          onUpdate(self);
35740	        }
35741	      }
35742
35743	      if (markerEndSetter) {
35744	        var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll;
35745	        markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0));
35746	        markerEndSetter(n);
35747	      }
35748
35749	      caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0));
35750	    };
35751
35752	    self.enable = function (reset, refresh) {
35753	      if (!self.enabled) {
35754	        self.enabled = true;
35755
35756	        _addListener(scroller, "resize", _onResize);
35757
35758	        _addListener(scroller, "scroll", _onScroll);
35759
35760	        onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
35761
35762	        if (reset !== false) {
35763	          self.progress = prevProgress = 0;
35764	          scroll1 = scroll2 = lastSnap = scrollFunc();
35765	        }
35766
35767	        refresh !== false && self.refresh();
35768	      }
35769	    };
35770
35771	    self.getTween = function (snap) {
35772	      return snap && tweenTo ? tweenTo.tween : scrubTween;
35773	    };
35774
35775	    self.disable = function (reset, allowAnimation) {
35776	      if (self.enabled) {
35777	        reset !== false && self.revert();
35778	        self.enabled = self.isActive = false;
35779	        allowAnimation || scrubTween && scrubTween.pause();
35780	        prevScroll = 0;
35781	        pinCache && (pinCache.uncache = 1);
35782	        onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
35783
35784	        if (snapDelayedCall) {
35785	          snapDelayedCall.pause();
35786	          tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0);
35787	        }
35788
35789	        if (!isViewport) {
35790	          var i = _triggers.length;
35791
35792	          while (i--) {
35793	            if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
35794	              return;
35795	            }
35796	          }
35797
35798	          _removeListener(scroller, "resize", _onResize);
35799
35800	          _removeListener(scroller, "scroll", _onScroll);
35801	        }
35802	      }
35803	    };
35804
35805	    self.kill = function (revert, allowAnimation) {
35806	      self.disable(revert, allowAnimation);
35807	      scrubTween && scrubTween.kill();
35808	      id && delete _ids[id];
35809
35810	      var i = _triggers.indexOf(self);
35811
35812	      _triggers.splice(i, 1);
35813
35814	      i === _i && _direction > 0 && _i--;
35815	      i = 0;
35816
35817	      _triggers.forEach(function (t) {
35818	        return t.scroller === self.scroller && (i = 1);
35819	      });
35820
35821	      i || (self.scroll.rec = 0);
35822
35823	      if (animation) {
35824	        animation.scrollTrigger = null;
35825	        revert && animation.render(-1);
35826	        allowAnimation || animation.kill();
35827	      }
35828
35829	      markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) {
35830	        return m.parentNode && m.parentNode.removeChild(m);
35831	      });
35832
35833	      if (pin) {
35834	        pinCache && (pinCache.uncache = 1);
35835	        i = 0;
35836
35837	        _triggers.forEach(function (t) {
35838	          return t.pin === pin && i++;
35839	        });
35840
35841	        i || (pinCache.spacer = 0);
35842	      }
35843	    };
35844
35845	    self.enable(false, false);
35846	    !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () {
35847	      return start || end || self.refresh();
35848	    }) && (change = 0.01) && (start = end = 0);
35849	  };
35850
35851	  ScrollTrigger.register = function register(core) {
35852	    if (!_coreInitted) {
35853	      gsap = core || _getGSAP();
35854
35855	      if (_windowExists() && window.document) {
35856	        _win = window;
35857	        _doc = document;
35858	        _docEl = _doc.documentElement;
35859	        _body = _doc.body;
35860	      }
35861
35862	      if (gsap) {
35863	        _toArray = gsap.utils.toArray;
35864	        _clamp = gsap.utils.clamp;
35865	        _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough;
35866	        gsap.core.globals("ScrollTrigger", ScrollTrigger);
35867
35868	        if (_body) {
35869	          _raf = _win.requestAnimationFrame || function (f) {
35870	            return setTimeout(f, 16);
35871	          };
35872
35873	          _addListener(_win, "wheel", _onScroll);
35874
35875	          _root = [_win, _doc, _docEl, _body];
35876
35877	          _addListener(_doc, "scroll", _onScroll);
35878
35879	          var bodyStyle = _body.style,
35880	              border = bodyStyle.borderTopStyle,
35881	              bounds;
35882	          bodyStyle.borderTopStyle = "solid";
35883	          bounds = _getBounds(_body);
35884	          _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
35885	          _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
35886	          border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style");
35887	          _syncInterval = setInterval(_sync, 200);
35888	          gsap.delayedCall(0.5, function () {
35889	            return _startup = 0;
35890	          });
35891
35892	          _addListener(_doc, "touchcancel", _passThrough);
35893
35894	          _addListener(_body, "touchstart", _passThrough);
35895
35896	          _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
35897	            return _pointerIsDown = 1;
35898	          });
35899
35900	          _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
35901	            return _pointerIsDown = 0;
35902	          });
35903
35904	          _transformProp = gsap.utils.checkPrefix("transform");
35905
35906	          _stateProps.push(_transformProp);
35907
35908	          _coreInitted = _getTime();
35909	          _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
35910	          _autoRefresh = [_doc, "visibilitychange", function () {
35911	            var w = _win.innerWidth,
35912	                h = _win.innerHeight;
35913
35914	            if (_doc.hidden) {
35915	              _prevWidth = w;
35916	              _prevHeight = h;
35917	            } else if (_prevWidth !== w || _prevHeight !== h) {
35918	              _onResize();
35919	            }
35920	          }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () {
35921	            return _lastScrollTime || _refreshAll();
35922	          }, _win, "resize", _onResize];
35923
35924	          _iterateAutoRefresh(_addListener);
35925	        }
35926	      }
35927	    }
35928
35929	    return _coreInitted;
35930	  };
35931
35932	  ScrollTrigger.defaults = function defaults(config) {
35933	    for (var p in config) {
35934	      _defaults[p] = config[p];
35935	    }
35936	  };
35937
35938	  ScrollTrigger.kill = function kill() {
35939	    _enabled = 0;
35940
35941	    _triggers.slice(0).forEach(function (trigger) {
35942	      return trigger.kill(1);
35943	    });
35944	  };
35945
35946	  ScrollTrigger.config = function config(vars) {
35947	    "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
35948	    var ms = vars.syncInterval;
35949	    ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
35950
35951	    if ("autoRefreshEvents" in vars) {
35952	      _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none");
35953	      _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1;
35954	    }
35955	  };
35956
35957	  ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) {
35958	    var t = _getTarget(target),
35959	        i = _scrollers.indexOf(t),
35960	        isViewport = _isViewport(t);
35961
35962	    if (~i) {
35963	      _scrollers.splice(i, isViewport ? 6 : 2);
35964	    }
35965
35966	    isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars);
35967	  };
35968
35969	  ScrollTrigger.matchMedia = function matchMedia(vars) {
35970	    var mq, p, i, func, result;
35971
35972	    for (p in vars) {
35973	      i = _media.indexOf(p);
35974	      func = vars[p];
35975	      _creatingMedia = p;
35976
35977	      if (p === "all") {
35978	        func();
35979	      } else {
35980	        mq = _win.matchMedia(p);
35981
35982	        if (mq) {
35983	          mq.matches && (result = func());
35984
35985	          if (~i) {
35986	            _media[i + 1] = _combineFunc(_media[i + 1], func);
35987	            _media[i + 2] = _combineFunc(_media[i + 2], result);
35988	          } else {
35989	            i = _media.length;
35990
35991	            _media.push(p, func, result);
35992
35993	            mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange);
35994	          }
35995
35996	          _media[i + 3] = mq.matches;
35997	        }
35998	      }
35999
36000	      _creatingMedia = 0;
36001	    }
36002
36003	    return _media;
36004	  };
36005
36006	  ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) {
36007	    query || (_media.length = 0);
36008	    query = _media.indexOf(query);
36009	    query >= 0 && _media.splice(query, 4);
36010	  };
36011
36012	  ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) {
36013	    var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(),
36014	        offset = bounds[horizontal ? _width : _height] * ratio || 0;
36015	    return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight;
36016	  };
36017
36018	  ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) {
36019	    _isString(element) && (element = _getTarget(element));
36020	    var bounds = element.getBoundingClientRect(),
36021	        size = bounds[horizontal ? _width : _height],
36022	        offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0;
36023	    return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight;
36024	  };
36025
36026	  return ScrollTrigger;
36027	}();
36028	ScrollTrigger.version = "3.8.0";
36029
36030	ScrollTrigger.saveStyles = function (targets) {
36031	  return targets ? _toArray(targets).forEach(function (target) {
36032	    if (target && target.style) {
36033	      var i = _savedStyles.indexOf(target);
36034
36035	      i >= 0 && _savedStyles.splice(i, 5);
36036
36037	      _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia);
36038	    }
36039	  }) : _savedStyles;
36040	};
36041
36042	ScrollTrigger.revert = function (soft, media) {
36043	  return _revertAll(!soft, media);
36044	};
36045
36046	ScrollTrigger.create = function (vars, animation) {
36047	  return new ScrollTrigger(vars, animation);
36048	};
36049
36050	ScrollTrigger.refresh = function (safe) {
36051	  return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true);
36052	};
36053
36054	ScrollTrigger.update = _updateAll;
36055	ScrollTrigger.clearScrollMemory = _clearScrollMemory;
36056
36057	ScrollTrigger.maxScroll = function (element, horizontal) {
36058	  return _maxScroll(element, horizontal ? _horizontal : _vertical);
36059	};
36060
36061	ScrollTrigger.getScrollFunc = function (element, horizontal) {
36062	  return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical);
36063	};
36064
36065	ScrollTrigger.getById = function (id) {
36066	  return _ids[id];
36067	};
36068
36069	ScrollTrigger.getAll = function () {
36070	  return _triggers.slice(0);
36071	};
36072
36073	ScrollTrigger.isScrolling = function () {
36074	  return !!_lastScrollTime;
36075	};
36076
36077	ScrollTrigger.snapDirectional = _snapDirectional;
36078
36079	ScrollTrigger.addEventListener = function (type, callback) {
36080	  var a = _listeners[type] || (_listeners[type] = []);
36081	  ~a.indexOf(callback) || a.push(callback);
36082	};
36083
36084	ScrollTrigger.removeEventListener = function (type, callback) {
36085	  var a = _listeners[type],
36086	      i = a && a.indexOf(callback);
36087	  i >= 0 && a.splice(i, 1);
36088	};
36089
36090	ScrollTrigger.batch = function (targets, vars) {
36091	  var result = [],
36092	      varsCopy = {},
36093	      interval = vars.interval || 0.016,
36094	      batchMax = vars.batchMax || 1e9,
36095	      proxyCallback = function proxyCallback(type, callback) {
36096	    var elements = [],
36097	        triggers = [],
36098	        delay = gsap.delayedCall(interval, function () {
36099	      callback(elements, triggers);
36100	      elements = [];
36101	      triggers = [];
36102	    }).pause();
36103	    return function (self) {
36104	      elements.length || delay.restart(true);
36105	      elements.push(self.trigger);
36106	      triggers.push(self);
36107	      batchMax <= elements.length && delay.progress(1);
36108	    };
36109	  },
36110	      p;
36111
36112	  for (p in vars) {
36113	    varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
36114	  }
36115
36116	  if (_isFunction(batchMax)) {
36117	    batchMax = batchMax();
36118
36119	    _addListener(ScrollTrigger, "refresh", function () {
36120	      return batchMax = vars.batchMax();
36121	    });
36122	  }
36123
36124	  _toArray(targets).forEach(function (target) {
36125	    var config = {};
36126
36127	    for (p in varsCopy) {
36128	      config[p] = varsCopy[p];
36129	    }
36130
36131	    config.trigger = target;
36132	    result.push(ScrollTrigger.create(config));
36133	  });
36134
36135	  return result;
36136	};
36137
36138	ScrollTrigger.sort = function (func) {
36139	  return _triggers.sort(func || function (a, b) {
36140	    return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6);
36141	  });
36142	};
36143
36144	_getGSAP() && gsap.registerPlugin(ScrollTrigger);
36145
36146	exports.ScrollTrigger = ScrollTrigger;
36147	exports.default = ScrollTrigger;
36148
36149	Object.defineProperty(exports, '__esModule', { value: true });
36150
36151})));
36152
36153/* ========================================================================
36154 * Bootstrap: collapse.js v3.1.1
36155 * http://getbootstrap.com/javascript/#collapse
36156 * ========================================================================
36157 * Copyright 2011-2014 Twitter, Inc.
36158 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36159 * ======================================================================== */
36160
36161
36162+function ($) {
36163	'use strict';
36164
36165	// COLLAPSE PUBLIC CLASS DEFINITION
36166	// ================================
36167
36168	var Collapse = function (element, options) {
36169		this.$element      = $(element)
36170		this.options       = $.extend({}, Collapse.DEFAULTS, options)
36171		this.transitioning = null
36172
36173		if (this.options.parent) this.$parent = $(this.options.parent)
36174		if (this.options.toggle) this.toggle()
36175	}
36176
36177	Collapse.DEFAULTS = {
36178		toggle: true
36179	}
36180
36181	Collapse.prototype.dimension = function () {
36182		var hasWidth = this.$element.hasClass('width')
36183		return hasWidth ? 'width' : 'height'
36184	}
36185
36186	Collapse.prototype.show = function () {
36187		if (this.transitioning || this.$element.hasClass('in')) return
36188
36189		var startEvent = $.Event('show.bs.collapse')
36190		this.$element.trigger(startEvent)
36191		if (startEvent.isDefaultPrevented()) return
36192
36193		var actives = this.$parent && this.$parent.find('> .panel > .in')
36194
36195		if (actives && actives.length) {
36196			var hasData = actives.data('bs.collapse')
36197			if (hasData && hasData.transitioning) return
36198			//START UNCODE EDIT
36199			var parentNoToggle = this.$parent.data('no-toggle')
36200			if (!parentNoToggle) {
36201				actives.collapse('hide')
36202			}
36203			//END UNCODE EDIT
36204			hasData || actives.data('bs.collapse', null)
36205		}
36206
36207		var dimension = this.dimension()
36208
36209		this.$element
36210			.removeClass('collapse')
36211			.addClass('collapsing')[dimension](0)
36212
36213		this.transitioning = 1
36214
36215		var complete = function (e) {
36216			if (e && e.target != this.$element[0]) return
36217			this.$element
36218				.removeClass('collapsing')
36219				.addClass('collapse in')[dimension]('auto')
36220			this.transitioning = 0
36221			this.$element.trigger('shown.bs.collapse')
36222		}
36223
36224		if (!$.support.transition) return complete.call(this)
36225
36226		var scrollSize = $.camelCase(['scroll', dimension].join('-'))
36227
36228		this.$element
36229			.one($.support.transition.end, $.proxy(complete, this))
36230			.emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
36231	}
36232
36233	Collapse.prototype.hide = function () {
36234		if (this.transitioning || !this.$element.hasClass('in')) return
36235
36236		var startEvent = $.Event('hide.bs.collapse')
36237		this.$element.trigger(startEvent)
36238		if (startEvent.isDefaultPrevented()) return
36239
36240		var dimension = this.dimension()
36241
36242		this.$element[dimension](this.$element[dimension]())[0].offsetHeight
36243
36244		this.$element
36245			.addClass('collapsing')
36246			.removeClass('collapse')
36247			.removeClass('in')
36248
36249		this.transitioning = 1
36250
36251		var complete = function (e) {
36252			if (e && e.target != this.$element[0]) return
36253			this.transitioning = 0
36254			this.$element
36255				.trigger('hidden.bs.collapse')
36256				.removeClass('collapsing')
36257				.addClass('collapse')
36258		}
36259
36260		if (!$.support.transition) return complete.call(this)
36261
36262		this.$element
36263			[dimension](0)
36264			.one($.support.transition.end, $.proxy(complete, this))
36265			.emulateTransitionEnd(350)
36266	}
36267
36268	Collapse.prototype.toggle = function () {
36269		this[this.$element.hasClass('in') ? 'hide' : 'show']()
36270	}
36271
36272
36273	// COLLAPSE PLUGIN DEFINITION
36274	// ==========================
36275
36276	var old = $.fn.collapse
36277
36278	$.fn.collapse = function (option) {
36279		return this.each(function () {
36280			var $this   = $(this)
36281			var data    = $this.data('bs.collapse')
36282			var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
36283
36284			if (!data && options.toggle && option == 'show') option = !option
36285			if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
36286			if (typeof option == 'string') data[option]()
36287		})
36288	}
36289
36290	$.fn.collapse.Constructor = Collapse
36291
36292
36293	// COLLAPSE NO CONFLICT
36294	// ====================
36295
36296	$.fn.collapse.noConflict = function () {
36297		$.fn.collapse = old
36298		return this
36299	}
36300
36301
36302	// COLLAPSE DATA-API
36303	// =================
36304
36305	$(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
36306		var $this   = $(this), href
36307		var target  = $this.attr('data-target')
36308				|| e.preventDefault()
36309				|| (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
36310		//Edited by Uncode to replace ID in panel [START]
36311		var _target = href.replace(/^#/, "");
36312		if ( $('[data-id="' + _target + '"]').length ) {
36313			var $target = $('[data-id="' + _target + '"]')
36314		} else {
36315			var $target = $(target)
36316		}
36317		//Edited by Uncode to replace ID in panel [END]
36318		var data    = $target.data('bs.collapse')
36319		var option  = data ? 'toggle' : $this.data()
36320		var parent  = $this.attr('data-parent')
36321		var $parent = parent && $(parent)
36322
36323		if (!data || !data.transitioning) {
36324			if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
36325			$this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
36326		}
36327
36328		$target.collapse(option)
36329	})
36330
36331}(jQuery);
36332
36333/* ========================================================================
36334 * Bootstrap: tab.js v3.1.1
36335 * http://getbootstrap.com/javascript/#tabs
36336 * ========================================================================
36337 * Copyright 2011-2014 Twitter, Inc.
36338 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36339 * ======================================================================== */
36340
36341
36342+function ($) {
36343  'use strict';
36344
36345  // TAB CLASS DEFINITION
36346  // ====================
36347
36348  var Tab = function (element) {
36349    this.element = $(element)
36350  }
36351
36352  Tab.prototype.show = function () {
36353    var $this    = this.element
36354    var $ul      = $this.closest('ul:not(.dropdown-menu)')
36355    var selector = $this.data('target')
36356
36357    if (!selector) {
36358      selector = $this.attr('href')
36359      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
36360    }
36361
36362    if ($this.parent('li').hasClass('active')) return
36363
36364    var previous = $ul.find('.active:last a')[0]
36365    var e        = $.Event('show.bs.tab', {
36366      relatedTarget: previous
36367    })
36368
36369    $this.trigger(e)
36370
36371    if (e.isDefaultPrevented()) return
36372
36373    //Edited by Uncode to replace ID in panel [START]
36374    var _target = selector.replace(/^#/, "");
36375    if ( $('[data-id="' + _target + '"]').length )
36376      var $target = $('[data-id="' + _target + '"]')
36377    else
36378      var $target = $(selector)
36379    //Edited by Uncode to replace ID in panel [END]
36380
36381    this.activate($this.parent('li'), $ul)
36382    this.activate($target, $target.parent(), function () {
36383      $this.trigger({
36384        type: 'shown.bs.tab',
36385        relatedTarget: previous
36386      })
36387    })
36388  }
36389
36390  Tab.prototype.activate = function (element, container, callback) {
36391    var $active    = container.find('> .active').add(container.find('> .active > .active'))
36392    var transition = callback
36393      && $.support.transition
36394      && $active.hasClass('fade')
36395
36396    function next() {
36397      $active
36398        .removeClass('active')
36399        .find('> .dropdown-menu > .active')
36400        .removeClass('active')
36401
36402      $active
36403        .find('.tab-excerpt').slideUp();
36404
36405      element.addClass('active')
36406      $('.tab-excerpt', element).slideDown();
36407
36408      //if (transition) {
36409        element[0].offsetWidth // reflow for transition
36410        element.add($active).addClass('in')
36411      /*} else {
36412        element.removeClass('fade')
36413      }*/
36414
36415      if (element.parent('.dropdown-menu')) {
36416        element.closest('li.dropdown').addClass('active')
36417      }
36418
36419      if ( ! element.is('li') ) {
36420        element.closest('.tab-content').find('> .active').not(element).removeClass('active');
36421      }
36422
36423      callback && callback()
36424    }
36425
36426    transition ?
36427      $active
36428        .one($.support.transition.end, next)
36429        .emulateTransitionEnd(150) :
36430      next()
36431
36432    $active.removeClass('in')
36433  }
36434
36435
36436  // TAB PLUGIN DEFINITION
36437  // =====================
36438
36439  var old = $.fn.tab
36440
36441  $.fn.tab = function ( option ) {
36442    return this.each(function () {
36443      var $this = $(this)
36444      var data  = $this.data('bs.tab')
36445
36446      if (!data) $this.data('bs.tab', (data = new Tab(this)))
36447      if (typeof option == 'string') data[option]()
36448    })
36449  }
36450
36451  $.fn.tab.Constructor = Tab
36452
36453
36454  // TAB NO CONFLICT
36455  // ===============
36456
36457  $.fn.tab.noConflict = function () {
36458    $.fn.tab = old
36459    return this
36460  }
36461
36462
36463  // TAB DATA-API
36464  // ============
36465
36466  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
36467    e.preventDefault()
36468    $(this).tab('show')
36469  })
36470
36471}(jQuery);
36472
36473/* ========================================================================
36474 * Bootstrap: tooltip.js v3.1.1
36475 * http://getbootstrap.com/javascript/#tooltip
36476 * Inspired by the original jQuery.tipsy by Jason Frame
36477 * ========================================================================
36478 * Copyright 2011-2014 Twitter, Inc.
36479 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36480 * ======================================================================== */
36481
36482
36483+function ($) {
36484  'use strict';
36485
36486  // TOOLTIP PUBLIC CLASS DEFINITION
36487  // ===============================
36488
36489  var Tooltip = function (element, options) {
36490    this.type       =
36491    this.options    =
36492    this.enabled    =
36493    this.timeout    =
36494    this.hoverState =
36495    this.$element   = null
36496
36497    this.init('tooltip', element, options)
36498  }
36499
36500  Tooltip.DEFAULTS = {
36501    animation: true,
36502    placement: 'top',
36503    selector: false,
36504    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
36505    trigger: 'hover focus',
36506    title: '',
36507    delay: 0,
36508    html: false,
36509    container: false,
36510    viewport: {
36511      selector: 'body',
36512      padding: 0
36513    }
36514  }
36515
36516  Tooltip.prototype.init = function (type, element, options) {
36517    this.enabled   = true
36518    this.type      = type
36519    this.$element  = $(element)
36520    this.options   = this.getOptions(options)
36521    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
36522
36523    var triggers = this.options.trigger.split(' ')
36524
36525    for (var i = triggers.length; i--;) {
36526      var trigger = triggers[i]
36527
36528      if (trigger == 'click') {
36529        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
36530      } else if (trigger != 'manual') {
36531        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
36532        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
36533
36534        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
36535        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
36536      }
36537    }
36538
36539    this.options.selector ?
36540      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
36541      this.fixTitle()
36542  }
36543
36544  Tooltip.prototype.getDefaults = function () {
36545    return Tooltip.DEFAULTS
36546  }
36547
36548  Tooltip.prototype.getOptions = function (options) {
36549    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
36550
36551    if (options.delay && typeof options.delay == 'number') {
36552      options.delay = {
36553        show: options.delay,
36554        hide: options.delay
36555      }
36556    }
36557
36558    return options
36559  }
36560
36561  Tooltip.prototype.getDelegateOptions = function () {
36562    var options  = {}
36563    var defaults = this.getDefaults()
36564
36565    this._options && $.each(this._options, function (key, value) {
36566      if (defaults[key] != value) options[key] = value
36567    })
36568
36569    return options
36570  }
36571
36572  Tooltip.prototype.enter = function (obj) {
36573    var self = obj instanceof this.constructor ?
36574      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36575
36576    clearTimeout(self.timeout)
36577
36578    self.hoverState = 'in'
36579
36580    if (!self.options.delay || !self.options.delay.show) return self.show()
36581
36582    self.timeout = setTimeout(function () {
36583      if (self.hoverState == 'in') self.show()
36584    }, self.options.delay.show)
36585  }
36586
36587  Tooltip.prototype.leave = function (obj) {
36588    var self = obj instanceof this.constructor ?
36589      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
36590
36591    clearTimeout(self.timeout)
36592
36593    self.hoverState = 'out'
36594
36595    if (!self.options.delay || !self.options.delay.hide) return self.hide()
36596
36597    self.timeout = setTimeout(function () {
36598      if (self.hoverState == 'out') self.hide()
36599    }, self.options.delay.hide)
36600  }
36601
36602  Tooltip.prototype.show = function () {
36603    var e = $.Event('show.bs.' + this.type)
36604
36605    if (this.hasContent() && this.enabled) {
36606      this.$element.trigger(e)
36607
36608      if (e.isDefaultPrevented()) return
36609      var that = this;
36610
36611      var $tip = this.tip()
36612
36613      this.setContent()
36614
36615      if (this.options.animation) $tip.addClass('fade')
36616
36617      var placement = typeof this.options.placement == 'function' ?
36618        this.options.placement.call(this, $tip[0], this.$element[0]) :
36619        this.options.placement
36620
36621      var autoToken = /\s?auto?\s?/i
36622      var autoPlace = autoT
36622oken.test(placement)
36623      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
36624
36625      $tip
36626        .detach()
36627        .css({ top: 0, left: 0, display: 'block' })
36628        .addClass(placement)
36629
36630      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
36631
36632      var pos          = this.getPosition()
36633      var actualWidth  = $tip[0].offsetWidth
36634      var actualHeight = $tip[0].offsetHeight
36635
36636      if (autoPlace) {
36637        var orgPlacement = placement
36638        var $parent      = this.$element.parent()
36639        var parentDim    = this.getPosition($parent)
36640
36641        placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
36642                    placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
36643                    placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
36644                    placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
36645                    placement
36646
36647        $tip
36648          .removeClass(orgPlacement)
36649          .addClass(placement)
36650      }
36651
36652      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
36653
36654      this.applyPlacement(calculatedOffset, placement)
36655      this.hoverState = null
36656
36657      var complete = function() {
36658        that.$element.trigger('shown.bs.' + that.type)
36659      }
36660
36661      $.support.transition && this.$tip.hasClass('fade') ?
36662        $tip
36663          .one($.support.transition.end, complete)
36664          .emulateTransitionEnd(150) :
36665        complete()
36666    }
36667  }
36668
36669  Tooltip.prototype.applyPlacement = function (offset, placement) {
36670    var $tip   = this.tip()
36671    var width  = $tip[0].offsetWidth
36672    var height = $tip[0].offsetHeight
36673
36674    // manually read margins because getBoundingClientRect includes difference
36675    var marginTop = parseInt($tip.css('margin-top'), 10)
36676    var marginLeft = parseInt($tip.css('margin-left'), 10)
36677
36678    // we must check for NaN for ie 8/9
36679    if (isNaN(marginTop))  marginTop  = 0
36680    if (isNaN(marginLeft)) marginLeft = 0
36681
36682    offset.top  = offset.top  + marginTop
36683    offset.left = offset.left + marginLeft
36684
36685    // $.fn.offset doesn't round pixel values
36686    // so we use setOffset directly with our own function B-0
36687    $.offset.setOffset($tip[0], $.extend({
36688      using: function (props) {
36689        $tip.css({
36690          top: Math.round(props.top),
36691          left: Math.round(props.left)
36692        })
36693      }
36694    }, offset), 0)
36695
36696    $tip.addClass('in')
36697
36698    // check to see if placing tip in new offset caused the tip to resize itself
36699    var actualWidth  = $tip[0].offsetWidth
36700    var actualHeight = $tip[0].offsetHeight
36701
36702    if (placement == 'top' && actualHeight != height) {
36703      offset.top = offset.top + height - actualHeight
36704    }
36705
36706    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
36707
36708    if (delta.left) offset.left += delta.left
36709    else offset.top += delta.top
36710
36711    var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
36712    var arrowPosition       = delta.left ? 'left'        : 'top'
36713    var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
36714
36715    $tip.offset(offset)
36716    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
36717  }
36718
36719  Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
36720    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
36721  }
36722
36723  Tooltip.prototype.setContent = function () {
36724    var $tip  = this.tip()
36725    var title = this.getTitle()
36726
36727    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
36728    $tip.removeClass('fade in top bottom left right')
36729  }
36730
36731  Tooltip.prototype.hide = function () {
36732    var that = this
36733    var $tip = this.tip()
36734    var e    = $.Event('hide.bs.' + this.type)
36735
36736    function complete() {
36737      if (that.hoverState != 'in') $tip.detach()
36738      that.$element.trigger('hidden.bs.' + that.type)
36739    }
36740
36741    this.$element.trigger(e)
36742
36743    if (e.isDefaultPrevented()) return
36744
36745    $tip.removeClass('in')
36746
36747    $.support.transition && this.$tip.hasClass('fade') ?
36748      $tip
36749        .one($.support.transition.end, complete)
36750        .emulateTransitionEnd(150) :
36751      complete()
36752
36753    this.hoverState = null
36754
36755    return this
36756  }
36757
36758  Tooltip.prototype.fixTitle = function () {
36759    var $e = this.$element
36760    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
36761      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
36762    }
36763  }
36764
36765  Tooltip.prototype.hasContent = function () {
36766    return this.getTitle()
36767  }
36768
36769  Tooltip.prototype.getPosition = function ($element) {
36770    $element   = $element || this.$element
36771    var el     = $element[0]
36772    var isBody = el.tagName == 'BODY'
36773    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
36774      scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
36775      width:  isBody ? $(window).width()  : $element.outerWidth(),
36776      height: isBody ? $(window).height() : $element.outerHeight()
36777    }, isBody ? {top: 0, left: 0} : $element.offset())
36778  }
36779
36780  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
36781    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
36782           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
36783           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
36784        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
36785
36786  }
36787
36788  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
36789    var delta = { top: 0, left: 0 }
36790    if (!this.$viewport) return delta
36791
36792    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
36793    var viewportDimensions = this.getPosition(this.$viewport)
36794
36795    if (/right|left/.test(placement)) {
36796      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
36797      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
36798      if (topEdgeOffset < viewportDimensions.top) { // top overflow
36799        delta.top = viewportDimensions.top - topEdgeOffset
36800      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
36801        delta.top = viewportDimensions.top + viewportDimensions.height - bottom
36801EdgeOffset
36802      }
36803    } else {
36804      var leftEdgeOffset  = pos.left - viewportPadding
36805      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
36806      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
36807        delta.left = viewportDimensions.left - leftEdgeOffset
36808      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
36809        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
36810      }
36811    }
36812
36813    return delta
36814  }
36815
36816  Tooltip.prototype.getTitle = function () {
36817    var title
36818    var $e = this.$element
36819    var o  = this.options
36820
36821    title = $e.attr('data-original-title')
36822      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
36823
36824    return title
36825  }
36826
36827  Tooltip.prototype.tip = function () {
36828    return this.$tip = this.$tip || $(this.options.template)
36829  }
36830
36831  Tooltip.prototype.arrow = function () {
36832    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
36833  }
36834
36835  Tooltip.prototype.validate = function () {
36836    if (!this.$element[0].parentNode) {
36837      this.hide()
36838      this.$element = null
36839      this.options  = null
36840    }
36841  }
36842
36843  Tooltip.prototype.enable = function () {
36844    this.enabled = true
36845  }
36846
36847  Tooltip.prototype.disable = function () {
36848    this.enabled = false
36849  }
36850
36851  Tooltip.prototype.toggleEnabled = function () {
36852    this.enabled = !this.enabled
36853  }
36854
36855  Tooltip.prototype.toggle = function (e) {
36856    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
36857    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
36858  }
36859
36860  Tooltip.prototype.destroy = function () {
36861    clearTimeout(this.timeout)
36862    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
36863  }
36864
36865
36866  // TOOLTIP PLUGIN DEFINITION
36867  // =========================
36868
36869  var old = $.fn.tooltip
36870
36871  $.fn.tooltip = function (option) {
36872    return this.each(function () {
36873      var $this   = $(this)
36874      var data    = $this.data('bs.tooltip')
36875      var options = typeof option == 'object' && option
36876
36877      if (!data && option == 'destroy') return
36878      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
36879      if (typeof option == 'string') data[option]()
36880    })
36881  }
36882
36883  $.fn.tooltip.Constructor = Tooltip
36884
36885
36886  // TOOLTIP NO CONFLICT
36887  // ===================
36888
36889  $.fn.tooltip.noConflict = function () {
36890    $.fn.tooltip = old
36891    return this
36892  }
36893
36894}(jQuery);
36895
36896/* ========================================================================
36897 * Bootstrap: transition.js v3.1.1
36898 * http://getbootstrap.com/javascript/#transitions
36899 * ========================================================================
36900 * Copyright 2011-2014 Twitter, Inc.
36901 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
36902 * ======================================================================== */
36903
36904
36905+function ($) {
36906  'use strict';
36907
36908  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
36909  // ============================================================
36910
36911  function transitionEnd() {
36912    var el = document.createElement('bootstrap')
36913
36914    var transEndEventNames = {
36915      WebkitTransition : 'webkitTransitionEnd',
36916      MozTransition    : 'transitionend',
36917      OTransition      : 'oTransitionEnd otransitionend',
36918      transition       : 'transitionend'
36919    }
36920
36921    for (var name in transEndEventNames) {
36922      if (el.style[name] !== undefined) {
36923        return { end: transEndEventNames[name] }
36924      }
36925    }
36926
36927    return false // explicit for ie8 (  ._.)
36928  }
36929
36930  // http://blog.alexmaccaw.com/css-transitions
36931  $.fn.emulateTransitionEnd = function (duration) {
36932    var called = false, $el = this
36933    $(this).one($.support.transition.end, function () { called = true })
36934    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
36935    setTimeout(callback, duration)
36936    return this
36937  }
36938
36939  $(function () {
36940    $.support.transition = transitionEnd()
36941  })
36942
36943}(jQuery);
36944
36945
36946// ------------------------------------------
36947// Rellax.js
36948// Buttery smooth parallax library
36949// Copyright (c) 2016 Moe Amaya (@moeamaya)
36950// MIT license
36951//
36952// Thanks to Paraxify.js and Jaime Cabllero
36953// for parallax concepts
36954// ------------------------------------------
36955
36956(function (root, factory) {
36957	if (typeof define === 'function' && define.amd) {
36958		// AMD. Register as an anonymous module.
36959		define([], factory);
36960	} else if (typeof module === 'object' && module.exports) {
36961		// Node. Does not work with strict CommonJS, but
36962		// only CommonJS-like environments that support module.exports,
36963		// like Node.
36964		module.exports = factory();
36965	} else {
36966		// Browser globals (root is window)
36967		root.Rellax = factory();
36968	}
36969}(typeof window !== "undefined" ? window : global, function () {
36970	var Rellax = function(el, options){
36971		"use strict";
36972
36973		var self = Object.create(Rellax.prototype);
36974
36975		var posY = 0;
36976		var screenY = 0;
36977		var posX = 0;
36978		var screenX = 0;
36979		var blocks = [];
36980		var pause = true;
36981
36982		// check what requestAnimationFrame to use, and if
36983		// it's not supported, use the onscroll event
36984		var loop = window.requestAnimationFrame ||
36985			window.webkitRequestAnimationFrame ||
36986			window.mozRequestAnimationFrame ||
36987			window.msRequestAnimationFrame ||
36988			window.oRequestAnimationFrame ||
36989			function(callback){ return setTimeout(callback, 1000 / 60); };
36990
36991		// store the id for later use
36992		var loopId = null;
36993
36994		// Test via a getter in the options object to see if the passive property is accessed
36995		var supportsPassive = false;
vendor: 10,724 bytes, lines 36996-37297
36996		try {
36997			var opts = Object.defineProperty({}, 'passive', {
36998				get: function() {
36999					supportsPassive = true;
37000				}
37001			});
37002			window.addEventListener("testPassive", null, opts);
37003			window.removeEventListener("testPassive", null, opts);
37004		} catch (e) {}
37005
37006		// check what cancelAnimation method to use
37007		var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout;
37008
37009		// check which transform property to use
37010		var transformProp = window.transformProp || (function(){
37011				var testEl = document.createElement('div');
37012				if (testEl.style.transform === null) {
37013					var vendors = ['Webkit', 'Moz', 'ms'];
37014					for (var vendor in vendors) {
37015						if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) {
37016							return vendors[vendor] + 'Transform';
37017						}
37018					}
37019				}
37020				return 'transform';
37021			})();
37022
37023		// Default Settings
37024		self.options = {
37025			speed: -2,
37026			verticalSpeed: null,
37027			horizontalSpeed: null,
37028			breakpoints: [576, 768, 1201],
37029			center: false,
37030			wrapper: null,
37031			relativeToWrapper: false,
37032			round: true,
37033			vertical: true,
37034			horizontal: false,
37035			verticalScrollAxis: "y",
37036			horizontalScrollAxis: "x",
37037			callback: function() {},
37038		};
37039
37040		// User defined options (might have more in the future)
37041		if (options){
37042			Object.keys(options).forEach(function(key){
37043				self.options[key] = options[key];
37044			});
37045		}
37046
37047		function validateCustomBreakpoints () {
37048			if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) {
37049				var isAscending = true;
37050				var isNumerical = true;
37051				var lastVal;
37052				self.options.breakpoints.forEach(function (i) {
37053					if (typeof i !== 'number') isNumerical = false;
37054					if (lastVal !== null) {
37055						if (i < lastVal) isAscending = false;
37056					}
37057					lastVal = i;
37058				});
37059				if (isAscending && isNumerical) return;
37060			}
37061			// revert defaults if set incorrectly
37062			self.options.breakpoints = [576, 768, 1201];
37063			console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted");
37064		}
37065
37066		if (options && options.breakpoints) {
37067			validateCustomBreakpoints();
37068		}
37069
37070		// By default, rellax class
37071		if (!el) {
37072			el = '.rellax';
37073		}
37074
37075		// check if el is a className or a node
37076		var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el];
37077
37078		// Now query selector
37079		if (elements.length > 0) {
37080			self.elems = elements;
37081		}
37082
37083		// The elements don't exist
37084		else {
37085			console.warn("Rellax: The elements you're trying to select don't exist.");
37086			return;
37087		}
37088
37089		// Has a wrapper and it exists
37090		if (self.options.wrapper) {
37091			if (!self.options.wrapper.nodeType) {
37092				var wrapper = document.querySelector(self.options.wrapper);
37093
37094				if (wrapper) {
37095					self.options.wrapper = wrapper;
37096				} else {
37097					console.warn("Rellax: The wrapper you're trying to use doesn't exist.");
37098					return;
37099				}
37100			}
37101		}
37102
37103		// set a placeholder for the current breakpoint
37104		var currentBreakpoint;
37105
37106		// helper to determine current breakpoint
37107		var getCurrentBreakpoint = function (w) {
37108			var bp = self.options.breakpoints;
37109			if (w < bp[0]) return 'xs';
37110			if (w >= bp[0] && w < bp[1]) return 'sm';
37111			if (w >= bp[1] && w < bp[2]) return 'md';
37112			return 'lg';
37113		};
37114
37115		// Get and cache initial position of all elements
37116		var cacheBlocks = function() {
37117			for (var i = 0; i < self.elems.length; i++){
37118				var block = createBlock(self.elems[i]);
37119				blocks.push(block);
37120			}
37121		};
37122
37123
37124		// Let's kick this script off
37125		// Build array for cached element values
37126		var init = function() {
37127			for (var i = 0; i < blocks.length; i++){
37128				self.elems[i].style.cssText = blocks[i].style;
37129			}
37130
37131			blocks = [];
37132
37133			screenY = window.innerHeight;
37134			screenX = window.innerWidth;
37135			currentBreakpoint = getCurrentBreakpoint(screenX);
37136
37137			setPosition();
37138
37139			cacheBlocks();
37140
37141			animate();
37142
37143			// If paused, unpause and set listener for window resizing events
37144			if (pause) {
37145				window.addEventListener('resize', init);
37146				pause = false;
37147				// Start the loop
37148				update();
37149			}
37150		};
37151
37152		// We want to cache the parallax blocks'
37153		// values: base, top, height, speed
37154		// el: is dom object, return: el cache values
37155		var createBlock = function(el) {
37156			var dataPercentage = el.getAttribute( 'data-rellax-percentage' );
37157			var dataSpeed = el.getAttribute( 'data-rellax-speed' );
37158			var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' );
37159			var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' );
37160			var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' );
37161			var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' );
37162			var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed');
37163			var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed');
37164			var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis');
37165			var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis');
37166			var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0;
37167			var dataMin = el.getAttribute( 'data-rellax-min' );
37168			var dataMax = el.getAttribute( 'data-rellax-max' );
37169			var dataMinX = el.getAttribute('data-rellax-min-x');
37170			var dataMaxX = el.getAttribute('data-rellax-max-x');
37171			var dataMinY = el.getAttribute('data-rellax-min-y');
37172			var dataMaxY = el.getAttribute('data-rellax-max-y');
37173			var mapBreakpoints;
37174			var breakpoints = true;
37175
37176			if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) {
37177				breakpoints = false;
37178			} else {
37179				mapBreakpoints = {
37180					'xs': dataXsSpeed,
37181					'sm': dataMobileSpeed,
37182					'md': dataTabletSpeed,
37183					'lg': dataDesktopSpeed
37184				};
37185			}
37186
37187			// initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser)
37188			// ensures elements are positioned based on HTML layout.
37189			//
37190			// If the element has the percentage attribute, the posY and posX needs to be
37191			// the current scroll position's value, so that the elements are still positioned based on HTML layout
37192			var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37193			// If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll.
37194			if (self.options.relativeToWrapper) {
37195				var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
37196				wrapperPosY = scrollPosY - self.options.wrapper.offsetTop;
37197			}
37198			var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0;
37199			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;
37200
37201			var blockTop = posY + el.getBoundingClientRect().top;
37202			var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight;
37203
37204			var blockLeft = posX + el.getBoundingClientRect().left;
37205			var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth;
37206
37207			// apparently parallax equation everyone uses
37208			var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY);
37209			var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX);
37210			if(self.options.center){ percentageX = 0.5; percentageY = 0.5; }
37211
37212			// Optional individual block speed as data attr, otherwise global speed
37213			var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed);
37214			var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed;
37215			var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed;
37216
37217			// Optional individual block movement axis direction as data attr, otherwise global movement direction
37218			var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis;
37219			var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis;
37220
37221			var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed);
37222
37223			// ~~Store non-translate3d transforms~~
37224			// Store inline styles and extract transforms
37225			var style = el.style.cssText;
37226			var transform = '';
37227
37228			// Check if there's an inline styled transform
37229			var searchResult = /transform\s*:/i.exec(style);
37230			if (searchResult) {
37231				// Get the index of the transform
37232				var index = searchResult.index;
37233
37234				// Trim the style to the transform point and get the following semi-colon index
37235				var trimmedStyle = style.slice(index);
37236				var delimiter = trimmedStyle.indexOf(';');
37237
37238				// Remove "transform" string and save the attribute
37239				if (delimiter) {
37240					transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,'');
37241				} else {
37242					transform = " " + trimmedStyle.slice(11).replace(/\s/g,'');
37243				}
37244			}
37245
37246			return {
37247				baseX: bases.x,
37248				baseY: bases.y,
37249				top: blockTop,
37250				left: blockLeft,
37251				height: blockHeight,
37252				width: blockWidth,
37253				speed: speed,
37254				verticalSpeed: verticalSpeed,
37255				horizontalSpeed: horizontalSpeed,
37256				verticalScrollAxis: verticalScrollAxis,
37257				horizontalScrollAxis: horizontalScrollAxis,
37258				style: style,
37259				transform: transform,
37260				zindex: dataZindex,
37261				min: dataMin,
37262				max: dataMax,
37263				minX: dataMinX,
37264				maxX: dataMaxX,
37265				minY: dataMinY,
37266				maxY: dataMaxY
37267			};
37268		};
37269
37270		// set scroll position (posY, posX)
37271		// side effect method is not ideal, but okay for now
37272		// returns true if the scroll changed, false if nothing happened
37273		var setPosition = function() {
37274			var oldY = posY;
37275			var oldX = posX;
37276
37277			posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37278			posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset;
37279			// If option relativeToWrapper is true, use relative wrapper value instead.
37280			if (self.options.relativeToWrapper) {
37281				var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset;
37282				posY = scrollPosY - self.options.wrapper.offsetTop;
37283			}
37284
37285
37286			if (oldY != posY && self.options.vertical) {
37287				// scroll changed, return true
37288				return true;
37289			}
37290
37291			if (oldX != posX && self.options.horizontal) {
37292				// scroll changed, return true
37293				return true;
37294			}
37295
37296			// scroll did not change
37297			return false;
37298		};
37299
37300		// Ahh a pure function, gets new transform value
37301		// based on scrollPosition and speed
37302		// Allow for decimal pixel values
37303		var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) {
37304			var result = {};
37305			var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX)));
37306			var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY)));
37307
37308			result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100;
37309			result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100;
37310
37311			return result;
37312		};
37313
37314		// Remove event listeners and loop again
37315		var deferredUpdate = function() {
37316			window.removeEventListener('resize', deferredUpdate);
37317			window.removeEventListener('orientationchange', deferredUpdate);
37318			(self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate);
37319			(self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate);
37320
37321			// loop again
37322			loopId = loop(update);
37323		};
37324
37325		// Loop
37326		var update = function() {
37327			if (setPosition() && pause === false) {
37328				animate();
37329
37330				// loop again
37331				loopId = loop(update);
37332			} else {
37333				loopId = null;
37334
37335				// Don't animate until we get a position updating event
37336				window.addEventListener('resize', deferredUpdate);
37337				window.addEventListener('orientationchange', deferredUpdate);
37338				(self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false);
37339				(self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false);
37340			}
37341		};
37342
37343		// Transform3d on parallax element
37344		var animate = function() {
37345			var positions;
37346			for (var i = 0; i < self.elems.length; i++){
37347				// Determine relevant movement directions
37348				var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase();
37349				var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase();
37350				var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0;
37351				var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0;
37352				var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0;
37353				var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0;
37354
37355				var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY));
37356				var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX));
37357
37358				// Subtracting initialize value, so element stays in same spot as HTML
37359				positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed);
37360				var positionY = positions.y - blocks[i].baseY;
37361				var positionX = positions.x - blocks[i].baseX;
37362
37363				// The next two "if" blocks go like this:
37364				// Check if a limit is defined (first "min", then "max");
37365				// Check if we need to change the Y or the X
37366				// (Currently working only if just one of the axes is enabled)
37367				// Then, check if the new position is inside the allowed limit
37368				// If so, use new position. If not, set position to limit.
37369
37370				// Check if a min limit is defined
37371				if (blocks[i].min !== null) {
37372					if (self.options.vertical && !self.options.horizontal) {
37373						positionY = positionY <= blocks[i].min ? blocks[i].min : positionY;
37374					}
37375					if (self.options.horizontal && !self.options.vertical) {
37376						positionX = positionX <= blocks[i].min ? blocks[i].min : positionX;
37377					}
37378				}
37379
37380				// Check if directional min limits are defined
37381				if (blocks[i].minY != null) {
37382						positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY;
37383				}
37384				if (blocks[i].minX != null) {
37385						positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX;
37386				}
37387
37388				// Check if a max limit is defined
37389				if (blocks[i].max !== null) {
37390					if (self.options.vertical && !self.options.horizontal) {
37391						positionY = positionY >= blocks[i].max ? blocks[i].max : positionY;
37392					}
37393					if (self.options.horizontal && !self.options.vertical) {
37394						positionX = positionX >= blocks[i].max ? blocks[i].max : positionX;
37395					}
37396				}
37397
37398				// Check if directional max limits are defined
37399				if (blocks[i].maxY != null) {
37400						positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY;
37401				}
37402				if (blocks[i].maxX != null) {
37403						positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX;
37404				}
37405
37406				var zindex = blocks[i].zindex;
37407
37408				// Move that element
37409				// (Set the new translation and append initial inline transforms.)
37410				var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform;
37411				self.elems[i].style[transformProp] = translate;
37412			}
37413			self.options.callback(positions);
37414		};
37415
37416		self.destroy = function() {
37417			for (var i = 0; i < self.elems.length; i++){
37418				self.elems[i].style.cssText = blocks[i].style;
37419			}
37420
37421			// Remove resize event listener if not pause, and pause
37422			if (!pause) {
37423				window.removeEventListener('resize', init);
37424				pause = true;
37425			}
37426
37427			// Clear the animation loop to prevent possible memory leak
37428			clearLoop(loopId);
37429			loopId = null;
37430		};
37431
37432		// Init
37433		init();
37434
37435		// Allow to recalculate the initial values whenever we want
37436		self.refresh = init;
37437
37438		return self;
37439	};
37440	return Rellax;
37441}));
37442
37443/*
37444 * OKVideo by OKFocus v2.3.2
37445 * http://okfoc.us
37446 *
37447 * Copyright 2014, OKFocus
37448 * Licensed under the MIT license.
37449 *
37450 */
37451var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array();
37452// youtube player ready
37453function onYouTubeIframeAPIReady() {
37454	YTplayers = new Array();
37455	jQuery('.uncode-video-container.video').each(function() {
37456		var playerY;
37457		if (jQuery(this).attr('data-provider') == 'youtube') {
37458			var id = jQuery(this).attr('data-id'),
37459				start = jQuery(this).attr('data-start'),
37460				end = jQuery(this).attr('data-end');
37461			start = typeof start && start !== null ? start : 0;
37462			end = typeof end && end !== null ? end : 0;
37463			options = jQuery(window).data('okoptions-' + id);
37464			if ( typeof options === 'undefined' ) {
37465				return true;
37466			}
37467			options.time = jQuery(this).attr('data-t');
37468			playerY = new YT.Player('okplayer-' + id, {
37469				videoId: options.video ? options.video.id : null,
37470				playerVars: {
37471					'autohide': 1,
37472					'autoplay': jQuery(this).hasClass('is-no-control') ? options.autoplay : 0, //options.autoplay,
37473					'disablekb': 1,
37474					'cc_load_policy': options.captions,
37475					'controls': 0,
37476					'enablejsapi': 1,
37477					'fs': 0,
37478					'modestbranding': 1,
37479					'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname),
37480					'iv_load_policy': options.annotations,
37481					'loop': options.loop,
37482					'showinfo': 0,
37483					'rel': 0,
37484					'wmode': 'opaque',
37485					'hd': options.hd,
37486					'mute': 1,
37487					'start': start,
37488					'end': end
37489				},
37490				events: {
37491					'onReady': OKEvents.yt.ready,
37492					'onStateChange': OKEvents.yt.onStateChange,
37493					'onError': OKEvents.yt.error
37494				}
37495			});
37496			YTplayers[id] = playerY;
37497			playerY.videoId = id;
37498		}
37499
37500	});
37501}
37502// vimeo player ready
37503function vimeoPlayerReady(id) {
37504	options = jQuery(window).data('okoptions-' + id);
37505	if ( typeof options === 'undefined' ) {
37506		return true;
37507	}
37508	var jIframe = options.jobject,
37509		iframe = jIframe[0];
37510
37511	jIframe.attr('src', jIframe.data('src'));
37512	var playerV = new Vimeo.Player(iframe);
37513	// hide player until Vimeo hides controls...
37514	playerV.on('loaded', function(e) {
37515		OKEvents.v.onReady(iframe);
37516		var carouselContainer = jQuery(iframe).closest('.owl-carousel');
37517		if (carouselContainer.length) {
37518			UNCODE.owlPlayVideo(carouselContainer);
37519		}
37520		// "Do not try to add listeners or call functions before receiving this event."
37521		if (OKEvents.utils.isMobile()) {
37522			// mobile devices cannot listen for play event
37523			OKEvents.v.onPlay(playerV);
37524		} else {
37525			playerV.on('play', function(){
37526				OKEvents.v.onPlay(playerV);
37527				jQuery(window).trigger('okevents.v.play', [playerV]);
37528			});
37529			playerV.on('pause', function(){
37530				OKEvents.v.onPause;
37531				jQuery(window).trigger('okevents.v.pause', [playerV]);
37532			});
37533			playerV.on('ended', function(){
37534				OKEvents.v.onFinish
37535				jQuery(window).trigger('okevents.v.ended', [playerV]);
37536			});
37537		}
37538		if (options.time != null) {
37539			var optsTimeStr = (options.time).replace('t=', ''),
37540				timeV = '';
37541
37542			if ( /[a-zA-Z]/g.test(optsTimeStr) ) {
37543				var timeArr = optsTimeStr.split(/([^\d.-])/);
37544				for ( var i = 0; i < timeArr.length; i++ ) {
37545					if ( timeArr[i] === 'h' ) {
37546						timeV += parseFloat(timeArr[i-1]) * 3600;
37547					} else if ( timeArr[i] === 'm' ) {
37548						timeV += parseFloat(timeArr[i-1]) * 60;
37549					} else if ( timeArr[i] === 's' ) {
37550						timeV += parseFloat(timeArr[i-1]);
37551					}
37552				}
37553			} else {
37554				timeV = optsTimeStr;
37555			}
37556
37557			playerV.setCurrentTime(timeV);
37558		}
37559
37560		playerV.setVolume(0);
37561		playerV.play();
37562		jQuery(iframe).css({
37563			visibility: 'visible',
37564			opacity: 1
37565		});
37566		jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37567		jQuery(iframe).closest('#page-header').addClass('video-started');
37568		jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37569
37570		jQuery(window).trigger('okevents.v.loaded', [playerV]);
37571	});
37572}
37573OKEvents = {
37574	yt: {
37575		ready: function(event) {
37576			var id = event.target.videoId,
37577				$video = jQuery('#okplayer-' + id),
37578				options = jQuery(window).data('okoptions-' + id);
37579			if ( typeof options === 'undefined' ) {
37580				return true;
37581			}
37582			youtubePlayers[id] = event.target;
37583			event.target.setVolume(options.volume);
37584			if (options.autoplay === 1) {
37585				if (options.playlist.list) {
37586					player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality);
37587				} else {
37588					var inCarousel = $video.closest('.owl-item');
37589					if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) {
37590						if (options.time != null) {
37591							event.target.seekTo(parseInt(options.time));
37592						}
37593						event.target.playVideo();
37594					} else {
37595						event.target.pauseVideo();
37596					}
37597				}
37598			}
37599			OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target);
37600
37601			$video.closest('[data-provider]').on('uncode-resume', function(){
37602				if (options.time != null) {
37603					event.target.seekTo(parseInt(options.time)).playVideo();
37604				} else {
37605					event.target.seekTo(0).playVideo();
37606				}
37607			});
37608
37609			$video.closest('[data-provider]').on('uncode-pause', function(){
37610				if (options.time != null) {
37611					event.target.seekTo(parseInt(options.time)).pauseVideo();
37612				} else {
37613					event.target.seekTo(0).pauseVideo();
37614				}
37615			});
37616			jQuery(window).trigger('okevents.y.loaded', [event]);
37617		},
37618		onStateChange: function(event) {
37619			var id = event.target.videoId,
37620				$video = jQuery('#okplayer-' + id),
37621				options = jQuery(window).data('okoptions-' + id);
37622			if ( typeof options === 'undefined' ) {
37623				return true;
37624			}
37625			youtubePlayers[id] = event.target;
37626			event.target.setVolume(options.volume);
37627			var $fluid = $video.closest('.fluid-object'),
37628				$tmb = $video.closest('.tmb'),
37629				setTime;
37630			switch (event.data) {
37631				case -1:
37632					OKEvents.utils.isFunction(options.unstarted) && options.unstarted();
37633					break;
37634				case 0:
37635					OKEvents.utils.isFunction(options.onFinished) && options.onFinished();
37636					options.loop && event.target.playVideo();
37637					break;
37638				case 1:
37639					OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37640					setTimeout(function() {
37641						UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)');
37642						jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37643						jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started');
37644						jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37645					}, 300);
37646				break;
37647				case 2:
37648					OKEvents.utils.isFunction(options.onPause) && options.onPause();
37649					break;
37650				case 3:
37651					OKEvents.utils.isFunction(options.buffering) && options.buffering();
37652					break;
37653				case 5:
37654					OKEvents.utils.isFunction(options.cued) && options.cued();
37655					break;
37656				default:
37657					throw "OKVideo: received invalid data from YT player.";
37658			}
37659
37660			jQuery(window).trigger('okevents.y.change', [event]);
37661		},
37662		error: function(event) {
37663			throw event;
37664		}
37665	},
37666	v: {
37667		onReady: function(target) {
37668			if ( typeof options === 'undefined' ) {
37669				return true;
37670			}
37671			OKEvents.utils.isFunction(options.onReady) && options.onReady(target);
37672		},
37673		onPlay: function(player) {
37674			if ( typeof options === 'undefined' ) {
37675				return true;
37676			}
37677			if (!OKEvents.utils.isMobile()) player.setVolume(options.volume);
37678			OKEvents.utils.isFunction(options.onPlay) && options.onPlay();
37679			jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1');
37680			jQuery(player.element).closest('#page-header').addClass('video-started');
37681			jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1');
37682		},
37683		onPause: function() {
37684			if ( typeof options === 'undefined' ) {
37685				return true;
37686			}
37687			OKEvents.utils.isFunction(options.onPause) && options.onPause();
37688		},
37689		onFinish: function() {
37690			if ( typeof options === 'undefined' ) {
37691				return true;
37692			}
37693			OKEvents.utils.isFunction(options.onFinish) && options.onFinish();
37694		}
37695	},
37696	utils: {
37697		isFunction: function(func) {
37698			if (typeof func === 'function') {
37699				return true;
37700			} else {
37701				return false;
37702			}
37703		},
37704		isMobile: function() {
37705			if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) {
37706				return true;
37707			} else {
37708				return false;
37709			}
37710		}
37711	}
37712};
37713
37714/**
37715 * vivus - JavaScript library to make drawing animation on SVG
37716 * @version v0.4.4
37717 * @link https://github.com/maxwellito/vivus
37718 * @license MIT
37719 */
37720
37721'use strict';
37722
37723(function () {
37724
37725  'use strict';
37726
37727/**
37728 * Pathformer
37729 * Beta version
37730 *
37731 * Take any SVG version 1.1 and transform
37732 * child elements to 'path' elements
37733 *
37734 * This code is purely forked from
37735 * https://github.com/Waest/SVGPathConverter
37736 */
37737
37738/**
37739 * Class constructor
37740 *
37741 * @param {DOM|String} element Dom element of the SVG or id of it
37742 */
37743function Pathformer(element) {
37744  // Test params
37745  if (typeof element === 'undefined') {
37746	throw new Error('Pathformer [constructor]: "element" parameter is required');
37747  }
37748
37749  // Set the element
37750  if (element.constructor === String) {
37751	element = document.getElementById(element);
37752	if (!element) {
37753	  throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
37754	}
37755  }
37756  if (element instanceof window.SVGElement ||
37757	  element instanceof window.SVGGElement ||
37758	  /^svg$/i.test(element.nodeName)) {
37759	this.el = element;
37760  } else {
37761	throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
37762  }
37763
37764  // Start
37765  this.scan(element);
37766}
37767
37768/**
37769 * List of tags which can be transformed
37770 * to path elements
37771 *
37772 * @type {Array}
37773 */
37774Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
37775
37776/**
37777 * List of attribute names which contain
37778 * data. This array list them to check if
37779 * they contain bad values, like percentage.
37780 *
37781 * @type {Array}
37782 */
37783Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 37783-38581
37783y1', 'y2'];
37784
37785/**
37786 * Finds the elements compatible for transform
37787 * and apply the liked method
37788 *
37789 * @param  {object} options Object from the constructor
37790 */
37791Pathformer.prototype.scan = function (svg) {
37792  var fn, element, pathData, pathDom,
37793	  elements = svg.querySelectorAll(this.TYPES.join(','));
37794
37795  for (var i = 0; i < elements.length; i++) {
37796	element = elements[i];
37797	fn = this[element.tagName.toLowerCase() + 'ToPath'];
37798	pathData = fn(this.parseAttr(element.attributes));
37799	pathDom = this.pathMaker(element, pathData);
37800	element.parentNode.replaceChild(pathDom, element);
37801  }
37802};
37803
37804
37805/**
37806 * Read `line` element to extract and transform
37807 * data, to make it ready for a `path` object.
37808 *
37809 * @param  {DOMelement} element Line element to transform
37810 * @return {object}			 Data for a `path` element
37811 */
37812Pathformer.prototype.lineToPath = function (element) {
37813  var newElement = {},
37814	  x1 = element.x1 || 0,
37815	  y1 = element.y1 || 0,
37816	  x2 = element.x2 || 0,
37817	  y2 = element.y2 || 0;
37818
37819  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
37820  return newElement;
37821};
37822
37823/**
37824 * Read `rect` element to extract and transform
37825 * data, to make it ready for a `path` object.
37826 * The radius-border is not taken in charge yet.
37827 * (your help is more than welcomed)
37828 *
37829 * @param  {DOMelement} element Rect element to transform
37830 * @return {object}             Data for a `path` element
37831 */
37832Pathformer.prototype.rectToPath = function (element) {
37833  var newElement = {},
37834      x      = parseFloat(element.x)      || 0,
37835      y      = parseFloat(element.y)      || 0,
37836      width  = parseFloat(element.width)  || 0,
37837      height = parseFloat(element.height) || 0;
37838
37839  if (element.rx || element.ry) {
37840    var rx = parseInt(element.rx, 10) || -1,
37841        ry = parseInt(element.ry, 10) || -1;
37842    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
37843    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
37844
37845    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
37846                   'L ' + (x + width - rx) + ',' + y + ' ' +
37847                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
37848                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
37849                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
37850                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
37851                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
37852                   'L ' + x + ',' + (y + ry) + ' ' +
37853                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
37854  }
37855  else {
37856    newElement.d = 'M' + x + ' ' + y + ' ' +
37857                   'L' + (x + width) + ' ' + y + ' ' +
37858                   'L' + (x + width) + ' ' + (y + height) + ' ' +
37859                   'L' + x + ' ' + (y + height) + ' Z';
37860  }
37861  return newElement;
37862};
37863
37864/**
37865 * Read `polyline` element to extract and transform
37866 * data, to make it ready for a `path` object.
37867 *
37868 * @param  {DOMelement} element Polyline element to transform
37869 * @return {object}             Data for a `path` element
37870 */
37871Pathformer.prototype.polylineToPath = function (element) {
37872  var newElement = {},
37873      points = element.points.trim().split(' '),
37874      i, path;
37875
37876  // Reformatting if points are defined without commas
37877  if (element.points.indexOf(',') === -1) {
37878    var formattedPoints = [];
37879    for (i = 0; i < points.length; i+=2) {
37880      formattedPoints.push(points[i] + ',' + points[i+1]);
37881    }
37882    points = formattedPoints;
37883  }
37884
37885  // Generate the path.d value
37886  path = 'M' + points[0];
37887  for(i = 1; i < points.length; i++) {
37888    if (points[i].indexOf(',') !== -1) {
37889      path += 'L' + points[i];
37890    }
37891  }
37892  newElement.d = path;
37893  return newElement;
37894};
37895
37896/**
37897 * Read `polygon` element to extract and transform
37898 * data, to make it ready for a `path` object.
37899 * This method rely on polylineToPath, because the
37900 * logic is similar. The path created is just closed,
37901 * so it needs an 'Z' at the end.
37902 *
37903 * @param  {DOMelement} element Polygon element to transform
37904 * @return {object}             Data for a `path` element
37905 */
37906Pathformer.prototype.polygonToPath = function (element) {
37907  var newElement = Pathformer.prototype.polylineToPath(element);
37908
37909  newElement.d += 'Z';
37910  return newElement;
37911};
37912
37913/**
37914 * Read `ellipse` element to extract and transform
37915 * data, to make it ready for a `path` object.
37916 *
37917 * @param  {DOMelement} element ellipse element to transform
37918 * @return {object}             Data for a `path` element
37919 */
37920Pathformer.prototype.ellipseToPath = function (element) {
37921  var newElement = {},
37922      rx = parseFloat(element.rx) || 0,
37923      ry = parseFloat(element.ry) || 0,
37924      cx = parseFloat(element.cx) || 0,
37925      cy = parseFloat(element.cy) || 0,
37926      startX = cx - rx,
37927      startY = cy,
37928      endX = parseFloat(cx) + parseFloat(rx),
37929      endY = cy;
37930
37931  newElement.d = 'M' + startX + ',' + startY +
37932                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
37933                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
37934  return newElement;
37935};
37936
37937/**
37938 * Read `circle` element to extract and transform
37939 * data, to make it ready for a `path` object.
37940 *
37941 * @param  {DOMelement} element Circle element to transform
37942 * @return {object}             Data for a `path` element
37943 */
37944Pathformer.prototype.circleToPath = function (element) {
37945  var newElement = {},
37946      r  = parseFloat(element.r)  || 0,
37947      cx = parseFloat(element.cx) || 0,
37948      cy = parseFloat(element.cy) || 0,
37949      startX = cx - r,
37950      startY = cy,
37951      endX = parseFloat(cx) + parseFloat(r),
37952      endY = cy;
37953
37954  newElement.d =  'M' + startX + ',' + startY +
37955                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
37956                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
37957  return newElement;
37958};
37959
37960/**
37961 * Create `path` elements form original element
37962 * and prepared objects
37963 *
37964 * @param  {DOMelement} element  Original element to transform
37965 * @param  {object} pathData     Path data (from `toPath` methods)
37966 * @return {DOMelement}          Path element
37967 */
37968Pathformer.prototype.pathMaker = function (element, pathData) {
37969  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
37970  for(i = 0; i < element.attributes.length; i++) {
37971    attr = element.attributes[i];
37972    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
37973      pathTag.setAttribute(attr.name, attr.value);
37974    }
37975  }
37976  for(i in pathData) {
37977    pathTag.setAttribute(i, pathData[i]);
37978  }
37979  return pathTag;
37980};
37981
37982/**
37983 * Parse attributes of a DOM element to
37984 * get an object of attribute => value
37985 *
37986 * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
37987 * @return {object}                  Object of attributes
37988 */
37989Pathformer.prototype.parseAttr = function (element) {
37990  var attr, output = {};
37991  for (var i = 0; i < element.length; i++) {
37992    attr = element[i];
37993    // Check if no data attribute contains '%', or the transformation is impossible
37994    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
37995      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
37996    }
37997    output[attr.name] = attr.value;
37998  }
37999  return output;
38000};
38001
38002  'use strict';
38003
38004var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
38005
38006/**
38007 * Vivus
38008 * Beta version
38009 *
38010 * Take any SVG and make the animation
38011 * to give give the impression of live drawing
38012 *
38013 * This in more than just inspired from codrops
38014 * At that point, it's a pure fork.
38015 */
38016
38017/**
38018 * Class constructor
38019 * option structure
38020 *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
38021 *   duration: <int> (in frames)
38022 *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
38023 *   delay: <int> (delay between the drawing of first and last path)
38024 *   dashGap <integer> whitespace extra margin between dashes
38025 *   pathTimingFunction <function> timing animation function for each path element of the SVG
38026 *   animTimingFunction <function> timing animation function for the complete SVG
38027 *   forceRender <boolean> force the browser to re-render all updated path items
38028 *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
38029 *
38030 * The attribute 'type' is by default on 'delayed'.
38031 *  - 'delayed'
38032 *    all paths are draw at the same time but with a
38033 *    little delay between them before start
38034 *  - 'sync'
38035 *    all path are start and finish at the same time
38036 *  - 'oneByOne'
38037 *    only one path is draw at the time
38038 *    the end of the first one will trigger the draw
38039 *    of the next one
38040 *
38041 * All these values can be overwritten individually
38042 * for each path item in the SVG
38043 * The value of frames will always take the advantage of
38044 * the duration value.
38045 * If you fail somewhere, an error will be thrown.
38046 * Good luck.
38047 *
38048 * @constructor
38049 * @this {Vivus}
38050 * @param {DOM|String}   element  Dom element of the SVG or id of it
38051 * @param {Object}       options  Options about the animation
38052 * @param {Function}     callback Callback for the end of the animation
38053 */
38054function Vivus (element, options, callback) {
38055
38056  setupEnv();
38057
38058  // Setup
38059  this.isReady = false;
38060  this.setElement(element, options);
38061  this.setOptions(options);
38062  this.setCallback(callback);
38063
38064  if (this.isReady) {
38065    this.init();
38066  }
38067}
38068
38069/**
38070 * Timing functions
38071 **************************************
38072 *
38073 * Default functions to help developers.
38074 * It always take a number as parameter (between 0 to 1) then
38075 * return a number (between 0 and 1)
38076 */
38077Vivus.LINEAR          = function (x) {return x;};
38078Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
38079Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
38080Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
38081Vivus.EASE_OUT_BOUNCE = function (x) {
38082  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
38083    rate = Math.pow(base,1.5),
38084    rateR = Math.pow(1 - x, 2),
38085    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
38086  return (1- rateR) + (progress * rateR);
38087};
38088
38089
38090/**
38091 * Setters
38092 **************************************
38093 */
38094
38095/**
38096 * Check and set the element in the instance
38097 * The method will not return anything, but will throw an
38098 * error if the parameter is invalid
38099 *
38100 * @param {DOM|String}   element  SVG Dom element or id of it
38101 */
38102Vivus.prototype.setElement = function (element, options) {
38103  var onLoad, self;
38104
38105  // Basic check
38106  if (typeof element === 'undefined') {
38107    throw new Error('Vivus [constructor]: "element" parameter is required');
38108  }
38109
38110  // Set the element
38111  if (element.constructor === String) {
38112    element = document.getElementById(element);
38113    if (!element) {
38114      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
38115    }
38116  }
38117  this.parentEl = element;
38118
38119  // Load the SVG with XMLHttpRequest and extract the SVG
38120  if (options && options.file) {
38121    var self = this;
38122    onLoad = function (e) {
38123      var domSandbox = document.createElement('div');
38124      domSandbox.innerHTML = this.responseText;
38125
38126      var svgTag = domSandbox.querySelector('svg');
38127      if (!svgTag) {
38128        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
38129      }
38130
38131      self.el = svgTag
38132      self.el.setAttribute('width', '100%');
38133      self.el.setAttribute('height', '100%');
38134      self.parentEl.appendChild(self.el)
38135      self.isReady = true;
38136      self.init();
38137      self = null;
38138    }
38139
38140    var oReq = new window.XMLHttpRequest();
38141    oReq.addEventListener('load', onLoad);
38142    oReq.open('GET', options.file);
38143    oReq.send();
38144    return;
38145  }
38146
38147  switch (element.constructor) {
38148  case window.SVGSVGElement:
38149  case window.SVGElement:
38150  case window.SVGGElement:
38151    this.el = element;
38152    this.isReady = true;
38153    break;
38154
38155  case window.HTMLObjectElement:
38156    self = this;
38157    onLoad = function (e) {
38158      if (self.isReady) {
38159        return;
38160      }
38161      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
38162      if (!self.el && e) {
38163        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
38164      }
38165      else if (self.el) {
38166        if (element.getAttribute('built-by-vivus')) {
38167          self.parentEl.insertBefore(self.el, element);
38168          self.parentEl.removeChild(element);
38169          self.el.setAttribute('width', '100%');
38170          self.el.setAttribute('height', '100%');
38171        }
38172        self.isReady = true;
38173        self.init();
38174        self = null;
38175      }
38176    };
38177
38178    if (!onLoad()) {
38179      element.addEventListener('load', onLoad);
38180    }
38181    break;
38182
38183  default:
38184    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
38185  }
38186};
38187
38188/**
38189 * Set up user option to the instance
38190 * The method will not return anything, but will throw an
38191 * error if the parameter is invalid
38192 *
38193 * @param  {object} options Object from the constructor
38194 */
38195Vivus.prototype.setOptions = function (options) {
38196  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
38197  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
38198
38199  // Basic check
38200  if (options !== undefined && options.constructor !== Object) {
38201    throw new Error('Vivus [constructor]: "options" parameter must be an object');
38202  }
38203  else {
38204    options = options || {};
38205  }
38206
38207  // Set the animation type
38208  if (options.type && allowedTypes.indexOf(options.type) === -1) {
38209    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
38210  }
38211  else {
38212    this.type = options.type || allowedTypes[0];
38213  }
38214
38215  // Set the start type
38216  if (options.start && allowedStarts.indexOf(options.start) === -1) {
38217    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
38218  }
38219  else {
38220    this.start = options.start || allowedStarts[0];
38221  }
38222
38223  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
38224  this.duration     = parsePositiveInt(options.duration, 120);
38225  this.delay        = parsePositiveInt(options.delay, null);
38226  //Uncode addition
38227  this.delayStart   = parsePositiveInt(options.delayStart, null);
38228  //#END
38229  this.dashGap      = parsePositiveInt(options.dashGap, 1);
38230  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
38231  this.reverseStack = !!options.reverseStack;
38232  this.selfDestroy  = !!options.selfDestroy;
38233  this.onReady      = options.onReady;
38234  this.map          = [];
38235  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
38236
38237  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
38238
38239  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
38240  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
38241
38242  if (this.delay >= this.duration) {
38243    throw new Error('Vivus [constructor]: delay must be shorter than duration');
38244  }
38245};
38246
38247/**
38248 * Set up callback to the instance
38249 * The method will not return enything, but will throw an
38250 * error if the parameter is invalid
38251 *
38252 * @param  {Function} callback Callback for the animation end
38253 */
38254Vivus.prototype.setCallback = function (callback) {
38255  // Basic check
38256  if (!!callback && callback.constructor !== Function) {
38257    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
38258  }
38259  this.callback = callback || function () {};
38260};
38261
38262
38263/**
38264 * Core
38265 **************************************
38266 */
38267
38268/**
38269 * Map the svg, path by path.
38270 * The method return nothing, it just fill the
38271 * `map` array. Each item in this array represent
38272 * a path element from the SVG, with informations for
38273 * the animation.
38274 *
38275 * ```
38276 * [
38277 *   {
38278 *     el: <DOMobj> the path element
38279 *     length: <number> length of the path line
38280 *     startAt: <number> time start of the path animation (in frames)
38281 *     duration: <number> path animation duration (in frames)
38282 *   },
38283 *   ...
38284 * ]
38285 * ```
38286 *
38287 */
38288Vivus.prototype.mapping = function () {
38289  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
38290  timePoint = totalLength = lengthMeter = 0;
38291  paths = this.el.querySelectorAll('path');
38292
38293  for (i = 0; i < paths.length; i++) {
38294    path = paths[i];
38295    if (this.isInvisible(path)) {
38296      continue;
38297    }
38298    pathObj = {
38299      el: path,
38300      length: Math.ceil(path.getTotalLength())
38301    };
38302    // Test if the path length is correct
38303    if (isNaN(pathObj.length)) {
38304      if (window.console && console.warn) {
38305        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
38306      }
38307      continue;
38308    }
38309    this.map.push(pathObj);
38310    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
38311    path.style.strokeDashoffset = pathObj.length + this.dashGap;
38312    pathObj.length += this.dashGap;
38313    totalLength += pathObj.length;
38314
38315    this.renderPath(i);
38316  }
38317
38318  totalLength = totalLength === 0 ? 1 : totalLength;
38319  this.delay = this.delay === null ? this.duration / 3 : this.delay;
38320  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
38321
38322  // Reverse stack if asked
38323  if (this.reverseStack) {
38324    this.map.reverse();
38325  }
38326
38327  for (i = 0; i < this.map.length; i++) {
38328    pathObj = this.map[i];
38329
38330    switch (this.type) {
38331    case 'delayed':
38332      pathObj.startAt = this.delayUnit * i;
38333      pathObj.duration = this.duration - this.delay;
38334      break;
38335
38336    case 'oneByOne':
38337      pathObj.startAt = lengthMeter / totalLength * this.duration;
38338      pathObj.duration = pathObj.length / totalLength * this.duration;
38339      break;
38340
38341    case 'sync':
38342    case 'async':
38343    case 'nsync':
38344      pathObj.startAt = 0;
38345      pathObj.duration = this.duration;
38346      break;
38347
38348    case 'scenario-sync':
38349      path = pathObj.el;
38350      pAttrs = this.parseAttr(path);
38351      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
38352      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38353      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
38354      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38355      break;
38356
38357    case 'scenario':
38358      path = pathObj.el;
38359      pAttrs = this.parseAttr(path);
38360      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
38361      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
38362      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
38363      break;
38364    }
38365    lengthMeter += pathObj.length;
38366    this.frameLength = this.frameLength || this.duration;
38367  }
38368};
38369
38370/**
38371 * Interval method to draw the SVG from current
38372 * position of the animation. It update the value of
38373 * `currentFrame` and re-trace the SVG.
38374 *
38375 * It use this.handle to store the requestAnimationFrame
38376 * and clear it one the animation is stopped. So this
38377 * attribute can be used to know if the animation is
38378 * playing.
38379 *
38380 * Once the animation at the end, this method will
38381 * trigger the Vivus callback.
38382 *
38383 */
38384Vivus.prototype.drawer = function () {
38385  var self = this;
38386  this.currentFrame += this.speed;
38387
38388  if (this.currentFrame <= 0) {
38389    this.stop();
38390    this.reset();
38391  } else if (this.currentFrame >= this.frameLength) {
38392    this.stop();
38393    this.currentFrame = this.frameLength;
38394    this.trace();
38395    if (this.selfDestroy) {
38396      this.destroy();
38397    }
38398  } else {
38399    this.trace();
38400    this.handle = requestAnimFrame(function () {
38401      self.drawer();
38402    });
38403    return;
38404  }
38405
38406  this.callback(this);
38407  if (this.instanceCallback) {
38408    this.instanceCallback(this);
38409    this.instanceCallback = null;
38410  }
38411};
38412
38413/**
38414 * Draw the SVG at the current instant from the
38415 * `currentFrame` value. Here is where most of the magic is.
38416 * The trick is to use the `strokeDashoffset` style property.
38417 *
38418 * For optimisation reasons, a new property called `progress`
38419 * is added in each item of `map`. This one contain the current
38420 * progress of the path element. Only if the new value is different
38421 * the new value will be applied to the DOM element. This
38422 * method save a lot of resources to re-render the SVG. And could
38423 * be improved if the animation couldn't be played forward.
38424 *
38425 */
38426Vivus.prototype.trace = function () {
38427  var i, progress, path, currentFrame;
38428  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
38429  for (i = 0; i < this.map.length; i++) {
38430    path = this.map[i];
38431    progress = (currentFrame - path.startAt) / path.duration;
38432    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
38433    if (path.progress !== progress) {
38434      path.progress = progress;
38435      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
38436      this.renderPath(i);
38437    }
38438  }
38439};
38440
38441/**
38442 * Method forcing the browser to re-render a path element
38443 * from it's index in the map. Depending on the `forceRender`
38444 * value.
38445 * The trick is to replace the path element by it's clone.
38446 * This practice is not recommended because it's asking more
38447 * ressources, too much DOM manupulation..
38448 * but it's the only way to let the magic happen on IE.
38449 * By default, this fallback is only applied on IE.
38450 *
38451 * @param  {Number} index Path index
38452 */
38453Vivus.prototype.renderPath = function (index) {
38454  if (this.forceRender && this.map && this.map[index]) {
38455    var pathObj = this.map[index],
38456        newPath = pathObj.el.cloneNode(true);
38457    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
38458    pathObj.el = newPath;
38459  }
38460};
38461
38462/**
38463 * When the SVG object is loaded and ready,
38464 * this method will continue the initialisation.
38465 *
38466 * This this mainly due to the case of passing an
38467 * object tag in the constructor. It will wait
38468 * the end of the loading to initialise.
38469 *
38470 */
38471Vivus.prototype.init = function () {
38472  // Set object variables
38473  this.frameLength = 0;
38474  this.currentFrame = 0;
38475  this.map = [];
38476
38477  // Start
38478  new Pathformer(this.el);
38479  this.mapping();
38480  this.starter();
38481
38482  if (this.onReady) {
38483    this.onReady(this);
38484  }
38485};
38486
38487/**
38488 * Trigger to start of the animation.
38489 * Depending on the `start` value, a different script
38490 * will be applied.
38491 *
38492 * If the `start` value is not valid, an error will be thrown.
38493 * Even if technically, this is impossible.
38494 *
38495 */
38496Vivus.prototype.starter = function () {
38497  switch (this.start) {
38498  case 'manual':
38499    return;
38500
38501  case 'autostart':
38502    this.play();
38503    break;
38504
38505  case 'inViewport':
38506    var self = this,
38507    listener = function () {
38508      if (self.isInViewport(self.parentEl, 1)) {
38509        self.play();
38510        window.removeEventListener('scroll', listener);
38511        //Uncode addition
38512        window.removeEventListener('fp-slide-changed', listener);
38513        window.removeEventListener('fp-slide-scroll', listener);
38514        //#END
38515      }
38516    };
38517    window.addEventListener('scroll', listener);
38518    //Uncode addition
38519    window.addEventListener('fp-slide-changed', listener);
38520    window.addEventListener('fp-slide-scroll', listener);
38521    //#END
38522    listener();
38523    break;
38524  }
38525};
38526
38527
38528/**
38529 * Controls
38530 **************************************
38531 */
38532
38533/**
38534 * Get the current status of the animation between
38535 * three different states: 'start', 'progress', 'end'.
38536 * @return {string} Instance status
38537 */
38538Vivus.prototype.getStatus = function () {
38539  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
38540};
38541
38542/**
38543 * Reset the instance to the initial state : undraw
38544 * Be careful, it just reset the animation, if you're
38545 * playing the animation, this won't stop it. But just
38546 * make it start from start.
38547 *
38548 */
38549Vivus.prototype.reset = function () {
38550  return this.setFrameProgress(0);
38551};
38552
38553/**
38554 * Set the instance to the final state : drawn
38555 * Be careful, it just set the animation, if you're
38556 * playing the animation on rewind, this won't stop it.
38557 * But just make it start from the end.
38558 *
38559 */
38560Vivus.prototype.finish = function () {
38561  return this.setFrameProgress(1);
38562};
38563
38564/**
38565 * Set the level of progress of the drawing.
38566 *
38567 * @param {number} progress Level of progress to set
38568 */
38569Vivus.prototype.setFrameProgress = function (progress) {
38570  progress = Math.min(1, Math.max(0, progress));
38571  this.currentFrame = Math.round(this.frameLength * progress);
38572  this.trace();
38573  return this;
38574};
38575
38576/**
38577 * Play the animation at the desired speed.
38578 * Speed must be a valid number (no zero).
38579 * By default, the speed value is 1.
38580 * But a negative value is accepted to go forward.
38581 *
38582 * And works with float too.
38583 * But don't forget we are in JavaScript, se be nice
38584 * with him and give him a 1/2^x value.
38585 *
38586 * @param  {number} speed Animation speed [optional]
38587 */
38588Vivus.prototype.play = function (speed, callback) {
38589  this.instanceCallback = null;
38590
38591  if (speed && typeof speed === 'function') {
38592    this.instanceCallback = speed; // first parameter is actually the callback function
38593    speed = null;
38594  }
38595  else if (speed && typeof speed !== 'number') {
38596    throw new Error('Vivus [play]: invalid speed');
38597  }
38598  // if the first parameter wasn't the callback, check if the seconds was
38599  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
38600    this.instanceCallback = callback;
38601  }
38602
38603
38604  this.speed = speed || 1;
38605  //Uncode addition
38606  if (!this.handle) {
38607    var $this = this,
38608    delay = (this.delayStart != null) ? this.delayStart : 0;
38609    setTimeout(function() {
38610      $this.drawer();
38611    }, delay);
38612  }
38613  //#END
38614  return this;
38615};
38616
38617/**
38618 * Stop the current animation, if on progress.
38619 * Should not trigger any error.
38620 *
38621 */
38622Vivus.prototype.stop = function () {
38623  if (this.handle) {
38624    cancelAnimFrame(this.handle);
38625    this.handle = null;
38626  }
38627  return this;
38628};
38629
38630/**
38631 * Destroy the instance.
38632 * Remove all bad styling attributes on all
38633 * path tags
38634 *
38635 */
38636Vivus.prototype.destroy = function () {
38637  this.stop();
38638  var i, path;
38639  for (i = 0; i < this.map.length; i++) {
38640    path = this.map[i];
38641    path.el.style.strokeDashoffset = null;
38642    path.el.style.strokeDasharray = null;
38643    this.renderPath(i);
38644  }
38645};
38646
38647
38648/**
38649 * Utils methods
38650 * include methods from Codrops
38651 **************************************
38652 */
38653
38654/**
38655 * Method to best guess if a path should added into
38656 * the animation or not.
38657 *
38658 * 1. Use the `data-vivus-ignore` attribute if set
38659 * 2. Check if the instance must ignore invisible paths
38660 * 3. Check if the path is visible
38661 *
38662 * For now the visibility checking is unstable.
38663 * It will be used for a beta phase.
38664 *
38665 * Other improvments are planned. Like detecting
38666 * is the path got a stroke or a valid opacity.
38667 */
38668Vivus.prototype.isInvisible = function (el) {
38669  var rect,
38670    ignoreAttr = el.getAttribute('data-ignore');
38671
38672  if (ignoreAttr !== null) {
38673    return ignoreAttr !== 'false';
38674  }
38675
38676  if (this.ignoreInvisible) {
38677    rect = el.getBoundingClientRect();
38678    return !rect.width && !rect.height;
38679  }
38680  else {
38681    return false;
38682  }
38683};
38684
38685/**
38686 * Parse attributes of a DOM element to
38687 * get an object of {attributeName => attributeValue}
38688 *
38689 * @param  {object} element DOM element to parse
38690 * @return {object}         Object of attributes
38691 */
38692Vivus.prototype.parseAttr = function (element) {
38693  var attr, output = {};
38694  if (element && element.attributes) {
38695    for (var i = 0; i < element.attributes.length; i++) {
38696      attr = element.attributes[i];
38697      output[attr.name] = attr.value;
38698    }
38699  }
38700  return output;
38701};
38702
38703/**
38704 * Reply if an element is in the page viewport
38705 *
38706 * @param  {object} el Element to observe
38707 * @param  {number} h  Percentage of height
38708 * @return {boolean}
38709 */
38710Vivus.prototype.isInViewport = function (el, h) {
38711  var scrolled   = this.scrollY(),
38712    viewed       = scrolled + this.getViewportH(),
38713    elBCR        = el.getBoundingClientRect(),
38714    elHeight     = elBCR.height,
38715    elTop        = scrolled + elBCR.top,
38716    elBottom     = elTop + elHeight;
38717
38718  // if 0, the element is considered in the viewport as soon as it enters.
38719  // if 1, the element is considered in the viewport only when it's fully inside
38720  // value in percentage (1 >= h >= 0)
38721  h = h || 0;
38722
38723  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
38724};
38725
38726
38727/**
38728 * Get the viewport height in pixels
38729 *
38730 * @return {integer} Viewport height
38731 */
38732Vivus.prototype.getViewportH = function () {
38733  var client = this.docElem.clientHeight,
38734    inner = window.innerHeight;
38735
38736  if (client < inner) {
38737    return inner;
38738  }
38739  else {
38740    return client;
38741  }
38742};
38743
38744/**
38745 * Get the page Y offset
38746 *
38747 * @return {integer} Page Y offset
38748 */
38749Vivus.prototype.scrollY = function () {
38750  return window.pageYOffset || this.docElem.scrollTop;
38751};
38752
38753setupEnv = function () {
38754
38755  if (Vivus.prototype.docElem) {
38756    return;
38757  }
38758
38759  /**
38760   * Alias for document element
38761   *
38762   * @type {DOMelement}
38763   */
38764  Vivus.prototype.docElem = window.document.documentElement;
38765
38766  /**
38767   * Alias for `requestAnimationFrame` or
38768   * `setTimeout` function for deprecated browsers.
38769   *
38770   */
38771  requestAnimFrame = (function () {
38772    return (
38773      window.requestAnimationFrame       ||
38774      window.webkitRequestAnimationFrame ||
38775      window.mozRequestAnimationFrame    ||
38776      window.oRequestAnimationFrame      ||
38777      window.msRequestAnimationFrame     ||
38778      function(/* function */ callback){
38779        return window.setTimeout(callback, 1000 / 60);
38780      }
38781    );
38782  })();
38783
38784  /**
38785   * Alias for `cancelAnimationFrame` or
38786   * `cancelTimeout` function for deprecated browsers.
38787   *
38788   */
38789  cancelAnimFrame = (function () {
38790    return (
38791      window.cancelAnimationFrame       ||
38792      window.webkitCancelAnimationFrame ||
38793      window.mozCancelAnimationFrame    ||
38794      window.oCancelAnimationFrame      ||
38795      window.msCancelAnimationFrame     ||
38796      function(id){
38797        return window.clearTimeout(id);
38798      }
38799    );
38800  })();
38801};
38802
38803/**
38804 * Parse string to integer.
38805 * If the number is not positive or null
38806 * the method will return the default value
38807 * or 0 if undefined
38808 *
38809 * @param {string} value String to parse
38810 * @param {*}
38810 defaultValue Value to return if the result parsed is invalid
38811 * @return {number}
38812 *
38813 */
38814parsePositiveInt = function (value, defaultValue) {
38815  var output = parseInt(value, 10);
38816  return (output >= 0) ? output : defaultValue;
38817};
38818
38819
38820  if (typeof define === 'function' && define.amd) {
38821    // AMD. Register as an anonymous module.
38822    define([], function() {
38823      return Vivus;
38824    });
38825  } else if (typeof exports === 'object') {
38826    // Node. Does not work with strict CommonJS, but
38827    // only CommonJS-like environments that support module.exports,
38828    // like Node.
38829    module.exports = Vivus;
38830  } else {
38831    // Browser globals
38832    window.Vivus = Vivus;
38833  }
38834
38835}());
38836
38837//Noise.js
38838!function(){"use strict";var r=.5*(Math.sqrt(3)-1),e=(3-Math.sqrt(3))/6,t=1/6,a=(Math.sqrt(5)-1)/4,o=(5-Math.sqrt(5))/20;function i(r){var e;e="function"==typeof r?r:r?function(){var r=0,e=0,t=0,a=1,o=(i=4022871197,function(r){r=r.toString();for(var e=0;e<r.length;e++){var t=.02519603282416938*(i+=r.charCodeAt(e));t-=i=t>>>0,i=(t*=i)>>>0,i+=4294967296*(t-=i)}return 2.3283064365386963e-10*(i>>>0)});var i;r=o(" "),e=o(" "),t=o(" ");for(var n=0;n<arguments.length;n++)(r-=o(arguments[n]))<0&&(r+=1),(e-=o(arguments[n]))<0&&(e+=1),(t-=o(arguments[n]))<0&&(t+=1);return o=null,function(){var o=2091639*r+2.3283064365386963e-10*a;return r=e,e=t,t=o-(a=0|o)}}(r):Math.random,this.p=n(e),this.perm=new Uint8Array(512),this.permMod12=new Uint8Array(512);for(var t=0;t<512;t++)this.perm[t]=this.p[255&t],this.permMod12[t]=this.perm[t]%12}function n(r){var e,t=new Uint8Array(256);for(e=0;e<256;e++)t[e]=e;for(e=0;e<255;e++){var a=e+~~(r()*(256-e)),o=t[e];t[e]=t[a],t[a]=o}return t}i.prototype={grad3:new Float32Array([1,1,0,-1,1,0,1,-1,0,-1,-1,0,1,0,1,-1,0,1,1,0,-1,-1,0,-1,0,1,1,0,-1,1,0,1,-1,0,-1,-1]),grad4:new Float32Array([0,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,1,0,1,1,1,0,1,-1,1,0,-1,1,1,0,-1,-1,-1,0,1,1,-1,0,1,-1,-1,0,-1,1,-1,0,-1,-1,1,1,0,1,1,1,0,-1,1,-1,0,1,1,-1,0,-1,-1,1,0,1,-1,1,0,-1,-1,-1,0,1,-1,-1,0,-1,1,1,1,0,1,1,-1,0,1,-1,1,0,1,-1,-1,0,-1,1,1,0,-1,1,-1,0,-1,-1,1,0,-1,-1,-1,0]),noise2D:function(t,a){var o,i,n=this.permMod12,f=this.perm,s=this.grad3,v=0,h=0,l=0,u=(t+a)*r,d=Math.floor(t+u),p=Math.floor(a+u),M=(d+p)*e,m=t-(d-M),c=a-(p-M);m>c?(o=1,i=0):(o=0,i=1);var y=m-o+e,w=c-i+e,g=m-1+2*e,A=c-1+2*e,x=255&d,q=255&p,D=.5-m*m-c*c;if(D>=0){var S=3*n[x+f[q]];v=(D*=D)*D*(s[S]*m+s[S+1]*c)}var U=.5-y*y-w*w;if(U>=0){var b=3*n[x+o+f[q+i]];h=(U*=U)*U*(s[b]*y+s[b+1]*w)}var F=.5-g*g-A*A;if(F>=0){var N=3*n[x+1+f[q+1]];l=(F*=F)*F*(s[N]*g+s[N+1]*A)}return 70*(v+h+l)},noise3D:function(r,e,a){var o,i,n,f,s,v,h,l,u,d,p=this.permMod12,M=this.perm,m=this.grad3,c=(r+e+a)*(1/3),y=Math.floor(r+c),w=Math.floor(e+c),g=Math.floor(a+c),A=(y+w+g)*t,x=r-(y-A),q=e-(w-A),D=a-(g-A);x>=q?q>=D?(s=1,v=0,h=0,l=1,u=1,d=0):x>=D?(s=1,v=0,h=0,l=1,u=0,d=1):(s=0,v=0,h=1,l=1,u=0,d=1):q<D?(s=0,v=0,h=1,l=0,u=1,d=1):x<D?(s=0,v=1,h=0,l=0,u=1,d=1):(s=0,v=1,h=0,l=1,u=1,d=0);var S=x-s+t,U=q-v+t,b=D-h+t,F=x-l+2*t,N=q-u+2*t,C=D-d+2*t,P=x-1+.5,T=q-1+.5,_=D-1+.5,j=255&y,k=255&w,z=255&g,B=.6-x*x-q*q-D*D;if(B<0)o=0;else{var E=3*p[j+M[k+M[z]]];o=(B*=B)*B*(m[E]*x+m[E+1]*q+m[E+2]*D)}var G=.6-S*S-U*U-b*b;if(G<0)i=0;else{var H=3*p[j+s+M[k+v+M[z+h]]];i=(G*=G)*G*(m[H]*S+m[H+1]*U+m[H+2]*b)}var I=.6-F*F-N*N-C*C;if(I<0)n=0;else{var J=3*p[j+l+M[k+u+M[z+d]]];n=(I*=I)*I*(m[J]*F+m[J+1]*N+m[J+2]*C)}var K=.6-P*P-T*T-_*_;if(K<0)f=0;else{var L=3*p[j+1+M[k+1+M[z+1]]];f=(K*=K)*K*(m[L]*P+m[L+1]*T+m[L+2]*_)}return 32*(o+i+n+f)},noise4D:function(r,e,t,i){var n,f,s,v,h,l,u,d,p,M,m,c,y,w,g,A,x,q=this.perm,D=this.grad4,S=(r+e+t+i)*a,U=Math.floor(r+S),b=Math.floor(e+S),F=Math.floor(t+S),N=Math.floor(i+S),C=(U+b+F+N)*o,P=r-(U-C),T=e-(b-C),_=t-(F-C),j=i-(N-C),k=0,z=0,B=0,E=0;P>T?k++:z++,P>_?k++:B++,P>j?k++:E++,T>_?z++:B++,T>j?z++:E++,_>j?B++:E++;var G=P-(l=k>=3?1:0)+o,H=T-(u=z>=3?1:0)+o,I=_-(d=B>=3?1:0)+o,J=j-(p=E>=3?1:0)+o,K=P-(M=k>=2?1:0)+2*o,L=T-(m=z>=2?1:0)+2*o,O=_-(c=B>=2?1:0)+2*o,Q=j-(y=E>=2?1:0)+2*o,R=P-(w=k>=1?1:0)+3*o,V=T-(g=z>=1?1:0)+3*o,W=_-(A=B>=1?1:0)+3*o,X=j-(x=E>=1?1:0)+3*o,Y=P-1+4*o,Z=T-1+4*o,$=_-1+4*o,rr=j-1+4*o,er=255&U,tr=255&b,ar=255&F,or=255&N,ir=.6-P*P-T*T-_*_-j*j;if(ir<0)n=0;else{var nr=q[er+q[tr+q[ar+q[or]]]]%32*4;n=(ir*=ir)*ir*(D[nr]*P+D[nr+1]*T+D[nr+2]*_+D[nr+3]*j)}var fr=.6-G*G-H*H-I*I-J*J;if(fr<0)f=0;else{var sr=q[er+l+q[tr+u+q[ar+d+q[or+p]]]]%32*4;f=(fr*=fr)*fr*(D[sr]*G+D[sr+1]*H+D[sr+2]*I+D[sr+3]*J)}var vr=.6-K*K-L*L-O*O-Q*Q;if(vr<0)s=0;else{var hr=q[er+M+q[tr+m+q[ar+c+q[or+y]]]]%32*4;s=(vr*=vr)*vr*(D[hr]*K+D[hr+1]*L+D[hr+2]*O+D[hr+3]*Q)}
38838var lr=.6-R*R-V*V-W*W-X*X;if(lr<0)v=0;else{var ur=q[er+w+q[tr+g+q[ar+A+q[or+x]]]]%32*4;v=(lr*=lr)*lr*(D[ur]*R+D[ur+1]*V+D[ur+2]*W+D[ur+3]*X)}var dr=.6-Y*Y-Z*Z-$*$-rr*rr;if(dr<0)h=0;else{var pr=q[er+1+q[tr+1+q[ar+1+q[or+1]]]]%32*4;h=(dr*=dr)*dr*(D[pr]*Y+D[pr+1]*Z+D[pr+2]*$+D[pr+3]*rr)}return 27*(n+f+s+v+h)}},i._buildPermutationTable=n,"undefined"!=typeof define&&define.amd&&define(function(){return i}),"undefined"!=typeof exports?exports.SimplexNoise=i:"undefined"!=typeof window&&(window.SimplexNoise=i),"undefined"!=typeof module&&(module.exports=i)}();

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.