vendor: 4,719 bytes, lines 1-147
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.6.1 27 * https://greensock.com 28 * 29 * @license Copyright 2008-2021, 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 _bigNum = 1e8, 49 _tinyNum = 1 / _bigNum, 50 _2PI = Math.PI * 2, 51 _HALF_PI = _2PI / 4, 52 _gsID = 0, 53 _sqrt = Math.sqrt, 54 _cos = Math.cos, 55 _sin = Math.sin, 56 _isString = function _isString(value) { 57 return typeof value === "string"; 58 }, 59 _isFunction = function _isFunction(value) { 60 return typeof value === "function"; 61 }, 62 _isNumber = function _isNumber(value) { 63 return typeof value === "number"; 64 }, 65 _isUndefined = function _isUndefined(value) { 66 return typeof value === "undefined"; 67 }, 68 _isObject = function _isObject(value) { 69 return typeof value === "object"; 70 }, 71 _isNotFalse = function _isNotFalse(value) { 72 return value !== false; 73 }, 74 _windowExists = function _windowExists() { 75 return typeof window !== "undefined"; 76 }, 77 _isFuncOrString = function _isFuncOrString(value) { 78 return _isFunction(value) || _isString(value); 79 }, 80 _isTypedArray = typeof ArrayBuffer === "function" && ArrayBuffer.isView || function () {}, 81 _isArray = Array.isArray, 82 _strictNumExp = /(?:-?\.?\d|\.)+/gi, 83 _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/g, 84 _numWithUnitExp = /[-+=.]*\d+[.e-]*\d*[a-z%]*/g, 85 _complexStringNumExp = /[-+=.]*\d+\.?\d*(?:e-|e\+)?\d*/gi, 86 _relExp = /[+-]=-?[.\d]+/, 87 _delimitedValueExp = /[#\-+.]*\b[a-z\d-=+%.]+/gi, 88 _unitExp = /[\d.+\-=]+(?:e[-+]\d*)*/i, 89 _globalTimeline, 90 _win, 91 _coreInitted, 92 _doc, 93 _globals = {}, 94 _installScope = {}, 95 _coreReady, 96 _install = function _install(scope) { 97 return (_installScope = _merge(scope, _globals)) && gsap; 98 }, 99 _missingPlugin = function _missingPlugin(property, value) { 100 return console.warn("Invalid property", property, "set to", value, "Missing plugin? gsap.registerPlugin()"); 101 }, 102 _warn = function _warn(message, suppress) { 103 return !suppress && console.warn(message); 104 }, 105 _addGlobal = function _addGlobal(name, obj) { 106 return name && (_globals[name] = obj) && _installScope && (_installScope[name] = obj) || _globals; 107 }, 108 _emptyFunc = function _emptyFunc() { 109 return 0; 110 }, 111 _reservedProps = {}, 112 _lazyTweens = [], 113 _lazyLookup = {}, 114 _lastRenderedFrame, 115 _plugins = {}, 116 _effects = {}, 117 _nextGCFrame = 30, 118 _harnessPlugins = [], 119 _callbackNames = "", 120 _harness = function _harness(targets) { 121 var target = targets[0], 122 harnessPlugin, 123 i; 124 _isObject(target) || _isFunction(target) || (targets = [targets]); 125 126 if (!(harnessPlugin = (target._gsap || {}).harness)) { 127 i = _harnessPlugins.length; 128 129 while (i-- && !_harnessPlugins[i].targetTest(target)) {} 130 131 harnessPlugin = _harnessPlugins[i]; 132 } 133 134 i = targets.length; 135 136 while (i--) { 137 targets[i] && (targets[i]._gsap || (targets[i]._gsap = new GSCache(targets[i], harnessPlugin))) || targets.splice(i, 1); 138 } 139 140 return targets; 141 }, 142 _getCache = function _getCache(target) { 143 return target._gsap || _harness(toArray(target))[0]._gsap; 144 }, 145 _getProperty = function _getProperty(target, property, v) { 146 return (v = target[property]) && _isFunction(v) ? target[property]() : _isUndefined(v) && target.getAttribute && target.getAttribute(property) || v; 147 },
vendor: 7,717 bytes, lines 148-411
148 _forEachName = function _forEachName(names, func) { 149 return (names = names.split(",")).forEach(func) || names; 150 }, 151 _round = function _round(value) { 152 return Math.round(value * 100000) / 100000 || 0; 153 }, 154 _arrayContainsAny = function _arrayContainsAny(toSearch, toFind) { 155 var l = toFind.length, 156 i = 0; 157 158 for (; toSearch.indexOf(toFind[i]) < 0 && ++i < l;) {} 159 160 return i < l; 161 }, 162 _parseVars = function _parseVars(params, type, parent) { 163 var isLegacy = _isNumber(params[1]), 164 varsIndex = (isLegacy ? 2 : 1) + (type < 2 ? 0 : 1), 165 vars = params[varsIndex], 166 irVars; 167 168 isLegacy && (vars.duration = params[1]); 169 vars.parent = parent; 170 171 if (type) { 172 irVars = vars; 173 174 while (parent && !("immediateRender" in irVars)) { 175 irVars = parent.vars.defaults || {}; 176 parent = _isNotFalse(parent.vars.inherit) && parent.parent; 177 } 178 179 vars.immediateRender = _isNotFalse(irVars.immediateRender); 180 type < 2 ? vars.runBackwards = 1 : vars.startAt = params[varsIndex - 1]; 181 } 182 183 return vars; 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); 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(obj, defaults) { 219 for (var p in defaults) { 220 p in obj || p === "duration" || p === "ease" || (obj[p] = defaults[p]); 221 } 222 }, 223 _merge = function _merge(base, toMerge) { 224 for (var p in toMerge) { 225 base[p] = toMerge[p]; 226 } 227 228 return base; 229 }, 230 _mergeDeep = function _mergeDeep(base, toMerge) { 231 for (var p in toMerge) { 232 p !== "__proto__" && p !== "constructor" && p !== "prototype" && (base[p] = _isObject(toMerge[p]) ? _mergeDeep(base[p] || (base[p] = {}), toMerge[p]) : toMerge[p]); 233 } 234 235 return base; 236 }, 237 _copyExcluding = function _copyExcluding(obj, excluding) { 238 var copy = {}, 239 p; 240 241 for (p in obj) { 242 p in excluding || (copy[p] = obj[p]); 243 } 244 245 return copy; 246 }, 247 _inheritDefaults = function _inheritDefaults(vars) { 248 var parent = vars.parent || _globalTimeline, 249 func = vars.keyframes ? _setKeyframeDefaults : _setDefaults; 250 251 if (_isNotFalse(vars.inherit)) { 252 while (parent) { 253 func(vars, parent.vars.defaults); 254 parent = parent.parent || parent._dp; 255 } 256 } 257 258 return vars; 259 }, 260 _arraysMatch = function _arraysMatch(a1, a2) { 261 var i = a1.length, 262 match = i === a2.length; 263 264 while (match && i-- && a1[i] === a2[i]) {} 265 266 return i < 0; 267 }, 268 _addLinkedListItem = function _addLinkedListItem(parent, child, firstProp, lastProp, sortBy) { 269 if (firstProp === void 0) { 270 firstProp = "_first"; 271 } 272 273 if (lastProp === void 0) { 274 lastProp = "_last"; 275 } 276 277 var prev = parent[lastProp], 278 t; 279 280 if (sortBy) { 281 t = child[sortBy]; 282 283 while (prev && prev[sortBy] > t) { 284 prev = prev._prev; 285 } 286 } 287 288 if (prev) { 289 child._next = prev._next; 290 prev._next = child; 291 } else { 292 child._next = parent[firstProp]; 293 parent[firstProp] = child; 294 } 295 296 if (child._next) { 297 child._next._prev = child; 298 } else { 299 parent[lastProp] = child; 300 } 301 302 child._prev = prev; 303 child.parent = child._dp = parent; 304 return child; 305 }, 306 _removeLinkedListItem = function _removeLinkedListItem(parent, child, firstProp, lastProp) { 307 if (firstProp === void 0) { 308 firstProp = "_first"; 309 } 310 311 if (lastProp === void 0) { 312 lastProp = "_last"; 313 } 314 315 var prev = child._prev, 316 next = child._next; 317 318 if (prev) { 319 prev._next = next; 320 } else if (parent[firstProp] === child) { 321 parent[firstProp] = next; 322 } 323 324 if (next) { 325 next._prev = prev; 326 } else if (parent[lastProp] === child) { 327 parent[lastProp] = prev; 328 } 329 330 child._next = child._prev = child.parent = null; 331 }, 332 _removeFromParent = function _removeFromParent(child, onlyIfParentHasAutoRemove) { 333 child.parent && (!onlyIfParentHasAutoRemove || child.parent.autoRemoveChildren) && child.parent.remove(child); 334 child._act = 0; 335 }, 336 _uncache = function _uncache(animation, child) { 337 if (animation && (!child || child._end > animation._dur || child._start < 0)) { 338 var a = animation; 339 340 while (a) { 341 a._dirty = 1; 342 a = a.parent; 343 } 344 } 345 346 return animation; 347 }, 348 _recacheAncestors = function _recacheAncestors(animation) { 349 var parent = animation.parent; 350 351 while (parent && parent.parent) { 352 parent._dirty = 1; 353 parent.totalDuration(); 354 parent = parent.parent; 355 } 356 357 return animation; 358 }, 359 _hasNoPausedAncestors = function _hasNoPausedAncestors(animation) { 360 return !animation || animation._ts && _hasNoPausedAncestors(animation.parent); 361 }, 362 _elapsedCycleDuration = function _elapsedCycleDuration(animation) { 363 return animation._repeat ? _animationCycle(animation._tTime, animation = animation.duration() + animation._rDelay) * animation : 0; 364 }, 365 _animationCycle = function _animationCycle(tTime, cycleDuration) { 366 var whole = Math.floor(tTime /= cycleDuration); 367 return tTime && whole === tTime ? whole - 1 : whole; 368 }, 369 _parentToChildTotalTime = function _parentToChildTotalTime(parentTime, child) { 370 return (parentTime - child._start) * child._ts + (child._ts >= 0 ? 0 : child._dirty ? child.totalDuration() : child._tDur); 371 }, 372 _setEnd = function _setEnd(animation) { 373 return animation._end = _round(animation._start + (animation._tDur / Math.abs(animation._ts || animation._rts || _tinyNum) || 0)); 374 }, 375 _alignPlayhead = function _alignPlayhead(animation, totalTime) { 376 var parent = animation._dp; 377 378 if (parent && parent.smoothChildTiming && animation._ts) { 379 animation._start = _round(parent._time - (animation._ts > 0 ? totalTime / animation._ts : ((animation._dirty ? animation.totalDuration() : animation._tDur) - totalTime) / -animation._ts)); 380 381 _setEnd(animation); 382 383 parent._dirty || _uncache(parent, animation); 384 } 385 386 return animation; 387 }, 388 _postAddChecks = function _postAddChecks(timeline, child) { 389 var t; 390 391 if (child._time || child._initted && !child._dur) { 392 t = _parentToChildTotalTime(timeline.rawTime(), child); 393 394 if (!child._dur || _clamp(0, child.totalDuration(), t) - child._tTime > _tinyNum) { 395 child.render(t, true); 396 } 397 } 398 399 if (_uncache(timeline, child)._dp && timeline._initted && timeline._time >= timeline._dur && timeline._ts) { 400 if (timeline._dur < timeline.duration()) { 401 t = timeline; 402 403 while (t._dp) { 404 t.rawTime() >= 0 && t.totalTime(t._tTime); 405 t = t._dp; 406 } 407 } 408 409 timeline._zTime = -_tinyNum; 410 } 411 },
412 _addToTimeline = function _addToTimeline(timeline, child, position, skipChecks) { 413 child.parent && _removeFromParent(child); 414 child._start = _round(position + child._delay); 415 child._end = _round(child._start + (child.totalDuration() / Math.abs(child.timeScale()) || 0)); 416 417 _addLinkedListItem(timeline, child, "_first", "_last", timeline._sort ? "_start" : 0); 418 419 timeline._recent = child; 420 skipChecks || _postAddChecks(timeline, child); 421 return timeline; 422 }, 423 _scrollTrigger = function _scrollTrigger(animation, trigger) { 424 return (_globals.ScrollTrigger || _missingPlugin("scrollTrigger", trigger)) && _globals.ScrollTrigger.create(trigger, animation); 425 }, 426 _attemptInitTween = function _attemptInitTween(tween, totalTime, force, suppressEvents) { 427 _initTween(tween, totalTime); 428 429 if (!tween._initted) { 430 return 1; 431 } 432 433 if (!force && tween._pt && (tween._dur && tween.vars.lazy !== false || !tween._dur && tween.vars.lazy) && _lastRenderedFrame !== _ticker.frame) { 434 _lazyTweens.push(tween); 435 436 tween._lazy = [totalTime, suppressEvents]; 437 return 1; 438 } 439 }, 440 _parentPlayheadIsBeforeStart = function _parentPlayheadIsBeforeStart(_ref) { 441 var parent = _ref.parent; 442 return parent && parent._ts && parent._initted && !parent._lock && (parent.rawTime() < 0 || _parentPlayheadIsBeforeStart(parent)); 443 }, 444 _renderZeroDurationTween = function _renderZeroDurationTween(tween, totalTime, suppressEvents, force) { 445 var prevRatio = tween.ratio, 446 ratio = totalTime < 0 || !totalTime && (!tween._start && _parentPlayheadIsBeforeStart(tween) || (tween._ts < 0 || tween._dp._ts < 0) && tween.data !== "isFromStart" && tween.data !== "isStart") ? 0 : 1, 447 repeatDelay = tween._rDelay, 448 tTime = 0, 449 pt, 450 iteration, 451 prevIteration; 452 453 if (repeatDelay && tween._repeat) { 454 tTime = _clamp(0, tween._tDur, totalTime); 455 iteration = _animationCycle(tTime, repeatDelay); 456 prevIteration = _animationCycle(tween._tTime, repeatDelay); 457 tween._yoyo && iteration & 1 && (ratio = 1 - ratio); 458 459 if (iteration !== prevIteration) { 460 prevRatio = 1 - ratio; 461 tween.vars.repeatRefresh && tween._initted && tween.invalidate(); 462 } 463 } 464 465 if (ratio !== prevRatio || force || tween._zTime === _tinyNum || !totalTime && tween._zTime) { 466 if (!tween._initted && _attemptInitTween(tween, totalTime, force, suppressEvents)) { 467 return; 468 } 469 470 prevIteration = tween._zTime; 471 tween._zTime = totalTime || (suppressEvents ? _tinyNum : 0); 472 suppressEvents || (suppressEvents = totalTime && !prevIteration); 473 tween.ratio = ratio; 474 tween._from && (ratio = 1 - ratio); 475 tween._time = 0; 476 tween._tTime = tTime; 477 pt = tween._pt; 478 479 while (pt) { 480 pt.r(ratio, pt.d); 481 pt = pt._next; 482 } 483 484 tween._startAt && totalTime < 0 && tween._startAt.render(totalTime, true, true);
vendor: 9,020 bytes, lines 485-753
485 tween._onUpdate && !suppressEvents && _callback(tween, "onUpdate"); 486 tTime && tween._repeat && !suppressEvents && tween.parent && _callback(tween, "onRepeat"); 487 488 if ((totalTime >= tween._tDur || totalTime < 0) && tween.ratio === ratio) { 489 ratio && _removeFromParent(tween, 1); 490 491 if (!suppressEvents) { 492 _callback(tween, ratio ? "onComplete" : "onReverseComplete", true); 493 494 tween._prom && tween._prom(); 495 } 496 } 497 } else if (!tween._zTime) { 498 tween._zTime = totalTime; 499 } 500 }, 501 _findNextPauseTween = function _findNextPauseTween(animation, prevTime, time) { 502 var child; 503 504 if (time > prevTime) { 505 child = animation._first; 506 507 while (child && child._start <= time) { 508 if (!child._dur && child.data === "isPause" && child._start > prevTime) { 509 return child; 510 } 511 512 child = child._next; 513 } 514 } else { 515 child = animation._last; 516 517 while (child && child._start >= time) { 518 if (!child._dur && child.data === "isPause" && child._start < prevTime) { 519 return child; 520 } 521 522 child = child._prev; 523 } 524 } 525 }, 526 _setDuration = function _setDuration(animation, duration, skipUncache, leavePlayhead) { 527 var repeat = animation._repeat, 528 dur = _round(duration) || 0, 529 totalProgress = animation._tTime / animation._tDur; 530 totalProgress && !leavePlayhead && (animation._time *= dur / animation._dur); 531 animation._dur = dur; 532 animation._tDur = !repeat ? dur : repeat < 0 ? 1e10 : _round(dur * (repeat + 1) + animation._rDelay * repeat); 533 totalProgress && !leavePlayhead ? _alignPlayhead(animation, animation._tTime = animation._tDur * totalProgress) : animation.parent && _setEnd(animation); 534 skipUncache || _uncache(animation.parent, animation); 535 return animation; 536 }, 537 _onUpdateTotalDuration = function _onUpdateTotalDuration(animation) { 538 return animation instanceof Timeline ? _uncache(animation) : _setDuration(animation, animation._dur); 539 }, 540 _zeroPosition = { 541 _start: 0, 542 endTime: _emptyFunc 543 }, 544 _parsePosition = function _parsePosition(animation, position) { 545 var labels = animation.labels, 546 recent = animation._recent || _zeroPosition, 547 clippedDuration = animation.duration() >= _bigNum ? recent.endTime(false) : animation._dur, 548 i, 549 offset; 550 551 if (_isString(position) && (isNaN(position) || position in labels)) { 552 i = position.charAt(0); 553 554 if (i === "<" || i === ">") { 555 return (i === "<" ? recent._start : recent.endTime(recent._repeat >= 0)) + (parseFloat(position.substr(1)) || 0); 556 } 557 558 i = position.indexOf("="); 559 560 if (i < 0) { 561 position in labels || (labels[position] = clippedDuration); 562 return labels[position]; 563 } 564 565 offset = +(position.charAt(i - 1) + position.substr(i + 1)); 566 return i > 1 ? _parsePosition(animation, position.substr(0, i - 1)) + offset : clippedDuration + offset; 567 } 568 569 return position == null ? clippedDuration : +position; 570 }, 571 _conditionalReturn = function _conditionalReturn(value, func) { 572 return value || value === 0 ? func(value) : func; 573 }, 574 _clamp = function _clamp(min, max, value) { 575 return value < min ? min : value > max ? max : value; 576 }, 577 getUnit = function getUnit(value) { 578 if (typeof value !== "string") { 579 return ""; 580 } 581 582 var v = _unitExp.exec(value); 583 584 return v ? value.substr(v.index + v[0].length) : ""; 585 }, 586 clamp = function clamp(min, max, value) { 587 return _conditionalReturn(value, function (v) { 588 return _clamp(min, max, v); 589 }); 590 }, 591 _slice = [].slice, 592 _isArrayLike = function _isArrayLike(value, nonEmpty) { 593 return value && _isObject(value) && "length" in value && (!nonEmpty && !value.length || value.length - 1 in value && _isObject(value[0])) && !value.nodeType && value !== _win; 594 }, 595 _flatten = function _flatten(ar, leaveStrings, accumulator) { 596 if (accumulator === void 0) { 597 accumulator = []; 598 } 599 600 return ar.forEach(function (value) { 601 var _accumulator; 602 603 return _isString(value) && !leaveStrings || _isArrayLike(value, 1) ? (_accumulator = accumulator).push.apply(_accumulator, toArray(value)) : accumulator.push(value); 604 }) || accumulator; 605 }, 606 toArray = function toArray(value, leaveStrings) { 607 return _isString(value) && !leaveStrings && (_coreInitted || !_wake()) ? _slice.call(_doc.querySelectorAll(value), 0) : _isArray(value) ? _flatten(value, leaveStrings) : _isArrayLike(value) ? _slice.call(value, 0) : value ? [value] : []; 608 }, 609 shuffle = function shuffle(a) { 610 return a.sort(function () { 611 return .5 - Math.random(); 612 }); 613 }, 614 distribute = function distribute(v) { 615 if (_isFunction(v)) { 616 return v; 617 } 618 619 var vars = _isObject(v) ? v : { 620 each: v 621 }, 622 ease = _parseEase(vars.ease), 623 from = vars.from || 0, 624 base = parseFloat(vars.base) || 0, 625 cache = {}, 626 isDecimal = from > 0 && from < 1, 627 ratios = isNaN(from) || isDecimal, 628 axis = vars.axis, 629 ratioX = from, 630 ratioY = from; 631 632 if (_isString(from)) { 633 ratioX = ratioY = { 634 center: .5, 635 edges: .5, 636 end: 1 637 }[from] || 0; 638 } else if (!isDecimal && ratios) { 639 ratioX = from[0]; 640 ratioY = from[1]; 641 } 642 643 return function (i, target, a) { 644 var l = (a || vars).length, 645 distances = cache[l], 646 originX, 647 originY, 648 x, 649 y, 650 d, 651 j, 652 max, 653 min, 654 wrapAt; 655 656 if (!distances) { 657 wrapAt = vars.grid === "auto" ? 0 : (vars.grid || [1, _bigNum])[1]; 658 659 if (!wrapAt) { 660 max = -_bigNum; 661 662 while (max < (max = a[wrapAt++].getBoundingClientRect().left) && wrapAt < l) {} 663 664 wrapAt--; 665 } 666 667 distances = cache[l] = []; 668 originX = ratios ? Math.min(wrapAt, l) * ratioX - .5 : from % wrapAt; 669 originY = ratios ? l * ratioY / wrapAt - .5 : from / wrapAt | 0; 670 max = 0; 671 min = _bigNum; 672 673 for (j = 0; j < l; j++) { 674 x = j % wrapAt - originX; 675 y = originY - (j / wrapAt | 0); 676 distances[j] = d = !axis ? _sqrt(x * x + y * y) : Math.abs(axis === "y" ? y : x); 677 d > max && (max = d); 678 d < min && (min = d); 679 } 680 681 from === "random" && shuffle(distances); 682 distances.max = max - min; 683 distances.min = min; 684 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); 685 distances.b = l < 0 ? base - l : base; 686 distances.u = getUnit(vars.amount || vars.each) || 0; 687 ease = ease && l < 0 ? _invertEase(ease) : ease; 688 } 689 690 l = (distances[i] - distances.min) / distances.max || 0; 691 return _round(distances.b + (ease ? ease(l) : l) * distances.v) + distances.u; 692 }; 693 }, 694 _roundModifier = function _roundModifier(v) { 695 var p = v < 1 ? Math.pow(10, (v + "").length - 2) : 1; 696 return function (raw) { 697 var n = Math.round(parseFloat(raw) / v) * v * p; 698 return (n - n % 1) / p + (_isNumber(raw) ? 0 : getUnit(raw)); 699 }; 700 }, 701 snap = function snap(snapTo, value) { 702 var isArray = _isArray(snapTo), 703 radius, 704 is2D; 705 706 if (!isArray && _isObject(snapTo)) { 707 radius = isArray = snapTo.radius || _bigNum; 708 709 if (snapTo.values) { 710 snapTo = toArray(snapTo.values); 711 712 if (is2D = !_isNumber(snapTo[0])) { 713 radius *= radius; 714 } 715 } else { 716 snapTo = _roundModifier(snapTo.increment); 717 } 718 } 719 720 return _conditionalReturn(value, !isArray ? _roundModifier(snapTo) : _isFunction(snapTo) ? function (raw) { 721 is2D = snapTo(raw); 722 return Math.abs(is2D - raw) <= radius ? is2D : raw; 723 } : function (raw) { 724 var x = parseFloat(is2D ? raw.x : raw), 725 y = parseFloat(is2D ? raw.y : 0), 726 min = _bigNum, 727 closest = 0, 728 i = snapTo.length, 729 dx, 730 dy; 731 732 while (i--) { 733 if (is2D) { 734 dx = snapTo[i].x - x; 735 dy = snapTo[i].y - y; 736 dx = dx * dx + dy * dy; 737 } else { 738 dx = Math.abs(snapTo[i] - x); 739 } 740 741 if (dx < min) { 742 min = dx; 743 closest = i; 744 } 745 } 746 747 closest = !radius || min <= radius ? snapTo[closest] : raw; 748 return is2D || closest === raw || _isNumber(raw) ? closest : closest + getUnit(raw); 749 }); 750 }, 751 random = function random(min, max, roundingIncrement, returnFunction) { 752 return _conditionalReturn(_isArray(min) ? !max : roundingIncrement === true ? !!(roundingIncrement = 0) : !returnFunction, function () { 753 return _isArray(min) ? min[~~(Math.random() * min.length)] : (roundingIncrement = roundingIncrement || 1e
vendor: 4,723 bytes, lines 753-909
753-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; 754 }); 755 }, 756 pipe = function pipe() { 757 for (var _len = arguments.length, functions = new Array(_len), _key = 0; _key < _len; _key++) { 758 functions[_key] = arguments[_key]; 759 } 760 761 return function (value) { 762 return functions.reduce(function (v, f) { 763 return f(v); 764 }, value); 765 }; 766 }, 767 unitize = function unitize(func, unit) { 768 return function (value) { 769 return func(parseFloat(value)) + (unit || getUnit(value)); 770 }; 771 }, 772 normalize = function normalize(min, max, value) { 773 return mapRange(min, max, 0, 1, value); 774 }, 775 _wrapArray = function _wrapArray(a, wrapper, value) { 776 return _conditionalReturn(value, function (index) { 777 return a[~~wrapper(index)]; 778 }); 779 }, 780 wrap = function wrap(min, max, value) { 781 var range = max - min; 782 return _isArray(min) ? _wrapArray(min, wrap(0, min.length), max) : _conditionalReturn(value, function (value) { 783 return (range + (value - min) % range) % range + min; 784 }); 785 }, 786 wrapYoyo = function wrapYoyo(min, max, value) { 787 var range = max - min, 788 total = range * 2; 789 return _isArray(min) ? _wrapArray(min, wrapYoyo(0, min.length - 1), max) : _conditionalReturn(value, function (value) { 790 value = (total + (value - min) % total) % total || 0; 791 return min + (value > range ? total - value : value); 792 }); 793 }, 794 _replaceRandom = function _replaceRandom(value) { 795 var prev = 0, 796 s = "", 797 i, 798 nums, 799 end, 800 isArray; 801 802 while (~(i = value.indexOf("random(", prev))) { 803 end = value.indexOf(")", i); 804 isArray = value.charAt(i + 7) === "["; 805 nums = value.substr(i + 7, end - i - 7).match(isArray ? _delimitedValueExp : _strictNumExp); 806 s += value.substr(prev, i - prev) + random(isArray ? nums : +nums[0], isArray ? 0 : +nums[1], +nums[2] || 1e-5); 807 prev = end + 1; 808 } 809 810 return s + value.substr(prev, value.length - prev); 811 }, 812 mapRange = function mapRange(inMin, inMax, outMin, outMax, value) { 813 var inRange = inMax - inMin, 814 outRange = outMax - outMin; 815 return _conditionalReturn(value, function (value) { 816 return outMin + ((value - inMin) / inRange * outRange || 0); 817 }); 818 }, 819 interpolate = function interpolate(start, end, progress, mutate) { 820 var func = isNaN(start + end) ? 0 : function (p) { 821 return (1 - p) * start + p * end; 822 }; 823 824 if (!func) { 825 var isString = _isString(start), 826 master = {}, 827 p, 828 i, 829 interpolators, 830 l, 831 il; 832 833 progress === true && (mutate = 1) && (progress = null); 834 835 if (isString) { 836 start = { 837 p: start 838 }; 839 end = { 840 p: end 841 }; 842 } else if (_isArray(start) && !_isArray(end)) { 843 interpolators = []; 844 l = start.length; 845 il = l - 2; 846 847 for (i = 1; i < l; i++) { 848 interpolators.push(interpolate(start[i - 1], start[i])); 849 } 850 851 l--; 852 853 func = function func(p) { 854 p *= l; 855 var i = Math.min(il, ~~p); 856 return interpolators[i](p - i); 857 }; 858 859 progress = end; 860 } else if (!mutate) { 861 start = _merge(_isArray(start) ? [] : {}, start); 862 } 863 864 if (!interpolators) { 865 for (p in end) { 866 _addPropTween.call(master, start, p, "get", end[p]); 867 } 868 869 func = function func(p) { 870 return _renderPropTweens(p, master) || (isString ? start.p : start); 871 }; 872 } 873 } 874 875 return _conditionalReturn(progress, func); 876 }, 877 _getLabelInDirection = function _getLabelInDirection(timeline, fromTime, backward) { 878 var labels = timeline.labels, 879 min = _bigNum, 880 p, 881 distance, 882 label; 883 884 for (p in labels) { 885 distance = labels[p] - fromTime; 886 887 if (distance < 0 === !!backward && distance && min > (distance = Math.abs(distance))) { 888 label = p; 889 min = distance; 890 } 891 } 892 893 return label; 894 }, 895 _callback = function _callback(animation, type, executeLazyFirst) { 896 var v = animation.vars, 897 callback = v[type], 898 params, 899 scope; 900 901 if (!callback) { 902 return; 903 } 904 905 params = v[type + "Params"]; 906 scope = v.callbackScope || animation; 907 executeLazyFirst && _lazyTweens.length && _lazyRender(); 908 return params ? callback.apply(scope, params) : callback.call(scope); 909 },
vendor: 11,709 bytes, lines 910-1323
910 _interrupt = function _interrupt(animation) { 911 _removeFromParent(animation); 912 913 animation.scrollTrigger && animation.scrollTrigger.kill(false); 914 animation.progress() < 1 && _callback(animation, "onInterrupt"); 915 return animation; 916 }, 917 _quickTween, 918 _createPlugin = function _createPlugin(config) { 919 config = !config.name && config["default"] || config; 920 921 var name = config.name, 922 isFunc = _isFunction(config), 923 Plugin = name && !isFunc && config.init ? function () { 924 this._props = []; 925 } : config, 926 instanceDefaults = { 927 init: _emptyFunc, 928 render: _renderPropTweens, 929 add: _addPropTween, 930 kill: _killPropTweensOf, 931 modifier: _addPluginModifier, 932 rawVars: 0 933 }, 934 statics = { 935 targetTest: 0, 936 get: 0, 937 getSetter: _getSetter, 938 aliases: {}, 939 register: 0 940 }; 941 942 _wake(); 943 944 if (config !== Plugin) { 945 if (_plugins[name]) { 946 return; 947 } 948 949 _setDefaults(Plugin, _setDefaults(_copyExcluding(config, instanceDefaults), statics)); 950 951 _merge(Plugin.prototype, _merge(instanceDefaults, _copyExcluding(config, statics))); 952 953 _plugins[Plugin.prop = name] = Plugin; 954 955 if (config.targetTest) { 956 _harnessPlugins.push(Plugin); 957 958 _reservedProps[name] = 1; 959 } 960 961 name = (name === "css" ? "CSS" : name.charAt(0).toUpperCase() + name.substr(1)) + "Plugin"; 962 } 963 964 _addGlobal(name, Plugin); 965 966 config.register && config.register(gsap, Plugin, PropTween); 967 }, 968 _255 = 255, 969 _colorLookup = { 970 aqua: [0, _255, _255], 971 lime: [0, _255, 0], 972 silver: [192, 192, 192], 973 black: [0, 0, 0], 974 maroon: [128, 0, 0], 975 teal: [0, 128, 128], 976 blue: [0, 0, _255], 977 navy: [0, 0, 128], 978 white: [_255, _255, _255], 979 olive: [128, 128, 0], 980 yellow: [_255, _255, 0], 981 orange: [_255, 165, 0], 982 gray: [128, 128, 128], 983 purple: [128, 0, 128], 984 green: [0, 128, 0], 985 red: [_255, 0, 0], 986 pink: [_255, 192, 203], 987 cyan: [0, _255, _255], 988 transparent: [_255, _255, _255, 0] 989 }, 990 _hue = function _hue(h, m1, m2) { 991 h = h < 0 ? h + 1 : h > 1 ? h - 1 : h; 992 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; 993 }, 994 splitColor = function splitColor(v, toHSL, forceAlpha) { 995 var a = !v ? _colorLookup.black : _isNumber(v) ? [v >> 16, v >> 8 & _255, v & _255] : 0, 996 r, 997 g, 998 b, 999 h, 1000 s, 1001 l, 1002 max, 1003 min, 1004 d, 1005 wasHSL; 1006 1007 if (!a) { 1008 if (v.substr(-1) === ",") { 1009 v = v.substr(0, v.length - 1); 1010 } 1011 1012 if (_colorLookup[v]) { 1013 a = _colorLookup[v]; 1014 } else if (v.charAt(0) === "#") { 1015 if (v.length < 6) { 1016 r = v.charAt(1); 1017 g = v.charAt(2); 1018 b = v.charAt(3); 1019 v = "#" + r + r + g + g + b + b + (v.length === 5 ? v.charAt(4) + v.charAt(4) : ""); 1020 } 1021 1022 if (v.length === 9) { 1023 a = parseInt(v.substr(1, 6), 16); 1024 return [a >> 16, a >> 8 & _255, a & _255, parseInt(v.substr(7), 16) / 255]; 1025 } 1026 1027 v = parseInt(v.substr(1), 16); 1028 a = [v >> 16, v >> 8 & _255, v & _255]; 1029 } else if (v.substr(0, 3) === "hsl") { 1030 a = wasHSL = v.match(_strictNumExp); 1031 1032 if (!toHSL) { 1033 h = +a[0] % 360 / 360; 1034 s = +a[1] / 100; 1035 l = +a[2] / 100; 1036 g = l <= .5 ? l * (s + 1) : l + s - l * s; 1037 r = l * 2 - g; 1038 a.length > 3 && (a[3] *= 1); 1039 a[0] = _hue(h + 1 / 3, r, g); 1040 a[1] = _hue(h, r, g); 1041 a[2] = _hue(h - 1 / 3, r, g); 1042 } else if (~v.indexOf("=")) { 1043 a = v.match(_numExp); 1044 forceAlpha && a.length < 4 && (a[3] = 1); 1045 return a; 1046 } 1047 } else { 1048 a = v.match(_strictNumExp) || _colorLookup.transparent; 1049 } 1050 1051 a = a.map(Number); 1052 } 1053 1054 if (toHSL && !wasHSL) { 1055 r = a[0] / _255; 1056 g = a[1] / _255; 1057 b = a[2] / _255; 1058 max = Math.max(r, g, b); 1059 min = Math.min(r, g, b); 1060 l = (max + min) / 2; 1061 1062 if (max === min) { 1063 h = s = 0; 1064 } else { 1065 d = max - min; 1066 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 1067 h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4; 1068 h *= 60; 1069 } 1070 1071 a[0] = ~~(h + .5); 1072 a[1] = ~~(s * 100 + .5); 1073 a[2] = ~~(l * 100 + .5); 1074 } 1075 1076 forceAlpha && a.length < 4 && (a[3] = 1); 1077 return a; 1078 }, 1079 _colorOrderData = function _colorOrderData(v) { 1080 var values = [], 1081 c = [], 1082 i = -1; 1083 v.split(_colorExp).forEach(function (v) { 1084 var a = v.match(_numWithUnitExp) || []; 1085 values.push.apply(values, a); 1086 c.push(i += a.length + 1); 1087 }); 1088 values.c = c; 1089 return values; 1090 }, 1091 _formatColors = function _formatColors(s, toHSL, orderMatchData) { 1092 var result = "", 1093 colors = (s + result).match(_colorExp), 1094 type = toHSL ? "hsla(" : "rgba(", 1095 i = 0, 1096 c, 1097 shell, 1098 d, 1099 l; 1100 1101 if (!colors) { 1102 return s; 1103 } 1104 1105 colors = colors.map(function (color) { 1106 return (color = splitColor(color, toHSL, 1)) && type + (toHSL ? color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : color.join(",")) + ")"; 1107 }); 1108 1109 if (orderMatchData) { 1110 d = _colorOrderData(s); 1111 c = orderMatchData.c; 1112 1113 if (c.join(result) !== d.c.join(result)) { 1114 shell = s.replace(_colorExp, "1").split(_numWithUnitExp); 1115 l = shell.length - 1; 1116 1117 for (; i < l; i++) { 1118 result += shell[i] + (~c.indexOf(i) ? colors.shift() || type + "0,0,0,0)" : (d.length ? d : colors.length ? colors : orderMatchData).shift()); 1119 } 1120 } 1121 } 1122 1123 if (!shell) { 1124 shell = s.split(_colorExp); 1125 l = shell.length - 1; 1126 1127 for (; i < l; i++) { 1128 result += shell[i] + colors[i]; 1129 } 1130 } 1131 1132 return result + shell[l]; 1133 }, 1134 _colorExp = function () { 1135 var s = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3,4}){1,2}\\b", 1136 p; 1137 1138 for (p in _colorLookup) { 1139 s += "|" + p + "\\b"; 1140 } 1141 1142 return new RegExp(s + ")", "gi"); 1143 }(), 1144 _hslExp = /hsl[a]?\(/, 1145 _colorStringFilter = function _colorStringFilter(a) { 1146 var combined = a.join(" "), 1147 toHSL; 1148 _colorExp.lastIndex = 0; 1149 1150 if (_colorExp.test(combined)) { 1151 toHSL = _hslExp.test(combined); 1152 a[1] = _formatColors(a[1], toHSL); 1153 a[0] = _formatColors(a[0], toHSL, _colorOrderData(a[1])); 1154 return true; 1155 } 1156 }, 1157 _tickerActive, 1158 _ticker = function () { 1159 var _getTime = Date.now, 1160 _lagThreshold = 500, 1161 _adjustedLag = 33, 1162 _startTime = _getTime(), 1163 _lastUpdate = _startTime, 1164 _gap = 1000 / 240, 1165 _nextTime = _gap, 1166 _listeners = [], 1167 _id, 1168 _req, 1169 _raf, 1170 _self, 1171 _delta, 1172 _i, 1173 _tick = function _tick(v) { 1174 var elapsed = _getTime() - _lastUpdate, 1175 manual = v === true, 1176 overlap, 1177 dispatch, 1178 time, 1179 frame; 1180 1181 elapsed > _lagThreshold && (_startTime += elapsed - _adjustedLag); 1182 _lastUpdate += elapsed; 1183 time = _lastUpdate - _startTime; 1184 overlap = time - _nextTime; 1185 1186 if (overlap > 0 || manual) { 1187 frame = ++_self.frame; 1188 _delta = time - _self.time * 1000; 1189 _self.time = time = time / 1000; 1190 _nextTime += overlap + (overlap >= _gap ? 4 : _gap - overlap); 1191 dispatch = 1; 1192 } 1193 1194 manual || (_id = _req(_tick)); 1195 1196 if (dispatch) { 1197 for (_i = 0; _i < _listeners.length; _i++) { 1198 _listeners[_i](time, _delta, frame, v); 1199 } 1200 } 1201 }; 1202 1203 _self = { 1204 time: 0, 1205 frame: 0, 1206 tick: function tick() { 1207 _tick(true); 1208 }, 1209 deltaRatio: function deltaRatio(fps) { 1210 return _delta / (1000 / (fps || 60)); 1211 }, 1212 wake: function wake() { 1213 if (_coreReady) { 1214 if (!_coreInitted && _windowExists()) { 1215 _win = _coreInitted = window; 1216 _doc = _win.document || {}; 1217 _globals.gsap = gsap; 1218 (_win.gsapVersions || (_win.gsapVersions = [])).push(gsap.version); 1219 1220 _install(_installScope || _win.GreenSockGlobals || !_win.gsap && _win || {}); 1221 1222 _raf = _win.requestAnimationFrame; 1223 } 1224 1225 _id && _self.sleep(); 1226 1227 _req = _raf || function (f) { 1228 return setTimeout(f, _nextTime - _self.time * 1000 + 1 | 0); 1229 }; 1230 1231 _tickerActive = 1; 1232 1233 _tick(2); 1234 } 1235 }, 1236 sleep: function sleep() { 1237 (_raf ? _win.cancelAnimationFrame : clearTimeout)(_id); 1238 _tickerActive = 0; 1239 _req = _emptyFunc; 1240 }, 1241 lagSmoothing: function lagSmoothing(threshold, adjustedLag) { 1242 _lagThreshold = threshold || 1 / _tinyNum; 1243 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0); 1244 }, 1245 fps: function fps(_fps) { 1246 _gap = 1000 / (_fps || 240); 1247 _nextTime = _self.time * 1000 + _gap; 1248 }, 1249 add: function add(callback) { 1250 _listeners.indexOf(callback) < 0 && _listeners.push(callback); 1251 1252 _wake(); 1253 }, 1254 remove: function remove(callback) { 1255 var i; 1256 ~(i = _listeners.indexOf(callback)) && _listeners.splice(i, 1) && _i >= i && _i--; 1257 }, 1258 _listeners: _listeners 1259 }; 1260 return _self; 1261 }(), 1262 _wake = function _wake() { 1263 return !_tickerActive && _ticker.wake(); 1264 }, 1265 _easeMap = {}, 1266 _customEaseExp = /^[\d.\-M][\d.\-,\s]/, 1267 _quotesExp = /["']/g, 1268 _parseObjectInString = function _parseObjectInString(value) { 1269 var obj = {}, 1270 split = value.substr(1, value.length - 3).split(":"), 1271 key = split[0], 1272 i = 1, 1273 l = split.length, 1274 index, 1275 val, 1276 parsedVal; 1277 1278 for (; i < l; i++) { 1279 val = split[i]; 1280 index = i !== l - 1 ? val.lastIndexOf(",") : val.length; 1281 parsedVal = val.substr(0, index); 1282 obj[key] = isNaN(parsedVal) ? parsedVal.replace(_quotesExp, "").trim() : +parsedVal; 1283 key = val.substr(index + 1).trim(); 1284 } 1285 1286 return obj; 1287 }, 1288 _valueInParentheses = function _valueInParentheses(value) { 1289 var open = value.indexOf("(") + 1, 1290 close = value.indexOf(")"), 1291 nested = value.indexOf("(", open); 1292 return value.substring(open, ~nested && nested < close ? value.indexOf(")", close + 1) : close); 1293 }, 1294 _configEaseFromString = function _configEaseFromString(name) { 1295 var split = (name + "").split("("), 1296 ease = _easeMap[split[0]]; 1297 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; 1298 }, 1299 _invertEase = function _invertEase(ease) { 1300 return function (p) { 1301 return 1 - ease(1 - p); 1302 }; 1303 }, 1304 _propagateYoyoEase = function _propagateYoyoEase(timeline, isYoyo) { 1305 var child = timeline._first, 1306 ease; 1307 1308 while (child) { 1309 if (child instanceof Timeline) { 1310 _propagateYoyoEase(child, isYoyo); 1311 } else if (child.vars.yoyoEase && (!child._yoyo || !child._repeat) && child._yoyo !== isYoyo) { 1312 if (child.timeline) { 1313 _propagateYoyoEase(child.timeline, isYoyo); 1314 } else { 1315 ease = child._ease; 1316 child._ease = child._yEase; 1317 child._yEase = ease; 1318 child._yoyo = isYoyo; 1319 } 1320 } 1321 1322 child = child._next; 1323 }
vendor: 3,445 bytes, lines 1323-1434
1323 1324 }, 1325 _parseEase = function _parseEase(ease, defaultEase) { 1326 return !ease ? defaultEase : (_isFunction(ease) ? ease : _easeMap[ease] || _configEaseFromString(ease)) || defaultEase; 1327 }, 1328 _insertEase = function _insertEase(names, easeIn, easeOut, easeInOut) { 1329 if (easeOut === void 0) { 1330 easeOut = function easeOut(p) { 1331 return 1 - easeIn(1 - p); 1332 }; 1333 } 1334 1335 if (easeInOut === void 0) { 1336 easeInOut = function easeInOut(p) { 1337 return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn((1 - p) * 2) / 2; 1338 }; 1339 } 1340 1341 var ease = { 1342 easeIn: easeIn, 1343 easeOut: easeOut, 1344 easeInOut: easeInOut 1345 }, 1346 lowercaseName; 1347 1348 _forEachName(names, function (name) { 1349 _easeMap[name] = _globals[name] = ease; 1350 _easeMap[lowercaseName = name.toLowerCase()] = easeOut; 1351 1352 for (var p in ease) { 1353 _easeMap[lowercaseName + (p === "easeIn" ? ".in" : p === "easeOut" ? ".out" : ".inOut")] = _easeMap[name + "." + p] = ease[p]; 1354 } 1355 }); 1356 1357 return ease; 1358 }, 1359 _easeInOutFromOut = function _easeInOutFromOut(easeOut) { 1360 return function (p) { 1361 return p < .5 ? (1 - easeOut(1 - p * 2)) / 2 : .5 + easeOut((p - .5) * 2) / 2; 1362 }; 1363 }, 1364 _configElastic = function _configElastic(type, amplitude, period) { 1365 var p1 = amplitude >= 1 ? amplitude : 1, 1366 p2 = (period || (type ? .3 : .45)) / (amplitude < 1 ? amplitude : 1), 1367 p3 = p2 / _2PI * (Math.asin(1 / p1) || 0), 1368 easeOut = function easeOut(p) { 1369 return p === 1 ? 1 : p1 * Math.pow(2, -10 * p) * _sin((p - p3) * p2) + 1; 1370 }, 1371 ease = type === "out" ? easeOut : type === "in" ? function (p) { 1372 return 1 - easeOut(1 - p); 1373 } : _easeInOutFromOut(easeOut); 1374 1375 p2 = _2PI / p2; 1376 1377 ease.config = function (amplitude, period) { 1378 return _configElastic(type, amplitude, period); 1379 }; 1380 1381 return ease; 1382 }, 1383 _configBack = function _configBack(type, overshoot) { 1384 if (overshoot === void 0) { 1385 overshoot = 1.70158; 1386 } 1387 1388 var easeOut = function easeOut(p) { 1389 return p ? --p * p * ((overshoot + 1) * p + overshoot) + 1 : 0; 1390 }, 1391 ease = type === "out" ? easeOut : type === "in" ? function (p) { 1392 return 1 - easeOut(1 - p); 1393 } : _easeInOutFromOut(easeOut); 1394 1395 ease.config = function (overshoot) { 1396 return _configBack(type, overshoot); 1397 }; 1398 1399 return ease; 1400 }; 1401 1402 _forEachName("Linear,Quad,Cubic,Quart,Quint,Strong", function (name, i) { 1403 var power = i < 5 ? i + 1 : i; 1404 1405 _insertEase(name + ",Power" + (power - 1), i ? function (p) { 1406 return Math.pow(p, power); 1407 } : function (p) { 1408 return p; 1409 }, function (p) { 1410 return 1 - Math.pow(1 - p, power); 1411 }, function (p) { 1412 return p < .5 ? Math.pow(p * 2, power) / 2 : 1 - Math.pow((1 - p) * 2, power) / 2; 1413 }); 1414 }); 1415 1416 _easeMap.Linear.easeNone = _easeMap.none = _easeMap.Linear.easeIn; 1417 1418 _insertEase("Elastic", _configElastic("in"), _configElastic("out"), _configElastic()); 1419 1420 (function (n, c) { 1421 var n1 = 1 / c, 1422 n2 = 2 * n1, 1423 n3 = 2.5 * n1, 1424 easeOut = function easeOut(p) { 1425 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; 1426 }; 1427 1428 _insertEase("Bounce", function (p) { 1429 return 1 - easeOut(1 - p); 1430 }, easeOut); 1431 })(7.5625, 2.75); 1432 1433 _insertEase("Expo", function (p) { 1434 return
vendor: 6,382 bytes, lines 1434-1617
1434p ? Math.pow(2, 10 * (p - 1)) : 0; 1435 }); 1436 1437 _insertEase("Circ", function (p) { 1438 return -(_sqrt(1 - p * p) - 1); 1439 }); 1440 1441 _insertEase("Sine", function (p) { 1442 return p === 1 ? 1 : -_cos(p * _HALF_PI) + 1; 1443 }); 1444 1445 _insertEase("Back", _configBack("in"), _configBack("out"), _configBack()); 1446 1447 _easeMap.SteppedEase = _easeMap.steps = _globals.SteppedEase = { 1448 config: function config(steps, immediateStart) { 1449 if (steps === void 0) { 1450 steps = 1; 1451 } 1452 1453 var p1 = 1 / steps, 1454 p2 = steps + (immediateStart ? 0 : 1), 1455 p3 = immediateStart ? 1 : 0, 1456 max = 1 - _tinyNum; 1457 return function (p) { 1458 return ((p2 * _clamp(0, max, p) | 0) + p3) * p1; 1459 }; 1460 } 1461 }; 1462 _defaults.ease = _easeMap["quad.out"]; 1463 1464 _forEachName("onComplete,onUpdate,onStart,onRepeat,onReverseComplete,onInterrupt", function (name) { 1465 return _callbackNames += name + "," + name + "Params,"; 1466 }); 1467 1468 var GSCache = function GSCache(target, harness) { 1469 this.id = _gsID++; 1470 target._gsap = this; 1471 this.target = target; 1472 this.harness = harness; 1473 this.get = harness ? harness.get : _getProperty; 1474 this.set = harness ? harness.getSetter : _getSetter; 1475 }; 1476 var Animation = function () { 1477 function Animation(vars, time) { 1478 var parent = vars.parent || _globalTimeline; 1479 this.vars = vars; 1480 this._delay = +vars.delay || 0; 1481 1482 if (this._repeat = vars.repeat === Infinity ? -2 : vars.repeat || 0) { 1483 this._rDelay = vars.repeatDelay || 0; 1484 this._yoyo = !!vars.yoyo || !!vars.yoyoEase; 1485 } 1486 1487 this._ts = 1; 1488 1489 _setDuration(this, +vars.duration, 1, 1); 1490 1491 this.data = vars.data; 1492 _tickerActive || _ticker.wake(); 1493 parent && _addToTimeline(parent, this, time || time === 0 ? time : parent._time, 1); 1494 vars.reversed && this.reverse(); 1495 vars.paused && this.paused(true); 1496 } 1497 1498 var _proto = Animation.prototype; 1499 1500 _proto.delay = function delay(value) { 1501 if (value || value === 0) { 1502 this.parent && this.parent.smoothChildTiming && this.startTime(this._start + value - this._delay); 1503 this._delay = value; 1504 return this; 1505 } 1506 1507 return this._delay; 1508 }; 1509 1510 _proto.duration = function duration(value) { 1511 return arguments.length ? this.totalDuration(this._repeat > 0 ? value + (value + this._rDelay) * this._repeat : value) : this.totalDuration() && this._dur; 1512 }; 1513 1514 _proto.totalDuration = function totalDuration(value) { 1515 if (!arguments.length) { 1516 return this._tDur; 1517 } 1518 1519 this._dirty = 0; 1520 return _setDuration(this, this._repeat < 0 ? value : (value - this._repeat * this._rDelay) / (this._repeat + 1)); 1521 }; 1522 1523 _proto.totalTime = function totalTime(_totalTime, suppressEvents) { 1524 _wake(); 1525 1526 if (!arguments.length) { 1527 return this._tTime; 1528 } 1529 1530 var parent = this._dp; 1531 1532 if (parent && parent.smoothChildTiming && this._ts) { 1533 _alignPlayhead(this, _totalTime); 1534 1535 !parent._dp || parent.parent || _postAddChecks(parent, this); 1536 1537 while (parent.parent) { 1538 if (parent.parent._time !== parent._start + (parent._ts >= 0 ? parent._tTime / parent._ts : (parent.totalDuration() - parent._tTime) / -parent._ts)) { 1539 parent.totalTime(parent._tTime, true); 1540 } 1541 1542 parent = parent.parent; 1543 } 1544 1545 if (!this.parent && this._dp.autoRemoveChildren && (this._ts > 0 && _totalTime < this._tDur || this._ts < 0 && _totalTime > 0 || !this._tDur && !_totalTime)) { 1546 _addToTimeline(this._dp, this, this._start - this._delay); 1547 } 1548 } 1549 1550 if (this._tTime !== _totalTime || !this._dur && !suppressEvents || this._initted && Math.abs(this._zTime) === _tinyNum || !_totalTime && !this._initted && (this.add || this._ptLookup)) { 1551 this._ts || (this._pTime = _totalTime); 1552 1553 _lazySafeRender(this, _totalTime, suppressEvents); 1554 } 1555 1556 return this; 1557 }; 1558 1559 _proto.time = function time(value, suppressEvents) { 1560 return arguments.length ? this.totalTime(Math.min(this.totalDuration(), value + _elapsedCycleDuration(this)) % this._dur || (value ? this._dur : 0), suppressEvents) : this._time; 1561 }; 1562 1563 _proto.totalProgress = function totalProgress(value, suppressEvents) { 1564 return arguments.length ? this.totalTime(this.totalDuration() * value, suppressEvents) : this.totalDuration() ? Math.min(1, this._tTime / this._tDur) : this.ratio; 1565 }; 1566 1567 _proto.progress = function progress(value, suppressEvents) { 1568 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; 1569 }; 1570 1571 _proto.iteration = function iteration(value, suppressEvents) { 1572 var cycleDuration = this.duration() + this._rDelay; 1573 1574 return arguments.length ? this.totalTime(this._time + (value - 1) * cycleDuration, suppressEvents) : this._repeat ? _animationCycle(this._tTime, cycleDuration) + 1 : 1; 1575 }; 1576 1577 _proto.timeScale = function timeScale(value) { 1578 if (!arguments.length) { 1579 return this._rts === -_tinyNum ? 0 : this._rts; 1580 } 1581 1582 if (this._rts === value) { 1583 return this; 1584 } 1585 1586 var tTime = this.parent && this._ts ? _parentToChildTotalTime(this.parent._time, this) : this._tTime; 1587 this._rts = +value || 0; 1588 this._ts = this._ps || value === -_tinyNum ? 0 : this._rts; 1589 return _recacheAncestors(this.totalTime(_clamp(-this._delay, this._tDur, tTime), true)); 1590 }; 1591 1592 _proto.paused = function paused(value) { 1593 if (!arguments.length) { 1594 return this._ps; 1595 } 1596 1597 if (this._ps !== value) { 1598 this._ps = value; 1599 1600 if (value) { 1601 this._pTime = this._tTime || Math.max(-this._delay, this.rawTime()); 1602 this._ts = this._act = 0; 1603 } else { 1604 _wake(); 1605 1606 this._ts = this._rts; 1607 this.totalTime(this.parent && !this.parent.smoothChildTiming ? this.rawTime() : this._tTime || this._pTime, this.progress() === 1 && (this._tTime -= _tinyNum) && Math.abs(this._zTime) !== _tinyNum); 1608 } 1609 } 1610 1611 return this; 1612 }; 1613 1614 _proto.startTime = function startTime(value) { 1615 if (arguments.length) { 1616 this._start = value; 1617 var parent = this.parent || this._dp;
vendor: 2,817 bytes, lines 1618-1708
1618 parent && (parent._sort || !this.parent) && _addToTimeline(parent, this, value - this._delay); 1619 return this; 1620 } 1621 1622 return this._start; 1623 }; 1624 1625 _proto.endTime = function endTime(includeRepeats) { 1626 return this._start + (_isNotFalse(includeRepeats) ? this.totalDuration() : this.duration()) / Math.abs(this._ts); 1627 }; 1628 1629 _proto.rawTime = function rawTime(wrapRepeats) { 1630 var parent = this.parent || this._dp; 1631 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); 1632 }; 1633 1634 _proto.globalTime = function globalTime(rawTime) { 1635 var animation = this, 1636 time = arguments.length ? rawTime : animation.rawTime(); 1637 1638 while (animation) { 1639 time = animation._start + time / (animation._ts || 1); 1640 animation = animation._dp; 1641 } 1642 1643 return time; 1644 }; 1645 1646 _proto.repeat = function repeat(value) { 1647 if (arguments.length) { 1648 this._repeat = value === Infinity ? -2 : value; 1649 return _onUpdateTotalDuration(this); 1650 } 1651 1652 return this._repeat === -2 ? Infinity : this._repeat; 1653 }; 1654 1655 _proto.repeatDelay = function repeatDelay(value) { 1656 if (arguments.length) { 1657 this._rDelay = value; 1658 return _onUpdateTotalDuration(this); 1659 } 1660 1661 return this._rDelay; 1662 }; 1663 1664 _proto.yoyo = function yoyo(value) { 1665 if (arguments.length) { 1666 this._yoyo = value; 1667 return this; 1668 } 1669 1670 return this._yoyo; 1671 }; 1672 1673 _proto.seek = function seek(position, suppressEvents) { 1674 return this.totalTime(_parsePosition(this, position), _isNotFalse(suppressEvents)); 1675 }; 1676 1677 _proto.restart = function restart(includeDelay, suppressEvents) { 1678 return this.play().totalTime(includeDelay ? -this._delay : 0, _isNotFalse(suppressEvents)); 1679 }; 1680 1681 _proto.play = function play(from, suppressEvents) { 1682 from != null && this.seek(from, suppressEvents); 1683 return this.reversed(false).paused(false); 1684 }; 1685 1686 _proto.reverse = function reverse(from, suppressEvents) { 1687 from != null && this.seek(from || this.totalDuration(), suppressEvents); 1688 return this.reversed(true).paused(false); 1689 }; 1690 1691 _proto.pause = function pause(atTime, suppressEvents) { 1692 atTime != null && this.seek(atTime, suppressEvents); 1693 return this.paused(true); 1694 }; 1695 1696 _proto.resume = function resume() { 1697 return this.paused(false); 1698 }; 1699 1700 _proto.reversed = function reversed(value) { 1701 if (arguments.length) { 1702 !!value !== this.reversed() && this.timeScale(-this._rts || (value ? -_tinyNum : 0)); 1703 return this; 1704 } 1705 1706 return this._rts < 0; 1707 }; 1708
vendor: 8,594 bytes, lines 1709-1972
1709 _proto.invalidate = function invalidate() { 1710 this._initted = this._act = 0; 1711 this._zTime = -_tinyNum; 1712 return this; 1713 }; 1714 1715 _proto.isActive = function isActive() { 1716 var parent = this.parent || this._dp, 1717 start = this._start, 1718 rawTime; 1719 return !!(!parent || this._ts && this._initted && parent.isActive() && (rawTime = parent.rawTime(true)) >= start && rawTime < this.endTime(true) - _tinyNum); 1720 }; 1721 1722 _proto.eventCallback = function eventCallback(type, callback, params) { 1723 var vars = this.vars; 1724 1725 if (arguments.length > 1) { 1726 if (!callback) { 1727 delete vars[type]; 1728 } else { 1729 vars[type] = callback; 1730 params && (vars[type + "Params"] = params); 1731 type === "onUpdate" && (this._onUpdate = callback); 1732 } 1733 1734 return this; 1735 } 1736 1737 return vars[type]; 1738 }; 1739 1740 _proto.then = function then(onFulfilled) { 1741 var self = this; 1742 return new Promise(function (resolve) { 1743 var f = _isFunction(onFulfilled) ? onFulfilled : _passThrough, 1744 _resolve = function _resolve() { 1745 var _then = self.then; 1746 self.then = null; 1747 _isFunction(f) && (f = f(self)) && (f.then || f === self) && (self.then = _then); 1748 resolve(f); 1749 self.then = _then; 1750 }; 1751 1752 if (self._initted && self.totalProgress() === 1 && self._ts >= 0 || !self._tTime && self._ts < 0) { 1753 _resolve(); 1754 } else { 1755 self._prom = _resolve; 1756 } 1757 }); 1758 }; 1759 1760 _proto.kill = function kill() { 1761 _interrupt(this); 1762 }; 1763 1764 return Animation; 1765 }(); 1766 1767 _setDefaults(Animation.prototype, { 1768 _time: 0, 1769 _start: 0, 1770 _end: 0, 1771 _tTime: 0, 1772 _tDur: 0, 1773 _dirty: 0, 1774 _repeat: 0, 1775 _yoyo: false, 1776 parent: null, 1777 _initted: false, 1778 _rDelay: 0, 1779 _ts: 1, 1780 _dp: 0, 1781 ratio: 0, 1782 _zTime: -_tinyNum, 1783 _prom: 0, 1784 _ps: false, 1785 _rts: 1 1786 }); 1787 1788 var Timeline = function (_Animation) { 1789 _inheritsLoose(Timeline, _Animation); 1790 1791 function Timeline(vars, time) { 1792 var _this; 1793 1794 if (vars === void 0) { 1795 vars = {}; 1796 } 1797 1798 _this = _Animation.call(this, vars, time) || this; 1799 _this.labels = {}; 1800 _this.smoothChildTiming = !!vars.smoothChildTiming; 1801 _this.autoRemoveChildren = !!vars.autoRemoveChildren; 1802 _this._sort = _isNotFalse(vars.sortChildren); 1803 _this.parent && _postAddChecks(_this.parent, _assertThisInitialized(_this)); 1804 vars.scrollTrigger && _scrollTrigger(_assertThisInitialized(_this), vars.scrollTrigger); 1805 return _this; 1806 } 1807 1808 var _proto2 = Timeline.prototype; 1809 1810 _proto2.to = function to(targets, vars, position) { 1811 new Tween(targets, _parseVars(arguments, 0, this), _parsePosition(this, _isNumber(vars) ? arguments[3] : position)); 1812 return this; 1813 }; 1814 1815 _proto2.from = function from(targets, vars, position) { 1816 new Tween(targets, _parseVars(arguments, 1, this), _parsePosition(this, _isNumber(vars) ? arguments[3] : position)); 1817 return this; 1818 }; 1819 1820 _proto2.fromTo = function fromTo(targets, fromVars, toVars, position) { 1821 new Tween(targets, _parseVars(arguments, 2, this), _parsePosition(this, _isNumber(fromVars) ? arguments[4] : position)); 1822 return this; 1823 }; 1824 1825 _proto2.set = function set(targets, vars, position) { 1826 vars.duration = 0; 1827 vars.parent = this; 1828 _inheritDefaults(vars).repeatDelay || (vars.repeat = 0); 1829 vars.immediateRender = !!vars.immediateRender; 1830 new Tween(targets, vars, _parsePosition(this, position), 1); 1831 return this; 1832 }; 1833 1834 _proto2.call = function call(callback, params, position) { 1835 return _addToTimeline(this, Tween.delayedCall(0, callback, params), _parsePosition(this, position)); 1836 }; 1837 1838 _proto2.staggerTo = function staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) { 1839 vars.duration = duration; 1840 vars.stagger = vars.stagger || stagger; 1841 vars.onComplete = onCompleteAll; 1842 vars.onCompleteParams = onCompleteAllParams; 1843 vars.parent = this; 1844 new Tween(targets, vars, _parsePosition(this, position)); 1845 return this; 1846 }; 1847 1848 _proto2.staggerFrom = function staggerFrom(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams) { 1849 vars.runBackwards = 1; 1850 _inheritDefaults(vars).immediateRender = _isNotFalse(vars.immediateRender); 1851 return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams); 1852 }; 1853 1854 _proto2.staggerFromTo = function staggerFromTo(targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams) { 1855 toVars.startAt = fromVars; 1856 _inheritDefaults(toVars).immediateRender = _isNotFalse(toVars.immediateRender); 1857 return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams); 1858 }; 1859 1860 _proto2.render = function render(totalTime, suppressEvents, force) { 1861 var prevTime = this._time, 1862 tDur = this._dirty ? this.totalDuration() : this._tDur, 1863 dur = this._dur, 1864 tTime = this !== _globalTimeline && totalTime > tDur - _tinyNum && totalTime >= 0 ? tDur : totalTime < _tinyNum ? 0 : totalTime, 1865 crossingStart = this._zTime < 0 !== totalTime < 0 && (this._initted || !dur), 1866 time, 1867 child, 1868 next, 1869 iteration, 1870 cycleDuration, 1871 prevPaused, 1872 pauseTween, 1873 timeScale, 1874 prevStart, 1875 prevIteration, 1876 yoyo, 1877 isYoyo; 1878 1879 if (tTime !== this._tTime || force || crossingStart) { 1880 if (prevTime !== this._time && dur) { 1881 tTime += this._time - prevTime; 1882 totalTime += this._time - prevTime; 1883 } 1884 1885 time = tTime; 1886 prevStart = this._start; 1887 timeScale = this._ts; 1888 prevPaused = !timeScale; 1889 1890 if (crossingStart) { 1891 dur || (prevTime = this._zTime); 1892 (totalTime || !suppressEvents) && (this._zTime = totalTime); 1893 } 1894 1895 if (this._repeat) { 1896 yoyo = this._yoyo; 1897 cycleDuration = dur + this._rDelay; 1898 1899 if (this._repeat < -1 && totalTime < 0) { 1900 return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force); 1901 } 1902 1903 time = _round(tTime % cycleDuration); 1904 1905 if (tTime === tDur) { 1906 iteration = this._repeat; 1907 time = dur; 1908 } else { 1909 iteration = ~~(tTime / cycleDuration); 1910 1911 if (iteration && iteration === tTime / cycleDuration) { 1912 time = dur; 1913 iteration--; 1914 } 1915 1916 time > dur && (time = dur); 1917 } 1918 1919 prevIteration = _animationCycle(this._tTime, cycleDuration); 1920 !prevTime && this._tTime && prevIteration !== iteration && (prevIteration = iteration); 1921 1922 if (yoyo && iteration & 1) { 1923 time = dur - time; 1924 isYoyo = 1; 1925 } 1926 1927 if (iteration !== prevIteration && !this._lock) { 1928 var rewinding = yoyo && prevIteration & 1, 1929 doesWrap = rewinding === (yoyo && iteration & 1); 1930 iteration < prevIteration && (rewinding = !rewinding); 1931 prevTime = rewinding ? 0 : dur; 1932 this._lock = 1; 1933 this.render(prevTime || (isYoyo ? 0 : _round(iteration * cycleDuration)), suppressEvents, !dur)._lock = 0; 1934 !suppressEvents && this.parent && _callback(this, "onRepeat"); 1935 this.vars.repeatRefresh && !isYoyo && (this.invalidate()._lock = 1); 1936 1937 if (prevTime && prevTime !== this._time || prevPaused !== !this._ts || this.vars.onRepeat && !this.parent && !this._act) { 1938 return this; 1939 } 1940 1941 dur = this._dur; 1942 tDur = this._tDur; 1943 1944 if (doesWrap) { 1945 this._lock = 2; 1946 prevTime = rewinding ? dur : -0.0001; 1947 this.render(prevTime, true); 1948 } 1949 1950 this._lock = 0; 1951 1952 if (!this._ts && !prevPaused) { 1953 return this; 1954 } 1955 1956 _propagateYoyoEase(this, isYoyo); 1957 } 1958 } 1959 1960 if (this._hasPause && !this._forcing && this._lock < 2) { 1961 pauseTween = _findNextPauseTween(this, _round(prevTime), _round(time)); 1962 1963 if (pauseTween) { 1964 tTime -= time - (time = pauseTween._start); 1965 } 1966 } 1967 1968 this._tTime = tTime; 1969 this._time = time; 1970 this._act = !timeScale; 1971 1972 if (!this._initted) {
vendor: 22,800 bytes, lines 1973-2719
1973 this._onUpdate = this.vars.onUpdate; 1974 this._initted = 1; 1975 this._zTime = totalTime; 1976 prevTime = 0; 1977 } 1978 1979 !prevTime && time && !suppressEvents && _callback(this, "onStart"); 1980 1981 if (time >= prevTime && totalTime >= 0) { 1982 child = this._first; 1983 1984 while (child) { 1985 next = child._next; 1986 1987 if ((child._act || time >= child._start) && child._ts && pauseTween !== child) { 1988 if (child.parent !== this) { 1989 return this.render(totalTime, suppressEvents, force); 1990 } 1991 1992 child.render(child._ts > 0 ? (time - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (time - child._start) * child._ts, suppressEvents, force); 1993 1994 if (time !== this._time || !this._ts && !prevPaused) { 1995 pauseTween = 0; 1996 next && (tTime += this._zTime = -_tinyNum); 1997 break; 1998 } 1999 } 2000 2001 child = next; 2002 } 2003 } else { 2004 child = this._last; 2005 var adjustedTime = totalTime < 0 ? totalTime : time; 2006 2007 while (child) { 2008 next = child._prev; 2009 2010 if ((child._act || adjustedTime <= child._end) && child._ts && pauseTween !== child) { 2011 if (child.parent !== this) { 2012 return this.render(totalTime, suppressEvents, force); 2013 } 2014 2015 child.render(child._ts > 0 ? (adjustedTime - child._start) * child._ts : (child._dirty ? child.totalDuration() : child._tDur) + (adjustedTime - child._start) * child._ts, suppressEvents, force); 2016 2017 if (time !== this._time || !this._ts && !prevPaused) { 2018 pauseTween = 0; 2019 next && (tTime += this._zTime = adjustedTime ? -_tinyNum : _tinyNum); 2020 break; 2021 } 2022 } 2023 2024 child = next; 2025 } 2026 } 2027 2028 if (pauseTween && !suppressEvents) { 2029 this.pause(); 2030 pauseTween.render(time >= prevTime ? 0 : -_tinyNum)._zTime = time >= prevTime ? 1 : -1; 2031 2032 if (this._ts) { 2033 this._start = prevStart; 2034 2035 _setEnd(this); 2036 2037 return this.render(totalTime, suppressEvents, force); 2038 } 2039 } 2040 2041 this._onUpdate && !suppressEvents && _callback(this, "onUpdate", true); 2042 if (tTime === tDur && tDur >= this.totalDuration() || !tTime && prevTime) if (prevStart === this._start || Math.abs(timeScale) !== Math.abs(this._ts)) if (!this._lock) { 2043 (totalTime || !dur) && (tTime === tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1); 2044 2045 if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime)) { 2046 _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true); 2047 2048 this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom(); 2049 } 2050 } 2051 } 2052 2053 return this; 2054 }; 2055 2056 _proto2.add = function add(child, position) { 2057 var _this2 = this; 2058 2059 _isNumber(position) || (position = _parsePosition(this, position)); 2060 2061 if (!(child instanceof Animation)) { 2062 if (_isArray(child)) { 2063 child.forEach(function (obj) { 2064 return _this2.add(obj, position); 2065 }); 2066 return this; 2067 } 2068 2069 if (_isString(child)) { 2070 return this.addLabel(child, position); 2071 } 2072 2073 if (_isFunction(child)) { 2074 child = Tween.delayedCall(0, child); 2075 } else { 2076 return this; 2077 } 2078 } 2079 2080 return this !== child ? _addToTimeline(this, child, position) : this; 2081 }; 2082 2083 _proto2.getChildren = function getChildren(nested, tweens, timelines, ignoreBeforeTime) { 2084 if (nested === void 0) { 2085 nested = true; 2086 } 2087 2088 if (tweens === void 0) { 2089 tweens = true; 2090 } 2091 2092 if (timelines === void 0) { 2093 timelines = true; 2094 } 2095 2096 if (ignoreBeforeTime === void 0) { 2097 ignoreBeforeTime = -_bigNum; 2098 } 2099 2100 var a = [], 2101 child = this._first; 2102 2103 while (child) { 2104 if (child._start >= ignoreBeforeTime) { 2105 if (child instanceof Tween) { 2106 tweens && a.push(child); 2107 } else { 2108 timelines && a.push(child); 2109 nested && a.push.apply(a, child.getChildren(true, tweens, timelines)); 2110 } 2111 } 2112 2113 child = child._next; 2114 } 2115 2116 return a; 2117 }; 2118 2119 _proto2.getById = function getById(id) { 2120 var animations = this.getChildren(1, 1, 1), 2121 i = animations.length; 2122 2123 while (i--) { 2124 if (animations[i].vars.id === id) { 2125 return animations[i]; 2126 } 2127 } 2128 }; 2129 2130 _proto2.remove = function remove(child) { 2131 if (_isString(child)) { 2132 return this.removeLabel(child); 2133 } 2134 2135 if (_isFunction(child)) { 2136 return this.killTweensOf(child); 2137 } 2138 2139 _removeLinkedListItem(this, child); 2140 2141 if (child === this._recent) { 2142 this._recent = this._last; 2143 } 2144 2145 return _uncache(this); 2146 }; 2147 2148 _proto2.totalTime = function totalTime(_totalTime2, suppressEvents) { 2149 if (!arguments.length) { 2150 return this._tTime; 2151 } 2152 2153 this._forcing = 1; 2154 2155 if (!this._dp && this._ts) { 2156 this._start = _round(_ticker.time - (this._ts > 0 ? _totalTime2 / this._ts : (this.totalDuration() - _totalTime2) / -this._ts)); 2157 } 2158 2159 _Animation.prototype.totalTime.call(this, _totalTime2, suppressEvents); 2160 2161 this._forcing = 0; 2162 return this; 2163 }; 2164 2165 _proto2.addLabel = function addLabel(label, position) { 2166 this.labels[label] = _parsePosition(this, position); 2167 return this; 2168 }; 2169 2170 _proto2.removeLabel = function removeLabel(label) { 2171 delete this.labels[label]; 2172 return this; 2173 }; 2174 2175 _proto2.addPause = function addPause(position, callback, params) { 2176 var t = Tween.delayedCall(0, callback || _emptyFunc, params); 2177 t.data = "isPause"; 2178 this._hasPause = 1; 2179 return _addToTimeline(this, t, _parsePosition(this, position)); 2180 }; 2181 2182 _proto2.removePause = function removePause(position) { 2183 var child = this._first; 2184 position = _parsePosition(this, position); 2185 2186 while (child) { 2187 if (child._start === position && child.data === "isPause") { 2188 _removeFromParent(child); 2189 } 2190 2191 child = child._next; 2192 } 2193 }; 2194 2195 _proto2.killTweensOf = function killTweensOf(targets, props, onlyActive) { 2196 var tweens = this.getTweensOf(targets, onlyActive), 2197 i = tweens.length; 2198 2199 while (i--) { 2200 _overwritingTween !== tweens[i] && tweens[i].kill(targets, props); 2201 } 2202 2203 return this; 2204 }; 2205 2206 _proto2.getTweensOf = function getTweensOf(targets, onlyActive) { 2207 var a = [], 2208 parsedTargets = toArray(targets), 2209 child = this._first, 2210 isGlobalTime = _isNumber(onlyActive), 2211 children; 2212 2213 while (child) { 2214 if (child instanceof Tween) { 2215 if (_arrayContainsAny(child._targets, parsedTargets) && (isGlobalTime ? (!_overwritingTween || child._initted && child._ts) && child.globalTime(0) <= onlyActive && child.globalTime(child.totalDuration()) > onlyActive : !onlyActive || child.isActive())) { 2216 a.push(child); 2217 } 2218 } else if ((children = child.getTweensOf(parsedTargets, onlyActive)).length) { 2219 a.push.apply(a, children); 2220 } 2221 2222 child = child._next; 2223 } 2224 2225 return a; 2226 }; 2227 2228 _proto2.tweenTo = function tweenTo(position, vars) { 2229 vars = vars || {}; 2230 2231 var tl = this, 2232 endTime = _parsePosition(tl, position), 2233 _vars = vars, 2234 startAt = _vars.startAt, 2235 _onStart = _vars.onStart, 2236 onStartParams = _vars.onStartParams, 2237 immediateRender = _vars.immediateRender, 2238 tween = Tween.to(tl, _setDefaults({ 2239 ease: vars.ease || "none", 2240 lazy: false, 2241 immediateRender: false, 2242 time: endTime, 2243 overwrite: "auto", 2244 duration: vars.duration || Math.abs((endTime - (startAt && "time" in startAt ? startAt.time : tl._time)) / tl.timeScale()) || _tinyNum, 2245 onStart: function onStart() { 2246 tl.pause(); 2247 var duration = vars.duration || Math.abs((endTime - tl._time) / tl.timeScale()); 2248 tween._dur !== duration && _setDuration(tween, duration, 0, 1).render(tween._time, true, true); 2249 _onStart && _onStart.apply(tween, onStartParams || []); 2250 } 2251 }, vars)); 2252 2253 return immediateRender ? tween.render(0) : tween; 2254 }; 2255 2256 _proto2.tweenFromTo = function tweenFromTo(fromPosition, toPosition, vars) { 2257 return this.tweenTo(toPosition, _setDefaults({ 2258 startAt: { 2259 time: _parsePosition(this, fromPosition) 2260 } 2261 }, vars)); 2262 }; 2263 2264 _proto2.recent = function recent() { 2265 return this._recent; 2266 }; 2267 2268 _proto2.nextLabel = function nextLabel(afterTime) { 2269 if (afterTime === void 0) { 2270 afterTime = this._time; 2271 } 2272 2273 return _getLabelInDirection(this, _parsePosition(this, afterTime)); 2274 }; 2275 2276 _proto2.previousLabel = function previousLabel(beforeTime) { 2277 if (beforeTime === void 0) { 2278 beforeTime = this._time; 2279 } 2280 2281 return _getLabelInDirection(this, _parsePosition(this, beforeTime), 1); 2282 }; 2283 2284 _proto2.currentLabel = function currentLabel(value) { 2285 return arguments.length ? this.seek(value, true) : this.previousLabel(this._time + _tinyNum); 2286 }; 2287 2288 _proto2.shiftChildren = function shiftChildren(amount, adjustLabels, ignoreBeforeTime) { 2289 if (ignoreBeforeTime === void 0) { 2290 ignoreBeforeTime = 0; 2291 } 2292 2293 var child = this._first, 2294 labels = this.labels, 2295 p; 2296 2297 while (child) { 2298 if (child._start >= ignoreBeforeTime) { 2299 child._start += amount; 2300 child._end += amount; 2301 } 2302 2303 child = child._next; 2304 } 2305 2306 if (adjustLabels) { 2307 for (p in labels) { 2308 if (labels[p] >= ignoreBeforeTime) { 2309 labels[p] += amount; 2310 } 2311 } 2312 } 2313 2314 return _uncache(this); 2315 }; 2316 2317 _proto2.invalidate = function invalidate() { 2318 var child = this._first; 2319 this._lock = 0; 2320 2321 while (child) { 2322 child.invalidate(); 2323 child = child._next; 2324 } 2325 2326 return _Animation.prototype.invalidate.call(this); 2327 }; 2328 2329 _proto2.clear = function clear(includeLabels) { 2330 if (includeLabels === void 0) { 2331 includeLabels = true; 2332 } 2333 2334 var child = this._first, 2335 next; 2336 2337 while (child) { 2338 next = child._next; 2339 this.remove(child); 2340 child = next; 2341 } 2342 2343 this._dp && (this._time = this._tTime = this._pTime = 0); 2344 includeLabels && (this.labels = {}); 2345 return _uncache(this); 2346 }; 2347 2348 _proto2.totalDuration = function totalDuration(value) { 2349 var max = 0, 2350 self = this, 2351 child = self._last, 2352 prevStart = _bigNum, 2353 prev, 2354 start, 2355 parent; 2356 2357 if (arguments.length) { 2358 return self.timeScale((self._repeat < 0 ? self.duration() : self.totalDuration()) / (self.reversed() ? -value : value)); 2359 } 2360 2361 if (self._dirty) { 2362 parent = self.parent; 2363 2364 while (child) { 2365 prev = child._prev; 2366 child._dirty && child.totalDuration(); 2367 start = child._start; 2368 2369 if (start > prevStart && self._sort && child._ts && !self._lock) { 2370 self._lock = 1; 2371 _addToTimeline(self, child, start - child._delay, 1)._lock = 0; 2372 } else { 2373 prevStart = start; 2374 } 2375 2376 if (start < 0 && child._ts) { 2377 max -= start; 2378 2379 if (!parent && !self._dp || parent && parent.smoothChildTiming) { 2380 self._start += start / self._ts; 2381 self._time -= start; 2382 self._tTime -= start; 2383 } 2384 2385 self.shiftChildren(-start, false, -1e999); 2386 prevStart = 0; 2387 } 2388 2389 child._end > max && child._ts && (max = child._end); 2390 child = prev; 2391 } 2392 2393 _setDuration(self, self === _globalTimeline && self._time > max ? self._time : max, 1, 1); 2394 2395 self._dirty = 0; 2396 } 2397 2398 return self._tDur; 2399 }; 2400 2401 Timeline.updateRoot = function updateRoot(time) { 2402 if (_globalTimeline._ts) { 2403 _lazySafeRender(_globalTimeline, _parentToChildTotalTime(time, _globalTimeline)); 2404 2405 _lastRenderedFrame = _ticker.frame; 2406 } 2407 2408 if (_ticker.frame >= _nextGCFrame) { 2409 _nextGCFrame += _config.autoSleep || 120; 2410 var child = _globalTimeline._first; 2411 if (!child || !child._ts) if (_config.autoSleep && _ticker._listeners.length < 2) { 2412 while (child && !child._ts) { 2413 child = child._next; 2414 } 2415 2416 child || _ticker.sleep(); 2417 } 2418 } 2419 }; 2420 2421 return Timeline; 2422 }(Animation); 2423 2424 _setDefaults(Timeline.prototype, { 2425 _lock: 0, 2426 _hasPause: 0, 2427 _forcing: 0 2428 }); 2429 2430 var _addComplexStringPropTween = function _addComplexStringPropTween(target, prop, start, end, setter, stringFilter, funcParam) { 2431 var pt = new PropTween(this._pt, target, prop, 0, 1, _renderComplexString, null, setter), 2432 index = 0, 2433 matchIndex = 0, 2434 result, 2435 startNums, 2436 color, 2437 endNum, 2438 chunk, 2439 startNum, 2440 hasRandom, 2441 a; 2442 pt.b = start; 2443 pt.e = end; 2444 start += ""; 2445 end += ""; 2446 2447 if (hasRandom = ~end.indexOf("random(")) { 2448 end = _replaceRandom(end); 2449 } 2450 2451 if (stringFilter) { 2452 a = [start, end]; 2453 stringFilter(a, target, prop); 2454 start = a[0]; 2455 end = a[1]; 2456 } 2457 2458 startNums = start.match(_complexStringNumExp) || []; 2459 2460 while (result = _complexStringNumExp.exec(end)) { 2461 endNum = result[0]; 2462 chunk = end.substring(index, result.index); 2463 2464 if (color) { 2465 color = (color + 1) % 5; 2466 } else if (chunk.substr(-5) === "rgba(") { 2467 color = 1; 2468 } 2469 2470 if (endNum !== startNums[matchIndex++]) { 2471 startNum = parseFloat(startNums[matchIndex - 1]) || 0; 2472 pt._pt = { 2473 _next: pt._pt, 2474 p: chunk || matchIndex === 1 ? chunk : ",", 2475 s: startNum, 2476 c: endNum.charAt(1) === "=" ? parseFloat(endNum.substr(2)) * (endNum.charAt(0) === "-" ? -1 : 1) : parseFloat(endNum) - startNum, 2477 m: color && color < 4 ? Math.round : 0 2478 }; 2479 index = _complexStringNumExp.lastIndex; 2480 } 2481 } 2482 2483 pt.c = index < end.length ? end.substring(index, end.length) : ""; 2484 pt.fp = funcParam; 2485 2486 if (_relExp.test(end) || hasRandom) { 2487 pt.e = 0; 2488 } 2489 2490 this._pt = pt; 2491 return pt; 2492 }, 2493 _addPropTween = function _addPropTween(target, prop, start, end, index, targets, modifier, stringFilter, funcParam) { 2494 _isFunction(end) && (end = end(index || 0, target, targets)); 2495 var currentValue = target[prop], 2496 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](), 2497 setter = !_isFunction(currentValue) ? _setterPlain : funcParam ? _setterFuncWithParam : _setterFunc, 2498 pt; 2499 2500 if (_isString(end)) { 2501 if (~end.indexOf("random(")) { 2502 end = _replaceRandom(end); 2503 } 2504 2505 if (end.charAt(1) === "=") { 2506 end = parseFloat(parsedStart) + parseFloat(end.substr(2)) * (end.charAt(0) === "-" ? -1 : 1) + (getUnit(parsedStart) || 0); 2507 } 2508 } 2509 2510 if (parsedStart !== end) { 2511 if (!isNaN(parsedStart * end)) { 2512 pt = new PropTween(this._pt, target, prop, +parsedStart || 0, end - (parsedStart || 0), typeof currentValue === "boolean" ? _renderBoolean : _renderPlain, 0, setter); 2513 funcParam && (pt.fp = funcParam); 2514 modifier && pt.modifier(modifier, this, target); 2515 return this._pt = pt; 2516 } 2517 2518 !currentValue && !(prop in target) && _missingPlugin(prop, end); 2519 return _addComplexStringPropTween.call(this, target, prop, parsedStart, end, setter, stringFilter || _config.stringFilter, funcParam); 2520 } 2521 }, 2522 _processVars = function _processVars(vars, index, target, targets, tween) { 2523 _isFunction(vars) && (vars = _parseFuncOrString(vars, tween, index, target, targets)); 2524 2525 if (!_isObject(vars) || vars.style && vars.nodeType || _isArray(vars) || _isTypedArray(vars)) { 2526 return _isString(vars) ? _parseFuncOrString(vars, tween, index, target, targets) : vars; 2527 } 2528 2529 var copy = {}, 2530 p; 2531 2532 for (p in vars) { 2533 copy[p] = _parseFuncOrString(vars[p], tween, index, target, targets); 2534 } 2535 2536 return copy; 2537 }, 2538 _checkPlugin = function _checkPlugin(property, vars, tween, index, target, targets) { 2539 var plugin, pt, ptLookup, i; 2540 2541 if (_plugins[property] && (plugin = new _plugins[property]()).init(target, plugin.rawVars ? vars[property] : _processVars(vars[property], index, target, targets, tween), tween, index, targets) !== false) { 2542 tween._pt = pt = new PropTween(tween._pt, target, property, 0, 1, plugin.render, plugin, 0, plugin.priority); 2543 2544 if (tween !== _quickTween) { 2545 ptLookup = tween._ptLookup[tween._targets.indexOf(target)]; 2546 i = plugin._props.length; 2547 2548 while (i--) { 2549 ptLookup[plugin._props[i]] = pt; 2550 } 2551 } 2552 } 2553 2554 return plugin; 2555 }, 2556 _overwritingTween, 2557 _initTween = function _initTween(tween, time) { 2558 var vars = tween.vars, 2559 ease = vars.ease, 2560 startAt = vars.startAt, 2561 immediateRender = vars.immediateRender, 2562 lazy = vars.lazy, 2563 onUpdate = vars.onUpdate, 2564 onUpdateParams = vars.onUpdateParams, 2565 callbackScope = vars.callbackScope, 2566 runBackwards = vars.runBackwards, 2567 yoyoEase = vars.yoyoEase, 2568 keyframes = vars.keyframes, 2569 autoRevert = vars.autoRevert, 2570 dur = tween._dur, 2571 prevStartAt = tween._startAt, 2572 targets = tween._targets, 2573 parent = tween.parent, 2574 fullTargets = parent && parent.data === "nested" ? parent.parent._targets : targets, 2575 autoOverwrite = tween._overwrite === "auto" && !_suppressOverwrites, 2576 tl = tween.timeline, 2577 cleanVars, 2578 i, 2579 p, 2580 pt, 2581 target, 2582 hasPriority, 2583 gsData, 2584 harness, 2585 plugin, 2586 ptLookup, 2587 index, 2588 harnessVars, 2589 overwritten; 2590 tl && (!keyframes || !ease) && (ease = "none"); 2591 tween._ease = _parseEase(ease, _defaults.ease); 2592 tween._yEase = yoyoEase ? _invertEase(_parseEase(yoyoEase === true ? ease : yoyoEase, _defaults.ease)) : 0; 2593 2594 if (yoyoEase && tween._yoyo && !tween._repeat) { 2595 yoyoEase = tween._yEase; 2596 tween._yEase = tween._ease; 2597 tween._ease = yoyoEase; 2598 } 2599 2600 if (!tl) { 2601 harness = targets[0] ? _getCache(targets[0]).harness : 0; 2602 harnessVars = harness && vars[harness.prop]; 2603 cleanVars = _copyExcluding(vars, _reservedProps); 2604 prevStartAt && prevStartAt.render(-1, true).kill(); 2605 2606 if (startAt) { 2607 _removeFromParent(tween._startAt = Tween.set(targets, _setDefaults({ 2608 data: "isStart", 2609 overwrite: false, 2610 parent: parent, 2611 immediateRender: true, 2612 lazy: _isNotFalse(lazy), 2613 startAt: null, 2614 delay: 0, 2615 onUpdate: onUpdate, 2616 onUpdateParams: onUpdateParams, 2617 callbackScope: callbackScope, 2618 stagger: 0 2619 }, startAt))); 2620 2621 if (immediateRender) { 2622 if (time > 0) { 2623 autoRevert || (tween._startAt = 0); 2624 } else if (dur && !(time < 0 && prevStartAt)) { 2625 time && (tween._zTime = time); 2626 return; 2627 } 2628 } else if (autoRevert === false) { 2629 tween._startAt = 0; 2630 } 2631 } else if (runBackwards && dur) { 2632 if (prevStartAt) { 2633 !autoRevert && (tween._startAt = 0); 2634 } else { 2635 time && (immediateRender = false); 2636 p = _setDefaults({ 2637 overwrite: false, 2638 data: "isFromStart", 2639 lazy: immediateRender && _isNotFalse(lazy), 2640 immediateRender: immediateRender, 2641 stagger: 0, 2642 parent: parent 2643 }, cleanVars); 2644 harnessVars && (p[harness.prop] = harnessVars); 2645 2646 _removeFromParent(tween._startAt = Tween.set(targets, p)); 2647 2648 if (!immediateRender) { 2649 _initTween(tween._startAt, _tinyNum); 2650 } else if (!time) { 2651 return; 2652 } 2653 } 2654 } 2655 2656 tween._pt = 0; 2657 lazy = dur && _isNotFalse(lazy) || lazy && !dur; 2658 2659 for (i = 0; i < targets.length; i++) { 2660 target = targets[i]; 2661 gsData = target._gsap || _harness(targets)[i]._gsap; 2662 tween._ptLookup[i] = ptLookup = {}; 2663 _lazyLookup[gsData.id] && _lazyTweens.length && _lazyRender(); 2664 index = fullTargets === targets ? i : fullTargets.indexOf(target); 2665 2666 if (harness && (plugin = new harness()).init(target, harnessVars || cleanVars, tween, index, fullTargets) !== false) { 2667 tween._pt = pt = new PropTween(tween._pt, target, plugin.name, 0, 1, plugin.render, plugin, 0, plugin.priority); 2668 2669 plugin._props.forEach(function (name) { 2670 ptLookup[name] = pt; 2671 }); 2672 2673 plugin.priority && (hasPriority = 1); 2674 } 2675 2676 if (!harness || harnessVars) { 2677 for (p in cleanVars) { 2678 if (_plugins[p] && (plugin = _checkPlugin(p, cleanVars, tween, index, target, fullTargets))) { 2679 plugin.priority && (hasPriority = 1); 2680 } else { 2681 ptLookup[p] = pt = _addPropTween.call(tween, target, p, "get", cleanVars[p], index, fullTargets, 0, vars.stringFilter); 2682 } 2683 } 2684 } 2685 2686 tween._op && tween._op[i] && tween.kill(target, tween._op[i]); 2687 2688 if (autoOverwrite && tween._pt) { 2689 _overwritingTween = tween; 2690 2691 _globalTimeline.killTweensOf(target, ptLookup, tween.globalTime(0)); 2692 2693 overwritten = !tween.parent; 2694 _overwritingTween = 0; 2695 } 2696 2697 tween._pt && lazy && (_lazyLookup[gsData.id] = 1); 2698 } 2699 2700 hasPriority && _sortPropTweensByPriority(tween); 2701 tween._onInit && tween._onInit(tween); 2702 } 2703 2704 tween._from = !tl && !!vars.runBackwards; 2705 tween._onUpdate = onUpdate; 2706 tween._initted = (!tween._op || tween._pt) && !overwritten; 2707 }, 2708 _addAliasesToVars = function _addAliasesToVars(targets, vars) { 2709 var harness = targets[0] ? _getCache(targets[0]).harness : 0, 2710 propertyAliases = harness && harness.aliases, 2711 copy, 2712 p, 2713 i, 2714 aliases; 2715 2716 if (!propertyAliases) { 2717 return vars; 2718 } 2719
2720 copy = _merge({}, vars); 2721 2722 for (p in propertyAliases) { 2723 if (p in copy) { 2724 aliases = propertyAliases[p].split(","); 2725 i = aliases.length; 2726 2727 while (i--) { 2728 copy[aliases[i]] = copy[p]; 2729 } 2730 } 2731 } 2732 2733 return copy; 2734 }, 2735 _parseFuncOrString = function _parseFuncOrString(value, tween, i, target, targets) { 2736 return _isFunction(value) ? value.call(tween, i, target, targets) : _isString(value) && ~value.indexOf("random(") ? _replaceRandom(value) : value; 2737 }, 2738 _staggerTweenProps = _callbackNames + "repeat,repeatDelay,yoyo,repeatRefresh,yoyoEase", 2739 _staggerPropsToSkip = (_staggerTweenProps + ",id,stagger,delay,duration,paused,scrollTrigger").split(","); 2740 2741 var Tween = function (_Animation2) { 2742 _inheritsLoose(Tween, _Animation2); 2743 2744 function Tween(targets, vars, time, skipInherit) { 2745 var _this3; 2746 2747 if (typeof vars === "number") { 2748 time.duration = vars; 2749 vars = time; 2750 time = null; 2751 } 2752 2753 _this3 = _Animation2.call(this, skipInherit ? vars : _inheritDefaults(vars), time) || this; 2754 var _this3$vars = _this3.vars, 2755 duration = _this3$vars.duration, 2756 delay = _this3$vars.delay, 2757 immediateRender = _this3$vars.immediateRender, 2758 stagger = _this3$vars.stagger, 2759 overwrite = _this3$vars.overwrite, 2760 keyframes = _this3$vars.keyframes, 2761 defaults = _this3$vars.defaults, 2762 scrollTrigger = _this3$vars.scrollTrigger, 2763 yoyoEase = _this3$vars.yoyoEase, 2764 parent = _this3.parent, 2765 parsedTargets = (_isArray(targets) || _isTypedArray(targets) ? _isNumber(targets[0]) : "length" in vars) ? [targets] : toArray(targets), 2766 tl, 2767 i, 2768 copy, 2769 l, 2770 p, 2771 curTarget, 2772 staggerFunc, 2773 staggerVarsToMerge; 2774 _this3._targets = parsedTargets.length ? _harness(parsedTargets) : _warn("GSAP target " + targets + " not found. https://greensock.com", !_config.nullTargetWarn) || []; 2775 _this3._ptLookup = []; 2776 _this3._overwrite = overwrite; 2777 2778 if (keyframes || stagger || _isFuncOrString(duration) || _isFuncOrString(delay)) { 2779 vars = _this3.vars; 2780 tl = _this3.timeline = new Timeline({ 2781 data: "nested", 2782 defaults: defaults || {} 2783 }); 2784 tl.kill(); 2785 tl.parent = tl._dp = _assertThisInitialized(_this3); 2786 tl._start = 0; 2787 2788 if (keyframes) { 2789 _setDefaults(tl.vars.defaults, { 2790 ease: "none" 2791 }); 2792 2793 keyframes.forEach(function (frame) { 2794 return tl.to(parsedTargets, frame, ">"); 2795 }); 2796 } else { 2797 l = parsedTargets.length; 2798 staggerFunc = stagger ? distribute(stagger) : _emptyFunc; 2799 2800 if (_isObject(stagger)) { 2801 for (p in stagger) { 2802 if (~_staggerTweenProps.indexOf(p)) { 2803 staggerVarsToMerge || (staggerVarsToMerge = {}); 2804 staggerVarsToMerge[p] = stagger[p]; 2805 } 2806 } 2807 } 2808 2809 for (i = 0; i < l; i++) { 2810 copy = {}; 2811 2812 for (p in vars) { 2813 if (_staggerPropsToSkip.indexOf(p) < 0) { 2814 copy[p] = vars[p]; 2815 } 2816 } 2817 2818 copy.stagger = 0; 2819 yoyoEase && (copy.yoyoEase = yoyoEase); 2820 staggerVarsToMerge && _merge(copy, staggerVarsToMerge); 2821 curTarget = parsedTargets[i]; 2822 copy.duration = +_parseFuncOrString(duration, _assertThisInitialized(_this3), i, curTarget, parsedTargets); 2823 copy.delay = (+_parseFuncOrString(delay, _assertThisInitialized(_this3), i, curTarget, parsedTargets) || 0) - _this3._delay; 2824 2825 if (!stagger && l === 1 && copy.delay) { 2826 _this3._delay = delay = copy.delay; 2827 _this3._start += delay; 2828 copy.delay = 0; 2829 } 2830 2831 tl.to(curTarget, copy, staggerFunc(i, curTarget, parsedTargets)); 2832 } 2833 2834 tl.duration() ? duration = delay = 0 : _this3.timeline = 0; 2835 } 2836 2837 duration || _this3.duration(duration = tl.duration()); 2838 } else { 2839 _this3.timeline = 0; 2840 } 2841 2842 if (overwrite === true && !_suppressOverwrites) { 2843 _overwritingTween = _assertThisInitialized(_this3); 2844 2845 _globalTimeline.killTweensOf(parsedTargets); 2846 2847 _overwritingTween = 0; 2848 } 2849 2850 parent && _postAddChecks(parent, _assertThisInitialized(_this3)); 2851 2852 if (immediateRender || !duration && !keyframes && _this3._start === _round(parent._time) && _isNotFalse(immediateRender) && _hasNoPausedAncestors(_assertThisInitialized(_this3)) && parent.data !== "nested") { 2853 _this3._tTime = -_tinyNum; 2854 2855 _this3.render(Math.max(0, -delay)); 2856 } 2857 2858 scrollTrigger && _scrollTrigger(_assertThisInitialized(_this3), scrollTrigger); 2859 return _this3; 2860 } 2861 2862 var _proto3 = Tween.prototype; 2863 2864 _proto3.render = function render(totalTime, suppressEvents, force) { 2865 var prevTime = this._time, 2866 tDur = this._tDur, 2867 dur = this._dur, 2868 tTime = totalTime > tDur - _tinyNum && totalTime >= 0 ? tDur : totalTime < _tinyNum ? 0 : totalTime, 2869 time, 2870 pt, 2871 iteration, 2872 cycleDuration, 2873 prevIteration, 2874 isYoyo, 2875 ratio, 2876 timeline, 2877 yoyoEase; 2878 2879 if (!dur) { 2880 _renderZeroDurationTween(this, totalTime, suppressEvents, force); 2881 } else if (tTime !== this._tTime || !totalTime || force || !this._initted && this._tTime || this._startAt && this._zTime < 0 !== totalTime < 0) { 2882 time = tTime; 2883 timeline = this.timeline; 2884 2885 if (this._repeat) { 2886 cycleDuration = dur + this._rDelay; 2887 2888 if (this._repeat < -1 && totalTime < 0) { 2889 return this.totalTime(cycleDuration * 100 + totalTime, suppressEvents, force); 2890 } 2891 2892 time = _round(tTime % cycleDuration); 2893 2894 if (tTime === tDur) { 2895 iteration = this._repeat; 2896 time = dur; 2897 } else { 2898 iteration = ~~(tTime / cycleDuration); 2899 2900 if (iteration && iteration === tTime / cycleDuration) { 2901 time = dur; 2902 iteration--; 2903 } 2904 2905 time > dur && (time = dur); 2906 } 2907 2908 isYoyo = this._yoyo && iteration & 1; 2909 2910 if (isYoyo) { 2911 yoyoEase = this._yEase; 2912 time = dur - time; 2913 } 2914 2915 prevIteration = _animationCycle(this._tTime, cycleDuration); 2916 2917 if (time === prevTime && !force && this._initted) { 2918 return this; 2919 } 2920 2921 if (iteration !== prevIteration) { 2922 timeline && this._yEase && _propagateYoyoEase(timeline, isYoyo); 2923 2924 if (this.vars.repeatRefresh && !isYoyo && !this._lock) { 2925 this._lock = force = 1; 2926 this.render(_round(cycleDuration * iteration), true).invalidate()._lock = 0; 2927 } 2928 } 2929 } 2930 2931 if (!this._initted) { 2932 if (_attemptInitTween(this, totalTime < 0 ? totalTime : time, force, suppressEvents)) { 2933 this._tTime = 0; 2934 return this; 2935 } 2936 2937 if (dur !== this._dur) { 2938 return this.render(totalTime, suppressEvents, force); 2939 } 2940 } 2941 2942 this._tTime = tTime; 2943 this._time = time; 2944 2945 if (!this._act && this._ts) { 2946 this._act = 1; 2947 this._lazy = 0; 2948 } 2949 2950 this.ratio = ratio = (yoyoEase || this._ease)(time / dur); 2951 2952 if (this._from) { 2953 this.ratio = ratio = 1 - ratio; 2954 } 2955
2956 time && !prevTime && !suppressEvents && _callback(this, "onStart"); 2957 pt = this._pt; 2958 2959 while (pt) { 2960 pt.r(ratio, pt.d); 2961 pt = pt._next; 2962 } 2963 2964 timeline && timeline.render(totalTime < 0 ? totalTime : !time && isYoyo ? -_tinyNum : timeline._dur * ratio, suppressEvents, force) || this._startAt && (this._zTime = totalTime); 2965 2966 if (this._onUpdate && !suppressEvents) { 2967 totalTime < 0 && this._startAt && this._startAt.render(totalTime, true, force); 2968 2969 _callback(this, "onUpdate"); 2970 } 2971 2972 this._repeat && iteration !== prevIteration && this.vars.onRepeat && !suppressEvents && this.parent && _callback(this, "onRepeat"); 2973 2974 if ((tTime === this._tDur || !tTime) && this._tTime === tTime) { 2975 totalTime < 0 && this._startAt && !this._onUpdate && this._startAt.render(totalTime, true, true); 2976 (totalTime || !dur) && (tTime === this._tDur && this._ts > 0 || !tTime && this._ts < 0) && _removeFromParent(this, 1); 2977 2978 if (!suppressEvents && !(totalTime < 0 && !prevTime) && (tTime || prevTime)) { 2979 _callback(this, tTime === tDur ? "onComplete" : "onReverseComplete", true); 2980 2981 this._prom && !(tTime < tDur && this.timeScale() > 0) && this._prom(); 2982 } 2983 } 2984 } 2985 2986 return this; 2987 }; 2988 2989 _proto3.targets = function targets() { 2990 return this._targets; 2991 }; 2992
vendor: 12,946 bytes, lines 2993-3420
2993 _proto3.invalidate = function invalidate() { 2994 this._pt = this._op = this._startAt = this._onUpdate = this._lazy = this.ratio = 0; 2995 this._ptLookup = []; 2996 this.timeline && this.timeline.invalidate(); 2997 return _Animation2.prototype.invalidate.call(this); 2998 }; 2999 3000 _proto3.kill = function kill(targets, vars) { 3001 if (vars === void 0) { 3002 vars = "all"; 3003 } 3004 3005 if (!targets && (!vars || vars === "all")) { 3006 this._lazy = this._pt = 0; 3007 return this.parent ? _interrupt(this) : this; 3008 } 3009 3010 if (this.timeline) { 3011 var tDur = this.timeline.totalDuration(); 3012 this.timeline.killTweensOf(targets, vars, _overwritingTween && _overwritingTween.vars.overwrite !== true)._first || _interrupt(this); 3013 this.parent && tDur !== this.timeline.totalDuration() && _setDuration(this, this._dur * this.timeline._tDur / tDur, 0, 1); 3014 return this; 3015 } 3016 3017 var parsedTargets = this._targets, 3018 killingTargets = targets ? toArray(targets) : parsedTargets, 3019 propTweenLookup = this._ptLookup, 3020 firstPT = this._pt, 3021 overwrittenProps, 3022 curLookup, 3023 curOverwriteProps, 3024 props, 3025 p, 3026 pt, 3027 i; 3028 3029 if ((!vars || vars === "all") && _arraysMatch(parsedTargets, killingTargets)) { 3030 vars === "all" && (this._pt = 0); 3031 return _interrupt(this); 3032 } 3033 3034 overwrittenProps = this._op = this._op || []; 3035 3036 if (vars !== "all") { 3037 if (_isString(vars)) { 3038 p = {}; 3039 3040 _forEachName(vars, function (name) { 3041 return p[name] = 1; 3042 }); 3043 3044 vars = p; 3045 } 3046 3047 vars = _addAliasesToVars(parsedTargets, vars); 3048 } 3049 3050 i = parsedTargets.length; 3051 3052 while (i--) { 3053 if (~killingTargets.indexOf(parsedTargets[i])) { 3054 curLookup = propTweenLookup[i]; 3055 3056 if (vars === "all") { 3057 overwrittenProps[i] = vars; 3058 props = curLookup; 3059 curOverwriteProps = {}; 3060 } else { 3061 curOverwriteProps = overwrittenProps[i] = overwrittenProps[i] || {}; 3062 props = vars; 3063 } 3064 3065 for (p in props) { 3066 pt = curLookup && curLookup[p]; 3067 3068 if (pt) { 3069 if (!("kill" in pt.d) || pt.d.kill(p) === true) { 3070 _removeLinkedListItem(this, pt, "_pt"); 3071 } 3072 3073 delete curLookup[p]; 3074 } 3075 3076 if (curOverwriteProps !== "all") { 3077 curOverwriteProps[p] = 1; 3078 } 3079 } 3080 } 3081 } 3082 3083 this._initted && !this._pt && firstPT && _interrupt(this); 3084 return this; 3085 }; 3086 3087 Tween.to = function to(targets, vars) { 3088 return new Tween(targets, vars, arguments[2]); 3089 }; 3090 3091 Tween.from = function from(targets, vars) { 3092 return new Tween(targets, _parseVars(arguments, 1)); 3093 }; 3094 3095 Tween.delayedCall = function delayedCall(delay, callback, params, scope) { 3096 return new Tween(callback, 0, { 3097 immediateRender: false, 3098 lazy: false, 3099 overwrite: false, 3100 delay: delay, 3101 onComplete: callback, 3102 onReverseComplete: callback, 3103 onCompleteParams: params, 3104 onReverseCompleteParams: params, 3105 callbackScope: scope 3106 }); 3107 }; 3108 3109 Tween.fromTo = function fromTo(targets, fromVars, toVars) { 3110 return new Tween(targets, _parseVars(arguments, 2)); 3111 }; 3112 3113 Tween.set = function set(targets, vars) { 3114 vars.duration = 0; 3115 vars.repeatDelay || (vars.repeat = 0); 3116 return new Tween(targets, vars); 3117 }; 3118 3119 Tween.killTweensOf = function killTweensOf(targets, props, onlyActive) { 3120 return _globalTimeline.killTweensOf(targets, props, onlyActive); 3121 }; 3122 3123 return Tween; 3124 }(Animation); 3125 3126 _setDefaults(Tween.prototype, { 3127 _targets: [], 3128 _lazy: 0, 3129 _startAt: 0, 3130 _op: 0, 3131 _onInit: 0 3132 }); 3133 3134 _forEachName("staggerTo,staggerFrom,staggerFromTo", function (name) { 3135 Tween[name] = function () { 3136 var tl = new Timeline(), 3137 params = _slice.call(arguments, 0); 3138 3139 params.splice(name === "staggerFromTo" ? 5 : 4, 0, 0); 3140 return tl[name].apply(tl, params); 3141 }; 3142 }); 3143 3144 var _setterPlain = function _setterPlain(target, property, value) { 3145 return target[property] = value; 3146 }, 3147 _setterFunc = function _setterFunc(target, property, value) { 3148 return target[property](value); 3149 }, 3150 _setterFuncWithParam = function _setterFuncWithParam(target, property, value, data) { 3151 return target[property](data.fp, value); 3152 }, 3153 _setterAttribute = function _setterAttribute(target, property, value) { 3154 return target.setAttribute(property, value); 3155 }, 3156 _getSetter = function _getSetter(target, property) { 3157 return _isFunction(target[property]) ? _setterFunc : _isUndefined(target[property]) && target.setAttribute ? _setterAttribute : _setterPlain; 3158 }, 3159 _renderPlain = function _renderPlain(ratio, data) { 3160 return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000, data); 3161 }, 3162 _renderBoolean = function _renderBoolean(ratio, data) { 3163 return data.set(data.t, data.p, !!(data.s + data.c * ratio), data); 3164 }, 3165 _renderComplexString = function _renderComplexString(ratio, data) { 3166 var pt = data._pt, 3167 s = ""; 3168 3169 if (!ratio && data.b) { 3170 s = data.b; 3171 } else if (ratio === 1 && data.e) { 3172 s = data.e; 3173 } else { 3174 while (pt) { 3175 s = pt.p + (pt.m ? pt.m(pt.s + pt.c * ratio) : Math.round((pt.s + pt.c * ratio) * 10000) / 10000) + s; 3176 pt = pt._next; 3177 } 3178 3179 s += data.c; 3180 } 3181 3182 data.set(data.t, data.p, s, data); 3183 }, 3184 _renderPropTweens = function _renderPropTweens(ratio, data) { 3185 var pt = data._pt; 3186 3187 while (pt) { 3188 pt.r(ratio, pt.d); 3189 pt = pt._next; 3190 } 3191 }, 3192 _addPluginModifier = function _addPluginModifier(modifier, tween, target, property) { 3193 var pt = this._pt, 3194 next; 3195 3196 while (pt) { 3197 next = pt._next; 3198 pt.p === property && pt.modifier(modifier, tween, target); 3199 pt = next; 3200 } 3201 }, 3202 _killPropTweensOf = function _killPropTweensOf(property) { 3203 var pt = this._pt, 3204 hasNonDependentRemaining, 3205 next; 3206 3207 while (pt) { 3208 next = pt._next; 3209 3210 if (pt.p === property && !pt.op || pt.op === property) { 3211 _removeLinkedListItem(this, pt, "_pt"); 3212 } else if (!pt.dep) { 3213 hasNonDependentRemaining = 1; 3214 } 3215 3216 pt = next; 3217 } 3218 3219 return !hasNonDependentRemaining; 3220 }, 3221 _setterWithModifier = function _setterWithModifier(target, property, value, data) { 3222 data.mSet(target, property, data.m.call(data.tween, value, data.mt), data); 3223 }, 3224 _sortPropTweensByPriority = function _sortPropTweensByPriority(parent) { 3225 var pt = parent._pt, 3226 next, 3227 pt2, 3228 first, 3229 last; 3230 3231 while (pt) { 3232 next = pt._next; 3233 pt2 = first; 3234 3235 while (pt2 && pt2.pr > pt.pr) { 3236 pt2 = pt2._next; 3237 } 3238 3239 if (pt._prev = pt2 ? pt2._prev : last) { 3240 pt._prev._next = pt; 3241 } else { 3242 first = pt; 3243 } 3244 3245 if (pt._next = pt2) { 3246 pt2._prev = pt; 3247 } else { 3248 last = pt; 3249 } 3250 3251 pt = next; 3252 } 3253 3254 parent._pt = first; 3255 }; 3256 3257 var PropTween = function () { 3258 function PropTween(next, target, prop, start, change, renderer, data, setter, priority) { 3259 this.t = target; 3260 this.s = start; 3261 this.c = change; 3262 this.p = prop; 3263 this.r = renderer || _renderPlain; 3264 this.d = data || this; 3265 this.set = setter || _setterPlain; 3266 this.pr = priority || 0; 3267 this._next = next; 3268 3269 if (next) { 3270 next._prev = this; 3271 } 3272 } 3273 3274 var _proto4 = PropTween.prototype; 3275 3276 _proto4.modifier = function modifier(func, tween, target) { 3277 this.mSet = this.mSet || this.set; 3278 this.set = _setterWithModifier; 3279 this.m = func; 3280 this.mt = target; 3281 this.tween = tween; 3282 }; 3283 3284 return PropTween; 3285 }(); 3286 3287 _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", function (name) { 3288 return _reservedProps[name] = 1; 3289 }); 3290 3291 _globals.TweenMax = _globals.TweenLite = Tween; 3292 _globals.TimelineLite = _globals.TimelineMax = Timeline; 3293 _globalTimeline = new Timeline({ 3294 sortChildren: false, 3295 defaults: _defaults, 3296 autoRemoveChildren: true, 3297 id: "root", 3298 smoothChildTiming: true 3299 }); 3300 _config.stringFilter = _colorStringFilter; 3301 var _gsap = { 3302 registerPlugin: function registerPlugin() { 3303 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 3304 args[_key2] = arguments[_key2]; 3305 } 3306 3307 args.forEach(function (config) { 3308 return _createPlugin(config); 3309 }); 3310 }, 3311 timeline: function timeline(vars) { 3312 return new Timeline(vars); 3313 }, 3314 getTweensOf: function getTweensOf(targets, onlyActive) { 3315 return _globalTimeline.getTweensOf(targets, onlyActive); 3316 }, 3317 getProperty: function getProperty(target, property, unit, uncache) { 3318 _isString(target) && (target = toArray(target)[0]); 3319 3320 var getter = _getCache(target || {}).get, 3321 format = unit ? _passThrough : _numericIfPossible; 3322 3323 unit === "native" && (unit = ""); 3324 return !target ? target : !property ? function (property, unit, uncache) { 3325 return format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache)); 3326 } : format((_plugins[property] && _plugins[property].get || getter)(target, property, unit, uncache)); 3327 }, 3328 quickSetter: function quickSetter(target, property, unit) { 3329 target = toArray(target); 3330 3331 if (target.length > 1) { 3332 var setters = target.map(function (t) { 3333 return gsap.quickSetter(t, property, unit); 3334 }), 3335 l = setters.length; 3336 return function (value) { 3337 var i = l; 3338 3339 while (i--) { 3340 setters[i](value); 3341 } 3342 }; 3343 } 3344 3345 target = target[0] || {}; 3346 3347 var Plugin = _plugins[property], 3348 cache = _getCache(target), 3349 p = cache.harness && (cache.harness.aliases || {})[property] || property, 3350 setter = Plugin ? function (value) { 3351 var p = new Plugin(); 3352 _quickTween._pt = 0; 3353 p.init(target, unit ? value + unit : value, _quickTween, 0, [target]); 3354 p.render(1, p); 3355 _quickTween._pt && _renderPropTweens(1, _quickTween); 3356 } : cache.set(target, p); 3357 3358 return Plugin ? setter : function (value) { 3359 return setter(target, p, unit ? value + unit : value, cache, 1); 3360 }; 3361 }, 3362 isTweening: function isTweening(targets) { 3363 return _globalTimeline.getTweensOf(targets, true).length > 0; 3364 }, 3365 defaults: function defaults(value) { 3366 value && value.ease && (value.ease = _parseEase(value.ease, _defaults.ease)); 3367 return _mergeDeep(_defaults, value || {}); 3368 }, 3369 config: function config(value) { 3370 return _mergeDeep(_config, value || {}); 3371 }, 3372 registerEffect: function registerEffect(_ref2) { 3373 var name = _ref2.name, 3374 effect = _ref2.effect, 3375 plugins = _ref2.plugins, 3376 defaults = _ref2.defaults, 3377 extendTimeline = _ref2.extendTimeline; 3378 (plugins || "").split(",").forEach(function (pluginName) { 3379 return pluginName && !_plugins[pluginName] && !_globals[pluginName] && _warn(name + " effect requires " + pluginName + " plugin."); 3380 }); 3381 3382 _effects[name] = function (targets, vars, tl) { 3383 return effect(toArray(targets), _setDefaults(vars || {}, defaults), tl); 3384 }; 3385 3386 if (extendTimeline) { 3387 Timeline.prototype[name] = function (targets, vars, position) { 3388 return this.add(_effects[name](targets, _isObject(vars) ? vars : (position = vars) && {}, this), position); 3389 }; 3390 } 3391 }, 3392 registerEase: function registerEase(name, ease) { 3393 _easeMap[name] = _parseEase(ease); 3394 }, 3395 parseEase: function parseEase(ease, defaultEase) { 3396 return arguments.length ? _parseEase(ease, defaultEase) : _easeMap; 3397 }, 3398 getById: function getById(id) { 3399 return _globalTimeline.getById(id); 3400 }, 3401 exportRoot: function exportRoot(vars, includeDelayedCalls) { 3402 if (vars === void 0) { 3403 vars = {}; 3404 } 3405 3406 var tl = new Timeline(vars), 3407 child, 3408 next; 3409 tl.smoothChildTiming = _isNotFalse(vars.smoothChildTiming); 3410 3411 _globalTimeline.remove(tl); 3412 3413 tl._dp = 0; 3414 tl._time = tl._tTime = _globalTimeline._time; 3415 child = _globalTimeline._first; 3416 3417 while (child) { 3418 next = child._next; 3419 3420 if (includeDelayedCalls || !(!child._dur && child instanceof Tween && child.vars.onComplete === child._targets[0])) {
3421 _addToTimeline(tl, child, child._start - child._delay); 3422 } 3423 3424 child = next; 3425 } 3426 3427 _addToTimeline(_globalTimeline, tl, 0); 3428 3429 return tl; 3430 }, 3431 utils: { 3432 wrap: wrap, 3433 wrapYoyo: wrapYoyo, 3434 distribute: distribute, 3435 random: random, 3436 snap: snap, 3437 normalize: normalize, 3438 getUnit: getUnit, 3439 clamp: clamp, 3440 splitColor: splitColor, 3441 toArray: toArray, 3442 mapRange: mapRange, 3443 pipe: pipe, 3444 unitize: unitize, 3445 interpolate: interpolate, 3446 shuffle: shuffle 3447 }, 3448 install: _install, 3449 effects: _effects, 3450 ticker: _ticker, 3451 updateRoot: Timeline.updateRoot, 3452 plugins: _plugins, 3453 globalTimeline: _globalTimeline, 3454 core: { 3455 PropTween: PropTween, 3456 globals: _addGlobal, 3457 Tween: Tween, 3458 Timeline: Timeline, 3459 Animation: Animation, 3460 getCache: _getCache, 3461 _removeLinkedListItem: _removeLinkedListItem, 3462 suppressOverwrites: function suppressOverwrites(value) { 3463 return _suppressOverwrites = value; 3464 } 3465 } 3466 }; 3467 3468 _forEachName("to,from,fromTo,delayedCall,set,killTweensOf", function (name) { 3469 return _gsap[name] = Tween[name]; 3470 }); 3471 3472 _ticker.add(Timeline.updateRoot); 3473 3474 _quickTween = _gsap.to({}, { 3475 duration: 0 3476 }); 3477 3478 var _getPluginPropTween = function _getPluginPropTween(plugin, prop
vendor: 18,114 bytes, lines 3478-4050
3478) { 3479 var pt = plugin._pt; 3480 3481 while (pt && pt.p !== prop && pt.op !== prop && pt.fp !== prop) { 3482 pt = pt._next; 3483 } 3484 3485 return pt; 3486 }, 3487 _addModifiers = function _addModifiers(tween, modifiers) { 3488 var targets = tween._targets, 3489 p, 3490 i, 3491 pt; 3492 3493 for (p in modifiers) { 3494 i = targets.length; 3495 3496 while (i--) { 3497 pt = tween._ptLookup[i][p]; 3498 3499 if (pt && (pt = pt.d)) { 3500 if (pt._pt) { 3501 pt = _getPluginPropTween(pt, p); 3502 } 3503 3504 pt && pt.modifier && pt.modifier(modifiers[p], tween, targets[i], p); 3505 } 3506 } 3507 } 3508 }, 3509 _buildModifierPlugin = function _buildModifierPlugin(name, modifier) { 3510 return { 3511 name: name, 3512 rawVars: 1, 3513 init: function init(target, vars, tween) { 3514 tween._onInit = function (tween) { 3515 var temp, p; 3516 3517 if (_isString(vars)) { 3518 temp = {}; 3519 3520 _forEachName(vars, function (name) { 3521 return temp[name] = 1; 3522 }); 3523 3524 vars = temp; 3525 } 3526 3527 if (modifier) { 3528 temp = {}; 3529 3530 for (p in vars) { 3531 temp[p] = modifier(vars[p]); 3532 } 3533 3534 vars = temp; 3535 } 3536 3537 _addModifiers(tween, vars); 3538 }; 3539 } 3540 }; 3541 }; 3542 3543 var gsap = _gsap.registerPlugin({ 3544 name: "attr", 3545 init: function init(target, vars, tween, index, targets) { 3546 var p, pt; 3547 3548 for (p in vars) { 3549 pt = this.add(target, "setAttribute", (target.getAttribute(p) || 0) + "", vars[p], index, targets, 0, 0, p); 3550 pt && (pt.op = p); 3551 3552 this._props.push(p); 3553 } 3554 } 3555 }, { 3556 name: "endArray", 3557 init: function init(target, value) { 3558 var i = value.length; 3559 3560 while (i--) { 3561 this.add(target, i, target[i] || 0, value[i]); 3562 } 3563 } 3564 }, _buildModifierPlugin("roundProps", _roundModifier), _buildModifierPlugin("modifiers"), _buildModifierPlugin("snap", snap)) || _gsap; 3565 Tween.version = Timeline.version = gsap.version = "3.6.1"; 3566 _coreReady = 1; 3567 3568 if (_windowExists()) { 3569 _wake(); 3570 } 3571 3572 var Power0 = _easeMap.Power0, 3573 Power1 = _easeMap.Power1, 3574 Power2 = _easeMap.Power2, 3575 Power3 = _easeMap.Power3, 3576 Power4 = _easeMap.Power4, 3577 Linear = _easeMap.Linear, 3578 Quad = _easeMap.Quad, 3579 Cubic = _easeMap.Cubic, 3580 Quart = _easeMap.Quart, 3581 Quint = _easeMap.Quint, 3582 Strong = _easeMap.Strong, 3583 Elastic = _easeMap.Elastic, 3584 Back = _easeMap.Back, 3585 SteppedEase = _easeMap.SteppedEase, 3586 Bounce = _easeMap.Bounce, 3587 Sine = _easeMap.Sine, 3588 Expo = _easeMap.Expo, 3589 Circ = _easeMap.Circ; 3590 3591 var _win$1, 3592 _doc$1, 3593 _docElement, 3594 _pluginInitted, 3595 _tempDiv, 3596 _tempDivStyler, 3597 _recentSetterPlugin, 3598 _windowExists$1 = function _windowExists() { 3599 return typeof window !== "undefined"; 3600 }, 3601 _transformProps = {}, 3602 _RAD2DEG = 180 / Math.PI, 3603 _DEG2RAD = Math.PI / 180, 3604 _atan2 = Math.atan2, 3605 _bigNum$1 = 1e8, 3606 _capsExp = /([A-Z])/g, 3607 _horizontalExp = /(?:left|right|width|margin|padding|x)/i, 3608 _complexExp = /[\s,\(]\S/, 3609 _propertyAliases = { 3610 autoAlpha: "opacity,visibility", 3611 scale: "scaleX,scaleY", 3612 alpha: "opacity" 3613 }, 3614 _renderCSSProp = function _renderCSSProp(ratio, data) { 3615 return data.set(data.t, data.p, Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); 3616 }, 3617 _renderPropWithEnd = function _renderPropWithEnd(ratio, data) { 3618 return data.set(data.t, data.p, ratio === 1 ? data.e : Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u, data); 3619 }, 3620 _renderCSSPropWithBeginning = function _renderCSSPropWithBeginning(ratio, data) { 3621 return data.set(data.t, data.p, ratio ? Math.round((data.s + data.c * ratio) * 10000) / 10000 + data.u : data.b, data); 3622 }, 3623 _renderRoundedCSSProp = function _renderRoundedCSSProp(ratio, data) { 3624 var value = data.s + data.c * ratio; 3625 data.set(data.t, data.p, ~~(value + (value < 0 ? -.5 : .5)) + data.u, data); 3626 }, 3627 _renderNonTweeningValue = function _renderNonTweeningValue(ratio, data) { 3628 return data.set(data.t, data.p, ratio ? data.e : data.b, data); 3629 }, 3630 _renderNonTweeningValueOnlyAtEnd = function _renderNonTweeningValueOnlyAtEnd(ratio, data) { 3631 return data.set(data.t, data.p, ratio !== 1 ? data.b : data.e, data); 3632 }, 3633 _setterCSSStyle = function _setterCSSStyle(target, property, value) { 3634 return target.style[property] = value; 3635 }, 3636 _setterCSSProp = function _setterCSSProp(target, property, value) { 3637 return target.style.setProperty(property, value); 3638 }, 3639 _setterTransform = function _setterTransform(target, property, value) { 3640 return target._gsap[property] = value; 3641 }, 3642 _setterScale = function _setterScale(target, property, value) { 3643 return target._gsap.scaleX = target._gsap.scaleY = value; 3644 }, 3645 _setterScaleWithRender = function _setterScaleWithRender(target, property, value, data, ratio) { 3646 var cache = target._gsap; 3647 cache.scaleX = cache.scaleY = value; 3648 cache.renderTransform(ratio, cache); 3649 }, 3650 _setterTransformWithRender = function _setterTransformWithRender(target, property, value, data, ratio) { 3651 var cache = target._gsap; 3652 cache[property] = value; 3653 cache.renderTransform(ratio, cache); 3654 }, 3655 _transformProp = "transform", 3656 _transformOriginProp = _transformProp + "Origin", 3657 _supports3D, 3658 _createElement = function _createElement(type, ns) { 3659 var e = _doc$1.createElementNS ? _doc$1.createElementNS((ns || "http://www.w3.org/1999/xhtml").replace(/^https/, "http"), type) : _doc$1.createElement(type); 3660 return e.style ? e : _doc$1.createElement(type); 3661 }, 3662 _getComputedProperty = function _getComputedProperty(target, property, skipPrefixFallback) { 3663 var cs = getComputedStyle(target); 3664 return cs[property] || cs.getPropertyValue(property.replace(_capsExp, "-$1").toLowerCase()) || cs.getPropertyValue(property) || !skipPrefixFallback && _getComputedProperty(target, _checkPropPrefix(property) || property, 1) || ""; 3665 }, 3666 _prefixes = "O,Moz,ms,Ms,Webkit".split(","), 3667 _checkPropPrefix = function _checkPropPrefix(property, element, preferPrefix) { 3668 var e = element || _tempDiv, 3669 s = e.style, 3670 i = 5; 3671 3672 if (property in s && !preferPrefix) { 3673 return property; 3674 } 3675 3676 property = property.charAt(0).toUpperCase() + property.substr(1); 3677 3678 while (i-- && !(_prefixes[i] + property in s)) {} 3679 3680 return i < 0 ? null : (i === 3 ? "ms" : i >= 0 ? _prefixes[i] : "") + property; 3681 }, 3682 _initCore = function _initCore() { 3683 if (_windowExists$1() && window.document) { 3684 _win$1 = window; 3685 _doc$1 = _win$1.document; 3686 _docElement = _doc$1.documentElement; 3687 _tempDiv = _createElement("div") || { 3688 style: {} 3689 }; 3690 _tempDivStyler = _createElement("div"); 3691 _transformProp = _checkPropPrefix(_transformProp); 3692 _transformOriginProp = _transformProp + "Origin"; 3693 _tempDiv.style.cssText = "border-width:0;line-height:0;position:absolute;padding:0"; 3694 _supports3D = !!_checkPropPrefix("perspective"); 3695 _pluginInitted = 1; 3696 } 3697 }, 3698 _getBBoxHack = function _getBBoxHack(swapIfPossible) { 3699 var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"), 3700 oldParent = this.parentNode, 3701 oldSibling = this.nextSibling, 3702 oldCSS = this.style.cssText, 3703 bbox; 3704 3705 _docElement.appendChild(svg); 3706 3707 svg.appendChild(this); 3708 this.style.display = "block"; 3709 3710 if (swapIfPossible) { 3711 try { 3712 bbox = this.getBBox(); 3713 this._gsapBBox = this.getBBox; 3714 this.getBBox = _getBBoxHack; 3715 } catch (e) {} 3716 } else if (this._gsapBBox) { 3717 bbox = this._gsapBBox(); 3718 } 3719 3720 if (oldParent) { 3721 if (oldSibling) { 3722 oldParent.insertBefore(this, oldSibling); 3723 } else { 3724 oldParent.appendChild(this); 3725 } 3726 } 3727 3728 _docElement.removeChild(svg); 3729 3730 this.style.cssText = oldCSS; 3731 return bbox; 3732 }, 3733 _getAttributeFallbacks = function _getAttributeFallbacks(target, attributesArray) { 3734 var i = attributesArray.length; 3735 3736 while (i--) { 3737 if (target.hasAttribute(attributesArray[i])) { 3738 return target.getAttribute(attributesArray[i]); 3739 } 3740 } 3741 }, 3742 _getBBox = function _getBBox(target) { 3743 var bounds; 3744 3745 try { 3746 bounds = target.getBBox(); 3747 } catch (error) { 3748 bounds = _getBBoxHack.call(target, true); 3749 } 3750 3751 bounds && (bounds.width || bounds.height) || target.getBBox === _getBBoxHack || (bounds = _getBBoxHack.call(target, true)); 3752 return bounds && !bounds.width && !bounds.x && !bounds.y ? { 3753 x: +_getAttributeFallbacks(target, ["x", "cx", "x1"]) || 0, 3754 y: +_getAttributeFallbacks(target, ["y", "cy", "y1"]) || 0, 3755 width: 0, 3756 height: 0 3757 } : bounds; 3758 }, 3759 _isSVG = function _isSVG(e) { 3760 return !!(e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e)); 3761 }, 3762 _removeProperty = function _removeProperty(target, property) { 3763 if (property) { 3764 var style = target.style; 3765 3766 if (property in _transformProps && property !== _transformOriginProp) { 3767 property = _transformProp; 3768 } 3769 3770 if (style.removeProperty) { 3771 if (property.substr(0, 2) === "ms" || property.substr(0, 6) === "webkit") { 3772 property = "-" + property; 3773 } 3774 3775 style.removeProperty(property.replace(_capsExp, "-$1").toLowerCase()); 3776 } else { 3777 style.removeAttribute(property); 3778 } 3779 } 3780 }, 3781 _addNonTweeningPT = function _addNonTweeningPT(plugin, target, property, beginning, end, onlySetAtEnd) { 3782 var pt = new PropTween(plugin._pt, target, property, 0, 1, onlySetAtEnd ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue); 3783 plugin._pt = pt; 3784 pt.b = beginning; 3785 pt.e = end; 3786 3787 plugin._props.push(property); 3788 3789 return pt; 3790 }, 3791 _nonConvertibleUnits = { 3792 deg: 1, 3793 rad: 1, 3794 turn: 1 3795 }, 3796 _convertToUnit = function _convertToUnit(target, property, value, unit) { 3797 var curValue = parseFloat(value) || 0, 3798 curUnit = (value + "").trim().substr((curValue + "").length) || "px", 3799 style = _tempDiv.style, 3800 horizontal = _horizontalExp.test(property), 3801 isRootSVG = target.tagName.toLowerCase() === "svg", 3802 measureProperty = (isRootSVG ? "client" : "offset") + (horizontal ? "Width" : "Height"), 3803 amount = 100, 3804 toPixels = unit === "px", 3805 toPercent = unit === "%", 3806 px, 3807 parent, 3808 cache, 3809 isSVG; 3810 3811 if (unit === curUnit || !curValue || _nonConvertibleUnits[unit] || _nonConvertibleUnits[curUnit]) { 3812 return curValue; 3813 } 3814 3815 curUnit !== "px" && !toPixels && (curValue = _convertToUnit(target, property, value, "px")); 3816 isSVG = target.getCTM && _isSVG(target); 3817 3818 if ((toPercent || curUnit === "%") && (_transformProps[property] || ~property.indexOf("adius"))) { 3819 px = isSVG ? target.getBBox()[horizontal ? "width" : "height"] : target[measureProperty]; 3820 return _round(toPercent ? curValue / px * amount : curValue / 100 * px); 3821 } 3822 3823 style[horizontal ? "width" : "height"] = amount + (toPixels ? curUnit : unit); 3824 parent = ~property.indexOf("adius") || unit === "em" && target.appendChild && !isRootSVG ? target : target.parentNode; 3825 3826 if (isSVG) { 3827 parent = (target.ownerSVGElement || {}).parentNode; 3828 } 3829 3830 if (!parent || parent === _doc$1 || !parent.appendChild) { 3831 parent = _doc$1.body; 3832 } 3833 3834 cache = parent._gsap; 3835 3836 if (cache && toPercent && cache.width && horizontal && cache.time === _ticker.time) { 3837 return _round(curValue / cache.width * amount); 3838 } else { 3839 (toPercent || curUnit === "%") && (style.position = _getComputedProperty(target, "position")); 3840 parent === target && (style.position = "static"); 3841 parent.appendChild(_tempDiv); 3842 px = _tempDiv[measureProperty]; 3843 parent.removeChild(_tempDiv); 3844 style.position = "absolute"; 3845 3846 if (horizontal && toPercent) { 3847 cache = _getCache(parent); 3848 cache.time = _ticker.time; 3849 cache.width = parent[measureProperty]; 3850 } 3851 } 3852 3853 return _round(toPixels ? px * curValue / amount : px && curValue ? amount / px * curValue : 0); 3854 }, 3855 _get = function _get(target, property, unit, uncache) { 3856 var value; 3857 _pluginInitted || _initCore(); 3858 3859 if (property in _propertyAliases && property !== "transform") { 3860 property = _propertyAliases[property]; 3861 3862 if (~property.indexOf(",")) { 3863 property = property.split(",")[0]; 3864 } 3865 } 3866 3867 if (_transformProps[property] && property !== "transform") { 3868 value = _parseTransform(target, uncache); 3869 value = property !== "transformOrigin" ? value[property] : _firstTwoOnly(_getComputedProperty(target, _transformOriginProp)) + " " + value.zOrigin + "px"; 3870 } else { 3871 value = target.style[property]; 3872 3873 if (!value || value === "auto" || uncache || ~(value + "").indexOf("calc(")) { 3874 value = _specialProps[property] && _specialProps[property](target, property, unit) || _getComputedProperty(target, property) || _getProperty(target, property) || (property === "opacity" ? 1 : 0); 3875 } 3876 } 3877 3878 return unit && !~(value + "").trim().indexOf(" ") ? _convertToUnit(target, property, value, unit) + unit : value; 3879 }, 3880 _tweenComplexCSSString = function _tweenComplexCSSString(target, prop, start, end) { 3881 if (!start || start === "none") { 3882 var p = _checkPropPrefix(prop, target, 1), 3883 s = p && _getComputedProperty(target, p, 1); 3884 3885 if (s && s !== start) { 3886 prop = p; 3887 start = s; 3888 } else if (prop === "borderColor") { 3889 start = _getComputedProperty(target, "borderTopColor"); 3890 } 3891 } 3892 3893 var pt = new PropTween(this._pt, target.style, prop, 0, 1, _renderComplexString), 3894 index = 0, 3895 matchIndex = 0, 3896 a, 3897 result, 3898 startValues, 3899 startNum, 3900 color, 3901 startValue, 3902 endValue, 3903 endNum, 3904 chunk, 3905 endUnit, 3906 startUnit, 3907 relative, 3908 endValues; 3909 pt.b = start; 3910 pt.e = end; 3911 start += ""; 3912 end += ""; 3913 3914 if (end === "auto") { 3915 target.style[prop] = end; 3916 end = _getComputedProperty(target, prop) || end; 3917 target.style[prop] = start; 3918 } 3919 3920 a = [start, end]; 3921 3922 _colorStringFilter(a); 3923 3924 start = a[0]; 3925 end = a[1]; 3926 startValues = start.match(_numWithUnitExp) || []; 3927 endValues = end.match(_numWithUnitExp) || []; 3928 3929 if (endValues.length) { 3930 while (result = _numWithUnitExp.exec(end)) { 3931 endValue = result[0]; 3932 chunk = end.substring(index, result.index); 3933 3934 if (color) { 3935 color = (color + 1) % 5; 3936 } else if (chunk.substr(-5) === "rgba(" || chunk.substr(-5) === "hsla(") { 3937 color = 1; 3938 } 3939 3940 if (endValue !== (startValue = startValues[matchIndex++] || "")) { 3941 startNum = parseFloat(startValue) || 0; 3942 startUnit = startValue.substr((startNum + "").length); 3943 relative = endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0; 3944 3945 if (relative) { 3946 endValue = endValue.substr(2); 3947 } 3948 3949 endNum = parseFloat(endValue); 3950 endUnit = endValue.substr((endNum + "").length); 3951 index = _numWithUnitExp.lastIndex - endUnit.length; 3952 3953 if (!endUnit) { 3954 endUnit = endUnit || _config.units[prop] || startUnit; 3955 3956 if (index === end.length) { 3957 end += endUnit; 3958 pt.e += endUnit; 3959 } 3960 } 3961 3962 if (startUnit !== endUnit) { 3963 startNum = _convertToUnit(target, prop, startValue, endUnit) || 0; 3964 } 3965 3966 pt._pt = { 3967 _next: pt._pt, 3968 p: chunk || matchIndex === 1 ? chunk : ",", 3969 s: startNum, 3970 c: relative ? relative * endNum : endNum - startNum, 3971 m: color && color < 4 || prop === "zIndex" ? Math.round : 0 3972 }; 3973 } 3974 } 3975 3976 pt.c = index < end.length ? end.substring(index, end.length) : ""; 3977 } else { 3978 pt.r = prop === "display" && end === "none" ? _renderNonTweeningValueOnlyAtEnd : _renderNonTweeningValue; 3979 } 3980 3981 _relExp.test(end) && (pt.e = 0); 3982 this._pt = pt; 3983 return pt; 3984 }, 3985 _keywordToPercent = { 3986 top: "0%", 3987 bottom: "100%", 3988 left: "0%", 3989 right: "100%", 3990 center: "50%" 3991 }, 3992 _convertKeywordsToPercentages = function _convertKeywordsToPercentages(value) { 3993 var split = value.split(" "), 3994 x = split[0], 3995 y = split[1] || "50%"; 3996 3997 if (x === "top" || x === "bottom" || y === "left" || y === "right") { 3998 value = x; 3999 x = y; 4000 y = value; 4001 } 4002 4003 split[0] = _keywordToPercent[x] || x; 4004 split[1] = _keywordToPercent[y] || y; 4005 return split.join(" "); 4006 }, 4007 _renderClearProps = function _renderClearProps(ratio, data) { 4008 if (data.tween && data.tween._time === data.tween._dur) { 4009 var target = data.t, 4010 style = target.style, 4011 props = data.u, 4012 cache = target._gsap, 4013 prop, 4014 clearTransforms, 4015 i; 4016 4017 if (props === "all" || props === true) { 4018 style.cssText = ""; 4019 clearTransforms = 1; 4020 } else { 4021 props = props.split(","); 4022 i = props.length; 4023 4024 while (--i > -1) { 4025 prop = props[i]; 4026 4027 if (_transformProps[prop]) { 4028 clearTransforms = 1; 4029 prop = prop === "transformOrigin" ? _transformOriginProp : _transformProp; 4030 } 4031 4032 _removeProperty(target, prop); 4033 } 4034 } 4035 4036 if (clearTransforms) { 4037 _removeProperty(target, _transformProp); 4038 4039 if (cache) { 4040 cache.svg && target.removeAttribute("transform"); 4041 4042 _parseTransform(target, 1); 4043 4044 cache.uncache = 1; 4045 } 4046 } 4047 } 4048 }, 4049 _specialProps = { 4050 clearProps: function clearProps(plugin, target, property, endValue, tween) {
vendor: 3,001 bytes, lines 4051-4131
4051 if (tween.data !== "isFromStart") { 4052 var pt = plugin._pt = new PropTween(plugin._pt, target, property, 0, 0, _renderClearProps); 4053 pt.u = endValue; 4054 pt.pr = -10; 4055 pt.tween = tween; 4056 4057 plugin._props.push(property); 4058 4059 return 1; 4060 } 4061 } 4062 }, 4063 _identity2DMatrix = [1, 0, 0, 1, 0, 0], 4064 _rotationalProperties = {}, 4065 _isNullTransform = function _isNullTransform(value) { 4066 return value === "matrix(1, 0, 0, 1, 0, 0)" || value === "none" || !value; 4067 }, 4068 _getComputedTransformMatrixAsArray = function _getComputedTransformMatrixAsArray(target) { 4069 var matrixString = _getComputedProperty(target, _transformProp); 4070 4071 return _isNullTransform(matrixString) ? _identity2DMatrix : matrixString.substr(7).match(_numExp).map(_round); 4072 }, 4073 _getMatrix = function _getMatrix(target, force2D) { 4074 var cache = target._gsap || _getCache(target), 4075 style = target.style, 4076 matrix = _getComputedTransformMatrixAsArray(target), 4077 parent, 4078 nextSibling, 4079 temp, 4080 addedToDOM; 4081 4082 if (cache.svg && target.getAttribute("transform")) { 4083 temp = target.transform.baseVal.consolidate().matrix; 4084 matrix = [temp.a, temp.b, temp.c, temp.d, temp.e, temp.f]; 4085 return matrix.join(",") === "1,0,0,1,0,0" ? _identity2DMatrix : matrix; 4086 } else if (matrix === _identity2DMatrix && !target.offsetParent && target !== _docElement && !cache.svg) { 4087 temp = style.display; 4088 style.display = "block"; 4089 parent = target.parentNode; 4090 4091 if (!parent || !target.offsetParent) { 4092 addedToDOM = 1; 4093 nextSibling = target.nextSibling; 4094 4095 _docElement.appendChild(target); 4096 } 4097 4098 matrix = _getComputedTransformMatrixAsArray(target); 4099 temp ? style.display = temp : _removeProperty(target, "display"); 4100 4101 if (addedToDOM) { 4102 nextSibling ? parent.insertBefore(target, nextSibling) : parent ? parent.appendChild(target) : _docElement.removeChild(target); 4103 } 4104 } 4105 4106 return force2D && matrix.length > 6 ? [matrix[0], matrix[1], matrix[4], matrix[5], matrix[12], matrix[13]] : matrix; 4107 }, 4108 _applySVGOrigin = function _applySVGOrigin(target, origin, originIsAbsolute, smooth, matrixArray, pluginToAddPropTweensTo) { 4109 var cache = target._gsap, 4110 matrix = matrixArray || _getMatrix(target, true), 4111 xOriginOld = cache.xOrigin || 0, 4112 yOriginOld = cache.yOrigin || 0, 4113 xOffsetOld = cache.xOffset || 0, 4114 yOffsetOld = cache.yOffset || 0, 4115 a = matrix[0], 4116 b = matrix[1], 4117 c = matrix[2], 4118 d = matrix[3], 4119 tx = matrix[4], 4120 ty = matrix[5], 4121 originSplit = origin.split(" "), 4122 xOrigin = parseFloat(originSplit[0]) || 0, 4123 yOrigin = parseFloat(originSplit[1]) || 0, 4124 bounds, 4125 determinant, 4126 x, 4127 y; 4128 4129 if (!originIsAbsolute) { 4130 bounds = _getBBox(target); 4131 xOrigin = bounds.x + (~originSplit[0].indexOf("%") ? xOrigin / 100 * boun
vendor: 6,518 bytes, lines 4131-4339
4131ds.width : xOrigin); 4132 yOrigin = bounds.y + (~(originSplit[1] || originSplit[0]).indexOf("%") ? yOrigin / 100 * bounds.height : yOrigin); 4133 } else if (matrix !== _identity2DMatrix && (determinant = a * d - b * c)) { 4134 x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant; 4135 y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant; 4136 xOrigin = x; 4137 yOrigin = y; 4138 } 4139 4140 if (smooth || smooth !== false && cache.smooth) { 4141 tx = xOrigin - xOriginOld; 4142 ty = yOrigin - yOriginOld; 4143 cache.xOffset = xOffsetOld + (tx * a + ty * c) - tx; 4144 cache.yOffset = yOffsetOld + (tx * b + ty * d) - ty; 4145 } else { 4146 cache.xOffset = cache.yOffset = 0; 4147 } 4148 4149 cache.xOrigin = xOrigin; 4150 cache.yOrigin = yOrigin; 4151 cache.smooth = !!smooth; 4152 cache.origin = origin; 4153 cache.originIsAbsolute = !!originIsAbsolute; 4154 target.style[_transformOriginProp] = "0px 0px"; 4155 4156 if (pluginToAddPropTweensTo) { 4157 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOrigin", xOriginOld, xOrigin); 4158 4159 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOrigin", yOriginOld, yOrigin); 4160 4161 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "xOffset", xOffsetOld, cache.xOffset); 4162 4163 _addNonTweeningPT(pluginToAddPropTweensTo, cache, "yOffset", yOffsetOld, cache.yOffset); 4164 } 4165 4166 target.setAttribute("data-svg-origin", xOrigin + " " + yOrigin); 4167 }, 4168 _parseTransform = function _parseTransform(target, uncache) { 4169 var cache = target._gsap || new GSCache(target); 4170 4171 if ("x" in cache && !uncache && !cache.uncache) { 4172 return cache; 4173 } 4174 4175 var style = target.style, 4176 invertedScaleX = cache.scaleX < 0, 4177 px = "px", 4178 deg = "deg", 4179 origin = _getComputedProperty(target, _transformOriginProp) || "0", 4180 x, 4181 y, 4182 z, 4183 scaleX, 4184 scaleY, 4185 rotation, 4186 rotationX, 4187 rotationY, 4188 skewX, 4189 skewY, 4190 perspective, 4191 xOrigin, 4192 yOrigin, 4193 matrix, 4194 angle, 4195 cos, 4196 sin, 4197 a, 4198 b, 4199 c, 4200 d, 4201 a12, 4202 a22, 4203 t1, 4204 t2, 4205 t3, 4206 a13, 4207 a23, 4208 a33, 4209 a42, 4210 a43, 4211 a32; 4212 x = y = z = rotation = rotationX = rotationY = skewX = skewY = perspective = 0; 4213 scaleX = scaleY = 1; 4214 cache.svg = !!(target.getCTM && _isSVG(target)); 4215 matrix = _getMatrix(target, cache.svg); 4216 4217 if (cache.svg) { 4218 t1 = !cache.uncache && !uncache && target.getAttribute("data-svg-origin"); 4219 4220 _applySVGOrigin(target, t1 || origin, !!t1 || cache.originIsAbsolute, cache.smooth !== false, matrix); 4221 } 4222 4223 xOrigin = cache.xOrigin || 0; 4224 yOrigin = cache.yOrigin || 0; 4225 4226 if (matrix !== _identity2DMatrix) { 4227 a = matrix[0]; 4228 b = matrix[1]; 4229 c = matrix[2]; 4230 d = matrix[3]; 4231 x = a12 = matrix[4]; 4232 y = a22 = matrix[5]; 4233 4234 if (matrix.length === 6) { 4235 scaleX = Math.sqrt(a * a + b * b); 4236 scaleY = Math.sqrt(d * d + c * c); 4237 rotation = a || b ? _atan2(b, a) * _RAD2DEG : 0; 4238 skewX = c || d ? _atan2(c, d) * _RAD2DEG + rotation : 0; 4239 skewX && (scaleY *= Math.abs(Math.cos(skewX * _DEG2RAD))); 4240 4241 if (cache.svg) { 4242 x -= xOrigin - (xOrigin * a + yOrigin * c); 4243 y -= yOrigin - (xOrigin * b + yOrigin * d); 4244 } 4245 } else { 4246 a32 = matrix[6]; 4247 a42 = matrix[7]; 4248 a13 = matrix[8]; 4249 a23 = matrix[9]; 4250 a33 = matrix[10]; 4251 a43 = matrix[11]; 4252 x = matrix[12]; 4253 y = matrix[13]; 4254 z = matrix[14]; 4255 angle = _atan2(a32, a33); 4256 rotationX = angle * _RAD2DEG; 4257 4258 if (angle) { 4259 cos = Math.cos(-angle); 4260 sin = Math.sin(-angle); 4261 t1 = a12 * cos + a13 * sin; 4262 t2 = a22 * cos + a23 * sin; 4263 t3 = a32 * cos + a33 * sin; 4264 a13 = a12 * -sin + a13 * cos; 4265 a23 = a22 * -sin + a23 * cos; 4266 a33 = a32 * -sin + a33 * cos; 4267 a43 = a42 * -sin + a43 * cos; 4268 a12 = t1; 4269 a22 = t2; 4270 a32 = t3; 4271 } 4272 4273 angle = _atan2(-c, a33); 4274 rotationY = angle * _RAD2DEG; 4275 4276 if (angle) { 4277 cos = Math.cos(-angle); 4278 sin = Math.sin(-angle); 4279 t1 = a * cos - a13 * sin; 4280 t2 = b * cos - a23 * sin; 4281 t3 = c * cos - a33 * sin; 4282 a43 = d * sin + a43 * cos; 4283 a = t1; 4284 b = t2; 4285 c = t3; 4286 } 4287 4288 angle = _atan2(b, a); 4289 rotation = angle * _RAD2DEG; 4290 4291 if (angle) { 4292 cos = Math.cos(angle); 4293 sin = Math.sin(angle); 4294 t1 = a * cos + b * sin; 4295 t2 = a12 * cos + a22 * sin; 4296 b = b * cos - a * sin; 4297 a22 = a22 * cos - a12 * sin; 4298 a = t1; 4299 a12 = t2; 4300 } 4301 4302 if (rotationX && Math.abs(rotationX) + Math.abs(rotation) > 359.9) { 4303 rotationX = rotation = 0; 4304 rotationY = 180 - rotationY; 4305 } 4306 4307 scaleX = _round(Math.sqrt(a * a + b * b + c * c)); 4308 scaleY = _round(Math.sqrt(a22 * a22 + a32 * a32)); 4309 angle = _atan2(a12, a22); 4310 skewX = Math.abs(angle) > 0.0002 ? angle * _RAD2DEG : 0; 4311 perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0; 4312 } 4313 4314 if (cache.svg) { 4315 t1 = target.getAttribute("transform"); 4316 cache.forceCSS = target.setAttribute("transform", "") || !_isNullTransform(_getComputedProperty(target, _transformProp)); 4317 t1 && target.setAttribute("transform", t1); 4318 } 4319 } 4320 4321 if (Math.abs(skewX) > 90 && Math.abs(skewX) < 270) { 4322 if (invertedScaleX) { 4323 scaleX *= -1; 4324 skewX += rotation <= 0 ? 180 : -180; 4325 rotation += rotation <= 0 ? 180 : -180; 4326 } else { 4327 scaleY *= -1; 4328 skewX += skewX <= 0 ? 180 : -180; 4329 } 4330 } 4331 4332 cache.x = x - ((cache.xPercent = x && (cache.xPercent || (Math.round(target.offsetWidth / 2) === Math.round(-x) ? -50 : 0))) ? target.offsetWidth * cache.xPercent / 100 : 0) + px; 4333 cache.y = y - ((cache.yPercent = y && (cache.yPercent || (Math.round(target.offsetHeight / 2) === Math.round(-y) ? -50 : 0))) ? target.offsetHeight * cache.yPercent / 100 : 0) + px; 4334 cache.z = z + px; 4335 cache.scaleX = _round(scaleX); 4336 cache.scaleY = _round(scaleY); 4337 cache.rotation = _round(rotation) + deg; 4338 cache.rotationX = _round(rotationX) + deg; 4339 cache.rotationY = _round(rotationY) + deg;
vendor: 4,199 bytes, lines 4340-4467
4340 cache.skewX = skewX + deg; 4341 cache.skewY = skewY + deg; 4342 cache.transformPerspective = perspective + px; 4343 4344 if (cache.zOrigin = parseFloat(origin.split(" ")[2]) || 0) { 4345 style[_transformOriginProp] = _firstTwoOnly(origin); 4346 } 4347 4348 cache.xOffset = cache.yOffset = 0; 4349 cache.force3D = _config.force3D; 4350 cache.renderTransform = cache.svg ? _renderSVGTransforms : _supports3D ? _renderCSSTransforms : _renderNon3DTransforms; 4351 cache.uncache = 0; 4352 return cache; 4353 }, 4354 _firstTwoOnly = function _firstTwoOnly(value) { 4355 return (value = value.split(" "))[0] + " " + value[1]; 4356 }, 4357 _addPxTranslate = function _addPxTranslate(target, start, value) { 4358 var unit = getUnit(start); 4359 return _round(parseFloat(start) + parseFloat(_convertToUnit(target, "x", value + "px", unit))) + unit; 4360 }, 4361 _renderNon3DTransforms = function _renderNon3DTransforms(ratio, cache) { 4362 cache.z = "0px"; 4363 cache.rotationY = cache.rotationX = "0deg"; 4364 cache.force3D = 0; 4365 4366 _renderCSSTransforms(ratio, cache); 4367 }, 4368 _zeroDeg = "0deg", 4369 _zeroPx = "0px", 4370 _endParenthesis = ") ", 4371 _renderCSSTransforms = function _renderCSSTransforms(ratio, cache) { 4372 var _ref = cache || this, 4373 xPercent = _ref.xPercent, 4374 yPercent = _ref.yPercent, 4375 x = _ref.x, 4376 y = _ref.y, 4377 z = _ref.z, 4378 rotation = _ref.rotation, 4379 rotationY = _ref.rotationY, 4380 rotationX = _ref.rotationX, 4381 skewX = _ref.skewX, 4382 skewY = _ref.skewY, 4383 scaleX = _ref.scaleX, 4384 scaleY = _ref.scaleY, 4385 transformPerspective = _ref.transformPerspective, 4386 force3D = _ref.force3D, 4387 target = _ref.target, 4388 zOrigin = _ref.zOrigin, 4389 transforms = "", 4390 use3D = force3D === "auto" && ratio && ratio !== 1 || force3D === true; 4391 4392 if (zOrigin && (rotationX !== _zeroDeg || rotationY !== _zeroDeg)) { 4393 var angle = parseFloat(rotationY) * _DEG2RAD, 4394 a13 = Math.sin(angle), 4395 a33 = Math.cos(angle), 4396 cos; 4397 4398 angle = parseFloat(rotationX) * _DEG2RAD; 4399 cos = Math.cos(angle); 4400 x = _addPxTranslate(target, x, a13 * cos * -zOrigin); 4401 y = _addPxTranslate(target, y, -Math.sin(angle) * -zOrigin); 4402 z = _addPxTranslate(target, z, a33 * cos * -zOrigin + zOrigin); 4403 } 4404 4405 if (transformPerspective !== _zeroPx) { 4406 transforms += "perspective(" + transformPerspective + _endParenthesis; 4407 } 4408 4409 if (xPercent || yPercent) { 4410 transforms += "translate(" + xPercent + "%, " + yPercent + "%) "; 4411 } 4412 4413 if (use3D || x !== _zeroPx || y !== _zeroPx || z !== _zeroPx) { 4414 transforms += z !== _zeroPx || use3D ? "translate3d(" + x + ", " + y + ", " + z + ") " : "translate(" + x + ", " + y + _endParenthesis; 4415 } 4416 4417 if (rotation !== _zeroDeg) { 4418 transforms += "rotate(" + rotation + _endParenthesis; 4419 } 4420 4421 if (rotationY !== _zeroDeg) { 4422 transforms += "rotateY(" + rotationY + _endParenthesis; 4423 } 4424 4425 if (rotationX !== _zeroDeg) { 4426 transforms += "rotateX(" + rotationX + _endParenthesis; 4427 } 4428 4429 if (skewX !== _zeroDeg || skewY !== _zeroDeg) { 4430 transforms += "skew(" + skewX + ", " + skewY + _endParenthesis; 4431 } 4432 4433 if (scaleX !== 1 || scaleY !== 1) { 4434 transforms += "scale(" + scaleX + ", " + scaleY + _endParenthesis; 4435 } 4436 4437 target.style[_transformProp] = transforms || "translate(0, 0)"; 4438 }, 4439 _renderSVGTransforms = function _renderSVGTransforms(ratio, cache) { 4440 var _ref2 = cache || this, 4441 xPercent = _ref2.xPercent, 4442 yPercent = _ref2.yPercent, 4443 x = _ref2.x, 4444 y = _ref2.y, 4445 rotation = _ref2.rotation, 4446 skewX = _ref2.skewX, 4447 skewY = _ref2.skewY, 4448 scaleX = _ref2.scaleX, 4449 scaleY = _ref2.scaleY, 4450 target = _ref2.target, 4451 xOrigin = _ref2.xOrigin, 4452 yOrigin = _ref2.yOrigin, 4453 xOffset = _ref2.xOffset, 4454 yOffset = _ref2.yOffset, 4455 forceCSS = _ref2.forceCSS, 4456 tx = parseFloat(x), 4457 ty = parseFloat(y), 4458 a11, 4459 a21, 4460 a12, 4461 a22, 4462 temp; 4463 4464 rotation = parseFloat(rotation); 4465 skewX = parseFloat(skewX); 4466 skewY = parseFloat(skewY); 4467
vendor: 4,432 bytes, lines 4468-4616
4468 if (skewY) { 4469 skewY = parseFloat(skewY); 4470 skewX += skewY; 4471 rotation += skewY; 4472 } 4473 4474 if (rotation || skewX) { 4475 rotation *= _DEG2RAD; 4476 skewX *= _DEG2RAD; 4477 a11 = Math.cos(rotation) * scaleX; 4478 a21 = Math.sin(rotation) * scaleX; 4479 a12 = Math.sin(rotation - skewX) * -scaleY; 4480 a22 = Math.cos(rotation - skewX) * scaleY; 4481 4482 if (skewX) { 4483 skewY *= _DEG2RAD; 4484 temp = Math.tan(skewX - skewY); 4485 temp = Math.sqrt(1 + temp * temp); 4486 a12 *= temp; 4487 a22 *= temp; 4488 4489 if (skewY) { 4490 temp = Math.tan(skewY); 4491 temp = Math.sqrt(1 + temp * temp); 4492 a11 *= temp; 4493 a21 *= temp; 4494 } 4495 } 4496 4497 a11 = _round(a11); 4498 a21 = _round(a21); 4499 a12 = _round(a12); 4500 a22 = _round(a22); 4501 } else { 4502 a11 = scaleX; 4503 a22 = scaleY; 4504 a21 = a12 = 0; 4505 } 4506 4507 if (tx && !~(x + "").indexOf("px") || ty && !~(y + "").indexOf("px")) { 4508 tx = _convertToUnit(target, "x", x, "px"); 4509 ty = _convertToUnit(target, "y", y, "px"); 4510 } 4511 4512 if (xOrigin || yOrigin || xOffset || yOffset) { 4513 tx = _round(tx + xOrigin - (xOrigin * a11 + yOrigin * a12) + xOffset); 4514 ty = _round(ty + yOrigin - (xOrigin * a21 + yOrigin * a22) + yOffset); 4515 } 4516 4517 if (xPercent || yPercent) { 4518 temp = target.getBBox(); 4519 tx = _round(tx + xPercent / 100 * temp.width); 4520 ty = _round(ty + yPercent / 100 * temp.height); 4521 } 4522 4523 temp = "matrix(" + a11 + "," + a21 + "," + a12 + "," + a22 + "," + tx + "," + ty + ")"; 4524 target.setAttribute("transform", temp); 4525 forceCSS && (target.style[_transformProp] = temp); 4526 }, 4527 _addRotationalPropTween = function _addRotationalPropTween(plugin, target, property, startNum, endValue, relative) { 4528 var cap = 360, 4529 isString = _isString(endValue), 4530 endNum = parseFloat(endValue) * (isString && ~endValue.indexOf("rad") ? _RAD2DEG : 1), 4531 change = relative ? endNum * relative : endNum - startNum, 4532 finalValue = startNum + change + "deg", 4533 direction, 4534 pt; 4535 4536 if (isString) { 4537 direction = endValue.split("_")[1]; 4538 4539 if (direction === "short") { 4540 change %= cap; 4541 4542 if (change !== change % (cap / 2)) { 4543 change += change < 0 ? cap : -cap; 4544 } 4545 } 4546 4547 if (direction === "cw" && change < 0) { 4548 change = (change + cap * _bigNum$1) % cap - ~~(change / cap) * cap; 4549 } else if (direction === "ccw" && change > 0) { 4550 change = (change - cap * _bigNum$1) % cap - ~~(change / cap) * cap; 4551 } 4552 } 4553 4554 plugin._pt = pt = new PropTween(plugin._pt, target, property, startNum, change, _renderPropWithEnd); 4555 pt.e = finalValue; 4556 pt.u = "deg"; 4557 4558 plugin._props.push(property); 4559 4560 return pt; 4561 }, 4562 _assign = function _assign(target, source) { 4563 for (var p in source) { 4564 target[p] = source[p]; 4565 } 4566 4567 return target; 4568 }, 4569 _addRawTransformPTs = function _addRawTransformPTs(plugin, transforms, target) { 4570 var startCache = _assign({}, target._gsap), 4571 exclude = "perspective,force3D,transformOrigin,svgOrigin", 4572 style = target.style, 4573 endCache, 4574 p, 4575 startValue, 4576 endValue, 4577 startNum, 4578 endNum, 4579 startUnit, 4580 endUnit; 4581 4582 if (startCache.svg) { 4583 startValue = target.getAttribute("transform"); 4584 target.setAttribute("transform", ""); 4585 style[_transformProp] = transforms; 4586 endCache = _parseTransform(target, 1); 4587 4588 _removeProperty(target, _transformProp); 4589 4590 target.setAttribute("transform", startValue); 4591 } else { 4592 startValue = getComputedStyle(target)[_transformProp]; 4593 style[_transformProp] = transforms; 4594 endCache = _parseTransform(target, 1); 4595 style[_transformProp] = startValue; 4596 } 4597 4598 for (p in _transformProps) { 4599 startValue = startCache[p]; 4600 endValue = endCache[p]; 4601 4602 if (startValue !== endValue && exclude.indexOf(p) < 0) { 4603 startUnit = getUnit(startValue); 4604 endUnit = getUnit(endValue); 4605 startNum = startUnit !== endUnit ? _convertToUnit(target, p, startValue, endUnit) : parseFloat(startValue); 4606 endNum = parseFloat(endValue); 4607 plugin._pt = new PropTween(plugin._pt, endCache, p, startNum, endNum - startNum, _renderCSSProp); 4608 plugin._pt.u = endUnit || 0; 4609 4610 plugin._props.push(p); 4611 } 4612 } 4613 4614 _assign(endCache, startCache); 4615 }; 4616
vendor: 4,076 bytes, lines 4617-4738
4617 _forEachName("padding,margin,Width,Radius", function (name, index) { 4618 var t = "Top", 4619 r = "Right", 4620 b = "Bottom", 4621 l = "Left", 4622 props = (index < 3 ? [t, r, b, l] : [t + l, t + r, b + r, b + l]).map(function (side) { 4623 return index < 2 ? name + side : "border" + side + name; 4624 }); 4625 4626 _specialProps[index > 1 ? "border" + name : name] = function (plugin, target, property, endValue, tween) { 4627 var a, vars; 4628 4629 if (arguments.length < 4) { 4630 a = props.map(function (prop) { 4631 return _get(plugin, prop, property); 4632 }); 4633 vars = a.join(" "); 4634 return vars.split(a[0]).length === 5 ? a[0] : vars; 4635 } 4636 4637 a = (endValue + "").split(" "); 4638 vars = {}; 4639 props.forEach(function (prop, i) { 4640 return vars[prop] = a[i] = a[i] || a[(i - 1) / 2 | 0]; 4641 }); 4642 plugin.init(target, vars, tween); 4643 }; 4644 }); 4645 4646 var CSSPlugin = { 4647 name: "css", 4648 register: _initCore, 4649 targetTest: function targetTest(target) { 4650 return target.style && target.nodeType; 4651 }, 4652 init: function init(target, vars, tween, index, targets) { 4653 var props = this._props, 4654 style = target.style, 4655 startAt = tween.vars.startAt, 4656 startValue, 4657 endValue, 4658 endNum, 4659 startNum, 4660 type, 4661 specialProp, 4662 p, 4663 startUnit, 4664 endUnit, 4665 relative, 4666 isTransformRelated, 4667 transformPropTween, 4668 cache, 4669 smooth, 4670 hasPriority; 4671 _pluginInitted || _initCore(); 4672 4673 for (p in vars) { 4674 if (p === "autoRound") { 4675 continue; 4676 } 4677 4678 endValue = vars[p]; 4679 4680 if (_plugins[p] && _checkPlugin(p, vars, tween, index, target, targets)) { 4681 continue; 4682 } 4683 4684 type = typeof endValue; 4685 specialProp = _specialProps[p]; 4686 4687 if (type === "function") { 4688 endValue = endValue.call(tween, index, target, targets); 4689 type = typeof endValue; 4690 } 4691 4692 if (type === "string" && ~endValue.indexOf("random(")) { 4693 endValue = _replaceRandom(endValue); 4694 } 4695 4696 if (specialProp) { 4697 specialProp(this, target, p, endValue, tween) && (hasPriority = 1); 4698 } else if (p.substr(0, 2) === "--") { 4699 startValue = (getComputedStyle(target).getPropertyValue(p) + "").trim(); 4700 endValue += ""; 4701 _colorExp.lastIndex = 0; 4702 4703 if (!_colorExp.test(startValue)) { 4704 startUnit = getUnit(startValue); 4705 endUnit = getUnit(endValue); 4706 } 4707 4708 endUnit ? startUnit !== endUnit && (startValue = _convertToUnit(target, p, startValue, endUnit) + endUnit) : startUnit && (endValue += startUnit); 4709 this.add(style, "setProperty", startValue, endValue, index, targets, 0, 0, p); 4710 } else if (type !== "undefined") { 4711 if (startAt && p in startAt) { 4712 startValue = typeof startAt[p] === "function" ? startAt[p].call(tween, index, target, targets) : startAt[p]; 4713 p in _config.units && !getUnit(startValue) && (startValue += _config.units[p]); 4714 (startValue + "").charAt(1) === "=" && (startValue = _get(target, p)); 4715 } else { 4716 startValue = _get(target, p); 4717 } 4718 4719 startNum = parseFloat(startValue); 4720 relative = type === "string" && endValue.charAt(1) === "=" ? +(endValue.charAt(0) + "1") : 0; 4721 relative && (endValue = endValue.substr(2)); 4722 endNum = parseFloat(endValue); 4723 4724 if (p in _propertyAliases) { 4725 if (p === "autoAlpha") { 4726 if (startNum === 1 && _get(target, "visibility") === "hidden" && endNum) { 4727 startNum = 0; 4728 } 4729 4730 _addNonTweeningPT(this, style, "visibility", startNum ? "inherit" : "hidden", endNum ? "inherit" : "hidden", !endNum); 4731 } 4732 4733 if (p !== "scale" && p !== "transform") { 4734 p = _propertyAliases[p]; 4735 ~p.indexOf(",") && (p = p.split(",")[0]); 4736 } 4737 } 4738
vendor: 4,279 bytes, lines 4739-4832
4739 isTransformRelated = p in _transformProps; 4740 4741 if (isTransformRelated) { 4742 if (!transformPropTween) { 4743 cache = target._gsap; 4744 cache.renderTransform && !vars.parseTransform || _parseTransform(target, vars.parseTransform); 4745 smooth = vars.smoothOrigin !== false && cache.smooth; 4746 transformPropTween = this._pt = new PropTween(this._pt, style, _transformProp, 0, 1, cache.renderTransform, cache, 0, -1); 4747 transformPropTween.dep = 1; 4748 } 4749 4750 if (p === "scale") { 4751 this._pt = new PropTween(this._pt, cache, "scaleY", cache.scaleY, relative ? relative * endNum : endNum - cache.scaleY); 4752 props.push("scaleY", p); 4753 p += "X"; 4754 } else if (p === "transformOrigin") { 4755 endValue = _convertKeywordsToPercentages(endValue); 4756 4757 if (cache.svg) { 4758 _applySVGOrigin(target, endValue, 0, smooth, 0, this); 4759 } else { 4760 endUnit = parseFloat(endValue.split(" ")[2]) || 0; 4761 endUnit !== cache.zOrigin && _addNonTweeningPT(this, cache, "zOrigin", cache.zOrigin, endUnit); 4762 4763 _addNonTweeningPT(this, style, p, _firstTwoOnly(startValue), _firstTwoOnly(endValue)); 4764 } 4765 4766 continue; 4767 } else if (p === "svgOrigin") { 4768 _applySVGOrigin(target, endValue, 1, smooth, 0, this); 4769 4770 continue; 4771 } else if (p in _rotationalProperties) { 4772 _addRotationalPropTween(this, cache, p, startNum, endValue, relative); 4773 4774 continue; 4775 } else if (p === "smoothOrigin") { 4776 _addNonTweeningPT(this, cache, "smooth", cache.smooth, endValue); 4777 4778 continue; 4779 } else if (p === "force3D") { 4780 cache[p] = endValue; 4781 continue; 4782 } else if (p === "transform") { 4783 _addRawTransformPTs(this, endValue, target); 4784 4785 continue; 4786 } 4787 } else if (!(p in style)) { 4788 p = _checkPropPrefix(p) || p; 4789 } 4790 4791 if (isTransformRelated || (endNum || endNum === 0) && (startNum || startNum === 0) && !_complexExp.test(endValue) && p in style) { 4792 startUnit = (startValue + "").substr((startNum + "").length); 4793 endNum || (endNum = 0); 4794 endUnit = getUnit(endValue) || (p in _config.units ? _config.units[p] : startUnit); 4795 startUnit !== endUnit && (startNum = _convertToUnit(target, p, startValue, endUnit)); 4796 this._pt = new PropTween(this._pt, isTransformRelated ? cache : style, p, startNum, relative ? relative * endNum : endNum - startNum, !isTransformRelated && (endUnit === "px" || p === "zIndex") && vars.autoRound !== false ? _renderRoundedCSSProp : _renderCSSProp); 4797 this._pt.u = endUnit || 0; 4798 4799 if (startUnit !== endUnit) { 4800 this._pt.b = startValue; 4801 this._pt.r = _renderCSSPropWithBeginning; 4802 } 4803 } else if (!(p in style)) { 4804 if (p in target) { 4805 this.add(target, p, target[p], endValue, index, targets); 4806 } else { 4807 _missingPlugin(p, endValue); 4808 4809 continue; 4810 } 4811 } else { 4812 _tweenComplexCSSString.call(this, target, p, startValue, endValue); 4813 } 4814 4815 props.push(p); 4816 } 4817 } 4818 4819 hasPriority && _sortPropTweensByPriority(this); 4820 }, 4821 get: _get, 4822 aliases: _propertyAliases, 4823 getSetter: function getSetter(target, property, plugin) { 4824 var p = _propertyAliases[property]; 4825 p && p.indexOf(",") < 0 && (property = p); 4826 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); 4827 }, 4828 core: { 4829 _removeProperty: _removeProperty, 4830 _getMatrix: _getMatrix 4831 } 4832 };
4833 gsap.utils.checkPrefix = _checkPropPrefix; 4834 4835 (function (positionAndScale, rotation, others, aliases) { 4836 var all = _forEachName(positionAndScale + "," + rotation + "," + others, function (name) { 4837 _transformProps[name] = 1; 4838 }); 4839 4840 _forEachName(rotation, function (name) { 4841 _config.units[name] = "deg"; 4842 _rotationalProperties[name] = 1; 4843 }); 4844 4845 _propertyAliases[all[13]] = positionAndScale + "," + rotation; 4846 4847 _forEachName(aliases, function (name) { 4848 var split = name.split(":"); 4849 _propertyAliases[split[1]] = all[split[0]]; 4850 }); 4851 })("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"); 4852 4853 _forEachName("x,y,z,top,right,bottom,left,width,height,fontSize,padding,margin,perspective", function (name) { 4854 _config.units[name] = "px"; 4855 }); 4856 4857 gsap.registerPlugin(CSSPlugin); 4858 4859 var gsapWithCSS = gsap.registerPlugin(CSSPlugin) || gsap, 4860 TweenMaxWithCSS = gsapWithCSS.core.Tween; 4861 4862 exports.Back = Back; 4863 exports.Bounce = Bounce; 4864 exports.CSSPlugin = CSSPlugin; 4865 exports.Circ = Circ; 4866 exports.Cubic = Cubic; 4867 exports.Elastic = Elastic; 4868 exports.Expo = Expo; 4869 exports.Linear = Linear; 4870 exports.Power0 = Power0; 4871 exports.Power1 = Power1; 4872 exports.Power2 = Power2; 4873 exports.Power3 = Power3; 4874 exports.Power4 = Power4; 4875 exports.Quad = Quad; 4876 exports.Quart = Quart; 4877 exports.Quint = Quint; 4878 exports.Sine = Sine; 4879 exports.SteppedEase = SteppedEase; 4880 exports.Strong = Strong; 4881 exports.TimelineLite = Timeline; 4882 exports.TimelineMax = Timeline; 4883 exports.TweenLite = Tween; 4884 exports.TweenMax = TweenMaxWithCSS; 4885 exports.default = gsapWithCSS; 4886 exports.gsap = gsapWithCSS; 4887 4888 if (typeof(window) === 'undefined' || window !== exports) {Object.defineProperty(exports, '__esModule', { value: true });} else {delete window.default;} 4889 4890}))); 4891 4892(function(window, $) { 4893 'use strict'; 4894 var counter = 0, 4895 $headCache = $('head'), 4896 oldBigText = window.BigText, 4897 oldjQueryMethod = $.fn.bigtext, 4898 BigText = { 4899 DEBUG_MODE: false, 4900 DEFAULT_MIN_FONT_SIZE_PX: null, 4901 DEFAULT_MAX_FONT_SIZE_PX: 528, 4902 GLOBAL_STYLE_ID: 'bigtext-style', 4903 STYLE_ID: 'bigtext-id', 4904 LINE_CLASS_PREFIX: 'bigtext-line', 4905 EXEMPT_CLASS: 'bigtext-exempt', 4906 noConflict: function(restore) 4907 { 4908 if(restore) { 4909 $.fn.bigtext = oldjQueryMethod; 4910 window.BigText = oldBigText; 4911 } 4912 return BigText; 4913 }, 4914 supports: { 4915 wholeNumberFontSizeOnly: (function() { 4916 if( !( 'getComputedStyle' in window ) ) { 4917 return true; 4918 } 4919 var test = $('<div/>').css({ 4920 position: 'absolute', 4921 'font-size': '14.1px' 4922 }).insertBefore( $('script').eq(0) ), 4923 computedStyle = window.getComputedStyle( test[0], null ); 4924 4925 var ret = computedStyle && computedStyle.getPropertyValue( 'font-size' ) === '14px'; 4926 test.remove(); 4927 return ret; 4928 })() 4929 }, 4930 init: function() { 4931 if(!$('#'+BigText.GLOBAL_STYLE_ID).length) { 4932 $headCache.append(BigText.generateStyleTag(BigText.GLOBAL_STYLE_ID, ['.bigtext * { white-space: nowrap; } .bigtext > * { display: block; }', 4933 '.bigtext .' + BigText.EXEMPT_CLASS + ', .bigtext .' + BigText.EXEMPT_CLASS + ' * { white-space: normal; }'])); 4934 } 4935 }, 4936 bindResize: function(eventName, resizeFunction) { 4937 var timeoutId; 4938 $(window).unbind(eventName).bind(eventName, function() { 4939 if( timeoutId ) { 4940 clearTimeout( timeoutId ); 4941 } 4942 timeoutId = setTimeout( resizeFunction, 300 ); 4943 }); 4944 }, 4945 getStyleId: function(id) 4946 { 4947 return BigText.STYLE_ID + '-' + id; 4948 }, 4949 generateStyleTag: function(id, css) 4950 { 4951 return $('<style>' + css.join('\n') + '</style>').attr('id', id); 4952 }, 4953 clearCss: function(id) 4954 { 4955 var styleId = BigText.getStyleId(id); 4956 $('#' + styleId).remove(); 4957 }, 4958 generateCss: function(id, linesFontSizes, lineWordSpacings, minFontSizes) 4959 { 4960 var css = []; 4961 4962 BigText.clearCss(id); 4963 4964 for(var j=0, k=linesFontSizes.length; j<k; j++) { 4965 css.push('#' + id + ' .' + BigText.LINE_CLASS_PREFIX + j + ' {' + 4966 (minFontSizes[j] ? ' white-space: normal;' : '') + 4967 (linesFontSizes[j] ? ' font-size: ' + linesFontSizes[j] + 'px;' : '') + 4968 (lineWordSpacings[j] ? ' word-spacing: ' + lineWordSpacings[j] + 'px;' : '') + 4969 '}'); 4970 } 4971 4972 return BigText.generateStyleTag(BigText.getStyleId(id), css); 4973 }, 4974 jQueryMethod: function(options) 4975 {
4976 BigText.init(); 4977 4978 options = $.extend({ 4979 minfontsize: BigText.DEFAULT_MIN_FONT_SIZE_PX, 4980 maxfontsize: BigText.DEFAULT_MAX_FONT_SIZE_PX, 4981 childSelector: '', 4982 resize: true 4983 }, options || {}); 4984 4985 this.each(function() 4986 { 4987 var $t = $(this).addClass('bigtext'), 4988 maxWidth = $t.width(), 4989 id = $t.attr('id'), 4990 $children = options.childSelector ? $t.find( options.childSelector ) : $t.children(); 4991 4992 if(!id) { 4993 id = 'bigtext-id' + (counter++); 4994 $t.attr('id', id); 4995 } 4996 4997 if(options.resize) { 4998 BigText.bindResize('resize.bigtext-event-' + id, function() 4999 { 5000 // TODO only call this if the width has changed. 5001 BigText.jQueryMethod.call($('#' + id), options); 5002 }); 5003 } 5004 5005 BigText.clearCss(id); 5006 5007 $children.addClass(function(lineNumber, className) 5008 { 5009 // remove existing line classes. 5010 return [className.replace(new RegExp('\\b' + BigText.LINE_CLASS_PREFIX + '\\d+\\b'), ''), 5011 BigText.LINE_CLASS_PREFIX + lineNumber].join(' '); 5012 }); 5013 5014 var sizes = calculateSizes($t, $children, maxWidth, options.maxfontsize, options.minfontsize); 5015 $headCache.append(BigText.generateCss(id, sizes.fontSizes, sizes.wordSpacings, sizes.minFontSizes)); 5016 }); 5017 5018 return this.trigger('bigtext:complete'); 5019 } 5020 }; 5021 5022 function testLineDimensions($line, maxWidth, property, size, interval, units, previousWidth) 5023 { 5024 var width; 5025 previousWidth = typeof previousWidth === 'number' ? previousWidth : 0; 5026 $line.css(property, size + units); 5027 5028 width = $line.width(); 5029 5030 if(width >= maxWidth) { 5031 5032 $line.css(property, ''); 5033 5034 if(width === maxWidth) { 5035 return { 5036 match: 'exact', 5037 size: parseFloat((parseFloat(size) - 0.1).toFixed(3)) 5038 }; 5039 } 5040 5041 // Since this is an estimate, we calculate how far over the width we went with the new value. 5042 // If this is word-spacing (our last resort guess) and the over is less than the under, we keep the higher value. 5043 // Otherwise, we revert to the underestimate. 5044 var under = maxWidth - previousWidth, 5045 over = width - maxWidth; 5046 5047 return { 5048 match: 'estimate', 5049 size: parseFloat((parseFloat(size) - (property === 'word-spacing' && previousWidth && ( over < under ) ? 0 : interval)).toFixed(3)) 5050 }; 5051 } 5052 5053 return width; 5054 } 5055 5056 function calculateSizes($t, $children, maxWidth, maxFontSize, minFontSize) 5057 { 5058 var $c = $t.clone(true) 5059 .addClass('bigtext-cloned') 5060 .css({ 5061 fontFamily: $t.css('font-family'), 5062 textTransform: $t.css('text-transform'), 5063 wordSpacing: $t.css('word-spacing'), 5064 letterSpacing: $t.css('letter-spacing'), 5065 position: 'absolute', 5066 left: BigText.DEBUG_MODE ? 0 : -9999, 5067 top: BigText.DEBUG_MODE ? 0 : -9999 5068 }) 5069 .appendTo(document.body); 5070 5071 // font-size isn't the only thing we can modify, we can also mess with: 5072 // word-spacing and letter-spacing. WebKit does not respect subpixel 5073 // letter-spacing, word-spacing, or font-size. 5074 // TODO try -webkit-transform: scale() as a workaround. 5075 var fontSizes = [], 5076 wordSpacings = [], 5077 minFontSizes = [], 5078 ratios = []; 5079 5080 $children.css('float', 'left').each(function() { 5081 var $line = $(this), 5082 // TODO replace 8, 4 with a proportional size to the calculated font-size. 5083 intervals = BigText.supports.wholeNumberFontSizeOnly ? [8, 4, 1] : [8, 4, 1, 0.1], 5084 lineMax, 5085 newFontSize; 5086 5087 if($line.hasClass(BigText.EXEMPT_CLASS)) { 5088 fontSizes.push(null); 5089 ratios.push(null); 5090 minFontSizes.push(false); 5091 return; 5092 } 5093 5094 // TODO we can cache this ratio? 5095 var autoGuessSubtraction = 32, // font size in px 5096 currentFontSize = parseFloat($line.css('font-size')), 5097 ratio = ( $line.width() / currentFontSize ).toFixed(6); 5098 5099 newFontSize = parseInt( maxWidth / ratio, 10 ) - autoGuessSubtraction; 5100 5101 outer: for(var m=0, n=intervals.length; m<n; m++) { 5102 inner: for(var j=1, k=10; j<=k; j++) { 5103 if(newFontSize + j*intervals[m] > maxFontSize) { 5104 newFontSize = maxFontSize; 5105 break outer; 5106 } 5107 5108 lineMax = testLineDimensions($line, maxWidth, 'font-size', newFontSize + j*intervals[m], intervals[m], 'px', lineMax); 5109 if(typeof lineMax !== 'number') { 5110 newFontSize = lineMax.size; 5111 5112 if(lineMax.match === 'exact') { 5113 break outer; 5114 } 5115 break inner; 5116 } 5117 } 5118 } 5119 5120 ratios.push(maxWidth / newFontSize); 5121 5122 if(newFontSize > maxFontSize) { 5123 fontSizes.push(maxFontSize); 5124 minFontSizes.push(false); 5125 } else if(!!minFontSize && newFontSize < minFontSize) { 5126 fontSizes.push(minFontSize); 5127 minFontSizes.push(true); 5128 } else { 5129 fontSizes.push(newFontSize); 5130 minFontSizes.push(false); 5131 } 5132 }).each(function(lineNumber) { 5133 var $line = $(this), 5134 wordSpacing = 0, 5135 interval = 1, 5136 maxWordSpacing; 5137 5138 if($line.hasClass(BigText.EXEMPT_CLASS)) { 5139 wordSpacings.push(null); 5140 return; 5141 } 5142 5143 // must re-use font-size, even though it was removed above. 5144 $line.css('font-size', fontSizes[lineNumber] + 'px'); 5145 5146 for(var m=1, n=3; m<n; m+=interval) { 5147 maxWordSpacing = testLineDimensions($line, maxWidth, 'word-spacing', m, interval, 'px', maxWordSpacing); 5148 if(typeof maxWordSpacing !== 'number') { 5149 wordSpacing = maxWordSpacing.size; 5150 break; 5151 } 5152 } 5153 5154 $line.css('font-size', ''); 5155 wordSpacings.push(wordSpacing); 5156 }).removeAttr('style'); 5157 5158 if( !BigText.DEBUG_MODE ) { 5159 $c.remove(); 5160 } else { 5161 $c.css({ 5162 'background-color': 'rgba(255,255,255,.4)' 5163 }); 5164 } 5165 5166 return { 5167 fontSizes: fontSizes, 5168 wordSpacings: wordSpacings, 5169 ratios: ratios, 5170 minFontSizes: minFontSizes 5171 }; 5172 } 5173 5174 $.fn.bigtext = BigText.jQueryMethod; 5175 window.BigText = BigText; 5176 5177})(this, jQuery); 5178/*! 5179 * Isotope PACKAGED v3.0.6 5180 * 5181 * Licensed GPLv3 for open source use 5182 * or Isotope Commercial License for commercial use 5183 * 5184 * https://isotope.metafizzy.co 5185 * Copyright 2010-2018 Metafizzy
vendor: 15,902 bytes, lines 5185-5835
5185 5186 */ 5187 5188/** 5189 * Bridget makes jQuery widgets 5190 * v2.0.1 5191 * MIT license 5192 */ 5193 5194/* jshint browser: true, strict: true, undef: true, unused: true */ 5195 5196( function( window, factory ) { 5197 // universal module definition 5198 /*jshint strict: false */ /* globals define, module, require */ 5199 if ( typeof define == 'function' && define.amd ) { 5200 // AMD 5201 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 5202 return factory( window, jQuery ); 5203 }); 5204 } else if ( typeof module == 'object' && module.exports ) { 5205 // CommonJS 5206 module.exports = factory( 5207 window, 5208 require('jquery') 5209 ); 5210 } else { 5211 // browser global 5212 window.jQueryBridget = factory( 5213 window, 5214 window.jQuery 5215 ); 5216 } 5217 5218}( window, function factory( window, jQuery ) { 5219'use strict'; 5220 5221// ----- utils ----- // 5222 5223var arraySlice = Array.prototype.slice; 5224 5225// helper function for logging errors 5226// $.error breaks jQuery chaining 5227var console = window.console; 5228var logError = typeof console == 'undefined' ? function() {} : 5229 function( message ) { 5230 console.error( message ); 5231 }; 5232 5233// ----- jQueryBridget ----- // 5234 5235function jQueryBridget( namespace, PluginClass, $ ) { 5236 $ = $ || jQuery || window.jQuery; 5237 if ( !$ ) { 5238 return; 5239 } 5240 5241 // add option method -> $().plugin('option', {...}) 5242 if ( !PluginClass.prototype.option ) { 5243 // option setter 5244 PluginClass.prototype.option = function( opts ) { 5245 // bail out if not an object 5246 if ( !$.isPlainObject( opts ) ){ 5247 return; 5248 } 5249 this.options = $.extend( true, this.options, opts ); 5250 }; 5251 } 5252 5253 // make jQuery plugin 5254 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 5255 if ( typeof arg0 == 'string' ) { 5256 // method call $().plugin( 'methodName', { options } ) 5257 // shift arguments by 1 5258 var args = arraySlice.call( arguments, 1 ); 5259 return methodCall( this, arg0, args ); 5260 } 5261 // just $().plugin({ options }) 5262 plainCall( this, arg0 ); 5263 return this; 5264 }; 5265 5266 // $().plugin('methodName') 5267 function methodCall( $elems, methodName, args ) { 5268 var returnValue; 5269 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 5270 5271 $elems.each( function( i, elem ) { 5272 // get instance 5273 var instance = $.data( elem, namespace ); 5274 if ( !instance ) { 5275 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 5276 pluginMethodStr ); 5277 return; 5278 } 5279 5280 var method = instance[ methodName ]; 5281 if ( !method || methodName.charAt(0) == '_' ) { 5282 logError( pluginMethodStr + ' is not a valid method' ); 5283 return; 5284 } 5285 5286 // apply method, get return value 5287 var value = method.apply( instance, args ); 5288 // set return value if value is returned, use only first value 5289 returnValue = returnValue === undefined ? value : returnValue; 5290 }); 5291 5292 return returnValue !== undefined ? returnValue : $elems; 5293 } 5294 5295 function plainCall( $elems, options ) { 5296 $elems.each( function( i, elem ) { 5297 var instance = $.data( elem, namespace ); 5298 if ( instance ) { 5299 // set options & init 5300 instance.option( options ); 5301 instance._init(); 5302 } else { 5303 // initialize new instance 5304 instance = new PluginClass( elem, options ); 5305 $.data( elem, namespace, instance ); 5306 } 5307 }); 5308 } 5309 5310 updateJQuery( $ ); 5311 5312} 5313 5314// ----- updateJQuery ----- // 5315 5316// set $.bridget for v1 backwards compatibility 5317function updateJQuery( $ ) { 5318 if ( !$ || ( $ && $.bridget ) ) { 5319 return; 5320 } 5321 $.bridget = jQueryBridget; 5322} 5323 5324updateJQuery( jQuery || window.jQuery ); 5325 5326// ----- ----- // 5327 5328return jQueryBridget; 5329 5330})); 5331 5332/** 5333 * EvEmitter v1.1.0 5334 * Lil' event emitter 5335 * MIT License 5336 */ 5337 5338/* jshint unused: true, undef: true, strict: true */ 5339 5340( function( global, factory ) { 5341 // universal module definition 5342 /* jshint strict: false */ /* globals define, module, window */ 5343 if ( typeof define == 'function' && define.amd ) { 5344 // AMD - RequireJS 5345 define( 'ev-emitter/ev-emitter',factory ); 5346 } else if ( typeof module == 'object' && module.exports ) { 5347 // CommonJS - Browserify, Webpack 5348 module.exports = factory(); 5349 } else { 5350 // Browser globals 5351 global.EvEmitter = factory(); 5352 } 5353 5354}( typeof window != 'undefined' ? window : this, function() { 5355 5356 5357 5358function EvEmitter() {} 5359 5360var proto = EvEmitter.prototype; 5361 5362proto.on = function( eventName, listener ) { 5363 if ( !eventName || !listener ) { 5364 return; 5365 } 5366 // set events hash 5367 var events = this._events = this._events || {}; 5368 // set listeners array 5369 var listeners = events[ eventName ] = events[ eventName ] || []; 5370 // only add once 5371 if ( listeners.indexOf( listener ) == -1 ) { 5372 listeners.push( listener ); 5373 } 5374 5375 return this; 5376}; 5377 5378proto.once = function( eventName, listener ) { 5379 if ( !eventName || !listener ) { 5380 return; 5381 } 5382 // add event 5383 this.on( eventName, listener ); 5384 // set once flag 5385 // set onceEvents hash 5386 var onceEvents = this._onceEvents = this._onceEvents || {}; 5387 // set onceListeners object 5388 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 5389 // set flag 5390 onceListeners[ listener ] = true; 5391 5392 return this; 5393}; 5394 5395proto.off = function( eventName, listener ) { 5396 var listeners = this._events && this._events[ eventName ]; 5397 if ( !listeners || !listeners.length ) { 5398 return; 5399 } 5400 var index = listeners.indexOf( listener ); 5401 if ( index != -1 ) { 5402 listeners.splice( index, 1 ); 5403 } 5404 5405 return this; 5406}; 5407 5408proto.emitEvent = function( eventName, args ) { 5409 var listeners = this._events && this._events[ eventName ]; 5410 if ( !listeners || !listeners.length ) { 5411 return; 5412 } 5413 // copy over to avoid interference if .off() in listener 5414 listeners = listeners.slice(0); 5415 args = args || []; 5416 // once stuff 5417 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 5418 5419 for ( var i=0; i < listeners.length; i++ ) { 5420 var listener = listeners[i] 5421 var isOnce = onceListeners && onceListeners[ listener ]; 5422 if ( isOnce ) { 5423 // remove listener 5424 // remove before trigger to prevent recursion 5425 this.off( eventName, listener ); 5426 // unset once flag 5427 delete onceListeners[ listener ]; 5428 } 5429 // trigger listener 5430 listener.apply( this, args ); 5431 } 5432 5433 return this; 5434}; 5435 5436proto.allOff = function() { 5437 delete this._events; 5438 delete this._onceEvents; 5439}; 5440 5441return EvEmitter; 5442 5443})); 5444 5445/*! 5446 * getSize v2.0.3 5447 * measure size of elements 5448 * MIT license 5449 */ 5450 5451/* jshint browser: true, strict: true, undef: true, unused: true */ 5452/* globals console: false */ 5453 5454( function( window, factory ) { 5455 /* jshint strict: false */ /* globals define, module */ 5456 if ( typeof define == 'function' && define.amd ) { 5457 // AMD 5458 define( 'get-size/get-size',factory ); 5459 } else if ( typeof module == 'object' && module.exports ) { 5460 // CommonJS 5461 module.exports = factory(); 5462 } else { 5463 // browser global 5464 window.getSize = factory(); 5465 } 5466 5467})( window, function factory() { 5468'use strict'; 5469 5470// -------------------------- helpers -------------------------- // 5471 5472// get a number from a string, not a percentage 5473function getStyleSize( value ) { 5474 var num = parseFloat( value ); 5475 // not a percent like '100%', and a number 5476 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 5477 return isValid && num; 5478} 5479 5480function noop() {} 5481 5482var logError = typeof console == 'undefined' ? noop : 5483 function( message ) { 5484 console.error( message ); 5485 }; 5486 5487// -------------------------- measurements -------------------------- // 5488 5489var measurements = [ 5490 'paddingLeft', 5491 'paddingRight', 5492 'paddingTop', 5493 'paddingBottom', 5494 'marginLeft', 5495 'marginRight', 5496 'marginTop', 5497 'marginBottom', 5498 'borderLeftWidth', 5499 'borderRightWidth', 5500 'borderTopWidth', 5501 'borderBottomWidth' 5502]; 5503 5504var measurementsLength = measurements.length; 5505 5506function getZeroSize() { 5507 var size = { 5508 width: 0, 5509 height: 0, 5510 innerWidth: 0, 5511 innerHeight: 0, 5512 outerWidth: 0, 5513 outerHeight: 0 5514 }; 5515 for ( var i=0; i < measurementsLength; i++ ) { 5516 var measurement = measurements[i]; 5517 size[ measurement ] = 0; 5518 } 5519 return size; 5520} 5521 5522// -------------------------- getStyle -------------------------- // 5523 5524/** 5525 * getStyle, get style of element, check for Firefox bug 5526 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 5527 */ 5528function getStyle( elem ) { 5529 var style = getComputedStyle( elem ); 5530 if ( !style ) { 5531 logError( 'Style returned ' + style + 5532 '. Are you running this code in a hidden iframe on Firefox? ' + 5533 'See https://bit.ly/getsizebug1' ); 5534 } 5535 return style; 5536} 5537 5538// -------------------------- setup -------------------------- // 5539 5540var isSetup = false; 5541 5542var isBoxSizeOuter; 5543 5544/** 5545 * setup 5546 * check isBoxSizerOuter 5547 * do on first getSize() rather than on page load for Firefox bug 5548 */ 5549function setup() { 5550 // setup once 5551 if ( isSetup ) { 5552 return; 5553 } 5554 isSetup = true; 5555 5556 // -------------------------- box sizing -------------------------- // 5557 5558 /** 5559 * Chrome & Safari measure the outer-width on style.width on border-box elems 5560 * IE11 & Firefox<29 measures the inner-width 5561 */ 5562 var div = document.createElement('div'); 5563 div.style.width = '200px'; 5564 div.style.padding = '1px 2px 3px 4px'; 5565 div.style.borderStyle = 'solid'; 5566 div.style.borderWidth = '1px 2px 3px 4px'; 5567 div.style.boxSizing = 'border-box'; 5568 5569 var body = document.body || document.documentElement; 5570 body.appendChild( div ); 5571 var style = getStyle( div ); 5572 // round value for browser zoom. desandro/masonry#928 5573 isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; 5574 getSize.isBoxSizeOuter = isBoxSizeOuter; 5575 5576 body.removeChild( div ); 5577} 5578 5579// -------------------------- getSize -------------------------- // 5580 5581function getSize( elem ) { 5582 setup(); 5583 5584 // use querySeletor if elem is string 5585 if ( typeof elem == 'string' ) { 5586 elem = document.querySelector( elem ); 5587 } 5588 5589 // do not proceed on non-objects 5590 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 5591 return; 5592 } 5593 5594 var style = getStyle( elem ); 5595 5596 // if hidden, everything is 0 5597 if ( style.display == 'none' ) { 5598 return getZeroSize(); 5599 } 5600 5601 var size = {}; 5602 size.width = elem.offsetWidth; 5603 size.height = elem.offsetHeight; 5604 5605 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 5606 5607 // get all measurements 5608 for ( var i=0; i < measurementsLength; i++ ) { 5609 var measurement = measurements[i]; 5610 var value = style[ measurement ]; 5611 var num = parseFloat( value ); 5612 // any 'auto', 'medium' value will be 0 5613 size[ measurement ] = !isNaN( num ) ? num : 0; 5614 } 5615 5616 var paddingWidth = size.paddingLeft + size.paddingRight; 5617 var paddingHeight = size.paddingTop + size.paddingBottom; 5618 var marginWidth = size.marginLeft + size.marginRight; 5619 var marginHeight = size.marginTop + size.marginBottom; 5620 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 5621 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 5622 5623 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 5624 5625 // overwrite width and height if we can get it from style 5626 var styleWidth = getStyleSize( style.width ); 5627 if ( styleWidth !== false ) { 5628 size.width = styleWidth + 5629 // add padding and border unless it's already including it 5630 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 5631 } 5632 5633 var styleHeight = getStyleSize( style.height ); 5634 if ( styleHeight !== false ) { 5635 size.height = styleHeight + 5636 // add padding and border unless it's already including it 5637 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 5638 } 5639 5640 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 5641 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 5642 5643 size.outerWidth = size.width + marginWidth; 5644 size.outerHeight = size.height + marginHeight; 5645 5646 return size; 5647} 5648 5649return getSize; 5650 5651}); 5652 5653/** 5654 * matchesSelector v2.0.2 5655 * matchesSelector( element, '.selector' ) 5656 * MIT license 5657 */ 5658 5659/*jshint browser: true, strict: true, undef: true, unused: true */ 5660 5661( function( window, factory ) { 5662 /*global define: false, module: false */ 5663 'use strict'; 5664 // universal module definition 5665 if ( typeof define == 'function' && define.amd ) { 5666 // AMD 5667 define( 'desandro-matches-selector/matches-selector',factory ); 5668 } else if ( typeof module == 'object' && module.exports ) { 5669 // CommonJS 5670 module.exports = factory(); 5671 } else { 5672 // browser global 5673 window.matchesSelector = factory(); 5674 } 5675 5676}( window, function factory() { 5677 'use strict'; 5678 5679 var matchesMethod = ( function() { 5680 var ElemProto = window.Element.prototype; 5681 // check for the standard method name first 5682 if ( ElemProto.matches ) { 5683 return 'matches'; 5684 } 5685 // check un-prefixed 5686 if ( ElemProto.matchesSelector ) { 5687 return 'matchesSelector'; 5688 } 5689 // check vendor prefixes 5690 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 5691 5692 for ( var i=0; i < prefixes.length; i++ ) { 5693 var prefix = prefixes[i]; 5694 var method = prefix + 'MatchesSelector'; 5695 if ( ElemProto[ method ] ) { 5696 return method; 5697 } 5698 } 5699 })(); 5700 5701 return function matchesSelector( elem, selector ) { 5702 return elem[ matchesMethod ]( selector ); 5703 }; 5704 5705})); 5706 5707/** 5708 * Fizzy UI utils v2.0.7 5709 * MIT license 5710 */ 5711 5712/*jshint browser: true, undef: true, unused: true, strict: true */ 5713 5714( function( window, factory ) { 5715 // universal module definition 5716 /*jshint strict: false */ /*globals define, module, require */ 5717 5718 if ( typeof define == 'function' && define.amd ) { 5719 // AMD 5720 define( 'fizzy-ui-utils/utils',[ 5721 'desandro-matches-selector/matches-selector' 5722 ], function( matchesSelector ) { 5723 return factory( window, matchesSelector ); 5724 }); 5725 } else if ( typeof module == 'object' && module.exports ) { 5726 // CommonJS 5727 module.exports = factory( 5728 window, 5729 require('desandro-matches-selector') 5730 ); 5731 } else { 5732 // browser global 5733 window.fizzyUIUtils = factory( 5734 window, 5735 window.matchesSelector 5736 ); 5737 } 5738 5739}( window, function factory( window, matchesSelector ) { 5740 5741 5742 5743var utils = {}; 5744 5745// ----- extend ----- // 5746 5747// extends objects 5748utils.extend = function( a, b ) { 5749 for ( var prop in b ) { 5750 a[ prop ] = b[ prop ]; 5751 } 5752 return a; 5753}; 5754 5755// ----- modulo ----- // 5756 5757utils.modulo = function( num, div ) { 5758 return ( ( num % div ) + div ) % div; 5759}; 5760 5761// ----- makeArray ----- // 5762 5763var arraySlice = Array.prototype.slice; 5764 5765// turn element or nodeList into an array 5766utils.makeArray = function( obj ) { 5767 if ( Array.isArray( obj ) ) { 5768 // use object if already an array 5769 return obj; 5770 } 5771 // return empty array if undefined or null. #6 5772 if ( obj === null || obj === undefined ) { 5773 return []; 5774 } 5775 5776 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 5777 if ( isArrayLike ) { 5778 // convert nodeList to array 5779 return arraySlice.call( obj ); 5780 } 5781 5782 // array of single index 5783 return [ obj ]; 5784}; 5785 5786// ----- removeFrom ----- // 5787 5788utils.removeFrom = function( ary, obj ) { 5789 var index = ary.indexOf( obj ); 5790 if ( index != -1 ) { 5791 ary.splice( index, 1 ); 5792 } 5793}; 5794 5795// ----- getParent ----- // 5796 5797utils.getParent = function( elem, selector ) { 5798 while ( elem.parentNode && elem != document.body ) { 5799 elem = elem.parentNode; 5800 if ( matchesSelector( elem, selector ) ) { 5801 return elem; 5802 } 5803 } 5804}; 5805 5806// ----- getQueryElement ----- // 5807 5808// use element as selector string 5809utils.getQueryElement = function( elem ) { 5810 if ( typeof elem == 'string' ) { 5811 return document.querySelector( elem ); 5812 } 5813 return elem; 5814}; 5815 5816// ----- handleEvent ----- // 5817 5818// enable .ontype to trigger from .addEventListener( elem, 'type' ) 5819utils.handleEvent = function( event ) { 5820 var method = 'on' + event.type; 5821 if ( this[ method ] ) { 5822 this[ method ]( event ); 5823 } 5824}; 5825 5826// ----- filterFindElements ----- // 5827 5828utils.filterFindElements = function( elems, selector ) { 5829 // make array of elems 5830 elems = utils.makeArray( elems ); 5831 var ffElems = []; 5832 5833 elems.forEach( function( elem ) { 5834 // check that elem is an actual element 5835
5835// START UNCODE EDIT 5836 // if ( !( elem instanceof HTMLElement ) ) { 5837 if ( !( elem instanceof HTMLElement ) && !SiteParameters.is_frontend_editor ) { 5838 // END UNCODE EDIT
vendor: 36,979 bytes, lines 5838-7319
5838 5839 return; 5840 } 5841 // add elem if no selector 5842 if ( !selector ) { 5843 ffElems.push( elem ); 5844 return; 5845 } 5846 // filter & find items if we have a selector 5847 // filter 5848 if ( matchesSelector( elem, selector ) ) { 5849 ffElems.push( elem ); 5850 } 5851 // find children 5852 var childElems = elem.querySelectorAll( selector ); 5853 // concat childElems to filterFound array 5854 for ( var i=0; i < childElems.length; i++ ) { 5855 ffElems.push( childElems[i] ); 5856 } 5857 }); 5858 5859 return ffElems; 5860}; 5861 5862// ----- debounceMethod ----- // 5863 5864utils.debounceMethod = function( _class, methodName, threshold ) { 5865 threshold = threshold || 100; 5866 // original method 5867 var method = _class.prototype[ methodName ]; 5868 var timeoutName = methodName + 'Timeout'; 5869 5870 _class.prototype[ methodName ] = function() { 5871 var timeout = this[ timeoutName ]; 5872 clearTimeout( timeout ); 5873 5874 var args = arguments; 5875 var _this = this; 5876 this[ timeoutName ] = setTimeout( function() { 5877 method.apply( _this, args ); 5878 delete _this[ timeoutName ]; 5879 }, threshold ); 5880 }; 5881}; 5882 5883// ----- docReady ----- // 5884 5885utils.docReady = function( callback ) { 5886 var readyState = document.readyState; 5887 if ( readyState == 'complete' || readyState == 'interactive' ) { 5888 // do async to allow for other scripts to run. metafizzy/flickity#441 5889 setTimeout( callback ); 5890 } else { 5891 document.addEventListener( 'DOMContentLoaded', callback ); 5892 } 5893}; 5894 5895// ----- htmlInit ----- // 5896 5897// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 5898utils.toDashed = function( str ) { 5899 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 5900 return $1 + '-' + $2; 5901 }).toLowerCase(); 5902}; 5903 5904var console = window.console; 5905/** 5906 * allow user to initialize classes via [data-namespace] or .js-namespace class 5907 * htmlInit( Widget, 'widgetName' ) 5908 * options are parsed from data-namespace-options 5909 */ 5910utils.htmlInit = function( WidgetClass, namespace ) { 5911 utils.docReady( function() { 5912 var dashedNamespace = utils.toDashed( namespace ); 5913 var dataAttr = 'data-' + dashedNamespace; 5914 var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); 5915 var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); 5916 var elems = utils.makeArray( dataAttrElems ) 5917 .concat( utils.makeArray( jsDashElems ) ); 5918 var dataOptionsAttr = dataAttr + '-options'; 5919 var jQuery = window.jQuery; 5920 5921 elems.forEach( function( elem ) { 5922 var attr = elem.getAttribute( dataAttr ) || 5923 elem.getAttribute( dataOptionsAttr ); 5924 var options; 5925 try { 5926 options = attr && JSON.parse( attr ); 5927 } catch ( error ) { 5928 // log error, do not initialize 5929 if ( console ) { 5930 console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + 5931 ': ' + error ); 5932 } 5933 return; 5934 } 5935 // initialize 5936 var instance = new WidgetClass( elem, options ); 5937 // make available via $().data('namespace') 5938 if ( jQuery ) { 5939 jQuery.data( elem, namespace, instance ); 5940 } 5941 }); 5942 5943 }); 5944}; 5945 5946// ----- ----- // 5947 5948return utils; 5949 5950})); 5951 5952/** 5953 * Outlayer Item 5954 */ 5955 5956( function( window, factory ) { 5957 // universal module definition 5958 /* jshint strict: false */ /* globals define, module, require */ 5959 if ( typeof define == 'function' && define.amd ) { 5960 // AMD - RequireJS 5961 define( 'outlayer/item',[ 5962 'ev-emitter/ev-emitter', 5963 'get-size/get-size' 5964 ], 5965 factory 5966 ); 5967 } else if ( typeof module == 'object' && module.exports ) { 5968 // CommonJS - Browserify, Webpack 5969 module.exports = factory( 5970 require('ev-emitter'), 5971 require('get-size') 5972 ); 5973 } else { 5974 // browser global 5975 window.Outlayer = {}; 5976 window.Outlayer.Item = factory( 5977 window.EvEmitter, 5978 window.getSize 5979 ); 5980 } 5981 5982}( window, function factory( EvEmitter, getSize ) { 5983'use strict'; 5984 5985// ----- helpers ----- // 5986 5987function isEmptyObj( obj ) { 5988 for ( var prop in obj ) { 5989 return false; 5990 } 5991 prop = null; 5992 return true; 5993} 5994 5995// -------------------------- CSS3 support -------------------------- // 5996 5997 5998var docElemStyle = document.documentElement.style; 5999 6000var transitionProperty = typeof docElemStyle.transition == 'string' ? 6001 'transition' : 'WebkitTransition'; 6002var transformProperty = typeof docElemStyle.transform == 'string' ? 6003 'transform' : 'WebkitTransform'; 6004 6005var transitionEndEvent = { 6006 WebkitTransition: 'webkitTransitionEnd', 6007 transition: 'transitionend' 6008}[ transitionProperty ]; 6009 6010// cache all vendor properties that could have vendor prefix 6011var vendorProperties = { 6012 transform: transformProperty, 6013 transition: transitionProperty, 6014 transitionDuration: transitionProperty + 'Duration', 6015 transitionProperty: transitionProperty + 'Property', 6016 transitionDelay: transitionProperty + 'Delay' 6017}; 6018 6019// -------------------------- Item -------------------------- // 6020 6021function Item( element, layout ) { 6022 if ( !element ) { 6023 return; 6024 } 6025 6026 this.element = element; 6027 // parent layout class, i.e. Masonry, Isotope, or Packery 6028 this.layout = layout; 6029 this.position = { 6030 x: 0, 6031 y: 0 6032 }; 6033 6034 this._create(); 6035} 6036 6037// inherit EvEmitter 6038var proto = Item.prototype = Object.create( EvEmitter.prototype ); 6039proto.constructor = Item; 6040 6041proto._create = function() { 6042 // transition objects 6043 this._transn = { 6044 ingProperties: {}, 6045 clean: {}, 6046 onEnd: {} 6047 }; 6048 6049 this.css({ 6050 position: 'absolute' 6051 }); 6052}; 6053 6054// trigger specified handler for event type 6055proto.handleEvent = function( event ) { 6056 var method = 'on' + event.type; 6057 if ( this[ method ] ) { 6058 this[ method ]( event ); 6059 } 6060}; 6061 6062proto.getSize = function() { 6063 this.size = getSize( this.element ); 6064}; 6065 6066/** 6067 * apply CSS styles to element 6068 * @param {Object} style 6069 */ 6070proto.css = function( style ) { 6071 var elemStyle = this.element.style; 6072 6073 for ( var prop in style ) { 6074 // use vendor property if available 6075 var supportedProp = vendorProperties[ prop ] || prop; 6076 elemStyle[ supportedProp ] = style[ prop ]; 6077 } 6078}; 6079 6080 // measure position, and sets it 6081proto.getPosition = function() { 6082 var style = getComputedStyle( this.element ); 6083 var isOriginLeft = this.layout._getOption('originLeft'); 6084 var isOriginTop = this.layout._getOption('originTop'); 6085 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 6086 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 6087 var x = parseFloat( xValue ); 6088 var y = parseFloat( yValue ); 6089 // convert percent to pixels 6090 var layoutSize = this.layout.size; 6091 if ( xValue.indexOf('%') != -1 ) { 6092 x = ( x / 100 ) * layoutSize.width; 6093 } 6094 if ( yValue.indexOf('%') != -1 ) { 6095 y = ( y / 100 ) * layoutSize.height; 6096 } 6097 // clean up 'auto' or other non-integer values 6098 x = isNaN( x ) ? 0 : x; 6099 y = isNaN( y ) ? 0 : y; 6100 // remove padding from measurement 6101 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 6102 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 6103 6104 this.position.x = x; 6105 this.position.y = y; 6106}; 6107 6108// set settled position, apply padding 6109proto.layoutPosition = function() { 6110 var layoutSize = this.layout.size; 6111 var style = {}; 6112 var isOriginLeft = this.layout._getOption('originLeft'); 6113 var isOriginTop = this.layout._getOption('originTop'); 6114 6115 // x 6116 var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; 6117 var xProperty = isOriginLeft ? 'left' : 'right'; 6118 var xResetProperty = isOriginLeft ? 'right' : 'left'; 6119 6120 var x = this.position.x + layoutSize[ xPadding ]; 6121 // set in percentage or pixels 6122 style[ xProperty ] = this.getXValue( x ); 6123 // reset other property 6124 style[ xResetProperty ] = ''; 6125 6126 // y 6127 var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; 6128 var yProperty = isOriginTop ? 'top' : 'bottom'; 6129 var yResetProperty = isOriginTop ? 'bottom' : 'top'; 6130 6131 var y = this.position.y + layoutSize[ yPadding ]; 6132 // set in percentage or pixels 6133 style[ yProperty ] = this.getYValue( y ); 6134 // reset other property 6135 style[ yResetProperty ] = ''; 6136 6137 this.css( style ); 6138 this.emitEvent( 'layout', [ this ] ); 6139}; 6140 6141proto.getXValue = function( x ) { 6142 var isHorizontal = this.layout._getOption('horizontal'); 6143 return this.layout.options.percentPosition && !isHorizontal ? 6144 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 6145}; 6146 6147proto.getYValue = function( y ) { 6148 var isHorizontal = this.layout._getOption('horizontal'); 6149 return this.layout.options.percentPosition && isHorizontal ? 6150 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 6151}; 6152 6153proto._transitionTo = function( x, y ) { 6154 this.getPosition(); 6155 // get current x & y from top/left 6156 var curX = this.position.x; 6157 var curY = this.position.y; 6158 6159 var didNotMove = x == this.position.x && y == this.position.y; 6160 6161 // save end position 6162 this.setPosition( x, y ); 6163 6164 // if did not move and not transitioning, just go to layout 6165 if ( didNotMove && !this.isTransitioning ) { 6166 this.layoutPosition(); 6167 return; 6168 } 6169 6170 var transX = x - curX; 6171 var transY = y - curY; 6172 var transitionStyle = {}; 6173 transitionStyle.transform = this.getTranslate( transX, transY ); 6174 6175 this.transition({ 6176 to: transitionStyle, 6177 onTransitionEnd: { 6178 transform: this.layoutPosition 6179 }, 6180 isCleaning: true 6181 }); 6182}; 6183 6184proto.getTranslate = function( x, y ) { 6185 // flip cooridinates if origin on right or bottom 6186 var isOriginLeft = this.layout._getOption('originLeft'); 6187 var isOriginTop = this.layout._getOption('originTop'); 6188 x = isOriginLeft ? x : -x; 6189 y = isOriginTop ? y : -y; 6190 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 6191}; 6192 6193// non transition + transform support 6194proto.goTo = function( x, y ) { 6195 this.setPosition( x, y ); 6196 this.layoutPosition(); 6197}; 6198 6199proto.moveTo = proto._transitionTo; 6200 6201proto.setPosition = function( x, y ) { 6202 this.position.x = parseFloat( x ); 6203 this.position.y = parseFloat( y ); 6204}; 6205 6206// ----- transition ----- // 6207 6208/** 6209 * @param {Object} style - CSS 6210 * @param {Function} onTransitionEnd 6211 */ 6212 6213// non transition, just trigger callback 6214proto._nonTransition = function( args ) { 6215 this.css( args.to ); 6216 if ( args.isCleaning ) { 6217 this._removeStyles( args.to ); 6218 } 6219 for ( var prop in args.onTransitionEnd ) { 6220 args.onTransitionEnd[ prop ].call( this ); 6221 } 6222}; 6223 6224/** 6225 * proper transition 6226 * @param {Object} args - arguments 6227 * @param {Object} to - style to transition to 6228 * @param {Object} from - style to start transition from 6229 * @param {Boolean} isCleaning - removes transition styles after transition 6230 * @param {Function} onTransitionEnd - callback 6231 */ 6232proto.transition = function( args ) { 6233 // redirect to nonTransition if no transition duration 6234 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 6235 this._nonTransition( args ); 6236 return; 6237 } 6238 6239 var _transition = this._transn; 6240 // keep track of onTransitionEnd callback by css property 6241 for ( var prop in args.onTransitionEnd ) { 6242 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 6243 } 6244 // keep track of properties that are transitioning 6245 for ( prop in args.to ) { 6246 _transition.ingProperties[ prop ] = true; 6247 // keep track of properties to clean up when transition is done 6248 if ( args.isCleaning ) { 6249 _transition.clean[ prop ] = true; 6250 } 6251 } 6252 6253 // set from styles 6254 if ( args.from ) { 6255 this.css( args.from ); 6256 // force redraw. http://blog.alexmaccaw.com/css-transitions 6257 var h = this.element.offsetHeight; 6258 // hack for JSHint to hush about unused var 6259 h = null; 6260 } 6261 // enable transition 6262 this.enableTransition( args.to ); 6263 // set styles that are transitioning 6264 this.css( args.to ); 6265 6266 this.isTransitioning = true; 6267 6268}; 6269 6270// dash before all cap letters, including first for 6271// WebkitTransform => -webkit-transform 6272function toDashedAll( str ) { 6273 return str.replace( /([A-Z])/g, function( $1 ) { 6274 return '-' + $1.toLowerCase(); 6275 }); 6276} 6277 6278var transitionProps = 'opacity,' + toDashedAll( transformProperty ); 6279 6280proto.enableTransition = function(/* style */) { 6281 // HACK changing transitionProperty during a transition 6282 // will cause transition to jump 6283 if ( this.isTransitioning ) { 6284 return; 6285 } 6286 6287 // make `transition: foo, bar, baz` from style object 6288 // HACK un-comment this when enableTransition can work 6289 // while a transition is happening 6290 // var transitionValues = []; 6291 // for ( var prop in style ) { 6292 // // dash-ify camelCased properties like WebkitTransition 6293 // prop = vendorProperties[ prop ] || prop; 6294 // transitionValues.push( toDashedAll( prop ) ); 6295 // } 6296 // munge number to millisecond, to match stagger 6297 var duration = this.layout.options.transitionDuration; 6298 duration = typeof duration == 'number' ? duration + 'ms' : duration; 6299 // enable transition styles 6300 this.css({ 6301 transitionProperty: transitionProps, 6302 transitionDuration: duration, 6303 transitionDelay: this.staggerDelay || 0 6304 }); 6305 // listen for transition end event 6306 this.element.addEventListener( transitionEndEvent, this, false ); 6307}; 6308 6309// ----- events ----- // 6310 6311proto.onwebkitTransitionEnd = function( event ) { 6312 this.ontransitionend( event ); 6313}; 6314 6315proto.onotransitionend = function( event ) { 6316 this.ontransitionend( event ); 6317}; 6318 6319// properties that I munge to make my life easier 6320var dashedVendorProperties = { 6321 '-webkit-transform': 'transform' 6322}; 6323 6324proto.ontransitionend = function( event ) { 6325 // disregard bubbled events from children 6326 if ( event.target !== this.element ) { 6327 return; 6328 } 6329 var _transition = this._transn; 6330 // get property name of transitioned property, convert to prefix-free 6331 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 6332 6333 // remove property that has completed transitioning 6334 delete _transition.ingProperties[ propertyName ]; 6335 // check if any properties are still transitioning 6336 if ( isEmptyObj( _transition.ingProperties ) ) { 6337 // all properties have completed transitioning 6338 this.disableTransition(); 6339 } 6340 // clean style 6341 if ( propertyName in _transition.clean ) { 6342 // clean up style 6343 this.element.style[ event.propertyName ] = ''; 6344 delete _transition.clean[ propertyName ]; 6345 } 6346 // trigger onTransitionEnd callback 6347 if ( propertyName in _transition.onEnd ) { 6348 var onTransitionEnd = _transition.onEnd[ propertyName ]; 6349 onTransitionEnd.call( this ); 6350 delete _transition.onEnd[ propertyName ]; 6351 } 6352 6353 this.emitEvent( 'transitionEnd', [ this ] ); 6354}; 6355 6356proto.disableTransition = function() { 6357 this.removeTransitionStyles(); 6358 this.element.removeEventListener( transitionEndEvent, this, false ); 6359 this.isTransitioning = false; 6360}; 6361 6362/** 6363 * removes style property from element 6364 * @param {Object} style 6365**/ 6366proto._removeStyles = function( style ) { 6367 // clean up transition styles 6368 var cleanStyle = {}; 6369 for ( var prop in style ) { 6370 cleanStyle[ prop ] = ''; 6371 } 6372 this.css( cleanStyle ); 6373}; 6374 6375var cleanTransitionStyle = { 6376 transitionProperty: '', 6377 transitionDuration: '', 6378 transitionDelay: '' 6379}; 6380 6381proto.removeTransitionStyles = function() { 6382 // remove transition 6383 this.css( cleanTransitionStyle ); 6384}; 6385 6386// ----- stagger ----- // 6387 6388proto.stagger = function( delay ) { 6389 delay = isNaN( delay ) ? 0 : delay; 6390 this.staggerDelay = delay + 'ms'; 6391}; 6392 6393// ----- show/hide/remove ----- // 6394 6395// remove element from DOM 6396proto.removeElem = function() { 6397 this.element.parentNode.removeChild( this.element ); 6398 // remove display: none 6399 this.css({ display: '' }); 6400 this.emitEvent( 'remove', [ this ] ); 6401}; 6402 6403proto.remove = function() { 6404 // just remove element if no transition support or no transition 6405 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 6406 this.removeElem(); 6407 return; 6408 } 6409 6410 // start transition 6411 this.once( 'transitionEnd', function() { 6412 this.removeElem(); 6413 }); 6414 this.hide(); 6415}; 6416 6417proto.reveal = function() { 6418 delete this.isHidden; 6419 // remove display: none 6420 this.css({ display: '' }); 6421 6422 var options = this.layout.options; 6423 6424 var onTransitionEnd = {}; 6425 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 6426 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 6427 6428 this.transition({ 6429 from: options.hiddenStyle, 6430 to: options.visibleStyle, 6431 isCleaning: true, 6432 onTransitionEnd: onTransitionEnd 6433 }); 6434}; 6435 6436proto.onRevealTransitionEnd = function() { 6437 // check if still visible 6438 // during transition, item may have been hidden 6439 if ( !this.isHidden ) { 6440 this.emitEvent('reveal'); 6441 } 6442}; 6443 6444/** 6445 * get style property use for hide/reveal transition end 6446 * @param {String} styleProperty - hiddenStyle/visibleStyle 6447 * @returns {String} 6448 */ 6449proto.getHideRevealTransitionEndProperty = function( styleProperty ) { 6450 var optionStyle = this.layout.options[ styleProperty ]; 6451 // use opacity 6452 if ( optionStyle.opacity ) { 6453 return 'opacity'; 6454 } 6455 // get first property 6456 for ( var prop in optionStyle ) { 6457 return prop; 6458 } 6459}; 6460 6461proto.hide = function() { 6462 // set flag 6463 this.isHidden = true; 6464 // remove display: none 6465 this.css({ display: '' }); 6466 6467 var options = this.layout.options; 6468 6469 var onTransitionEnd = {}; 6470 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 6471 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 6472 6473 this.transition({ 6474 from: options.visibleStyle, 6475 to: options.hiddenStyle, 6476 // keep hidden stuff hidden 6477 isCleaning: true, 6478 onTransitionEnd: onTransitionEnd 6479 }); 6480}; 6481 6482proto.onHideTransitionEnd = function() { 6483 // check if still hidden 6484 // during transition, item may have been un-hidden 6485 if ( this.isHidden ) { 6486 this.css({ display: 'none' }); 6487 this.emitEvent('hide'); 6488 } 6489}; 6490 6491proto.destroy = function() { 6492 this.css({ 6493 position: '', 6494 left: '', 6495 right: '', 6496 top: '', 6497 bottom: '', 6498 transition: '', 6499 transform: '' 6500 }); 6501}; 6502 6503return Item; 6504 6505})); 6506 6507/*! 6508 * Outlayer v2.1.1 6509 * the brains and guts of a layout library 6510 * MIT license 6511 */ 6512 6513( function( window, factory ) { 6514 'use strict'; 6515 // universal module definition 6516 /* jshint strict: false */ /* globals define, module, require */ 6517 if ( typeof define == 'function' && define.amd ) { 6518 // AMD - RequireJS 6519 define( 'outlayer/outlayer',[ 6520 'ev-emitter/ev-emitter', 6521 'get-size/get-size', 6522 'fizzy-ui-utils/utils', 6523 './item' 6524 ], 6525 function( EvEmitter, getSize, utils, Item ) { 6526 return factory( window, EvEmitter, getSize, utils, Item); 6527 } 6528 ); 6529 } else if ( typeof module == 'object' && module.exports ) { 6530 // CommonJS - Browserify, Webpack 6531 module.exports = factory( 6532 window, 6533 require('ev-emitter'), 6534 require('get-size'), 6535 require('fizzy-ui-utils'), 6536 require('./item') 6537 ); 6538 } else { 6539 // browser global 6540 window.Outlayer = factory( 6541 window, 6542 window.EvEmitter, 6543 window.getSize, 6544 window.fizzyUIUtils, 6545 window.Outlayer.Item 6546 ); 6547 } 6548 6549}( window, function factory( window, EvEmitter, getSize, utils, Item ) { 6550'use strict'; 6551 6552// ----- vars ----- // 6553 6554var console = window.console; 6555var jQuery = window.jQuery; 6556var noop = function() {}; 6557 6558// -------------------------- Outlayer -------------------------- // 6559 6560// globally unique identifiers 6561var GUID = 0; 6562// internal store of all Outlayer intances 6563var instances = {}; 6564 6565 6566/** 6567 * @param {Element, String} element 6568 * @param {Object} options 6569 * @constructor 6570 */ 6571function Outlayer( element, options ) { 6572 var queryElement = utils.getQueryElement( element ); 6573 if ( !queryElement ) { 6574 if ( console ) { 6575 console.error( 'Bad element for ' + this.constructor.namespace + 6576 ': ' + ( queryElement || element ) ); 6577 } 6578 return; 6579 } 6580 this.element = queryElement; 6581 // add jQuery 6582 if ( jQuery ) { 6583 this.$element = jQuery( this.element ); 6584 } 6585 6586 // options 6587 this.options = utils.extend( {}, this.constructor.defaults ); 6588 this.option( options ); 6589 6590 // add id for Outlayer.getFromElement 6591 var id = ++GUID; 6592 this.element.outlayerGUID = id; // expando 6593 instances[ id ] = this; // associate via id 6594 6595 // kick it off 6596 this._create(); 6597 6598 var isInitLayout = this._getOption('initLayout'); 6599 if ( isInitLayout ) { 6600 this.layout(); 6601 } 6602} 6603 6604// settings are for internal use only 6605Outlayer.namespace = 'outlayer'; 6606Outlayer.Item = Item; 6607 6608// default options 6609Outlayer.defaults = { 6610 containerStyle: { 6611 position: 'relative' 6612 }, 6613 initLayout: true, 6614 originLeft: true, 6615 originTop: true, 6616 resize: true, 6617 resizeContainer: true, 6618 // item options 6619 transitionDuration: '0.4s', 6620 hiddenStyle: { 6621 opacity: 0, 6622 transform: 'scale(0.001)' 6623 }, 6624 visibleStyle: { 6625 opacity: 1, 6626 transform: 'scale(1)' 6627 } 6628}; 6629 6630var proto = Outlayer.prototype; 6631// inherit EvEmitter 6632utils.extend( proto, EvEmitter.prototype ); 6633 6634/** 6635 * set options 6636 * @param {Object} opts 6637 */ 6638proto.option = function( opts ) { 6639 utils.extend( this.options, opts ); 6640}; 6641 6642/** 6643 * get backwards compatible option value, check old name 6644 */ 6645proto._getOption = function( option ) { 6646 var oldOption = this.constructor.compatOptions[ option ]; 6647 return oldOption && this.options[ oldOption ] !== undefined ? 6648 this.options[ oldOption ] : this.options[ option ]; 6649}; 6650 6651Outlayer.compatOptions = { 6652 // currentName: oldName 6653 initLayout: 'isInitLayout', 6654 horizontal: 'isHorizontal', 6655 layoutInstant: 'isLayoutInstant', 6656 originLeft: 'isOriginLeft', 6657 originTop: 'isOriginTop', 6658 resize: 'isResizeBound', 6659 resizeContainer: 'isResizingContainer' 6660}; 6661 6662proto._create = function() { 6663 // get items from children 6664 this.reloadItems(); 6665 // elements that affect layout, but are not laid out 6666 this.stamps = []; 6667 this.stamp( this.options.stamp ); 6668 // set container style 6669 utils.extend( this.element.style, this.options.containerStyle ); 6670 6671 // bind resize method 6672 var canBindResize = this._getOption('resize'); 6673 if ( canBindResize ) { 6674 this.bindResize(); 6675 } 6676}; 6677 6678// goes through all children again and gets bricks in proper order 6679proto.reloadItems = function() { 6680 // collection of item elements 6681 this.items = this._itemize( this.element.children ); 6682}; 6683 6684 6685/** 6686 * turn elements into Outlayer.Items to be used in layout 6687 * @param {Array or NodeList or HTMLElement} elems 6688 * @returns {Array} items - collection of new Outlayer Items 6689 */ 6690proto._itemize = function( elems ) { 6691 6692 var itemElems = this._filterFindItemElements( elems ); 6693 var Item = this.constructor.Item; 6694 6695 // create new Outlayer Items for collection 6696 var items = []; 6697 for ( var i=0; i < itemElems.length; i++ ) { 6698 var elem = itemElems[i]; 6699 var item = new Item( elem, this ); 6700 items.push( item ); 6701 } 6702 6703 return items; 6704}; 6705 6706/** 6707 * get item elements to be used in layout 6708 * @param {Array or NodeList or HTMLElement} elems 6709 * @returns {Array} items - item elements 6710 */ 6711proto._filterFindItemElements = function( elems ) { 6712 return utils.filterFindElements( elems, this.options.itemSelector ); 6713}; 6714 6715/** 6716 * getter method for getting item elements 6717 * @returns {Array} elems - collection of item elements 6718 */ 6719proto.getItemElements = function() { 6720 return this.items.map( function( item ) { 6721 return item.element; 6722 }); 6723}; 6724 6725// ----- init & layout ----- // 6726 6727/** 6728 * lays out all items 6729 */ 6730proto.layout = function() { 6731 this._resetLayout(); 6732 this._manageStamps(); 6733 6734 // don't animate first layout 6735 var layoutInstant = this._getOption('layoutInstant'); 6736 var isInstant = layoutInstant !== undefined ? 6737 layoutInstant : !this._isLayoutInited; 6738 this.layoutItems( this.items, isInstant ); 6739 6740 // flag for initalized 6741 this._isLayoutInited = true; 6742}; 6743 6744// _init is alias for layout 6745proto._init = proto.layout; 6746 6747/** 6748 * logic before any new layout 6749 */ 6750proto._resetLayout = function() { 6751 this.getSize(); 6752}; 6753 6754 6755proto.getSize = function() { 6756 this.size = getSize( this.element ); 6757}; 6758 6759/** 6760 * get measurement from option, for columnWidth, rowHeight, gutter 6761 * if option is String -> get element from selector string, & get size of element 6762 * if option is Element -> get size of element 6763 * else use option as a number 6764 * 6765 * @param {String} measurement 6766 * @param {String} size - width or height 6767 * @private 6768 */ 6769proto._getMeasurement = function( measurement, size ) { 6770 var option = this.options[ measurement ]; 6771 var elem; 6772 if ( !option ) { 6773 // default to 0 6774 this[ measurement ] = 0; 6775 } else { 6776 // use option as an element 6777 if ( typeof option == 'string' ) { 6778 elem = this.element.querySelector( option ); 6779 } else if ( option instanceof HTMLElement ) { 6780 elem = option; 6781 } 6782 // use size of element, if element 6783 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 6784 } 6785}; 6786 6787/** 6788 * layout a collection of item elements 6789 * @api public 6790 */ 6791proto.layoutItems = function( items, isInstant ) { 6792 items = this._getItemsForLayout( items ); 6793 6794 this._layoutItems( items, isInstant ); 6795 6796 this._postLayout(); 6797}; 6798 6799/** 6800 * get the items to be laid out 6801 * you may want to skip over some items 6802 * @param {Array} items 6803 * @returns {Array} items 6804 */ 6805proto._getItemsForLayout = function( items ) { 6806 return items.filter( function( item ) { 6807 return !item.isIgnored; 6808 }); 6809}; 6810 6811/** 6812 * layout items 6813 * @param {Array} items 6814 * @param {Boolean} isInstant 6815 */ 6816proto._layoutItems = function( items, isInstant ) { 6817 this._emitCompleteOnItems( 'layout', items ); 6818 6819 if ( !items || !items.length ) { 6820 // no items, emit event with empty array 6821 return; 6822 } 6823 6824 var queue = []; 6825 6826 items.forEach( function( item ) { 6827 // get x/y object from method 6828 var position = this._getItemLayoutPosition( item ); 6829 // enqueue 6830 position.item = item; 6831 position.isInstant = isInstant || item.isLayoutInstant; 6832 queue.push( position ); 6833 }, this ); 6834 6835 this._processLayoutQueue( queue ); 6836}; 6837 6838/** 6839 * get item layout position 6840 * @param {Outlayer.Item} item 6841 * @returns {Object} x and y position 6842 */ 6843proto._getItemLayoutPosition = function( /* item */ ) { 6844 return { 6845 x: 0, 6846 y: 0 6847 }; 6848}; 6849 6850/** 6851 * iterate over array and position each item 6852 * Reason being - separating this logic prevents 'layout invalidation' 6853 * thx @paul_irish 6854 * @param {Array} queue 6855 */ 6856proto._processLayoutQueue = function( queue ) { 6857 this.updateStagger(); 6858 queue.forEach( function( obj, i ) { 6859 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); 6860 }, this ); 6861}; 6862 6863// set stagger from option in milliseconds number 6864proto.updateStagger = function() { 6865 var stagger = this.options.stagger; 6866 if ( stagger === null || stagger === undefined ) { 6867 this.stagger = 0; 6868 return; 6869 } 6870 this.stagger = getMilliseconds( stagger ); 6871 return this.stagger; 6872}; 6873 6874/** 6875 * Sets position of item in DOM 6876 * @param {Outlayer.Item} item 6877 * @param {Number} x - horizontal position 6878 * @param {Number} y - vertical position 6879 * @param {Boolean} isInstant - disables transitions 6880 */ 6881proto._positionItem = function( item, x, y, isInstant, i ) { 6882 if ( isInstant ) { 6883 // if not transition, just set CSS 6884 item.goTo( x, y ); 6885 } else { 6886 item.stagger( i * this.stagger ); 6887 item.moveTo( x, y ); 6888 } 6889}; 6890 6891/** 6892 * Any logic you want to do after each layout, 6893 * i.e. size the container 6894 */ 6895proto._postLayout = function() { 6896 this.resizeContainer(); 6897}; 6898 6899proto.resizeContainer = function() { 6900 var isResizingContainer = this._getOption('resizeContainer'); 6901 if ( !isResizingContainer ) { 6902 return; 6903 } 6904 var size = this._getContainerSize(); 6905 if ( size ) { 6906 this._setContainerMeasure( size.width, true ); 6907 this._setContainerMeasure( size.height, false ); 6908 } 6909}; 6910 6911/** 6912 * Sets width or height of container if returned 6913 * @returns {Object} size 6914 * @param {Number} width 6915 * @param {Number} height 6916 */ 6917proto._getContainerSize = noop; 6918 6919/** 6920 * @param {Number} measure - size of width or height 6921 * @param {Boolean} isWidth 6922 */ 6923proto._setContainerMeasure = function( measure, isWidth ) { 6924 if ( measure === undefined ) { 6925 return; 6926 } 6927 6928 var elemSize = this.size; 6929 // add padding and border width if border box 6930 if ( elemSize.isBorderBox ) { 6931 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 6932 elemSize.borderLeftWidth + elemSize.borderRightWidth : 6933 elemSize.paddingBottom + elemSize.paddingTop + 6934 elemSize.borderTopWidth + elemSize.borderBottomWidth; 6935 } 6936 6937 measure = Math.max( measure, 0 ); 6938 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 6939}; 6940 6941/** 6942 * emit eventComplete on a collection of items events 6943 * @param {String} eventName 6944 * @param {Array} items - Outlayer.Items 6945 */ 6946proto._emitCompleteOnItems = function( eventName, items ) { 6947 var _this = this; 6948 function onComplete() { 6949 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 6950 } 6951 6952 var count = items.length; 6953 if ( !items || !count ) { 6954 onComplete(); 6955 return; 6956 } 6957 6958 var doneCount = 0; 6959 function tick() { 6960 doneCount++; 6961 if ( doneCount == count ) { 6962 onComplete(); 6963 } 6964 } 6965 6966 // bind callback 6967 items.forEach( function( item ) { 6968 item.once( eventName, tick ); 6969 }); 6970}; 6971 6972/** 6973 * emits events via EvEmitter and jQuery events 6974 * @param {String} type - name of event 6975 * @param {Event} event - original event 6976 * @param {Array} args - extra arguments 6977 */ 6978proto.dispatchEvent = function( type, event, args ) { 6979 // add original event to arguments 6980 var emitArgs = event ? [ event ].concat( args ) : args; 6981 this.emitEvent( type, emitArgs ); 6982 6983 if ( jQuery ) { 6984 // set this.$element 6985 this.$element = this.$element || jQuery( this.element ); 6986 if ( event ) { 6987 // create jQuery event 6988 var $event = jQuery.Event( event ); 6989 $event.type = type; 6990 this.$element.trigger( $event, args ); 6991 } else { 6992 // just trigger with type if no event available 6993 this.$element.trigger( type, args ); 6994 } 6995 } 6996}; 6997 6998// -------------------------- ignore & stamps -------------------------- // 6999 7000 7001/** 7002 * keep item in collection, but do not lay it out 7003 * ignored items do not get skipped in layout 7004 * @param {Element} elem 7005 */ 7006proto.ignore = function( elem ) { 7007 var item = this.getItem( elem ); 7008 if ( item ) { 7009 item.isIgnored = true; 7010 } 7011}; 7012 7013/** 7014 * return item to layout collection 7015 * @param {Element} elem 7016 */ 7017proto.unignore = function( elem ) { 7018 var item = this.getItem( elem ); 7019 if ( item ) { 7020 delete item.isIgnored; 7021 } 7022}; 7023 7024/** 7025 * adds elements to stamps 7026 * @param {NodeList, Array, Element, or String} elems 7027 */ 7028proto.stamp = function( elems ) { 7029 elems = this._find( elems ); 7030 if ( !elems ) { 7031 return; 7032 } 7033 7034 this.stamps = this.stamps.concat( elems ); 7035 // ignore 7036 elems.forEach( this.ignore, this ); 7037}; 7038 7039/** 7040 * removes elements to stamps 7041 * @param {NodeList, Array, or Element} elems 7042 */ 7043proto.unstamp = function( elems ) { 7044 elems = this._find( elems ); 7045 if ( !elems ){ 7046 return; 7047 } 7048 7049 elems.forEach( function( elem ) { 7050 // filter out removed stamp elements 7051 utils.removeFrom( this.stamps, elem ); 7052 this.unignore( elem ); 7053 }, this ); 7054}; 7055 7056/** 7057 * finds child elements 7058 * @param {NodeList, Array, Element, or String} elems 7059 * @returns {Array} elems 7060 */ 7061proto._find = function( elems ) { 7062 if ( !elems ) { 7063 return; 7064 } 7065 // if string, use argument as selector string 7066 if ( typeof elems == 'string' ) { 7067 elems = this.element.querySelectorAll( elems ); 7068 } 7069 elems = utils.makeArray( elems ); 7070 return elems; 7071}; 7072 7073proto._manageStamps = function() { 7074 if ( !this.stamps || !this.stamps.length ) { 7075 return; 7076 } 7077 7078 this._getBoundingRect(); 7079 7080 this.stamps.forEach( this._manageStamp, this ); 7081}; 7082 7083// update boundingLeft / Top 7084proto._getBoundingRect = function() { 7085 // get bounding rect for container element 7086 var boundingRect = this.element.getBoundingClientRect(); 7087 var size = this.size; 7088 this._boundingRect = { 7089 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 7090 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 7091 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 7092 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 7093 }; 7094}; 7095 7096/** 7097 * @param {Element} stamp 7098**/ 7099proto._manageStamp = noop; 7100 7101/** 7102 * get x/y position of element relative to container element 7103 * @param {Element} elem 7104 * @returns {Object} offset - has left, top, right, bottom 7105 */ 7106proto._getElementOffset = function( elem ) { 7107 var boundingRect = elem.getBoundingClientRect(); 7108 var thisRect = this._boundingRect; 7109 var size = getSize( elem ); 7110 var offset = { 7111 left: boundingRect.left - thisRect.left - size.marginLeft, 7112 top: boundingRect.top - thisRect.top - size.marginTop, 7113 right: thisRect.right - boundingRect.right - size.marginRight, 7114 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 7115 }; 7116 return offset; 7117}; 7118 7119// -------------------------- resize -------------------------- // 7120 7121// enable event handlers for listeners 7122// i.e. resize -> onresize 7123proto.handleEvent = utils.handleEvent; 7124 7125/** 7126 * Bind layout to window resizing 7127 */ 7128proto.bindResize = function() { 7129 window.addEventListener( 'resize', this ); 7130 this.isResizeBound = true; 7131}; 7132 7133/** 7134 * Unbind layout to window resizing 7135 */ 7136proto.unbindResize = function() { 7137 window.removeEventListener( 'resize', this ); 7138 this.isResizeBound = false; 7139}; 7140 7141proto.onresize = function() { 7142 this.resize(); 7143}; 7144 7145utils.debounceMethod( Outlayer, 'onresize', 100 ); 7146 7147proto.resize = function() { 7148 // don't trigger if size did not change 7149 // or if resize was unbound. See #9 7150 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 7151 return; 7152 } 7153 7154 this.layout(); 7155}; 7156 7157/** 7158 * check if layout is needed post layout 7159 * @returns Boolean 7160 */ 7161proto.needsResizeLayout = function() { 7162 var size = getSize( this.element ); 7163 // check that this.size and size are there 7164 // IE8 triggers resize on body size change, so they might not be 7165 var hasSizes = this.size && size; 7166 return hasSizes && size.innerWidth !== this.size.innerWidth; 7167}; 7168 7169// -------------------------- methods -------------------------- // 7170 7171/** 7172 * add items to Outlayer instance 7173 * @param {Array or NodeList or Element} elems 7174 * @returns {Array} items - Outlayer.Items 7175**/ 7176proto.addItems = function( elems ) { 7177 var items = this._itemize( elems ); 7178 // add items to collection 7179 if ( items.length ) { 7180 this.items = this.items.concat( items ); 7181 } 7182 return items; 7183}; 7184 7185/** 7186 * Layout newly-appended item elements 7187 * @param {Array or NodeList or Element} elems 7188 */ 7189proto.appended = function( elems ) { 7190 var items = this.addItems( elems ); 7191 if ( !items.length ) { 7192 return; 7193 } 7194 // layout and reveal just the new items 7195 this.layoutItems( items, true ); 7196 this.reveal( items ); 7197}; 7198 7199/** 7200 * Layout prepended elements 7201 * @param {Array or NodeList or Element} elems 7202 */ 7203proto.prepended = function( elems ) { 7204 var items = this._itemize( elems ); 7205 if ( !items.length ) { 7206 return; 7207 } 7208 // add items to beginning of collection 7209 var previousItems = this.items.slice(0); 7210 this.items = items.concat( previousItems ); 7211 // start new layout 7212 this._resetLayout(); 7213 this._manageStamps(); 7214 // layout new stuff without transition 7215 this.layoutItems( items, true ); 7216 this.reveal( items ); 7217 // layout previous items 7218 this.layoutItems( previousItems ); 7219}; 7220 7221/** 7222 * reveal a collection of items 7223 * @param {Array of Outlayer.Items} items 7224 */ 7225proto.reveal = function( items ) { 7226 this._emitCompleteOnItems( 'reveal', items ); 7227 if ( !items || !items.length ) { 7228 return; 7229 } 7230 var stagger = this.updateStagger(); 7231 items.forEach( function( item, i ) { 7232 item.stagger( i * stagger ); 7233 item.reveal(); 7234 }); 7235}; 7236 7237/** 7238 * hide a collection of items 7239 * @param {Array of Outlayer.Items} items 7240 */ 7241proto.hide = function( items ) { 7242 this._emitCompleteOnItems( 'hide', items ); 7243 if ( !items || !items.length ) { 7244 return; 7245 } 7246 var stagger = this.updateStagger(); 7247 items.forEach( function( item, i ) { 7248 item.stagger( i * stagger ); 7249 item.hide(); 7250 }); 7251}; 7252 7253/** 7254 * reveal item elements 7255 * @param {Array}, {Element}, {NodeList} items 7256 */ 7257proto.revealItemElements = function( elems ) { 7258 var items = this.getItems( elems ); 7259 this.reveal( items ); 7260}; 7261 7262/** 7263 * hide item elements 7264 * @param {Array}, {Element}, {NodeList} items 7265 */ 7266proto.hideItemElements = function( elems ) { 7267 var items = this.getItems( elems ); 7268 this.hide( items ); 7269}; 7270 7271/** 7272 * get Outlayer.Item, given an Element 7273 * @param {Element} elem 7274 * @param {Function} callback 7275 * @returns {Outlayer.Item} item 7276 */ 7277proto.getItem = function( elem ) { 7278 // loop through items to get the one that matches 7279 for ( var i=0; i < this.items.length; i++ ) { 7280 var item = this.items[i]; 7281 if ( item.element == elem ) { 7282 // return item 7283 return item; 7284 } 7285 } 7286}; 7287 7288/** 7289 * get collection of Outlayer.Items, given Elements 7290 * @param {Array} elems 7291 * @returns {Array} items - Outlayer.Items 7292 */ 7293proto.getItems = function( elems ) { 7294 elems = utils.makeArray( elems ); 7295 var items = []; 7296 elems.forEach( function( elem ) { 7297 var item = this.getItem( elem ); 7298 if ( item ) { 7299 items.push( item ); 7300 } 7301 }, this ); 7302 7303 return items; 7304}; 7305 7306/** 7307 * remove element(s) from instance and DOM 7308 * @param {Array or NodeList or Element} elems 7309 */ 7310proto.remove = function( elems ) { 7311 var removeItems = this.getItems( elems ); 7312 7313 this._emitCompleteOnItems( 'remove', removeItems ); 7314 7315 // bail if no items to remove 7316 if ( !removeItems || !removeItems.length ) { 7317 return; 7318 } 7319
vendor: 38,285 bytes, lines 7320-8743
7320 removeItems.forEach( function( item ) { 7321 item.remove(); 7322 // remove item from collection 7323 utils.removeFrom( this.items, item ); 7324 }, this ); 7325}; 7326 7327// ----- destroy ----- // 7328 7329// remove and disable Outlayer instance 7330proto.destroy = function() { 7331 // clean up dynamic styles 7332 var style = this.element.style; 7333 style.height = ''; 7334 style.position = ''; 7335 style.width = ''; 7336 // destroy items 7337 this.items.forEach( function( item ) { 7338 item.destroy(); 7339 }); 7340 7341 this.unbindResize(); 7342 7343 var id = this.element.outlayerGUID; 7344 delete instances[ id ]; // remove reference to instance by id 7345 delete this.element.outlayerGUID; 7346 // remove data for jQuery 7347 if ( jQuery ) { 7348 jQuery.removeData( this.element, this.constructor.namespace ); 7349 } 7350 7351}; 7352 7353// -------------------------- data -------------------------- // 7354 7355/** 7356 * get Outlayer instance from element 7357 * @param {Element} elem 7358 * @returns {Outlayer} 7359 */ 7360Outlayer.data = function( elem ) { 7361 elem = utils.getQueryElement( elem ); 7362 var id = elem && elem.outlayerGUID; 7363 return id && instances[ id ]; 7364}; 7365 7366 7367// -------------------------- create Outlayer class -------------------------- // 7368 7369/** 7370 * create a layout class 7371 * @param {String} namespace 7372 */ 7373Outlayer.create = function( namespace, options ) { 7374 // sub-class Outlayer 7375 var Layout = subclass( Outlayer ); 7376 // apply new options and compatOptions 7377 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 7378 utils.extend( Layout.defaults, options ); 7379 Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); 7380 7381 Layout.namespace = namespace; 7382 7383 Layout.data = Outlayer.data; 7384 7385 // sub-class Item 7386 Layout.Item = subclass( Item ); 7387 7388 // -------------------------- declarative -------------------------- // 7389 7390 utils.htmlInit( Layout, namespace ); 7391 7392 // -------------------------- jQuery bridge -------------------------- // 7393 7394 // make into jQuery plugin 7395 if ( jQuery && jQuery.bridget ) { 7396 jQuery.bridget( namespace, Layout ); 7397 } 7398 7399 return Layout; 7400}; 7401 7402function subclass( Parent ) { 7403 function SubClass() { 7404 Parent.apply( this, arguments ); 7405 } 7406 7407 SubClass.prototype = Object.create( Parent.prototype ); 7408 SubClass.prototype.constructor = SubClass; 7409 7410 return SubClass; 7411} 7412 7413// ----- helpers ----- // 7414 7415// how many milliseconds are in each unit 7416var msUnits = { 7417 ms: 1, 7418 s: 1000 7419}; 7420 7421// munge time-like parameter into millisecond number 7422// '0.4s' -> 40 7423function getMilliseconds( time ) { 7424 if ( typeof time == 'number' ) { 7425 return time; 7426 } 7427 var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); 7428 var num = matches && matches[1]; 7429 var unit = matches && matches[2]; 7430 if ( !num.length ) { 7431 return 0; 7432 } 7433 num = parseFloat( num ); 7434 var mult = msUnits[ unit ] || 1; 7435 return num * mult; 7436} 7437 7438// ----- fin ----- // 7439 7440// back in global 7441Outlayer.Item = Item; 7442 7443return Outlayer; 7444 7445})); 7446 7447/** 7448 * Isotope Item 7449**/ 7450 7451( function( window, factory ) { 7452 // universal module definition 7453 /* jshint strict: false */ /*globals define, module, require */ 7454 if ( typeof define == 'function' && define.amd ) { 7455 // AMD 7456 define( 'isotope-layout/js/item',[ 7457 'outlayer/outlayer' 7458 ], 7459 factory ); 7460 } else if ( typeof module == 'object' && module.exports ) { 7461 // CommonJS 7462 module.exports = factory( 7463 require('outlayer') 7464 ); 7465 } else { 7466 // browser global 7467 window.Isotope = window.Isotope || {}; 7468 window.Isotope.Item = factory( 7469 window.Outlayer 7470 ); 7471 } 7472 7473}( window, function factory( Outlayer ) { 7474'use strict'; 7475 7476// -------------------------- Item -------------------------- // 7477 7478// sub-class Outlayer Item 7479function Item() { 7480 Outlayer.Item.apply( this, arguments ); 7481} 7482 7483var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 7484 7485var _create = proto._create; 7486proto._create = function() { 7487 // assign id, used for original-order sorting 7488 this.id = this.layout.itemGUID++; 7489 _create.call( this ); 7490 this.sortData = {}; 7491}; 7492 7493proto.updateSortData = function() { 7494 if ( this.isIgnored ) { 7495 return; 7496 } 7497 // default sorters 7498 this.sortData.id = this.id; 7499 // for backward compatibility 7500 this.sortData['original-order'] = this.id; 7501 this.sortData.random = Math.random(); 7502 // go thru getSortData obj and apply the sorters 7503 var getSortData = this.layout.options.getSortData; 7504 var sorters = this.layout._sorters; 7505 for ( var key in getSortData ) { 7506 var sorter = sorters[ key ]; 7507 this.sortData[ key ] = sorter( this.element, this ); 7508 } 7509}; 7510 7511var _destroy = proto.destroy; 7512proto.destroy = function() { 7513 // call super 7514 _destroy.apply( this, arguments ); 7515 // reset display, #741 7516 this.css({ 7517 display: '' 7518 }); 7519}; 7520 7521return Item; 7522 7523})); 7524 7525/** 7526 * Isotope LayoutMode 7527 */ 7528 7529( function( window, factory ) { 7530 // universal module definition 7531 /* jshint strict: false */ /*globals define, module, require */ 7532 if ( typeof define == 'function' && define.amd ) { 7533 // AMD 7534 define( 'isotope-layout/js/layout-mode',[ 7535 'get-size/get-size', 7536 'outlayer/outlayer' 7537 ], 7538 factory ); 7539 } else if ( typeof module == 'object' && module.exports ) { 7540 // CommonJS 7541 module.exports = factory( 7542 require('get-size'), 7543 require('outlayer') 7544 ); 7545 } else { 7546 // browser global 7547 window.Isotope = window.Isotope || {}; 7548 window.Isotope.LayoutMode = factory( 7549 window.getSize, 7550 window.Outlayer 7551 ); 7552 } 7553 7554}( window, function factory( getSize, Outlayer ) { 7555 'use strict'; 7556 7557 // layout mode class 7558 function LayoutMode( isotope ) { 7559 this.isotope = isotope; 7560 // link properties 7561 if ( isotope ) { 7562 this.options = isotope.options[ this.namespace ]; 7563 this.element = isotope.element; 7564 this.items = isotope.filteredItems; 7565 this.size = isotope.size; 7566 } 7567 } 7568 7569 var proto = LayoutMode.prototype; 7570 7571 /** 7572 * some methods should just defer to default Outlayer method 7573 * and reference the Isotope instance as `this` 7574 **/ 7575 var facadeMethods = [ 7576 '_resetLayout', 7577 '_getItemLayoutPosition', 7578 '_manageStamp', 7579 '_getContainerSize', 7580 '_getElementOffset', 7581 'needsResizeLayout', 7582 '_getOption' 7583 ]; 7584 7585 facadeMethods.forEach( function( methodName ) { 7586 proto[ methodName ] = function() { 7587 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 7588 }; 7589 }); 7590 7591 // ----- ----- // 7592 7593 // for horizontal layout modes, check vertical size 7594 proto.needsVerticalResizeLayout = function() { 7595 // don't trigger if size did not change 7596 var size = getSize( this.isotope.element ); 7597 // check that this.size and size are there 7598 // IE8 triggers resize on body size change, so they might not be 7599 var hasSizes = this.isotope.size && size; 7600 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 7601 }; 7602 7603 // ----- measurements ----- // 7604 7605 proto._getMeasurement = function() { 7606 this.isotope._getMeasurement.apply( this, arguments ); 7607 }; 7608 7609 proto.getColumnWidth = function() { 7610 this.getSegmentSize( 'column', 'Width' ); 7611 }; 7612 7613 proto.getRowHeight = function() { 7614 this.getSegmentSize( 'row', 'Height' ); 7615 }; 7616 7617 /** 7618 * get columnWidth or rowHeight 7619 * segment: 'column' or 'row' 7620 * size 'Width' or 'Height' 7621 **/ 7622 proto.getSegmentSize = function( segment, size ) { 7623 var segmentName = segment + size; 7624 var outerSize = 'outer' + size; 7625 // columnWidth / outerWidth // rowHeight / outerHeight 7626 this._getMeasurement( segmentName, outerSize ); 7627 // got rowHeight or columnWidth, we can chill 7628 if ( this[ segmentName ] ) { 7629 return; 7630 } 7631 // fall back to item of first element 7632 var firstItemSize = this.getFirstItemSize(); 7633 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 7634 // or size of container 7635 this.isotope.size[ 'inner' + size ]; 7636 }; 7637 7638 proto.getFirstItemSize = function() { 7639 var firstItem = this.isotope.filteredItems[0]; 7640 return firstItem && firstItem.element && getSize( firstItem.element ); 7641 }; 7642 7643 // ----- methods that should reference isotope ----- // 7644 7645 proto.layout = function() { 7646 this.isotope.layout.apply( this.isotope, arguments ); 7647 }; 7648 7649 proto.getSize = function() { 7650 this.isotope.getSize(); 7651 this.size = this.isotope.size; 7652 }; 7653 7654 // -------------------------- create -------------------------- // 7655 7656 LayoutMode.modes = {}; 7657 7658 LayoutMode.create = function( namespace, options ) { 7659 7660 function Mode() { 7661 LayoutMode.apply( this, arguments ); 7662 } 7663 7664 Mode.prototype = Object.create( proto ); 7665 Mode.prototype.constructor = Mode; 7666 7667 // default options 7668 if ( options ) { 7669 Mode.options = options; 7670 } 7671 7672 Mode.prototype.namespace = namespace; 7673 // register in Isotope 7674 LayoutMode.modes[ namespace ] = Mode; 7675 7676 return Mode; 7677 }; 7678 7679 return LayoutMode; 7680 7681})); 7682 7683/*! 7684 * Masonry v4.2.1 7685 * Cascading grid layout library 7686 * https://masonry.desandro.com 7687 * MIT License 7688 * by David DeSandro 7689 */ 7690 7691( function( window, factory ) { 7692 // universal module definition 7693 /* jshint strict: false */ /*globals define, module, require */ 7694 if ( typeof define == 'function' && define.amd ) { 7695 // AMD 7696 define( 'masonry-layout/masonry',[ 7697 'outlayer/outlayer', 7698 'get-size/get-size' 7699 ], 7700 factory ); 7701 } else if ( typeof module == 'object' && module.exports ) { 7702 // CommonJS 7703 module.exports = factory( 7704 require('outlayer'), 7705 require('get-size') 7706 ); 7707 } else { 7708 // browser global 7709 window.Masonry = factory( 7710 window.Outlayer, 7711 window.getSize 7712 ); 7713 } 7714 7715}( window, function factory( Outlayer, getSize ) { 7716 7717 7718 7719// -------------------------- masonryDefinition -------------------------- // 7720 7721 // create an Outlayer layout class 7722 var Masonry = Outlayer.create('masonry'); 7723 // isFitWidth -> fitWidth 7724 Masonry.compatOptions.fitWidth = 'isFitWidth'; 7725 7726 var proto = Masonry.prototype; 7727 7728 proto._resetLayout = function() { 7729 this.getSize(); 7730 this._getMeasurement( 'columnWidth', 'outerWidth' ); 7731 this._getMeasurement( 'gutter', 'outerWidth' ); 7732 this.measureColumns(); 7733 7734 // reset column Y 7735 this.colYs = []; 7736 for ( var i=0; i < this.cols; i++ ) { 7737 this.colYs.push( 0 ); 7738 } 7739 7740 this.maxY = 0; 7741 this.horizontalColIndex = 0; 7742 }; 7743 7744 proto.measureColumns = function() { 7745 this.getContainerWidth(); 7746 // if columnWidth is 0, default to outerWidth of first item 7747 if ( !this.columnWidth ) { 7748 var firstItem = this.items[0]; 7749 var firstItemElem = firstItem && firstItem.element; 7750 // columnWidth fall back to item of first element 7751 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 7752 // if first elem has no width, default to size of container 7753 this.containerWidth; 7754 } 7755 7756 var columnWidth = this.columnWidth += this.gutter; 7757 7758 // calculate columns 7759 var containerWidth = this.containerWidth + this.gutter; 7760 var cols = containerWidth / columnWidth; 7761 // fix rounding errors, typically with gutters 7762 var excess = columnWidth - containerWidth % columnWidth; 7763 // if overshoot is less than a pixel, round up, otherwise floor it 7764 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 7765 cols = Math[ mathMethod ]( cols ); 7766 this.cols = Math.max( cols, 1 ); 7767 }; 7768 7769 proto.getContainerWidth = function() { 7770 // container is parent if fit width 7771 var isFitWidth = this._getOption('fitWidth'); 7772 var container = isFitWidth ? this.element.parentNode : this.element; 7773 // check that this.size and size are there 7774 // IE8 triggers resize on body size change, so they might not be 7775 var size = getSize( container ); 7776 this.containerWidth = size && size.innerWidth; 7777 }; 7778 7779 proto._getItemLayoutPosition = function( item ) { 7780 item.getSize(); 7781 // how many columns does this brick span 7782 var remainder = item.size.outerWidth % this.columnWidth; 7783 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 7784 // round if off by 1 pixel, otherwise use ceil 7785 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 7786 colSpan = Math.min( colSpan, this.cols ); 7787 // use horizontal or top column position 7788 var colPosMethod = this.options.horizontalOrder ? 7789 '_getHorizontalColPosition' : '_getTopColPosition'; 7790 var colPosition = this[ colPosMethod ]( colSpan, item ); 7791 // position the brick 7792 var position = { 7793 x: this.columnWidth * colPosition.col, 7794 y: colPosition.y 7795 }; 7796 // apply setHeight to necessary columns 7797 var setHeight = colPosition.y + item.size.outerHeight; 7798 var setMax = colSpan + colPosition.col; 7799 for ( var i = colPosition.col; i < setMax; i++ ) { 7800 this.colYs[i] = setHeight; 7801 } 7802 7803 return position; 7804 }; 7805 7806 proto._getTopColPosition = function( colSpan ) { 7807 var colGroup = this._getTopColGroup( colSpan ); 7808 // get the minimum Y value from the columns 7809 var minimumY = Math.min.apply( Math, colGroup ); 7810 7811 return { 7812 col: colGroup.indexOf( minimumY ), 7813 y: minimumY, 7814 }; 7815 }; 7816 7817 /** 7818 * @param {Number} colSpan - number of columns the element spans 7819 * @returns {Array} colGroup 7820 */ 7821 proto._getTopColGroup = function( colSpan ) { 7822 if ( colSpan < 2 ) { 7823 // if brick spans only one column, use all the column Ys 7824 return this.colYs; 7825 } 7826 7827 var colGroup = []; 7828 // how many different places could this brick fit horizontally 7829 var groupCount = this.cols + 1 - colSpan; 7830 // for each group potential horizontal position 7831 for ( var i = 0; i < groupCount; i++ ) { 7832 colGroup[i] = this._getColGroupY( i, colSpan ); 7833 } 7834 return colGroup; 7835 }; 7836 7837 proto._getColGroupY = function( col, colSpan ) { 7838 if ( colSpan < 2 ) { 7839 return this.colYs[ col ]; 7840 } 7841 // make an array of colY values for that one group 7842 var groupColYs = this.colYs.slice( col, col + colSpan ); 7843 // and get the max value of the array 7844 return Math.max.apply( Math, groupColYs ); 7845 }; 7846 7847 // get column position based on horizontal index. #873 7848 proto._getHorizontalColPosition = function( colSpan, item ) { 7849 var col = this.horizontalColIndex % this.cols; 7850 var isOver = colSpan > 1 && col + colSpan > this.cols; 7851 // shift to next row if item can't fit on current row 7852 col = isOver ? 0 : col; 7853 // don't let zero-size items take up space 7854 var hasSize = item.size.outerWidth && item.size.outerHeight; 7855 this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; 7856 7857 return { 7858 col: col, 7859 y: this._getColGroupY( col, colSpan ), 7860 }; 7861 }; 7862 7863 proto._manageStamp = function( stamp ) { 7864 var stampSize = getSize( stamp ); 7865 var offset = this._getElementOffset( stamp ); 7866 // get the columns that this stamp affects 7867 var isOriginLeft = this._getOption('originLeft'); 7868 var firstX = isOriginLeft ? offset.left : offset.right; 7869 var lastX = firstX + stampSize.outerWidth; 7870 var firstCol = Math.floor( firstX / this.columnWidth ); 7871 firstCol = Math.max( 0, firstCol ); 7872 var lastCol = Math.floor( lastX / this.columnWidth ); 7873 // lastCol should not go over if multiple of columnWidth #425 7874 lastCol -= lastX % this.columnWidth ? 0 : 1; 7875 lastCol = Math.min( this.cols - 1, lastCol ); 7876 // set colYs to bottom of the stamp 7877 7878 var isOriginTop = this._getOption('originTop'); 7879 var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + 7880 stampSize.outerHeight; 7881 for ( var i = firstCol; i <= lastCol; i++ ) { 7882 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 7883 } 7884 }; 7885 7886 proto._getContainerSize = function() { 7887 this.maxY = Math.max.apply( Math, this.colYs ); 7888 var size = { 7889 height: this.maxY 7890 }; 7891 7892 if ( this._getOption('fitWidth') ) { 7893 size.width = this._getContainerFitWidth(); 7894 } 7895 7896 return size; 7897 }; 7898 7899 proto._getContainerFitWidth = function() { 7900 var unusedCols = 0; 7901 // count unused columns 7902 var i = this.cols; 7903 while ( --i ) { 7904 if ( this.colYs[i] !== 0 ) { 7905 break; 7906 } 7907 unusedCols++; 7908 } 7909 // fit container to columns that have been used 7910 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 7911 }; 7912 7913 proto.needsResizeLayout = function() { 7914 var previousWidth = this.containerWidth; 7915 this.getContainerWidth(); 7916 return previousWidth != this.containerWidth; 7917 }; 7918 7919 return Masonry; 7920 7921})); 7922 7923/*! 7924 * Masonry layout mode 7925 * sub-classes Masonry 7926 * https://masonry.desandro.com 7927 */ 7928 7929( function( window, factory ) { 7930 // universal module definition 7931 /* jshint strict: false */ /*globals define, module, require */ 7932 if ( typeof define == 'function' && define.amd ) { 7933 // AMD 7934 define( 'isotope-layout/js/layout-modes/masonry',[ 7935 '../layout-mode', 7936 'masonry-layout/masonry' 7937 ], 7938 factory ); 7939 } else if ( typeof module == 'object' && module.exports ) { 7940 // CommonJS 7941 module.exports = factory( 7942 require('../layout-mode'), 7943 require('masonry-layout') 7944 ); 7945 } else { 7946 // browser global 7947 factory( 7948 window.Isotope.LayoutMode, 7949 window.Masonry 7950 ); 7951 } 7952 7953}( window, function factory( LayoutMode, Masonry ) { 7954'use strict'; 7955 7956// -------------------------- masonryDefinition -------------------------- // 7957 7958 // create an Outlayer layout class 7959 var MasonryMode = LayoutMode.create('masonry'); 7960 7961 var proto = MasonryMode.prototype; 7962 7963 var keepModeMethods = { 7964 _getElementOffset: true, 7965 layout: true, 7966 _getMeasurement: true 7967 }; 7968 7969 // inherit Masonry prototype 7970 for ( var method in Masonry.prototype ) { 7971 // do not inherit mode methods 7972 if ( !keepModeMethods[ method ] ) { 7973 proto[ method ] = Masonry.prototype[ method ]; 7974 } 7975 } 7976 7977 var measureColumns = proto.measureColumns; 7978 proto.measureColumns = function() { 7979 // set items, used if measuring first item 7980 this.items = this.isotope.filteredItems; 7981 measureColumns.call( this ); 7982 }; 7983 7984 // point to mode options for fitWidth 7985 var _getOption = proto._getOption; 7986 proto._getOption = function( option ) { 7987 if ( option == 'fitWidth' ) { 7988 return this.options.isFitWidth !== undefined ? 7989 this.options.isFitWidth : this.options.fitWidth; 7990 } 7991 return _getOption.apply( this.isotope, arguments ); 7992 }; 7993 7994 return MasonryMode; 7995 7996})); 7997 7998/** 7999 * fitRows layout mode 8000 */ 8001 8002( function( window, factory ) { 8003 // universal module definition 8004 /* jshint strict: false */ /*globals define, module, require */ 8005 if ( typeof define == 'function' && define.amd ) { 8006 // AMD 8007 define( 'isotope-layout/js/layout-modes/fit-rows',[ 8008 '../layout-mode' 8009 ], 8010 factory ); 8011 } else if ( typeof exports == 'object' ) { 8012 // CommonJS 8013 module.exports = factory( 8014 require('../layout-mode') 8015 ); 8016 } else { 8017 // browser global 8018 factory( 8019 window.Isotope.LayoutMode 8020 ); 8021 } 8022 8023}( window, function factory( LayoutMode ) { 8024'use strict'; 8025 8026var FitRows = LayoutMode.create('fitRows'); 8027 8028var proto = FitRows.prototype; 8029 8030proto._resetLayout = function() { 8031 this.x = 0; 8032 this.y = 0; 8033 this.maxY = 0; 8034 this._getMeasurement( 'gutter', 'outerWidth' ); 8035}; 8036 8037proto._getItemLayoutPosition = function( item ) { 8038 item.getSize(); 8039 8040 var itemWidth = item.size.outerWidth + this.gutter; 8041 // if this element cannot fit in the current row 8042 var containerWidth = this.isotope.size.innerWidth + this.gutter; 8043 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 8044 this.x = 0; 8045 this.y = this.maxY; 8046 } 8047 8048 var position = { 8049 x: this.x, 8050 y: this.y 8051 }; 8052 8053 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 8054 this.x += itemWidth; 8055 8056 return position; 8057}; 8058 8059proto._getContainerSize = function() { 8060 return { height: this.maxY }; 8061}; 8062 8063return FitRows; 8064 8065})); 8066 8067/** 8068 * vertical layout mode 8069 */ 8070 8071( function( window, factory ) { 8072 // universal module definition 8073 /* jshint strict: false */ /*globals define, module, require */ 8074 if ( typeof define == 'function' && define.amd ) { 8075 // AMD 8076 define( 'isotope-layout/js/layout-modes/vertical',[ 8077 '../layout-mode' 8078 ], 8079 factory ); 8080 } else if ( typeof module == 'object' && module.exports ) { 8081 // CommonJS 8082 module.exports = factory( 8083 require('../layout-mode') 8084 ); 8085 } else { 8086 // browser global 8087 factory( 8088 window.Isotope.LayoutMode 8089 ); 8090 } 8091 8092}( window, function factory( LayoutMode ) { 8093'use strict'; 8094 8095var Vertical = LayoutMode.create( 'vertical', { 8096 horizontalAlignment: 0 8097}); 8098 8099var proto = Vertical.prototype; 8100 8101proto._resetLayout = function() { 8102 this.y = 0; 8103}; 8104 8105proto._getItemLayoutPosition = function( item ) { 8106 item.getSize(); 8107 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 8108 this.options.horizontalAlignment; 8109 var y = this.y; 8110 this.y += item.size.outerHeight; 8111 return { x: x, y: y }; 8112}; 8113 8114proto._getContainerSize = function() { 8115 return { height: this.y }; 8116}; 8117 8118return Vertical; 8119 8120})); 8121 8122/*! 8123 * Isotope v3.0.6 8124 * 8125 * Licensed GPLv3 for open source use 8126 * or Isotope Commercial License for commercial use 8127 * 8128 * https://isotope.metafizzy.co 8129 * Copyright 2010-2018 Metafizzy 8130 */ 8131 8132( function( window, factory ) { 8133 // universal module definition 8134 /* jshint strict: false */ /*globals define, module, require */ 8135 if ( typeof define == 'function' && define.amd ) { 8136 // AMD 8137 define( [ 8138 'outlayer/outlayer', 8139 'get-size/get-size', 8140 'desandro-matches-selector/matches-selector', 8141 'fizzy-ui-utils/utils', 8142 'isotope-layout/js/item', 8143 'isotope-layout/js/layout-mode', 8144 // include default layout modes 8145 'isotope-layout/js/layout-modes/masonry', 8146 'isotope-layout/js/layout-modes/fit-rows', 8147 'isotope-layout/js/layout-modes/vertical' 8148 ], 8149 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 8150 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 8151 }); 8152 } else if ( typeof module == 'object' && module.exports ) { 8153 // CommonJS 8154 module.exports = factory( 8155 window, 8156 require('outlayer'), 8157 require('get-size'), 8158 require('desandro-matches-selector'), 8159 require('fizzy-ui-utils'), 8160 require('isotope-layout/js/item'), 8161 require('isotope-layout/js/layout-mode'), 8162 // include default layout modes 8163 require('isotope-layout/js/layout-modes/masonry'), 8164 require('isotope-layout/js/layout-modes/fit-rows'), 8165 require('isotope-layout/js/layout-modes/vertical') 8166 ); 8167 } else { 8168 // browser global 8169 window.Isotope = factory( 8170 window, 8171 window.Outlayer, 8172 window.getSize, 8173 window.matchesSelector, 8174 window.fizzyUIUtils, 8175 window.Isotope.Item, 8176 window.Isotope.LayoutMode 8177 ); 8178 } 8179 8180}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 8181 Item, LayoutMode ) { 8182 8183 8184 8185// -------------------------- vars -------------------------- // 8186 8187var jQuery = window.jQuery; 8188 8189// -------------------------- helpers -------------------------- // 8190 8191var trim = String.prototype.trim ? 8192 function( str ) { 8193 return str.trim(); 8194 } : 8195 function( str ) { 8196 return str.replace( /^\s+|\s+$/g, '' ); 8197 }; 8198 8199// -------------------------- isotopeDefinition -------------------------- // 8200 8201 // create an Outlayer layout class 8202 var Isotope = Outlayer.create( 'isotope', { 8203 layoutMode: 'masonry', 8204 isJQueryFiltering: true, 8205 sortAscending: true 8206 }); 8207 8208 Isotope.Item = Item; 8209 Isotope.LayoutMode = LayoutMode; 8210 8211 var proto = Isotope.prototype; 8212 8213 proto._create = function() { 8214 this.itemGUID = 0; 8215 // functions that sort items 8216 this._sorters = {}; 8217 this._getSorters(); 8218 // call super 8219 Outlayer.prototype._create.call( this ); 8220 8221 // create layout modes 8222 this.modes = {}; 8223 // start filteredItems with all items 8224 this.filteredItems = this.items; 8225 // keep of track of sortBys 8226 this.sortHistory = [ 'original-order' ]; 8227 // create from registered layout modes 8228 for ( var name in LayoutMode.modes ) { 8229 this._initLayoutMode( name ); 8230 } 8231 }; 8232 8233 proto.reloadItems = function() { 8234 // reset item ID counter 8235 this.itemGUID = 0; 8236 // call super 8237 Outlayer.prototype.reloadItems.call( this ); 8238 }; 8239 8240 proto._itemize = function() { 8241 var items = Outlayer.prototype._itemize.apply( this, arguments ); 8242 // assign ID for original-order 8243 for ( var i=0; i < items.length; i++ ) { 8244 var item = items[i]; 8245 item.id = this.itemGUID++; 8246 } 8247 this._updateItemsSortData( items ); 8248 return items; 8249 }; 8250 8251 8252 // -------------------------- layout -------------------------- // 8253 8254 proto._initLayoutMode = function( name ) { 8255 var Mode = LayoutMode.modes[ name ]; 8256 // set mode options 8257 // HACK extend initial options, back-fill in default options 8258 var initialOpts = this.options[ name ] || {}; 8259 this.options[ name ] = Mode.options ? 8260 utils.extend( Mode.options, initialOpts ) : initialOpts; 8261 // init layout mode instance 8262 this.modes[ name ] = new Mode( this ); 8263 }; 8264 8265 8266 proto.layout = function() { 8267 // if first time doing layout, do all magic 8268 if ( !this._isLayoutInited && this._getOption('initLayout') ) { 8269 this.arrange(); 8270 return; 8271 } 8272 this._layout(); 8273 }; 8274 8275 // private method to be used in layout() & magic() 8276 proto._layout = function() { 8277 // don't animate first layout 8278 var isInstant = this._getIsInstant(); 8279 // layout flow 8280 this._resetLayout(); 8281 this._manageStamps(); 8282 this.layoutItems( this.filteredItems, isInstant ); 8283 8284 // flag for initalized 8285 this._isLayoutInited = true; 8286 }; 8287 8288 // filter + sort + layout 8289 proto.arrange = function( opts ) { 8290 // set any options pass 8291 this.option( opts ); 8292 this._getIsInstant(); 8293 // filter, sort, and layout 8294 8295 // filter 8296 var filtered = this._filter( this.items ); 8297 this.filteredItems = filtered.matches; 8298 8299 this._bindArrangeComplete(); 8300 8301 if ( this._isInstant ) { 8302 this._noTransition( this._hideReveal, [ filtered ] ); 8303 } else { 8304 this._hideReveal( filtered ); 8305 } 8306 8307 this._sort(); 8308 this._layout(); 8309 }; 8310 // alias to _init for main plugin method 8311 proto._init = proto.arrange; 8312 8313 proto._hideReveal = function( filtered ) { 8314 this.reveal( filtered.needReveal ); 8315 this.hide( filtered.needHide ); 8316 }; 8317 8318 // HACK 8319 // Don't animate/transition first layout 8320 // Or don't animate/transition other layouts 8321 proto._getIsInstant = function() { 8322 var isLayoutInstant = this._getOption('layoutInstant'); 8323 var isInstant = isLayoutInstant !== undefined ? isLayoutInstant : 8324 !this._isLayoutInited; 8325 this._isInstant = isInstant; 8326 return isInstant; 8327 }; 8328 8329 // listen for layoutComplete, hideComplete and revealComplete 8330 // to trigger arrangeComplete 8331 proto._bindArrangeComplete = function() { 8332 // listen for 3 events to trigger arrangeComplete 8333 var isLayoutComplete, isHideComplete, isRevealComplete; 8334 var _this = this; 8335 function arrangeParallelCallback() { 8336 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 8337 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 8338 } 8339 } 8340 this.once( 'layoutComplete', function() { 8341 isLayoutComplete = true; 8342 arrangeParallelCallback(); 8343 }); 8344 this.once( 'hideComplete', function() { 8345 isHideComplete = true; 8346 arrangeParallelCallback(); 8347 }); 8348 this.once( 'revealComplete', function() { 8349 isRevealComplete = true; 8350 arrangeParallelCallback(); 8351 }); 8352 }; 8353 8354 // -------------------------- filter -------------------------- // 8355 8356 proto._filter = function( items ) { 8357 var filter = this.options.filter; 8358 filter = filter || '*'; 8359 var matches = []; 8360 var hiddenMatched = []; 8361 var visibleUnmatched = []; 8362 8363 var test = this._getFilterTest( filter ); 8364 8365 // test each item 8366 for ( var i=0; i < items.length; i++ ) { 8367 var item = items[i]; 8368 if ( item.isIgnored ) { 8369 continue; 8370 } 8371 // add item to either matched or unmatched group 8372 var isMatched = test( item ); 8373 // item.isFilterMatched = isMatched; 8374 // add to matches if its a match 8375 if ( isMatched ) { 8376 matches.push( item ); 8377 } 8378 // add to additional group if item needs to be hidden or revealed 8379 if ( isMatched && item.isHidden ) { 8380 hiddenMatched.push( item ); 8381 } else if ( !isMatched && !item.isHidden ) { 8382 visibleUnmatched.push( item ); 8383 } 8384 } 8385 8386 // return collections of items to be manipulated 8387 return { 8388 matches: matches, 8389 needReveal: hiddenMatched, 8390 needHide: visibleUnmatched 8391 }; 8392 }; 8393 8394 // get a jQuery, function, or a matchesSelector test given the filter 8395 proto._getFilterTest = function( filter ) { 8396 if ( jQuery && this.options.isJQueryFiltering ) { 8397 // use jQuery 8398 return function( item ) { 8399 return jQuery( item.element ).is( filter ); 8400 }; 8401 } 8402 if ( typeof filter == 'function' ) { 8403 // use filter as function 8404 return function( item ) { 8405 return filter( item.element ); 8406 }; 8407 } 8408 // default, use filter as selector string 8409 return function( item ) { 8410 return matchesSelector( item.element, filter ); 8411 }; 8412 }; 8413 8414 // -------------------------- sorting -------------------------- // 8415 8416 /** 8417 * @params {Array} elems 8418 * @public 8419 */ 8420 proto.updateSortData = function( elems ) { 8421 // get items 8422 var items; 8423 if ( elems ) { 8424 elems = utils.makeArray( elems ); 8425 items = this.getItems( elems ); 8426 } else { 8427 // update all items if no elems provided 8428 items = this.items; 8429 } 8430 8431 this._getSorters(); 8432 this._updateItemsSortData( items ); 8433 }; 8434 8435 proto._getSorters = function() { 8436 var getSortData = this.options.getSortData; 8437 for ( var key in getSortData ) { 8438 var sorter = getSortData[ key ]; 8439 this._sorters[ key ] = mungeSorter( sorter ); 8440 } 8441 }; 8442 8443 /** 8444 * @params {Array} items - of Isotope.Items 8445 * @private 8446 */ 8447 proto._updateItemsSortData = function( items ) { 8448 // do not update if no items 8449 var len = items && items.length; 8450 8451 for ( var i=0; len && i < len; i++ ) { 8452 var item = items[i]; 8453 item.updateSortData(); 8454 } 8455 }; 8456 8457 // ----- munge sorter ----- // 8458 8459 // encapsulate this, as we just need mungeSorter 8460 // other functions in here are just for munging 8461 var mungeSorter = ( function() { 8462 // add a magic layer to sorters for convienent shorthands 8463 // `.foo-bar` will use the text of .foo-bar querySelector 8464 // `[foo-bar]` will use attribute 8465 // you can also add parser 8466 // `.foo-bar parseInt` will parse that as a number 8467 function mungeSorter( sorter ) { 8468 // if not a string, return function or whatever it is 8469 if ( typeof sorter != 'string' ) { 8470 return sorter; 8471 } 8472 // parse the sorter string 8473 var args = trim( sorter ).split(' '); 8474 var query = args[0]; 8475 // check if query looks like [an-attribute] 8476 var attrMatch = query.match( /^\[(.+)\]$/ ); 8477 var attr = attrMatch && attrMatch[1]; 8478 var getValue = getValueGetter( attr, query ); 8479 // use second argument as a parser 8480 var parser = Isotope.sortDataParsers[ args[1] ]; 8481 // parse the value, if there was a parser 8482 sorter = parser ? function( elem ) { 8483 return elem && parser( getValue( elem ) ); 8484 } : 8485 // otherwise just return value 8486 function( elem ) { 8487 return elem && getValue( elem ); 8488 }; 8489 8490 return sorter; 8491 } 8492 8493 // get an attribute getter, or get text of the querySelector 8494 function getValueGetter( attr, query ) { 8495 // if query looks like [foo-bar], get attribute 8496 if ( attr ) { 8497 return function getAttribute( elem ) { 8498 return elem.getAttribute( attr ); 8499 }; 8500 } 8501 8502 // otherwise, assume its a querySelector, and get its text 8503 return function getChildText( elem ) { 8504 var child = elem.querySelector( query ); 8505 return child && child.textContent; 8506 }; 8507 } 8508 8509 return mungeSorter; 8510 })(); 8511 8512 // parsers used in getSortData shortcut strings 8513 Isotope.sortDataParsers = { 8514 'parseInt': function( val ) { 8515 return parseInt( val, 10 ); 8516 }, 8517 'parseFloat': function( val ) { 8518 return parseFloat( val ); 8519 } 8520 }; 8521 8522 // ----- sort method ----- // 8523 8524 // sort filteredItem order 8525 proto._sort = function() { 8526 if ( !this.options.sortBy ) { 8527 return; 8528 } 8529 // keep track of sortBy History 8530 var sortBys = utils.makeArray( this.options.sortBy ); 8531 if ( !this._getIsSameSortBy( sortBys ) ) { 8532 // concat all sortBy and sortHistory, add to front, oldest goes in last 8533 this.sortHistory = sortBys.concat( this.sortHistory ); 8534 } 8535 // sort magic 8536 var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending ); 8537 this.filteredItems.sort( itemSorter ); 8538 }; 8539 8540 // check if sortBys is same as start of sortHistory 8541 proto._getIsSameSortBy = function( sortBys ) { 8542 for ( var i=0; i < sortBys.length; i++ ) { 8543 if ( sortBys[i] != this.sortHistory[i] ) { 8544 return false; 8545 } 8546 } 8547 return true; 8548 }; 8549 8550 // returns a function used for sorting 8551 function getItemSorter( sortBys, sortAsc ) { 8552 return function sorter( itemA, itemB ) { 8553 // cycle through all sortKeys 8554 for ( var i = 0; i < sortBys.length; i++ ) { 8555 var sortBy = sortBys[i]; 8556 var a = itemA.sortData[ sortBy ]; 8557 var b = itemB.sortData[ sortBy ]; 8558 if ( a > b || a < b ) { 8559 // if sortAsc is an object, use the value given the sortBy key 8560 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 8561 var direction = isAscending ? 1 : -1; 8562 return ( a > b ? 1 : -1 ) * direction; 8563 } 8564 } 8565 return 0; 8566 }; 8567 } 8568 8569 // -------------------------- methods -------------------------- // 8570 8571 // get layout mode 8572 proto._mode = function() { 8573 var layoutMode = this.options.layoutMode; 8574 var mode = this.modes[ layoutMode ]; 8575 if ( !mode ) { 8576 // TODO console.error 8577 throw new Error( 'No layout mode: ' + layoutMode ); 8578 } 8579 // HACK sync mode's options 8580 // any options set after init for layout mode need to be synced 8581 mode.options = this.options[ layoutMode ]; 8582 return mode; 8583 }; 8584 8585 proto._resetLayout = function() { 8586 // trigger original reset layout 8587 Outlayer.prototype._resetLayout.call( this ); 8588 this._mode()._resetLayout(); 8589 }; 8590 8591 proto._getItemLayoutPosition = function( item ) { 8592 return this._mode()._getItemLayoutPosition( item ); 8593 }; 8594 8595 proto._manageStamp = function( stamp ) { 8596 this._mode()._manageStamp( stamp ); 8597 }; 8598 8599 proto._getContainerSize = function() { 8600 return this._mode()._getContainerSize(); 8601 }; 8602 8603 proto.needsResizeLayout = function() { 8604 return this._mode().needsResizeLayout(); 8605 }; 8606 8607 // -------------------------- adding & removing -------------------------- // 8608 8609 // HEADS UP overwrites default Outlayer appended 8610 proto.appended = function( elems ) { 8611 var items = this.addItems( elems ); 8612 if ( !items.length ) { 8613 return; 8614 } 8615 // filter, layout, reveal new items 8616 var filteredItems = this._filterRevealAdded( items ); 8617 // add to filteredItems 8618 this.filteredItems = this.filteredItems.concat( filteredItems ); 8619 }; 8620 8621 // HEADS UP overwrites default Outlayer prepended 8622 proto.prepended = function( elems ) { 8623 var items = this._itemize( elems ); 8624 if ( !items.length ) { 8625 return; 8626 } 8627 // start new layout 8628 this._resetLayout(); 8629 this._manageStamps(); 8630 // filter, layout, reveal new items 8631 var filteredItems = this._filterRevealAdded( items ); 8632 // layout previous items 8633 this.layoutItems( this.filteredItems ); 8634 // add to items and filteredItems 8635 this.filteredItems = filteredItems.concat( this.filteredItems ); 8636 this.items = items.concat( this.items ); 8637 }; 8638 8639 proto._filterRevealAdded = function( items ) { 8640 var filtered = this._filter( items ); 8641 this.hide( filtered.needHide ); 8642 // reveal all new items 8643 this.reveal( filtered.matches ); 8644 // layout new items, no transition 8645 this.layoutItems( filtered.matches, true ); 8646 return filtered.matches; 8647 }; 8648 8649 /** 8650 * Filter, sort, and layout newly-appended item elements 8651 * @param {Array or NodeList or Element} elems 8652 */ 8653 proto.insert = function( elems ) { 8654 var items = this.addItems( elems ); 8655 if ( !items.length ) { 8656 return; 8657 } 8658 // append item elements 8659 var i, item; 8660 var len = items.length; 8661 for ( i=0; i < len; i++ ) { 8662 item = items[i]; 8663 this.element.appendChild( item.element ); 8664 } 8665 // filter new stuff 8666 var filteredInsertItems = this._filter( items ).matches; 8667 // set flag 8668 for ( i=0; i < len; i++ ) { 8669 items[i].isLayoutInstant = true; 8670 } 8671 this.arrange(); 8672 // reset flag 8673 for ( i=0; i < len; i++ ) { 8674 delete items[i].isLayoutInstant; 8675 } 8676 this.reveal( filteredInsertItems ); 8677 }; 8678 8679 var _remove = proto.remove; 8680 proto.remove = function( elems ) { 8681 elems = utils.makeArray( elems ); 8682 var removeItems = this.getItems( elems ); 8683 // do regular thing 8684 _remove.call( this, elems ); 8685 // bail if no items to remove 8686 var len = removeItems && removeItems.length; 8687 // remove elems from filteredItems 8688 for ( var i=0; len && i < len; i++ ) { 8689 var item = removeItems[i]; 8690 // remove item from collection 8691 utils.removeFrom( this.filteredItems, item ); 8692 } 8693 }; 8694 8695 proto.shuffle = function() { 8696 // update random sortData 8697 for ( var i=0; i < this.items.length; i++ ) { 8698 var item = this.items[i]; 8699 item.sortData.random = Math.random(); 8700 } 8701 this.options.sortBy = 'random'; 8702 this._sort(); 8703 this._layout(); 8704 }; 8705 8706 /** 8707 * trigger fn without transition 8708 * kind of hacky to have this in the first place 8709 * @param {Function} fn 8710 * @param {Array} args 8711 * @returns ret 8712 * @private 8713 */ 8714 proto._noTransition = function( fn, args ) { 8715 // save transitionDuration before disabling 8716 var transitionDuration = this.options.transitionDuration; 8717 // disable transition 8718 this.options.transitionDuration = 0; 8719 // do it 8720 var returnValue = fn.apply( this, args ); 8721 // re-enable transition for reveal 8722 this.options.transitionDuration = transitionDuration; 8723 return returnValue; 8724 }; 8725 8726 // ----- helper methods ----- // 8727 8728 /** 8729 * getter method for getting filtered item elements 8730 * @returns {Array} elems - collection of item elements 8731 */ 8732 proto.getFilteredItemElements = function() { 8733 return this.filteredItems.map( function( item ) { 8734 return item.element; 8735 }); 8736 }; 8737 8738 // ----- ----- // 8739 8740 return Isotope; 8741 8742})); 8743
8744/*! 8745 * Packery layout mode PACKAGED v2.0.1 8746 * sub-classes Packery 8747 */ 8748 8749/** 8750 * Rect 8751 * low-level utility class for basic geometry 8752 */ 8753 8754( function( window, factory ) { 8755 // universal module definition 8756 /* jshint strict: false */ /* globals define, module */ 8757 if ( typeof define == 'function' && define.amd ) { 8758 // AMD 8759 define( 'packery/js/rect',factory ); 8760 } else if ( typeof module == 'object' && module.exports ) { 8761 // CommonJS 8762 module.exports = factory(); 8763 } else { 8764 // browser global 8765 window.Packery = window.Packery || {}; 8766 window.Packery.Rect = factory(); 8767 } 8768 8769}( window, function factory() { 8770 8771 8772// -------------------------- Rect -------------------------- // 8773 8774function Rect( props ) { 8775 // extend properties from defaults 8776 for ( var prop in Rect.defaults ) { 8777 this[ prop ] = Rect.defaults[ prop ]; 8778 } 8779 8780 for ( prop in props ) { 8781 this[ prop ] = props[ prop ]; 8782 } 8783 8784} 8785 8786Rect.defaults = { 8787 x: 0, 8788 y: 0, 8789 width: 0, 8790 height: 0 8791}; 8792 8793var proto = Rect.prototype; 8794 8795/** 8796 * Determines whether or not this rectangle wholly encloses another rectangle or point. 8797 * @param {Rect} rect 8798 * @returns {Boolean} 8799**/ 8800proto.contains = function( rect ) { 8801 // points don't have width or height 8802 var otherWidth = rect.width || 0; 8803 var otherHeight = rect.height || 0; 8804 return this.x <= rect.x && 8805 this.y <= rect.y && 8806 this.x + this.width >= rect.x + otherWidth && 8807 this.y + this.height >= rect.y + otherHeight; 8808}; 8809 8810/** 8811 * Determines whether or not the rectangle intersects with another. 8812 * @param {Rect} rect 8813 * @returns {Boolean} 8814**/ 8815proto.overlaps = function( rect ) { 8816 var thisRight = this.x + this.width; 8817 var thisBottom = this.y + this.height; 8818 var rectRight = rect.x + rect.width; 8819 var rectBottom = rect.y + rect.height; 8820 8821 // http://stackoverflow.com/a/306332 8822 return this.x < rectRight && 8823 thisRight > rect.x && 8824 this.y < rectBottom && 8825 thisBottom > rect.y; 8826}; 8827 8828/** 8829 * @param {Rect} rect - the overlapping rect 8830 * @returns {Array} freeRects - rects representing the area around the rect 8831**/ 8832proto.getMaximalFreeRects = function( rect ) { 8833 8834 // if no intersection, return false 8835 if ( !this.overlaps( rect ) ) { 8836 return false; 8837 } 8838 8839 var freeRects = []; 8840 var freeRect; 8841 8842 var thisRight = this.x + this.width; 8843 var thisBottom = this.y + this.height; 8844 var rectRight = rect.x + rect.width; 8845 var rectBottom = rect.y + rect.height; 8846 8847 // top 8848 if ( this.y < rect.y ) { 8849 freeRect = new Rect({ 8850 x: this.x, 8851 y: this.y, 8852 width: this.width, 8853 height: rect.y - this.y 8854 }); 8855 freeRects.push( freeRect ); 8856 } 8857 8858 // right 8859 if ( thisRight > rectRight ) { 8860 freeRect = new Rect({ 8861 x: rectRight, 8862 y: this.y, 8863 width: thisRight - rectRight, 8864 height: this.height 8865 }); 8866 freeRects.push( freeRect ); 8867 } 8868 8869 // bottom 8870 if ( thisBottom > rectBottom ) { 8871 freeRect = new Rect({ 8872 x: this.x, 8873 y: rectBottom, 8874 width: this.width, 8875 height: thisBottom - rectBottom 8876 }); 8877 freeRects.push( freeRect ); 8878 } 8879 8880 // left 8881 if ( this.x < rect.x ) { 8882 freeRect = new Rect({ 8883 x: this.x, 8884 y: this.y, 8885 width: rect.x - this.x, 8886 height: this.height 8887 }); 8888 freeRects.push( freeRect ); 8889 } 8890 8891 return freeRects; 8892}; 8893 8894proto.canFit = function( rect ) { 8895 return this.width >= rect.width && this.height >= rect.height; 8896}; 8897 8898return Rect; 8899 8900})); 8901 8902/** 8903 * Packer 8904 * bin-packing algorithm 8905 */ 8906 8907( function( window, factory ) { 8908 // universal module definition 8909 /* jshint strict: false */ /* globals define, module, require */ 8910 if ( typeof define == 'function' && define.amd ) { 8911 // AMD 8912 define( 'packery/js/packer',[ './rect' ], factory ); 8913 } else if ( typeof module == 'object' && module.exports ) { 8914 // CommonJS 8915 module.exports = factory( 8916 require('./rect') 8917 ); 8918 } else { 8919 // browser global 8920 var Packery = window.Packery = window.Packery || {}; 8921 Packery.Packer = factory( Packery.Rect ); 8922 } 8923 8924}( window, function factory( Rect ) { 8925 8926 8927// -------------------------- Packer -------------------------- // 8928 8929/** 8930 * @param {Number} width 8931 * @param {Number} height 8932 * @param {String} sortDirection 8933 * topLeft for vertical, leftTop for horizontal 8934 */ 8935function Packer( width, height, sortDirection ) { 8936 this.width = width || 0; 8937 this.height = height || 0; 8938 this.sortDirection = sortDirection || 'downwardLeftToRight'; 8939 8940 this.reset(); 8941} 8942 8943var proto = Packer.prototype; 8944 8945proto.reset = function() { 8946 this.spaces = []; 8947 8948 var initialSpace = new Rect({ 8949 x: 0, 8950 y: 0, 8951 width: this.width, 8952 height: this.height 8953 }); 8954 8955 this.spaces.push( initialSpace ); 8956 // set sorter 8957 this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight; 8958}; 8959 8960// change x and y of rect to fit with in Packer's available space
8960s 8961proto.pack = function( rect ) { 8962 for ( var i=0; i < this.spaces.length; i++ ) { 8963 var space = this.spaces[i]; 8964 if ( space.canFit( rect ) ) { 8965 this.placeInSpace( rect, space ); 8966 break; 8967 } 8968 } 8969}; 8970 8971proto.columnPack = function( rect ) { 8972 for ( var i=0; i < this.spaces.length; i++ ) { 8973 var space = this.spaces[i]; 8974 var canFitInSpaceColumn = space.x <= rect.x && 8975 space.x + space.width >= rect.x + rect.width && 8976 space.height >= rect.height - 0.01; // fudge number for rounding error 8977 if ( canFitInSpaceColumn ) { 8978 rect.y = space.y; 8979 this.placed( rect ); 8980 break; 8981 } 8982 } 8983}; 8984 8985proto.rowPack = function( rect ) { 8986 for ( var i=0; i < this.spaces.length; i++ ) { 8987 var space = this.spaces[i]; 8988 var canFitInSpaceRow = space.y <= rect.y && 8989 space.y + space.height >= rect.y + rect.height && 8990 space.width >= rect.width - 0.01; // fudge number for rounding error 8991 if ( canFitInSpaceRow ) { 8992 rect.x = space.x; 8993 this.placed( rect ); 8994 break; 8995 } 8996 } 8997}; 8998 8999proto.placeInSpace = function( rect, space ) { 9000 // place rect in space 9001 rect.x = space.x; 9002 rect.y = space.y; 9003 9004 this.placed( rect ); 9005}; 9006 9007// update spaces with placed rect 9008proto.placed = function( rect ) { 9009 // update spaces 9010 var revisedSpaces = []; 9011 for ( var i=0; i < this.spaces.length; i++ ) { 9012 var space = this.spaces[i]; 9013 var newSpaces = space.getMaximalFreeRects( rect ); 9014 // add either the original space or the new spaces to the revised spaces 9015 if ( newSpaces ) { 9016 revisedSpaces.push.apply( revisedSpaces, newSpaces ); 9017 } else { 9018 revisedSpaces.push( space ); 9019 } 9020 } 9021 9022 this.spaces = revisedSpaces; 9023 9024 this.mergeSortSpaces(); 9025}; 9026 9027proto.mergeSortSpaces = function() { 9028 // remove redundant spaces 9029 Packer.mergeRects( this.spaces ); 9030 this.spaces.sort( this.sorter ); 9031}; 9032 9033// add a space back 9034proto.addSpace = function( rect ) { 9035 this.spaces.push( rect ); 9036 this.mergeSortSpaces(); 9037}; 9038 9039// -------------------------- utility functions -------------------------- // 9040 9041/** 9042 * Remove redundant rectangle from array of rectangles 9043 * @param {Array} rects: an array of Rects 9044 * @returns {Array} rects: an array of Rects 9045**/ 9046Packer.mergeRects = function( rects ) { 9047 var i = 0; 9048 var rect = rects[i]; 9049 9050 rectLoop: 9051 while ( rect ) { 9052 var j = 0; 9053 var compareRect = rects[ i + j ]; 9054 9055 while ( compareRect ) { 9056 if ( compareRect == rect ) { 9057 j++; // next 9058 } else if ( compareRect.contains( rect ) ) { 9059 // remove rect 9060 rects.splice( i, 1 ); 9061 rect = rects[i]; // set next rect 9062 continue rectLoop; // bail on compareLoop 9063 } else if ( rect.contains( compareRect ) ) { 9064 // remove compareRect 9065 rects.splice( i + j, 1 ); 9066 } else { 9067 j++; 9068 } 9069 compareRect = rects[ i + j ]; // set next compareRect 9070 } 9071 i++; 9072 rect = rects[i]; 9073 } 9074 9075 return rects; 9076}; 9077 9078 9079// -------------------------- sorters -------------------------- // 9080 9081// functions for sorting rects in order 9082var sorters = { 9083 // top down, then left to right 9084 downwardLeftToRight: function( a, b ) { 9085 return a.y - b.y || a.x - b.x; 9086 }, 9087 // left to right, then top down 9088 rightwardTopToBottom: function( a, b ) { 9089 return a.x - b.x || a.y - b.y; 9090 } 9091}; 9092 9093 9094// -------------------------- -------------------------- // 9095 9096return Packer; 9097 9098})); 9099 9100/** 9101 * Packery Item Element 9102**/ 9103 9104( function( window, factory ) { 9105 // universal module definition 9106 /* jshint strict: false */ /* globals define, module, require */ 9107 if ( typeof define == 'function' && define.amd ) { 9108 // AMD 9109 define( 'packery/js/item',[ 9110 'outlayer/outlayer', 9111 './rect' 9112 ], 9113 factory ); 9114 } else if ( typeof module == 'object' && module.exports ) { 9115 // CommonJS 9116 module.exports = factory( 9117 require('outlayer'), 9118 require('./rect') 9119 ); 9120 } else { 9121 // browser global 9122 window.Packery.Item = factory( 9123 window.Outlayer, 9124 window.Packery.Rect 9125 ); 9126 } 9127 9128}( window, function factory( Outlayer, Rect ) { 9129 9130 9131// -------------------------- Item -------------------------- // 9132 9133var docElemStyle = document.documentElement.style; 9134 9135var transformProperty = typeof docElemStyle.transform == 'string' ? 9136 'transform' : 'WebkitTransform'; 9137 9138// sub-class Item 9139var Item = function PackeryItem() { 9140 Outlayer.Item.apply( this, arguments ); 9141}; 9142 9143var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 9144 9145var __create = proto._create; 9146proto._create = function() { 9147 // call default _create logic 9148 __create.call( this ); 9149 this.rect = new Rect(); 9150}; 9151 9152var _moveTo = proto.moveTo; 9153proto.moveTo = function( x, y ) {
9154 // don't shift 1px while dragging 9155 var dx = Math.abs( this.position.x - x ); 9156 var dy = Math.abs( this.position.y - y ); 9157 9158 var canHackGoTo = this.layout.dragItemCount && !this.isPlacing && 9159 !this.isTransitioning && dx < 1 && dy < 1; 9160 if ( canHackGoTo ) { 9161 this.goTo( x, y ); 9162 return; 9163 } 9164 _moveTo.apply( this, arguments ); 9165}; 9166 9167// -------------------------- placing -------------------------- // 9168 9169proto.enablePlacing = function() { 9170 this.removeTransitionStyles(); 9171 // remove transform property from transition 9172 if ( this.isTransitioning && transformProperty ) { 9173 this.element.style[ transformProperty ] = 'none'; 9174 } 9175 this.isTransitioning = false; 9176 this.getSize(); 9177 this.layout._setRectSize( this.element, this.rect ); 9178 this.isPlacing = true; 9179}; 9180 9181proto.disablePlacing = function() { 9182 this.isPlacing = false; 9183}; 9184 9185// ----- ----- // 9186 9187// remove element from DOM 9188proto.removeElem = function() { 9189 this.element.parentNode.removeChild( this.element ); 9190 // add space back to packer 9191 this.layout.packer.addSpace( this.rect ); 9192 this.emitEvent( 'remove', [ this ] ); 9193}; 9194 9195// ----- dropPlaceholder ----- // 9196 9197proto.showDropPlaceholder = function() { 9198 var dropPlaceholder = this.dropPlaceholder; 9199 if ( !dropPlaceholder ) { 9200 // create dropPlaceholder 9201 dropPlaceholder = this.dropPlaceholder = document.createElement('div'); 9202 dropPlaceholder.className = 'packery-drop-placeholder'; 9203 dropPlaceholder.style.position = 'absolute'; 9204 } 9205 9206 dropPlaceholder.style.width = this.size.width + 'px'; 9207 dropPlaceholder.style.height = this.size.height + 'px'; 9208 this.positionDropPlaceholder(); 9209 this.layout.element.appendChild( dropPlaceholder ); 9210}; 9211 9212proto.positionDropPlaceholder = function() { 9213 this.dropPlaceholder.style[ transformProperty ] = 'translate(' + 9214 this.rect.x + 'px, ' + this.rect.y + 'px)'; 9215}; 9216 9217proto.hideDropPlaceholder = function() { 9218 this.layout.element.removeChild( this.dropPlaceholder ); 9219}; 9220 9221// ----- ----- // 9222 9223return Item; 9224 9225})); 9226 9227/*! 9228 * Packery v2.0.0 9229 * Gapless, draggable grid layouts 9230 * 9231 * Licensed GPLv3 for open source use 9232 * or Packery Commercial License for commercial use 9233 * 9234 * http://packery.metafizzy.co 9235 * Copyright 2016 Metafizzy 9236 */ 9237 9238( function( window, factory ) { 9239 // universal module definition 9240 /* jshint strict: false */ /* globals define, module, require */ 9241 if ( typeof define == 'function' && define.amd ) { 9242 // AMD 9243 define( 'packery/js/packery',[ 9244 'get-size/get-size', 9245 'outlayer/outlayer', 9246 './rect', 9247 './packer', 9248 './item' 9249 ], 9250 factory ); 9251 } else if ( typeof module == 'object' && module.exports ) { 9252 // CommonJS 9253 module.exports = factory( 9254 require('get-size'), 9255 require('outlayer'), 9256 require('./rect'), 9257 require('./packer'), 9258 require('./item') 9259 ); 9260 } else { 9261 // browser global 9262 window.Packery = factory( 9263 window.getSize, 9264 window.Outlayer, 9265 window.Packery.Rect, 9266 window.Packery.Packer, 9267 window.Packery.Item 9268 ); 9269 } 9270 9271}( window, function factory( getSize, Outlayer, Rect, Packer, Item ) { 9272 9273 9274// ----- Rect ----- // 9275 9276// allow for pixel rounding errors IE8-IE11 & Firefox; #227 9277Rect.prototype.canFit = function( rect ) { 9278 return this.width >= rect.width - 1 && this.height >= rect.height - 1; 9279}; 9280 9281// -------------------------- Packery -------------------------- // 9282 9283// create an Outlayer layout class 9284var Packery = Outlayer.create('packery'); 9285Packery.Item = Item; 9286 9287var proto = Packery.prototype; 9288 9289proto._create = function() { 9290 // call super 9291 Outlayer.prototype._create.call( this ); 9292 9293 // initial properties 9294 this.packer = new Packer(); 9295 // packer for drop targets 9296 this.shiftPacker = new Packer(); 9297 this.isEnabled = true; 9298 9299 this.dragItemCount = 0; 9300 9301 // create drag handlers 9302 var _this = this; 9303 this.handleDraggabilly = { 9304 dragStart: function() { 9305 _this.itemDragStart( this.element ); 9306 }, 9307 dragMove: function() { 9308 _this.itemDragMove( this.element, this.position.x, this.position.y ); 9309 }, 9310 dragEnd: function() { 9311 _this.itemDragEnd( this.element ); 9312 } 9313 }; 9314 9315 this.handleUIDraggable = { 9316 start: function handleUIDraggableStart( event, ui ) { 9317 // HTML5 may trigger dragstart, dismiss HTML5 dragging 9318 if ( !ui ) { 9319 return; 9320 } 9321 _this.itemDragStart( event.currentTarget ); 9322 }, 9323 drag: function handleUIDraggableDrag( event, ui ) { 9324 if ( !ui ) { 9325 return; 9326 } 9327 _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top ); 9328 }, 9329 stop: function handleUIDraggableStop( event, ui ) { 9330 if ( !ui ) { 9331 return; 9332 } 9333 _this.itemDragEnd( event.currentTarget ); 9334 } 9335 }; 9336 9337}; 9338 9339 9340// ----- init & layout ----- // 9341 9342/** 9343 * logic before any new layout 9344 */ 9345proto._resetLayout = function() {
9346 this.getSize(); 9347 9348 this._getMeasurements(); 9349 9350 // reset packer 9351 var width, height, sortDirection; 9352 // packer settings, if horizontal or vertical 9353 if ( this._getOption('horizontal') ) { 9354 width = Infinity; 9355 height = this.size.innerHeight + this.gutter; 9356 sortDirection = 'rightwardTopToBottom'; 9357 } else { 9358 width = this.size.innerWidth + this.gutter; 9359 height = Infinity; 9360 sortDirection = 'downwardLeftToRight'; 9361 } 9362 9363 this.packer.width = this.shiftPacker.width = width; 9364 this.packer.height = this.shiftPacker.height = height; 9365 this.packer.sortDirection = this.shiftPacker.sortDirection = sortDirection; 9366 9367 this.packer.reset(); 9368 9369 // layout 9370 this.maxY = 0; 9371 this.maxX = 0; 9372}; 9373 9374/** 9375 * update columnWidth, rowHeight, & gutter 9376 * @private 9377 */ 9378proto._getMeasurements = function() { 9379 this._getMeasurement( 'columnWidth', 'width' ); 9380 this._getMeasurement( 'rowHeight', 'height' ); 9381 this._getMeasurement( 'gutter', 'width' ); 9382}; 9383 9384proto._getItemLayoutPosition = function( item ) { 9385 this._setRectSize( item.element, item.rect ); 9386 if ( this.isShifting || this.dragItemCount > 0 ) { 9387 var packMethod = this._getPackMethod(); 9388 this.packer[ packMethod ]( item.rect ); 9389 } else { 9390 this.packer.pack( item.rect ); 9391 } 9392 9393 this._setMaxXY( item.rect ); 9394 return item.rect; 9395}; 9396 9397proto.shiftLayout = function() { 9398 this.isShifting = true; 9399 this.layout(); 9400 delete this.isShifting; 9401}; 9402 9403proto._getPackMethod = function() { 9404 return this._getOption('horizontal') ? 'rowPack' : 'columnPack'; 9405}; 9406 9407 9408/** 9409 * set max X and Y value, for size of container 9410 * @param {Packery.Rect} rect 9411 * @private 9412 */ 9413proto._setMaxXY = function( rect ) { 9414 this.maxX = Math.max( rect.x + rect.width, this.maxX ); 9415 this.maxY = Math.max( rect.y + rect.height, this.maxY ); 9416}; 9417 9418/** 9419 * set the width and height of a rect, applying columnWidth and rowHeight 9420 * @param {Element} elem 9421 * @param {Packery.Rect} rect 9422 */ 9423proto._setRectSize = function( elem, rect ) { 9424 var size = getSize( elem ); 9425 var w = size.outerWidth; 9426 var h = size.outerHeight; 9427 // size for columnWidth and rowHeight, if available 9428 // only check if size is non-zero, #177 9429 if ( w || h ) { 9430 w = this._applyGridGutter( w, this.columnWidth ); 9431 h = this._applyGridGutter( h, this.rowHeight ); 9432 } 9433 // rect must fit in packer 9434 rect.width = Math.min( w, this.packer.width ); 9435 rect.height = Math.min( h, this.packer.height ); 9436}; 9437 9438/** 9439 * fits item to columnWidth/rowHeight and adds gutter 9440 * @param {Number} measurement - item width or height 9441 * @param {Number} gridSize - columnWidth or rowHeight 9442 * @returns measurement 9443 */ 9444proto._applyGridGutter = function( measurement, gridSize ) { 9445 // just add gutter if no gridSize 9446 if ( !gridSize ) { 9447 return measurement + this.gutter; 9448 } 9449 gridSize += this.gutter; 9450 // fit item to columnWidth/rowHeight 9451 var remainder = measurement % gridSize; 9452 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 9453 measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize; 9454 return measurement; 9455}; 9456 9457proto._getContainerSize = function() { 9458 if ( this._getOption('horizontal') ) { 9459 return { 9460 width: this.maxX - this.gutter 9461 }; 9462 } else { 9463 return { 9464 height: this.maxY - this.gutter 9465 }; 9466 } 9467}; 9468 9469 9470// -------------------------- stamp -------------------------- // 9471 9472/** 9473 * makes space for element 9474 * @param {Element} elem 9475 */ 9476proto._manageStamp = function( elem ) { 9477 9478 var item = this.getItem( elem ); 9479 var rect; 9480 if ( item && item.isPlacing ) { 9481 rect = item.rect; 9482 } else { 9483 var offset = this._getElementOffset( elem ); 9484 rect = new Rect({ 9485 x: this._getOption('originLeft') ? offset.left : offset.right, 9486 y: this._getOption('originTop') ? offset.top : offset.bottom 9487 }); 9488 } 9489 9490 this._setRectSize( elem, rect ); 9491 // save its space in the packer 9492 this.packer.placed( rect ); 9493 this._setMaxXY( rect ); 9494}; 9495 9496// -------------------------- methods -------------------------- // 9497 9498function verticalSorter( a, b ) { 9499 return a.position.y - b.position.y || a.position.x - b.position.x; 9500} 9501 9502function horizontalSorter( a, b ) { 9503 return a.position.x - b.position.x || a.position.y - b.position.y; 9504} 9505
9506proto.sortItemsByPosition = function() { 9507 var sorter = this._getOption('horizontal') ? horizontalSorter : verticalSorter; 9508 this.items.sort( sorter ); 9509}; 9510 9511/** 9512 * Fit item element in its current position 9513 * Packery will position elements around it 9514 * useful for expanding elements 9515 * 9516 * @param {Element} elem 9517 * @param {Number} x - horizontal destination position, optional 9518 * @param {Number} y - vertical destination position, optional 9519 */ 9520proto.fit = function( elem, x, y ) { 9521 var item = this.getItem( elem ); 9522 if ( !item ) { 9523 return; 9524 } 9525 9526 // stamp item to get it out of layout 9527 this.stamp( item.element ); 9528 // set placing flag 9529 item.enablePlacing(); 9530 this.updateShiftTargets( item ); 9531 // fall back to current position for fitting 9532 x = x === undefined ? item.rect.x: x; 9533 y = y === undefined ? item.rect.y: y; 9534 // position it best at its destination 9535 this.shift( item, x, y ); 9536 this._bindFitEvents( item ); 9537 item.moveTo( item.rect.x, item.rect.y ); 9538 // layout everything else 9539 this.shiftLayout(); 9540 // return back to regularly scheduled programming 9541 this.unstamp( item.element ); 9542 this.sortItemsByPosition(); 9543 item.disablePlacing(); 9544}; 9545 9546/** 9547 * emit event when item is fit and other items are laid out 9548 * @param {Packery.Item} item 9549 * @private 9550 */ 9551proto._bindFitEvents = function( item ) { 9552 var _this = this; 9553 var ticks = 0; 9554 function onLayout() { 9555 ticks++; 9556 if ( ticks != 2 ) { 9557 return; 9558 } 9559 _this.dispatchEvent( 'fitComplete', null, [ item ] ); 9560 } 9561 // when item is laid out 9562 item.once( 'layout', onLayout ); 9563 // when all items are laid out 9564 this.once( 'layoutComplete', onLayout ); 9565}; 9566 9567// -------------------------- resize -------------------------- // 9568 9569// debounced, layout on resize 9570proto.resize = function() { 9571 // don't trigger if size did not change 9572 // or if resize was unbound. See #285, outlayer#9 9573 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 9574 return; 9575 } 9576 9577 if ( this.options.shiftPercentResize ) { 9578 this.resizeShiftPercentLayout(); 9579 } else { 9580 this.layout(); 9581 } 9582}; 9583 9584/** 9585 * check if layout is needed post layout 9586 * @returns Boolean 9587 */ 9588proto.needsResizeLayout = function() { 9589 var size = getSize( this.element ); 9590 var innerSize = this._getOption('horizontal') ? 'innerHeight' : 'innerWidth'; 9591 return size[ innerSize ] != this.size[ innerSize ]; 9592}; 9593 9594proto.resizeShiftPercentLayout = function() { 9595 var items = this._getItemsForLayout( this.items ); 9596 9597 var isHorizontal = this._getOption('horizontal'); 9598 var coord = isHorizontal ? 'y' : 'x'; 9599 var measure = isHorizontal ? 'height' : 'width'; 9600 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 9601 var innerSize = isHorizontal ? 'innerHeight' : 'innerWidth'; 9602 9603 // proportional re-align items 9604 var previousSegment = this[ segmentName ]; 9605 previousSegment = previousSegment && previousSegment + this.gutter; 9606 9607 if ( previousSegment ) { 9608 this._getMeasurements(); 9609 var currentSegment = this[ segmentName ] + this.gutter; 9610 items.forEach( function( item ) { 9611 var seg = Math.round( item.rect[ coord ] / previousSegment ); 9612 item.rect[ coord ] = seg * currentSegment; 9613 }); 9614 } else { 9615 var currentSize = getSize( this.element )[ innerSize ] + this.gutter; 9616 var previousSize = this.packer[ measure ]; 9617 items.forEach( function( item ) { 9618 item.rect[ coord ] = ( item.rect[ coord ] / previousSize ) * currentSize; 9619 }); 9620 } 9621 9622 this.shiftLayout(); 9623}; 9624 9625// -------------------------- drag -------------------------- // 9626 9627/** 9628 * handle an item drag start event 9629 * @param {Element} elem 9630 */ 9631proto.itemDragStart = function( elem ) { 9632 if ( !this.isEnabled ) { 9633 return; 9634 } 9635 this.stamp( elem ); 9636 // this.ignore( elem ); 9637 var item = this.getItem( elem ); 9638 if ( !item ) { 9639 return; 9640 } 9641 9642 item.enablePlacing(); 9643 item.showDropPlaceholder(); 9644 this.dragItemCount++; 9645 this.updateShiftTargets( item ); 9646}; 9647 9648proto.updateShiftTargets = function( dropItem ) { 9649 this.shiftPacker.reset(); 9650 9651 // pack stamps 9652 this._getBoundingRect(); 9653 var isOriginLeft = this._getOption('originLeft'); 9654 var isOriginTop = this._getOption('originTop'); 9655 this.stamps.forEach( function( stamp ) { 9656 // ignore dragged item 9657 var item = this.getItem( stamp ); 9658 if ( item && item.isPlacing ) { 9659 return; 9660 } 9661 var offset = this._getElementOffset( stamp ); 9662 var rect = new Rect({ 9663 x: isOriginLeft ? offset.left : offset.right, 9664 y: isOriginTop ? offset.top : offset.bottom 9665 }); 9666 this._setRectSize( stamp, rect ); 9667 // save its space in the packer 9668 this.shiftPacker.placed( rect ); 9669 }, this ); 9670 9671 // reset shiftTargets 9672 var isHorizontal = this._getOption('horizontal'); 9673 var segmentName = isHorizontal ? 'rowHeight' : 'columnWidth'; 9674 var measure = isHorizontal ? 'height' : 'width'; 9675 9676 this.shiftTargetKeys = []; 9677 this.shiftTargets = []; 9678 var boundsSize; 9679 var segment = this[ segmentName ]; 9680 segment = segment && segment + this.gutter; 9681 9682 if ( segment ) { 9683 var segmentSpan = Math.ceil( dropItem.rect[ measure ] / segment ); 9684 var segs = Math.floor( ( this.shiftPacker[ measure ] + this.gutter ) / segment ); 9685 boundsSize = ( segs - segmentSpan ) * segment; 9686 // add targets on top 9687 for ( var i=0; i < segs; i++ ) { 9688 this._addShiftTarget( i * segment, 0, boundsSize ); 9689 } 9690 } else { 9691 boundsSize = ( this.shiftPacker[ measure ] + this.gutter ) - dropItem.rect[ measure ]; 9692 this._addShiftTarget( 0, 0, boundsSize ); 9693 } 9694 9695 // pack each item to measure where shiftTargets are 9696 var items = this._getItemsForLayout( this.items ); 9697 var packMethod = this._getPackMethod();
9698 items.forEach( function( item ) { 9699 var rect = item.rect; 9700 this._setRectSize( item.element, rect ); 9701 this.shiftPacker[ packMethod ]( rect ); 9702 9703 // add top left corner 9704 this._addShiftTarget( rect.x, rect.y, boundsSize ); 9705 // add bottom left / top right corner 9706 var cornerX = isHorizontal ? rect.x + rect.width : rect.x; 9707 var cornerY = isHorizontal ? rect.y : rect.y + rect.height; 9708 this._addShiftTarget( cornerX, cornerY, boundsSize ); 9709 9710 if ( segment ) { 9711 // add targets for each column on bottom / row on right 9712 var segSpan = Math.round( rect[ measure ] / segment ); 9713 for ( var i=1; i < segSpan; i++ ) { 9714 var segX = isHorizontal ? cornerX : rect.x + segment * i; 9715 var segY = isHorizontal ? rect.y + segment * i : cornerY; 9716 this._addShiftTarget( segX, segY, boundsSize ); 9717 } 9718 } 9719 }, this ); 9720 9721}; 9722 9723proto._addShiftTarget = function( x, y, boundsSize ) { 9724 var checkCoord = this._getOption('horizontal') ? y : x; 9725 if ( checkCoord !== 0 && checkCoord > boundsSize ) { 9726 return; 9727 } 9728 // create string for a key, easier to keep track of what targets 9729 var key = x + ',' + y; 9730 var hasKey = this.shiftTargetKeys.indexOf( key ) != -1; 9731 if ( hasKey ) { 9732 return; 9733 } 9734 this.shiftTargetKeys.push( key ); 9735 this.shiftTargets.push({ x: x, y: y }); 9736}; 9737 9738// -------------------------- drop -------------------------- // 9739 9740proto.shift = function( item, x, y ) { 9741 var shiftPosition; 9742 var minDistance = Infinity; 9743 var position = { x: x, y: y }; 9744 this.shiftTargets.forEach( function( target ) { 9745 var distance = getDistance( target, position ); 9746 if ( distance < minDistance ) { 9747 shiftPosition = target; 9748 minDistance = distance; 9749 } 9750 }); 9751 item.rect.x = shiftPosition.x; 9752 item.rect.y = shiftPosition.y; 9753}; 9754 9755function getDistance( a, b ) { 9756 var dx = b.x - a.x; 9757 var dy = b.y - a.y; 9758 return Math.sqrt( dx * dx + dy * dy ); 9759} 9760 9761// -------------------------- drag move -------------------------- // 9762 9763var DRAG_THROTTLE_TIME = 120; 9764 9765/** 9766 * handle an item drag move event 9767 * @param {Element} elem 9768 * @param {Number} x - horizontal change in position 9769 * @param {Number} y - vertical change in position 9770 */ 9771proto.itemDragMove = function( elem, x, y ) { 9772 var item = this.isEnabled && this.getItem( elem ); 9773 if ( !item ) { 9774 return; 9775 } 9776 9777 x -= this.size.paddingLeft; 9778 y -= this.size.paddingTop; 9779 9780 var _this = this; 9781 function onDrag() { 9782 _this.shift( item, x, y ); 9783 item.positionDropPlaceholder(); 9784 _this.layout(); 9785 } 9786 9787 // throttle 9788 var now = new Date(); 9789 if ( this._itemDragTime && now - this._itemDragTime < DRAG_THROTTLE_TIME ) { 9790 clearTimeout( this.dragTimeout ); 9791 this.dragTimeout = setTimeout( onDrag, DRAG_THROTTLE_TIME ); 9792 } else { 9793 onDrag(); 9794 this._itemDragTime = now; 9795 } 9796}; 9797 9798// -------------------------- drag end -------------------------- // 9799 9800/** 9801 * handle an item drag end event 9802 * @param {Element} elem 9803 */ 9804proto.itemDragEnd = function( elem ) { 9805 var item = this.isEnabled && this.getItem( elem ); 9806 if ( !item ) { 9807 return; 9808 } 9809 9810 clearTimeout( this.dragTimeout ); 9811 item.element.classList.add('is-positioning-post-drag'); 9812 9813 var completeCount = 0; 9814 var _this = this; 9815 function onDragEndLayoutComplete() { 9816 completeCount++; 9817 if ( completeCount != 2 ) { 9818 return; 9819 } 9820 // reset drag item 9821 item.element.classList.remove('is-positioning-post-drag'); 9822 item.hideDropPlaceholder(); 9823 _this.dispatchEvent( 'dragItemPositioned', null, [ item ] ); 9824 } 9825 9826 item.once( 'layout', onDragEndLayoutComplete ); 9827 this.once( 'layoutComplete', onDragEndLayoutComplete ); 9828 item.moveTo( item.rect.x, item.rect.y ); 9829 this.layout(); 9830 this.dragItemCount = Math.max( 0, this.dragItemCount - 1 ); 9831 this.sortItemsByPosition(); 9832 item.disablePlacing(); 9833 this.unstamp( item.element ); 9834}; 9835 9836/** 9837 * binds Draggabilly events 9838 * @param {Draggabilly} draggie 9839 */ 9840proto.bindDraggabillyEvents = function( draggie ) { 9841 this._bindDraggabillyEvents( draggie, 'on' ); 9842}; 9843 9844proto.unbindDraggabillyEvents = function( draggie ) { 9845 this._bindDraggabillyEvents( draggie, 'off' ); 9846}; 9847 9848proto._bindDraggabillyEvents = function( draggie, method ) { 9849 var handlers = this.handleDraggabilly; 9850 draggie[ method ]( 'dragStart', handlers.dragStart ); 9851 draggie[ method ]( 'dragMove', handlers.dragMove ); 9852 draggie[ method ]( 'dragEnd', handlers.dragEnd ); 9853}; 9854 9855/** 9856 * binds jQuery UI Draggable events 9857 * @param {jQuery} $elems 9858 */ 9859proto.bindUIDraggableEvents = function( $elems ) { 9860 this._bindUIDraggableEvents( $elems, 'on' ); 9861}; 9862 9863proto.unbindUIDraggableEvents = function( $elems ) { 9864 this._bindUIDraggableEvents( $elems, 'off' ); 9865}; 9866 9867proto._bindUIDraggableEvents = function( $elems, method ) { 9868 var handlers = this.handleUIDraggable; 9869 $elems 9870 [ method ]( 'dragstart', handlers.start ) 9871 [ method ]( 'drag', handlers.drag ) 9872 [ method ]( 'dragstop', handlers.stop ); 9873}; 9874 9875// ----- destroy ----- // 9876 9877var _destroy = proto.destroy; 9878proto.destroy = function() { 9879 _destroy.apply( this, arguments ); 9880 // disable flag; prevent drag events from triggering. #72 9881 this.isEnabled = false;
9882}; 9883 9884// ----- ----- // 9885 9886Packery.Rect = Rect; 9887Packery.Packer = Packer; 9888 9889return Packery; 9890 9891})); 9892 9893/*! 9894 * Packery layout mode v2.0.1 9895 * sub-classes Packery 9896 */ 9897 9898/*jshint browser: true, strict: true, undef: true, unused: true */ 9899 9900( function( window, factory ) { 9901 9902 // universal module definition 9903 if ( typeof define == 'function' && define.amd ) { 9904 // AMD 9905 define( [ 9906 'isotope-layout/js/layout-mode', 9907 'packery/js/packery' 9908 ], 9909 factory ); 9910 } else if ( typeof module == 'object' && module.exports ) { 9911 // CommonJS 9912 module.exports = factory( 9913 require('isotope-layout/js/layout-mode'), 9914 require('packery') 9915 ); 9916 } else { 9917 // browser global 9918 factory( 9919 window.Isotope.LayoutMode, 9920 window.Packery 9921 ); 9922 } 9923 9924}( window, function factor( LayoutMode, Packery ) { 9925 9926 9927 // create an Outlayer layout class 9928 var PackeryMode = LayoutMode.create('packery'); 9929 var proto = PackeryMode.prototype; 9930 9931 var keepModeMethods = { 9932 _getElementOffset: true, 9933 _getMeasurement: true 9934 }; 9935 9936 // inherit Packery prototype 9937 for ( var method in Packery.prototype ) { 9938 // do not inherit mode methods 9939 if ( !keepModeMethods[ method ] ) { 9940 proto[ method ] = Packery.prototype[ method ]; 9941 } 9942 } 9943 9944 // set packer in _resetLayout 9945 var _resetLayout = proto._resetLayout; 9946 proto._resetLayout = function() { 9947 this.packer = this.packer || new Packery.Packer(); 9948 this.shiftPacker = this.shiftPacker || new Packery.Packer(); 9949 _resetLayout.apply( this, arguments ); 9950 }; 9951 9952 var _getItemLayoutPosition = proto._getItemLayoutPosition; 9953 proto._getItemLayoutPosition = function( item ) { 9954 // set packery rect 9955 item.rect = item.rect || new Packery.Rect(); 9956 return _getItemLayoutPosition.call( this, item ); 9957 }; 9958 9959 // needsResizeLayout for vertical or horizontal 9960 var _needsResizeLayout = proto.needsResizeLayout; 9961 proto.needsResizeLayout = function() { 9962 if ( this._getOption('horizontal') ) { 9963 return this.needsVerticalResizeLayout(); 9964 } else { 9965 return _needsResizeLayout.call( this ); 9966 } 9967 }; 9968 9969 // point to mode options for horizontal 9970 var _getOption = proto._getOption; 9971 proto._getOption = function( option ) { 9972 if ( option == 'horizontal' ) { 9973 return this.options.isHorizontal !== undefined ? 9974 this.options.isHorizontal : this.options.horizontal; 9975 } 9976 return _getOption.apply( this.isotope, arguments ); 9977 }; 9978 9979 return PackeryMode; 9980 9981})); 9982 9983/*! 9984 * cellsByRows layout mode for Isotope 9985 * v1.1.3 9986 * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html 9987 */ 9988 9989/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ 9990 9991( function( window, factory ) { 9992 // universal module definition 9993 /* jshint strict: false */ /*globals define, module, require */ 9994 if ( typeof define === 'function' && define.amd ) { 9995 // AMD 9996 define( [ 9997 'isotope/js/layout-mode' 9998 ], 9999 factory ); 10000 } else if ( typeof exports === 'object' ) { 10001 // CommonJS 10002 module.exports = factory( 10003 require('isotope-layout/js/layout-mode') 10004 ); 10005 } else { 10006 // browser global 10007 factory( 10008 window.Isotope.LayoutMode 10009 ); 10010 } 10011 10012}( window, function factory( LayoutMode ) { 10013 'use strict'; 10014 10015 var CellsByRow = LayoutMode.create( 'cellsByRow' ); 10016 var proto = CellsByRow.prototype; 10017 10018 proto._resetLayout = function() { 10019 // reset properties 10020 this.itemIndex = 0; 10021 // measurements 10022 this.getColumnWidth(); 10023 this.getRowHeight(); 10024 // set cols 10025 this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); 10026 this.cols = Math.max( this.cols, 1 ); 10027 }; 10028 10029 proto._getItemLayoutPosition = function( item ) { 10030 item.getSize(); 10031 var col = this.itemIndex % this.cols; 10032 var row = Math.floor( this.itemIndex / this.cols ); 10033 // center item within cell 10034 var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; 10035 var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; 10036 this.itemIndex++; 10037 return { x: x, y: y }; 10038 }; 10039 10040 proto._getContainerSize = function() { 10041 return { 10042 height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight 10043 }; 10044 }; 10045 10046 return CellsByRow; 10047 10048})); 10049/*global jQuery: true */ 10050 10051/*! 10052 -------------------------------- 10053 Infinite Scroll 10054 -------------------------------- 10055 + https://github.com/paulirish/infinite-scroll 10056 + version 2.1.0 10057 + Copyright 2011/12 Paul Irish & Luke Shumard 10058 + Licensed under the MIT license 10059 10060 + Documentation: http://infinite-scroll.com/ 10061*/ 10062 10063// Uses AMD or browser globals to create a jQuery plugin. 10064(function (factory) { 10065 if (typeof define === 'function' && define.amd) { 10066 // AMD. Register as an anonymous module. 10067 define(['jquery'], factory); 10068 } else { 10069 // Browser globals 10070 factory(jQuery); 10071 } 10072}(function ($, undefined) { 10073 'use strict'; 10074
10075 $.infinitescroll = function infscr(options, callback, element) { 10076 this.element = $(element); 10077 10078 // Flag the object in the event of a failed creation 10079 if (!this._create(options, callback)) { 10080 this.failed = true; 10081 } 10082 }; 10083 10084 $.infinitescroll.defaults = { 10085 loading: { 10086 finished: undefined, 10087 finishedMsg: "<em>Congratulations, you've reached the end of the internet.</em>", 10088 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
10088MzExnbRvQ2Sy7vN0zvVtNfU2tLY3rPgLdnDvca4VQS/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
10088iqpQpZ4apwSwRtjqrB3muoF9BboaXKmshlqWqsWiGt2wphJkQbAU5hoCACH5BAUKABsALAcABADOAAsAAAX/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', 10089 msg: null, 10090 msgText: '<em>Loading the next set of posts...</em>', 10091 selector: null, 10092 speed: 'fast', 10093 start: undefined 10094 }, 10095 state: { 10096 isDuringAjax: false, 10097 isInvalidPage: false,
10098 isDestroyed: false, 10099 isDone: false, // For when it goes all the way through the archive. 10100 isPaused: false, 10101 isBeyondMaxPage: false, 10102 currPage: 1 10103 }, 10104 debug: false, 10105 behavior: undefined, 10106 binder: $(window), // used to cache the selector 10107 nextSelector: 'div.navigation a:first', 10108 navSelector: 'div.navigation', 10109 contentSelector: null, // rename to pageFragment 10110 extraScrollPx: 150, 10111 itemSelector: 'div.post', 10112 animate: false, 10113 pathParse: undefined, 10114 dataType: 'html', 10115 appendCallback: true, 10116 bufferPx: 40, 10117 errorCallback: function () { }, 10118 infid: 0, //Instance ID 10119 pixelsFromNavToBottom: undefined, 10120 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 10121 prefill: false, // When the document is smaller than the window, load data until the document is larger or links are exhausted 10122 maxPage: undefined // to manually control maximum page (when maxPage is undefined, maximum page limitation is not work) 10123 }; 10124 10125 $.infinitescroll.prototype = { 10126 10127 /* 10128 ---------------------------- 10129 Private methods 10130 ---------------------------- 10131 */ 10132 10133 // Bind or unbind from scroll 10134 _binding: function infscr_binding(binding) { 10135 10136 var instance = this, 10137 opts = instance.options; 10138 10139 opts.v = '2.0b2.120520'; 10140 10141 // if behavior is defined and this function is extended, call that instead of default 10142 if (!!opts.behavior && this['_binding_'+opts.behavior] !== undefined) { 10143 this['_binding_'+opts.behavior].call(this); 10144 return; 10145 } 10146 10147 if (binding !== 'bind' && binding !== 'unbind') { 10148 this._debug('Binding value ' + binding + ' not valid'); 10149 return false; 10150 } 10151 10152 if (binding === 'unbind') { 10153 (this.options.binder).unbind('smartscroll.infscr.' + instance.options.infid); 10154 } else { 10155 (this.options.binder)[binding]('smartscroll.infscr.' + instance.options.infid, function () { 10156 instance.scroll(); 10157 }); 10158 } 10159 10160 this._debug('Binding', binding); 10161 }, 10162 10163 // Fundamental aspects of the plugin are initialized 10164 _create: function infscr_create(options, callback) { 10165 10166 // Add custom options to defaults 10167 var opts = $.extend(true, {}, $.infinitescroll.defaults, options); 10168 this.options = opts; 10169 var $window = $(window); 10170 var instance = this; 10171 10172 // Validate selectors 10173 if (!instance._validate(options)) { 10174 return false; 10175 } 10176 10177 // Validate page fragment path 10178 var path = $(opts.nextSelector).attr('href'); 10179 if (!path) { 10180 this._debug('Navigation selector not found'); 10181 return false; 10182 } 10183 10184 // Set the path to be a relative URL from root. 10185 opts.path = opts.path || this._determinepath(path); 10186 10187 // contentSelector is 'page fragment' option for .load() / .ajax() calls 10188 opts.contentSelector = opts.contentSelector || this.element; 10189 10190 // loading.selector - if we want to place the load message in a specific selector, defaulted to the contentSelector 10191 opts.loading.selector = opts.loading.selector || opts.contentSelector; 10192 10193 // Define loading.msg 10194 opts.loading.msg = opts.loading.msg || $('<div id="infscr-loading"><img alt="Loading..." src="' + opts.loading.img + '" /><div>' + opts.loading.msgText + '</div></div>'); 10195 10196 // Preload loading.img 10197 (new Image()).src = opts.loading.img; 10198 10199 // distance from nav links to bottom 10200 // computed as: height of the document + top offset of container - top offset of nav link 10201 if(opts.pixelsFromNavToBottom === undefined) { 10202 opts.pixelsFromNavToBottom = $(document).height() - $(opts.navSelector).offset().top; 10203 this._debug('pixelsFromNavToBottom: ' + opts.pixelsFromNavToBottom); 10204 } 10205 10206 var self = this; 10207 10208 // determine loading.start actions 10209 opts.loading.start = opts.loading.start || function() { 10210 $(opts.navSelector).hide(); 10211 opts.loading.msg 10212 .appendTo(opts.loading.selector) 10213 .show(opts.loading.speed, $.proxy(function() { 10214 this.beginAjax(opts); 10215 }, self)); 10216 }; 10217 10218 // determine loading.finished actions 10219 opts.loading.finished = opts.loading.finished || function() { 10220 if (!opts.state.isBeyondMaxPage) 10221 opts.loading.msg.fadeOut(opts.loading.speed); 10222 }; 10223 10224 // callback loading 10225 opts.callback = function(instance, data, url) { 10226 if (!!opts.behavior && instance['_callback_'+opts.behavior] !== undefined) { 10227 instance['_callback_'+opts.behavior].call($(opts.contentSelector)[0], data, url); 10228 } 10229 10230 if (callback) { 10231 callback.call($(opts.contentSelector)[0], data, opts, url); 10232 } 10233 10234 if (opts.prefill) { 10235 $window.bind('resize.infinite-scroll', instance._prefill); 10236 } 10237 }; 10238 10239 if (options.debug) { 10240 // Tell IE9 to use its built-in console 10241 if (Function.prototype.bind && (typeof console === 'object' || typeof console === 'function') && typeof console.log === 'object') { 10242 ['log','info','warn','error','assert','dir','clear','profile','profileEnd'] 10243 .forEach(function (method) { 10244 console[method] = this.call(console[method], console); 10245 }, Function.prototype.bind); 10246 } 10247 } 10248 10249 this._setup(); 10250 10251 // Setups the prefill method for use 10252 if (opts.prefill) { 10253 this._prefill(); 10254 } 10255 10256 // Return true to indicate successful creation 10257 return true; 10258 }, 10259 10260 _prefill: function infscr_prefill() { 10261 var instance = this; 10262 var $window = $(window); 10263 10264 function needsPrefill() { 10265 return ( $(instance.options.contentSelector).height() <= $window.height() ); 10266 } 10267 10268 this._prefill = function() { 10269 if (needsPrefill()) { 10270 instance.scroll(); 10271 } 10272 10273 $window.bind('resize.infinite-scroll', function() { 10274 if (needsPrefill()) { 10275 $window.unbind('resize.infinite-scroll'); 10276 instance.scroll(); 10277 } 10278 }); 10279 }; 10280 10281 // Call self after setting up the new function 10282 this._prefill(); 10283 }, 10284 10285 // Console log wrapper 10286 _debug: function infscr_debug() { 10287 if (true !== this.options.debug) { 10288 return; 10289 } 10290 10291 if (typeof console !== 'undefined' && typeof console.log === 'function') { 10292 // Modern browsers 10293 // Single argument, which is a string 10294 if ((Array.prototype.slice.call(arguments)).length === 1 && typeof Array.prototype.slice.call(arguments)[0] === 'string') { 10295 console.log( (Array.prototype.slice.call(arguments)).toString() ); 10296 } else { 10297 console.log( Array.prototype.slice.call(arguments) ); 10298 } 10299 } else if (!Function.prototype.bind && typeof console !== 'undefined' && typeof console.log === 'object') { 10300 // IE8 10301 Function.prototype.call.call(console.log, console, Array.prototype.slice.call(arguments)); 10302 } 10303 }, 10304 10305 // find the number to increment in the path.
10306 _determinepath: function infscr_determinepath(path) { 10307 10308 var opts = this.options; 10309 10310 // if behavior is defined and this function is extended, call that instead of default 10311 if (!!opts.behavior && this['_determinepath_'+opts.behavior] !== undefined) { 10312 return this['_determinepath_'+opts.behavior].call(this,path); 10313 } 10314 10315 if (!!opts.pathParse) { 10316 10317 this._debug('pathParse manual'); 10318 return opts.pathParse(path, this.options.state.currPage+1); 10319 10320 } else if (path.match(/^(.*?)\b2\b(.*?$)/)) { 10321 path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 10322 10323 // if there is any 2 in the url at all. 10324 } else if (path.match(/^(.*?)2(.*?$)/)) { 10325 10326 // page= is used in django: 10327 // http://www.infinite-scroll.com/changelog/comment-page-1/#comment-127 10328 if (path.match(/^(.*?page=)2(\/.*|$)/)) { 10329 path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 10330 return path; 10331 } 10332 10333 path = path.match(/^(.*?)2(.*?$)/).slice(1); 10334 10335 } else { 10336 10337 // page= is used in drupal too but second page is page=1 not page=2: 10338 // thx Jerod Fritz, vladikoff 10339 if (path.match(/^(.*?page=)1(\/.*|$)/)) { 10340 path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 10341 return path; 10342 } else { 10343 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."); 10344 // Get rid of isInvalidPage to allow permalink to state 10345 opts.state.isInvalidPage = true; //prevent it from running on this page. 10346 } 10347 } 10348 this._debug('determinePath', path); 10349 return path; 10350 10351 }, 10352 10353 // Custom error 10354 _error: function infscr_error(xhr) { 10355 10356 var opts = this.options; 10357 10358 // if behavior is defined and this function is extended, call that instead of default 10359 if (!!opts.behavior && this['_error_'+opts.behavior] !== undefined) { 10360 this['_error_'+opts.behavior].call(this,xhr); 10361 return; 10362 } 10363 10364 if (xhr !== 'destroy' && xhr !== 'end') { 10365 xhr = 'unknown'; 10366 } 10367 10368 this._debug('Error', xhr); 10369 10370 if (xhr === 'end' || opts.state.isBeyondMaxPage) { 10371 this._showdonemsg(); 10372 } 10373 10374 opts.state.isDone = true; 10375 opts.state.currPage = 1; // if you need to go back to this instance 10376 opts.state.isPaused = false; 10377 opts.state.isBeyondMaxPage = false; 10378 this._binding('unbind'); 10379 10380 }, 10381 10382 // Load Callback 10383 _loadcallback: function infscr_loadcallback(box, data, url) { 10384 var opts = this.options, 10385 callback = this.options.callback, // GLOBAL OBJECT FOR CALLBACK 10386 result = (opts.state.isDone) ? 'done' : (!opts.appendCallback) ? 'no-append' : 'append', 10387 frag; 10388 10389 // if behavior is defined and this function is extended, call that instead of default 10390 if (!!opts.behavior && this['_loadcallback_'+opts.behavior] !== undefined) { 10391 this['_loadcallback_'+opts.behavior].call(this,box,data); 10392 return; 10393 } 10394 10395 switch (result) { 10396 case 'done': 10397 this._showdonemsg(); 10398 return false; 10399 10400 case 'no-append': 10401 if (opts.dataType === 'html') { 10402 data = '<div>' + data + '</div>'; 10403 data = $(data).find(opts.itemSelector); 10404 } 10405 10406 // if it didn't return anything 10407 if (data.length === 0) { 10408 return this._error('end'); 10409 } 10410 10411 break; 10412 10413 case 'append': 10414 var children = box.children(); 10415 // if it didn't return anything 10416 if (children.length === 0) { 10417 return this._error('end'); 10418 } 10419 10420 // use a documentFragment because it works when content is going into a table or UL 10421 frag = document.createDocumentFragment(); 10422 while (box[0].firstChild) { 10423 frag.appendChild(box[0].firstChild); 10424 } 10425 10426 this._debug('contentSelector', $(opts.contentSelector)[0]); 10427 $(opts.contentSelector)[0].appendChild(frag); 10428 // previously, we would pass in the new DOM element as context for the callback 10429 // however we're now using a documentfragment, which doesn't have parents or children, 10430 // so the context is the contentContainer guy, and we pass in an array 10431 // of the elements collected as the first argument. 10432 10433 data = children.get(); 10434 break; 10435 } 10436 10437 // loadingEnd function 10438 opts.loading.finished.call($(opts.contentSelector)[0],opts); 10439 10440 // smooth scroll to ease in the new content 10441 if (opts.animate) { 10442 var scrollTo = $(window).scrollTop() + $(opts.loading.msg).height() + opts.extraScrollPx + 'px'; 10443 $('html,body').animate({ scrollTop: scrollTo }, 800, function () { opts.state.isDuringAjax = false; }); 10444 } 10445 10446 if (!opts.animate) { 10447 // once the call is done, we can allow it again. 10448 opts.state.isDuringAjax = false;
10449 } 10450 10451 callback(this, data, url); 10452 10453 if (opts.prefill) { 10454 this._prefill(); 10455 } 10456 }, 10457 10458 _nearbottom: function infscr_nearbottom() { 10459 10460 var opts = this.options, 10461 pixelsFromWindowBottomToBottom = 0 + $(document).height() - (opts.binder.scrollTop()) - $(window).height(); 10462 10463 // if behavior is defined and this function is extended, call that instead of default 10464 if (!!opts.behavior && this['_nearbottom_'+opts.behavior] !== undefined) { 10465 return this['_nearbottom_'+opts.behavior].call(this); 10466 } 10467 10468 this._debug('math:', pixelsFromWindowBottomToBottom, opts.pixelsFromNavToBottom); 10469 10470 // if distance remaining in the scroll (including buffer) is less than the orignal nav to bottom.... 10471 return (pixelsFromWindowBottomToBottom - opts.bufferPx < opts.pixelsFromNavToBottom); 10472 10473 }, 10474 10475 // Pause / temporarily disable plugin from firing 10476 _pausing: function infscr_pausing(pause) { 10477 10478 var opts = this.options; 10479 10480 // if behavior is defined and this function is extended, call that instead of default 10481 if (!!opts.behavior && this['_pausing_'+opts.behavior] !== undefined) { 10482 this['_pausing_'+opts.behavior].call(this,pause); 10483 return; 10484 } 10485 10486 // If pause is not 'pause' or 'resume', toggle it's value 10487 if (pause !== 'pause' && pause !== 'resume' && pause !== null) { 10488 this._debug('Invalid argument. Toggling pause value instead'); 10489 } 10490 10491 pause = (pause && (pause === 'pause' || pause === 'resume')) ? pause : 'toggle'; 10492 10493 switch (pause) { 10494 case 'pause': 10495 opts.state.isPaused = true; 10496 break; 10497 10498 case 'resume': 10499 opts.state.isPaused = false; 10500 break; 10501 10502 case 'toggle': 10503 opts.state.isPaused = !opts.state.isPaused; 10504 break; 10505 } 10506 10507 this._debug('Paused', opts.state.isPaused); 10508 return false; 10509 10510 }, 10511 10512 // Behavior is determined 10513 // If the behavior option is undefined, it will set to default and bind to scroll 10514 _setup: function infscr_setup() { 10515 10516 var opts = this.options; 10517 10518 // if behavior is defined and this function is extended, call that instead of default 10519 if (!!opts.behavior && this['_setup_'+opts.behavior] !== undefined) { 10520 this['_setup_'+opts.behavior].call(this); 10521 return; 10522 } 10523 10524 this._binding('bind'); 10525 10526 return false; 10527 10528 }, 10529 10530 // Show done message 10531 _showdonemsg: function infscr_showdonemsg() { 10532 10533 var opts = this.options; 10534 10535 // if behavior is defined and this function is extended, call that instead of default 10536 if (!!opts.behavior && this['_showdonemsg_'+opts.behavior] !== undefined) { 10537 this['_showdonemsg_'+opts.behavior].call(this); 10538 return; 10539 } 10540 10541 opts.loading.msg 10542 .find('img') 10543 .hide() 10544 .parent() 10545 .find('div').html(opts.loading.finishedMsg).animate({ opacity: 1 }, 2000, function () { 10546 $(this).parent().fadeOut(opts.loading.speed); 10547 }); 10548 10549 // user provided callback when done 10550 opts.errorCallback.call($(opts.contentSelector)[0],'done'); 10551 }, 10552 10553 // grab each selector option and see if any fail 10554 _validate: function infscr_validate(opts) { 10555 for (var key in opts) { 10556 if (key.indexOf && key.indexOf('Selector') > -1 && $(opts[key]).length === 0) { 10557 this._debug('Your ' + key + ' found no elements.'); 10558 return false; 10559 } 10560 } 10561 10562 return true; 10563 }, 10564 10565 /* 10566 ---------------------------- 10567 Public methods 10568 ---------------------------- 10569 */ 10570 10571 // Bind to scroll 10572 bind: function infscr_bind() { 10573 this._binding('bind'); 10574 }, 10575 10576 // Destroy current instance of plugin 10577 destroy: function infscr_destroy() { 10578 this.options.state.isDestroyed = true; 10579 this.options.loading.finished(); 10580 return this._error('destroy'); 10581 }, 10582 10583 // Set pause value to false 10584 pause: function infscr_pause() { 10585 this._pausing('pause'); 10586 }, 10587 10588 // Set pause value to false 10589 resume: function infscr_resume() { 10590 this._pausing('resume'); 10591 }, 10592 10593 beginAjax: function infscr_ajax(opts) { 10594 var instance = this, 10595 path = opts.path, 10596 box, desturl, method, condition; 10597 10598 // increment the URL bit. e.g. /page/3/ 10599 opts.state.currPage++; 10600 10601 // Manually control maximum page 10602 if ( opts.maxPage !== undefined && opts.state.currPage > opts.maxPage ){ 10603 opts.state.isBeyondMaxPage = true; 10604 this.destroy(); 10605 return; 10606 } 10607 10608 // if we're dealing with a table we can't use DIVs 10609 box = $(opts.contentSelector).is('table, tbody') ? $('<tbody/>') : $('<div/>'); 10610 10611 desturl = (typeof path === 'function') ? path(opts.state.currPage) : path.join(opts.state.currPage); 10612 instance._debug('heading into ajax', desturl); 10613 10614 method = (opts.dataType === 'html' || opts.dataType === 'json' ) ? opts.dataType : 'html+callback'; 10615 if (opts.appendCallback && opts.dataType === 'html') { 10616 method += '+callback'; 10617 } 10618 10619 switch (method) { 10620 case 'html+callback': 10621 instance._debug('Using HTML via .load() method'); 10622 box.load(desturl + ' ' + opts.itemSelector, undefined, function infscr_ajax_callback(responseText) { 10623 instance._loadcallback(box, responseText, desturl); 10624 }); 10625 10626 break; 10627 10628 case 'html': 10629 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 10630 $.ajax({ 10631 // params 10632 url: desturl, 10633 dataType: opts.dataType, 10634 complete: function infscr_ajax_callback(jqXHR, textStatus) { 10635 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 10636 if (condition) { 10637 instance._loadcallback(box, jqXHR.responseText, desturl); 10638 } else { 10639 instance._error('end'); 10640 } 10641 } 10642 }); 10643 10644 break; 10645 case 'json': 10646 instance._debug('Using ' + (method.toUpperCase()) + ' via $.ajax() method'); 10647 $.ajax({ 10648 dataType: 'json', 10649 type: 'GET', 10650 url: desturl, 10651 success: function (data, textStatus, jqXHR) { 10652 condition = (typeof (jqXHR.isResolved) !== 'undefined') ? (jqXHR.isResolved()) : (textStatus === 'success' || textStatus === 'notmodified'); 10653 if (opts.appendCallback) { 10654 // if appendCallback is true, you must defined template in options. 10655 // note that data passed into _loadcallback is already an html (after processed in opts.template(data)). 10656 if (opts.template !== undefined) { 10657 var theData = opts.template(data); 10658 box.append(theData); 10659 if (condition) { 10660 instance._loadcallback(box, theData); 10661 } else { 10662 instance._error('end'); 10663 } 10664 } else { 10665 instance._debug('template must be defined.'); 10666 instance._error('end'); 10667 } 10668 } else { 10669 // if appendCallback is false, we will pass in the JSON object. you should handle it yourself in your callback. 10670 if (condition) { 10671 instance._loadcallback(box, data, desturl); 10672 } else { 10673 instance._error('end'); 10674 } 10675 } 10676 }, 10677 error: function() { 10678 instance._debug('JSON ajax request failed.'); 10679 instance._error('end'); 10680 } 10681 }); 10682 10683 break; 10684 } 10685 }, 10686 10687 // Retrieve next set of content items 10688 retrieve: function infscr_retrieve(pageNum) { 10689 pageNum = pageNum || null; 10690 10691 var instance = this, 10692 opts = instance.options; 10693 10694 // if behavior is defined and this function is extended, call that instead of default 10695 if (!!opts.behavior && this['retrieve_'+opts.behavior] !== undefined) { 10696 this['retrieve_'+opts.behavior].call(this,pageNum); 10697 return; 10698 } 10699 10700 // for manual triggers, if destroyed, get out of here 10701 if (opts.state.isDestroyed) { 10702 this._debug('Instance is destroyed'); 10703 return false;
10704 } 10705 10706 // we dont want to fire the ajax multiple times 10707 opts.state.isDuringAjax = true; 10708 10709 opts.loading.start.call($(opts.contentSelector)[0],opts); 10710 }, 10711 10712 // Check to see next page is needed 10713 scroll: function infscr_scroll() { 10714 10715 var opts = this.options, 10716 state = opts.state; 10717 10718 // if behavior is defined and this function is extended, call that instead of default 10719 if (!!opts.behavior && this['scroll_'+opts.behavior] !== undefined) { 10720 this['scroll_'+opts.behavior].call(this); 10721 return; 10722 } 10723 10724 if (state.isDuringAjax || state.isInvalidPage || state.isDone || state.isDestroyed || state.isPaused) { 10725 return; 10726 } 10727 10728 if (!this._nearbottom()) { 10729 return; 10730 } 10731 10732 this.retrieve(); 10733 10734 }, 10735 10736 // Toggle pause value 10737 toggle: function infscr_toggle() { 10738 this._pausing(); 10739 }, 10740 10741 // Unbind from scroll 10742 unbind: function infscr_unbind() { 10743 this._binding('unbind'); 10744 }, 10745 10746 // update options 10747 update: function infscr_options(key) { 10748 if ($.isPlainObject(key)) { 10749 this.options = $.extend(true,this.options,key); 10750 } 10751 } 10752 }; 10753 10754 10755 /* 10756 ---------------------------- 10757 Infinite Scroll function 10758 ---------------------------- 10759 10760 Borrowed logic from the following... 10761 10762 jQuery UI 10763 - https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.widget.js 10764 10765 jCarousel 10766 - https://github.com/jsor/jcarousel/blob/master/lib/jquery.jcarousel.js 10767 10768 Masonry 10769 - https://github.com/desandro/masonry/blob/master/jquery.masonry.js 10770 10771*/ 10772 10773 $.fn.infinitescroll = function infscr_init(options, callback) { 10774 10775 10776 var thisCall = typeof options; 10777 10778 switch (thisCall) { 10779 10780 // method 10781 case 'string': 10782 var args = Array.prototype.slice.call(arguments, 1); 10783 10784 this.each(function () { 10785 var instance = $.data(this, 'infinitescroll'); 10786 10787 if (!instance) { 10788 // not setup yet 10789 // return $.error('Method ' + options + ' cannot be called until Infinite Scroll is setup'); 10790 return false; 10791 } 10792 10793 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 10794 // return $.error('No such method ' + options + ' for Infinite Scroll'); 10795 return false; 10796 } 10797 10798 // no errors! 10799 instance[options].apply(instance, args); 10800 }); 10801 10802 break; 10803 10804 // creation 10805 case 'object': 10806 10807 this.each(function () { 10808 10809 var instance = $.data(this, 'infinitescroll'); 10810 10811 if (instance) { 10812 10813 // update options of current instance 10814 instance.update(options); 10815 10816 } else { 10817 10818 // initialize new instance 10819 instance = new $.infinitescroll(options, callback, this); 10820 10821 // don't attach if instantiation failed 10822 if (!instance.failed) { 10823 $.data(this, 'infinitescroll', instance); 10824 } 10825 10826 } 10827 10828 }); 10829 10830 break; 10831 10832 } 10833 10834 return this; 10835 }; 10836 10837 10838 10839 /* 10840 * smartscroll: debounced scroll event for jQuery * 10841 * https://github.com/lukeshumard/smartscroll 10842 * Based on smartresize by @louis_remi: https://github.com/lrbabe/jquery.smartresize.js * 10843 * Copyright 2011 Louis-Remi & Luke Shumard * Licensed under the MIT license. * 10844 */ 10845 10846 var event = $.event, 10847 scrollTimeout; 10848 10849 event.special.smartscroll = { 10850 setup: function () { 10851 $(this).bind('scroll', event.special.smartscroll.handler); 10852 }, 10853 teardown: function () { 10854 $(this).unbind('scroll', event.special.smartscroll.handler); 10855 }, 10856 handler: function (event, execAsap) { 10857 // Save the context 10858 var context = this, 10859 args = arguments; 10860 10861 // set correct event type 10862 event.type = 'smartscroll'; 10863 10864 if (scrollTimeout) { clearTimeout(scrollTimeout); } 10865 scrollTimeout = setTimeout(function () { 10866 $(context).trigger('smartscroll', args); 10867 }, execAsap === 'execAsap' ? 0 : 100); 10868 } 10869 }; 10870 10871 $.fn.smartscroll = function (fn) {
10872 return fn ? this.bind('smartscroll', fn) : this.trigger('smartscroll', ['execAsap']); 10873 }; 10874 10875})); 10876 10877/*! 10878Waypoints - 4.0.1 10879Copyright © 2011-2016 Caleb Troughton 10880Licensed under the MIT license. 10881https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 10882*/ 10883(function() { 10884 'use strict' 10885 10886 var keyCounter = 0 10887 var allWaypoints = {} 10888 10889 /* http://imakewebthings.com/waypoints/api/waypoint */ 10890 function Waypoint(options) { 10891 if (!options) { 10892 throw new Error('No options passed to Waypoint constructor') 10893 } 10894 if (!options.element) { 10895 throw new Error('No element option passed to Waypoint constructor') 10896 } 10897 if (!options.handler) { 10898 throw new Error('No handler option passed to Waypoint constructor') 10899 } 10900 10901 this.key = 'waypoint-' + keyCounter 10902 this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) 10903 this.element = this.options.element 10904 this.adapter = new Waypoint.Adapter(this.element) 10905 this.callback = options.handler 10906 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 10907 this.enabled = this.options.enabled 10908 this.triggerPoint = null 10909 this.group = Waypoint.Group.findOrCreate({ 10910 name: this.options.group, 10911 axis: this.axis 10912 }) 10913 this.context = Waypoint.Context.findOrCreateByElement(this.options.context) 10914 10915 if (Waypoint.offsetAliases[this.options.offset]) { 10916 this.options.offset = Waypoint.offsetAliases[this.options.offset] 10917 } 10918 this.group.add(this) 10919 this.context.add(this) 10920 allWaypoints[this.key] = this 10921 keyCounter += 1 10922 } 10923 10924 /* Private */ 10925 Waypoint.prototype.queueTrigger = function(direction) { 10926 this.group.queueTrigger(this, direction) 10927 } 10928 10929 /* Private */ 10930 Waypoint.prototype.trigger = function(args) { 10931 if (!this.enabled) { 10932 return 10933 } 10934 if (this.callback) { 10935 this.callback.apply(this, args) 10936 } 10937 } 10938 10939 /* Public */ 10940 /* http://imakewebthings.com/waypoints/api/destroy */ 10941 Waypoint.prototype.destroy = function() { 10942 this.context.remove(this) 10943 this.group.remove(this) 10944 delete allWaypoints[this.key] 10945 } 10946 10947 /* Public */ 10948 /* http://imakewebthings.com/waypoints/api/disable */ 10949 Waypoint.prototype.disable = function() { 10950 this.enabled = false 10951 return this 10952 } 10953 10954 /* Public */ 10955 /* http://imakewebthings.com/waypoints/api/enable */ 10956 Waypoint.prototype.enable = function() { 10957 this.context.refresh() 10958 this.enabled = true 10959 return this 10960 } 10961 10962 /* Public */ 10963 /* http://imakewebthings.com/waypoints/api/next */ 10964 Waypoint.prototype.next = function() { 10965 return this.group.next(this) 10966 } 10967 10968 /* Public */ 10969 /* http://imakewebthings.com/waypoints/api/previous */ 10970 Waypoint.prototype.previous = function() { 10971 return this.group.previous(this) 10972 } 10973 10974 /* Private */ 10975 Waypoint.invokeAll = function(method) { 10976 var allWaypointsArray = []
10977 for (var waypointKey in allWaypoints) { 10978 allWaypointsArray.push(allWaypoints[waypointKey]) 10979 } 10980 for (var i = 0, end = allWaypointsArray.length; i < end; i++) { 10981 allWaypointsArray[i][method]() 10982 } 10983 } 10984 10985 /* Public */ 10986 /* http://imakewebthings.com/waypoints/api/destroy-all */ 10987 Waypoint.destroyAll = function() { 10988 Waypoint.invokeAll('destroy') 10989 } 10990 10991 /* Public */ 10992 /* http://imakewebthings.com/waypoints/api/disable-all */ 10993 Waypoint.disableAll = function() { 10994 Waypoint.invokeAll('disable') 10995 } 10996 10997 /* Public */ 10998 /* http://imakewebthings.com/waypoints/api/enable-all */ 10999 Waypoint.enableAll = function() { 11000 Waypoint.Context.refreshAll() 11001 for (var waypointKey in allWaypoints) { 11002 allWaypoints[waypointKey].enabled = true 11003 } 11004 return this 11005 } 11006 11007 /* Public */ 11008 /* http://imakewebthings.com/waypoints/api/refresh-all */ 11009 Waypoint.refreshAll = function() { 11010 Waypoint.Context.refreshAll() 11011 } 11012 11013 /* Public */ 11014 /* http://imakewebthings.com/waypoints/api/viewport-height */ 11015 Waypoint.viewportHeight = function() { 11016 return window.innerHeight || document.documentElement.clientHeight 11017 } 11018 11019 /* Public */ 11020 /* http://imakewebthings.com/waypoints/api/viewport-width */ 11021 Waypoint.viewportWidth = function() { 11022 return document.documentElement.clientWidth 11023 } 11024 11025 Waypoint.adapters = [] 11026 11027 Waypoint.defaults = { 11028 context: window, 11029 continuous: true, 11030 enabled: true, 11031 group: 'default', 11032 horizontal: false, 11033 offset: 0 11034 } 11035 11036 Waypoint.offsetAliases = { 11037 'bottom-in-view': function() { 11038 return this.context.innerHeight() - this.adapter.outerHeight() 11039 }, 11040 'right-in-view': function() { 11041 return this.context.innerWidth() - this.adapter.outerWidth() 11042 } 11043 } 11044 11045 window.Waypoint = Waypoint 11046}()) 11047;(function() { 11048 'use strict' 11049 11050 function requestAnimationFrameShim(callback) { 11051 window.setTimeout(callback, 1000 / 60) 11052 } 11053 11054 var keyCounter = 0 11055 var contexts = {} 11056 var Waypoint = window.Waypoint 11057 var oldWindowLoad = window.onload 11058 11059 /* http://imakewebthings.com/waypoints/api/context */ 11060 function Context(element) { 11061 this.element = element 11062 this.Adapter = Waypoint.Adapter 11063 this.adapter = new this.Adapter(element) 11064 this.key = 'waypoint-context-' + keyCounter 11065 this.didScroll = false 11066 this.didResize = false 11067 this.oldScroll = { 11068 x: this.adapter.scrollLeft(), 11069 y: this.adapter.scrollTop() 11070 } 11071 this.waypoints = { 11072 vertical: {}, 11073 horizontal: {} 11074 } 11075 11076 element.waypointContextKey = this.key 11077 contexts[element.waypointContextKey] = this 11078 keyCounter += 1 11079 if (!Waypoint.windowContext) { 11080 Waypoint.windowContext = true 11081 Waypoint.windowContext = new Context(window) 11082 } 11083 11084 this.createThrottledScrollHandler() 11085 this.createThrottledResizeHandler() 11086 } 11087 11088 /* Private */ 11089 Context.prototype.add = function(waypoint) { 11090 var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' 11091 this.waypoints[axis][waypoint.key] = waypoint 11092 this.refresh() 11093 } 11094 11095 /* Private */ 11096 Context.prototype.checkEmpty = function() { 11097 var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) 11098 var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) 11099 var isWindow = this.element == this.element.window 11100 if (horizontalEmpty && verticalEmpty && !isWindow) { 11101 this.adapter.off('.waypoints') 11102 delete contexts[this.key] 11103 } 11104 } 11105 11106 /* Private */ 11107 Context.prototype.createThrottledResizeHandler = function() { 11108 var self = this 11109 11110 function resizeHandler() { 11111 self.handleResize() 11112 self.didResize = false 11113 } 11114 11115 this.adapter.on('resize.waypoints', function() { 11116 if (!self.didResize) { 11117 self.didResize = true 11118 Waypoint.requestAnimationFrame(resizeHandler) 11119 } 11120 }) 11121 } 11122 11123 /* Private */ 11124 Context.prototype.createThrottledScrollHandler = function() { 11125 var self = this 11126 function scrollHandler() { 11127 self.handleScroll() 11128 self.didScroll = false 11129 } 11130 11131 this.adapter.on('scroll.waypoints', function() { 11132 if (!self.didScroll || Waypoint.isTouch) { 11133 self.didScroll = true 11134 Waypoint.requestAnimationFrame(scrollHandler) 11135 } 11136 }) 11137 } 11138 11139 /* Private */ 11140 Context.prototype.handleResize = function() { 11141 Waypoint.Context.refreshAll() 11142 } 11143 11144 /* Private */ 11145 Context.prototype.handleScroll = function() { 11146 var triggeredGroups = {} 11147 var axes = { 11148 horizontal: { 11149 newScroll: this.adapter.scrollLeft(), 11150 oldScroll: this.oldScroll.x, 11151 forward: 'right', 11152 backward: 'left' 11153 }, 11154 vertical: { 11155 newScroll: this.adapter.scrollTop(), 11156 oldScroll: this.oldScroll.y, 11157 forward: 'down', 11158 backward: 'up' 11159 } 11160 } 11161 11162 for (var axisKey in axes) { 11163 var axis = axes[axisKey] 11164 var isForward = axis.newScroll > axis.oldScroll 11165 var direction = isForward ? axis.forward : axis.backward 11166
11167 for (var waypointKey in this.waypoints[axisKey]) { 11168 var waypoint = this.waypoints[axisKey][waypointKey] 11169 if (waypoint.triggerPoint === null) { 11170 continue 11171 } 11172 var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint 11173 var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint 11174 var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint 11175 var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint 11176 if (crossedForward || crossedBackward) { 11177 waypoint.queueTrigger(direction) 11178 triggeredGroups[waypoint.group.id] = waypoint.group 11179 } 11180 } 11181 } 11182 11183 for (var groupKey in triggeredGroups) { 11184 triggeredGroups[groupKey].flushTriggers() 11185 } 11186 11187 this.oldScroll = { 11188 x: axes.horizontal.newScroll, 11189 y: axes.vertical.newScroll 11190 } 11191 } 11192 11193 /* Private */ 11194 Context.prototype.innerHeight = function() { 11195 /*eslint-disable eqeqeq */ 11196 if (this.element == this.element.window) { 11197 return Waypoint.viewportHeight() 11198 } 11199 /*eslint-enable eqeqeq */ 11200 return this.adapter.innerHeight() 11201 } 11202 11203 /* Private */ 11204 Context.prototype.remove = function(waypoint) { 11205 delete this.waypoints[waypoint.axis][waypoint.key] 11206 this.checkEmpty() 11207 } 11208 11209 /* Private */ 11210 Context.prototype.innerWidth = function() { 11211 /*eslint-disable eqeqeq */ 11212 if (this.element == this.element.window) { 11213 return Waypoint.viewportWidth() 11214 } 11215 /*eslint-enable eqeqeq */ 11216 return this.adapter.innerWidth() 11217 } 11218 11219 /* Public */ 11220 /* http://imakewebthings.com/waypoints/api/context-destroy */ 11221 Context.prototype.destroy = function() { 11222 var allWaypoints = [] 11223 for (var axis in this.waypoints) {
11224 for (var waypointKey in this.waypoints[axis]) { 11225 allWaypoints.push(this.waypoints[axis][waypointKey]) 11226 } 11227 } 11228 for (var i = 0, end = allWaypoints.length; i < end; i++) { 11229 allWaypoints[i].destroy() 11230 } 11231 } 11232 11233 /* Public */ 11234 /* http://imakewebthings.com/waypoints/api/context-refresh */ 11235 Context.prototype.refresh = function() { 11236 /*eslint-disable eqeqeq */ 11237 var isWindow = this.element == this.element.window 11238 /*eslint-enable eqeqeq */ 11239 var contextOffset = isWindow ? undefined : this.adapter.offset() 11240 var triggeredGroups = {} 11241 var axes 11242 11243 this.handleScroll() 11244 axes = { 11245 horizontal: { 11246 contextOffset: isWindow ? 0 : contextOffset.left, 11247 contextScroll: isWindow ? 0 : this.oldScroll.x, 11248 contextDimension: this.innerWidth(), 11249 oldScroll: this.oldScroll.x, 11250 forward: 'right', 11251 backward: 'left', 11252 offsetProp: 'left' 11253 }, 11254 vertical: { 11255 contextOffset: isWindow ? 0 : contextOffset.top, 11256 contextScroll: isWindow ? 0 : this.oldScroll.y, 11257 contextDimension: this.innerHeight(), 11258 oldScroll: this.oldScroll.y, 11259 forward: 'down', 11260 backward: 'up', 11261 offsetProp: 'top' 11262 } 11263 } 11264 11265 for (var axisKey in axes) { 11266 var axis = axes[axisKey]
11267 for (var waypointKey in this.waypoints[axisKey]) { 11268 var waypoint = this.waypoints[axisKey][waypointKey] 11269 var adjustment = waypoint.options.offset 11270 var oldTriggerPoint = waypoint.triggerPoint 11271 var elementOffset = 0 11272 var freshWaypoint = oldTriggerPoint == null 11273 var contextModifier, wasBeforeScroll, nowAfterScroll 11274 var triggeredBackward, triggeredForward 11275 11276 if (waypoint.element !== waypoint.element.window) { 11277 elementOffset = waypoint.adapter.offset()[axis.offsetProp] 11278 } 11279 11280 if (typeof adjustment === 'function') { 11281 adjustment = adjustment.apply(waypoint) 11282 } 11283 else if (typeof adjustment === 'string') { 11284 adjustment = parseFloat(adjustment) 11285 if (waypoint.options.offset.indexOf('%') > - 1) { 11286 adjustment = Math.ceil(axis.contextDimension * adjustment / 100) 11287 } 11288 } 11289 11290 contextModifier = axis.contextScroll - axis.contextOffset 11291 waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) 11292 wasBeforeScroll = oldTriggerPoint < axis.oldScroll 11293 nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll 11294 triggeredBackward = wasBeforeScroll && nowAfterScroll 11295 triggeredForward = !wasBeforeScroll && !nowAfterScroll 11296 11297 if (!freshWaypoint && triggeredBackward) { 11298 waypoint.queueTrigger(axis.backward) 11299 triggeredGroups[waypoint.group.id] = waypoint.group 11300 } 11301 else if (!freshWaypoint && triggeredForward) { 11302 waypoint.queueTrigger(axis.forward) 11303 triggeredGroups[waypoint.group.id] = waypoint.group 11304 } 11305 else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { 11306 waypoint.queueTrigger(axis.forward) 11307 triggeredGroups[waypoint.group.id] = waypoint.group 11308 } 11309 } 11310 } 11311 11312 Waypoint.requestAnimationFrame(function() { 11313 for (var groupKey in triggeredGroups) { 11314 triggeredGroups[groupKey].flushTriggers() 11315 } 11316 }) 11317 11318 return this 11319 } 11320 11321 /* Private */ 11322 Context.findOrCreateByElement = function(element) { 11323 return Context.findByElement(element) || new Context(element) 11324 } 11325 11326 /* Private */ 11327 Context.refreshAll = function() { 11328 for (var contextId in contexts) { 11329 contexts[contextId].refresh() 11330 } 11331 } 11332 11333 /* Public */ 11334 /* http://imakewebthings.com/waypoints/api/context-find-by-element */ 11335 Context.findByElement = function(element) { 11336 return contexts[element.waypointContextKey] 11337 } 11338 11339 window.onload = function() { 11340 if (oldWindowLoad) { 11341 oldWindowLoad() 11342 } 11343 Context.refreshAll() 11344 } 11345 11346 11347 Waypoint.requestAnimationFrame = function(callback) { 11348 var requestFn = window.requestAnimationFrame || 11349 window.mozRequestAnimationFrame || 11350 window.webkitRequestAnimationFrame || 11351 requestAnimationFrameShim 11352 requestFn.call(window, callback) 11353 } 11354 Waypoint.Context = Context 11355}()) 11356;(function() { 11357 'use strict' 11358 11359 function byTriggerPoint(a, b) { 11360 return a.triggerPoint - b.triggerPoint 11361 } 11362 11363 function byReverseTriggerPoint(a, b) { 11364 return b.triggerPoint - a.triggerPoint 11365 } 11366 11367 var groups = { 11368 vertical: {}, 11369 horizontal: {} 11370 } 11371 var Waypoint = window.Waypoint 11372 11373 /* http://imakewebthings.com/waypoints/api/group */ 11374 function Group(options) { 11375 this.name = options.name 11376 this.axis = options.axis 11377 this.id = this.name + '-' + this.axis 11378 this.waypoints = [] 11379 this.clearTriggerQueues() 11380 groups[this.axis][this.name] = this 11381 } 11382 11383 /* Private */ 11384 Group.prototype.add = function(waypoint) { 11385 this.waypoints.push(waypoint) 11386 } 11387 11388 /* Private */ 11389 Group.prototype.clearTriggerQueues = function() { 11390 this.triggerQueues = { 11391 up: [], 11392 down: [], 11393 left: [], 11394 right: [] 11395 } 11396 } 11397 11398 /* Private */ 11399 Group.prototype.flushTriggers = function() { 11400 for (var direction in this.triggerQueues) { 11401 var waypoints = this.triggerQueues[direction] 11402 var reverse = direction === 'up' || direction === 'left' 11403 waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) 11404 for (var i = 0, end = waypoints.length; i < end; i += 1) { 11405 var waypoint = waypoints[i] 11406 if (waypoint.options.continuous || i === waypoints.length - 1) { 11407 waypoint.trigger([direction]) 11408 } 11409 } 11410 } 11411 this.clearTriggerQueues() 11412 } 11413 11414 /* Private */ 11415 Group.prototype.next = function(waypoint) { 11416 this.waypoints.sort(byTriggerPoint) 11417 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 11418 var isLast = index === this.waypoints.length - 1 11419 return isLast ? null : this.waypoints[index + 1] 11420 } 11421 11422 /* Private */ 11423 Group.prototype.previous = function(waypoint) { 11424 this.waypoints.sort(byTriggerPoint) 11425 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 11426 return index ? this.waypoints[index - 1] : null 11427 } 11428 11429 /* Private */ 11430 Group.prototype.queueTrigger = function(waypoint, direction) { 11431 this.triggerQueues[direction].push(waypoint) 11432 } 11433 11434 /* Private */ 11435 Group.prototype.remove = function(waypoint) { 11436 var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) 11437 if (index > -1) { 11438 this.waypoints.splice(index, 1) 11439 } 11440 } 11441 11442 /* Public */ 11443 /* http://imakewebthings.com/waypoints/api/first */ 11444 Group.prototype.first = function() { 11445 return this.waypoints[0] 11446 } 11447 11448 /* Public */ 11449 /* http://imakewebthings.com/waypoints/api/last */ 11450 Group.prototype.last = function() { 11451 return this.waypoints[this.waypoints.length - 1] 11452 } 11453 11454 /* Private */ 11455 Group.findOrCreate = function(options) { 11456 return groups[options.axis][options.name] || new Group(options) 11457 } 11458 11459 Waypoint.Group = Group 11460}()) 11461;(function() { 11462 'use strict' 11463 11464 var $ = window.jQuery 11465 var Waypoint = window.Waypoint 11466 11467 function JQueryAdapter(element) { 11468 this.$element = $(element) 11469 } 11470 11471 $.each([
11472 'innerHeight', 11473 'innerWidth', 11474 'off', 11475 'offset', 11476 'on', 11477 'outerHeight', 11478 'outerWidth', 11479 'scrollLeft', 11480 'scrollTop' 11481 ], function(i, method) { 11482 JQueryAdapter.prototype[method] = function() { 11483 var args = Array.prototype.slice.call(arguments) 11484 return this.$element[method].apply(this.$element, args) 11485 } 11486 }) 11487 11488 $.each([ 11489 'extend', 11490 'inArray', 11491 'isEmptyObject' 11492 ], function(i, method) { 11493 JQueryAdapter[method] = $[method] 11494 }) 11495 11496 Waypoint.adapters.push({ 11497 name: 'jquery', 11498 Adapter: JQueryAdapter 11499 }) 11500 Waypoint.Adapter = JQueryAdapter 11501}()) 11502;(function() { 11503 'use strict' 11504 11505 var Waypoint = window.Waypoint 11506 11507 function createExtension(framework) { 11508 return function() { 11509 var waypoints = [] 11510 var overrides = arguments[0] 11511 11512 if (framework.isFunction(arguments[0])) { 11513 overrides = framework.extend({}, arguments[1]) 11514 overrides.handler = arguments[0] 11515 } 11516 11517 this.each(function() { 11518 var options = framework.extend({}, overrides, { 11519 element: this 11520 }) 11521 if (typeof options.context === 'string') { 11522 options.context = framework(this).closest(options.context)[0] 11523 } 11524 waypoints.push(new Waypoint(options)) 11525 }) 11526 11527 return waypoints 11528 } 11529 } 11530 11531 if (window.jQuery) { 11532 window.jQuery.fn.waypoint = createExtension(window.jQuery) 11533 } 11534 if (window.Zepto) { 11535 window.Zepto.fn.waypoint = createExtension(window.Zepto) 11536 } 11537}()) 11538; 11539/*! 11540Waypoints Inview Shortcut - 4.0.1 11541Copyright © 2011-2016 Caleb Troughton 11542Licensed under the MIT license. 11543https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 11544*/ 11545(function() { 11546 'use strict' 11547 11548 function noop() {} 11549 11550 var Waypoint = window.Waypoint 11551 11552 /* http://imakewebthings.com/waypoints/shortcuts/inview */ 11553 function Inview(options) { 11554 this.options = Waypoint.Adapter.extend({}, Inview.defaults, options) 11555 this.axis = this.options.horizontal ? 'horizontal' : 'vertical' 11556 this.waypoints = [] 11557 this.element = this.options.element 11558 this.createWaypoints() 11559 } 11560 11561 /* Private */ 11562 Inview.prototype.createWaypoints = function() { 11563 var configs = { 11564 vertical: [{ 11565 down: 'enter', 11566 up: 'exited', 11567 offset: '100%' 11568 }, { 11569 down: 'entered', 11570 up: 'exit', 11571 offset: 'bottom-in-view' 11572 }, { 11573 down: 'exit', 11574 up: 'entered', 11575 offset: 0 11576 }, { 11577 down: 'exited', 11578 up: 'enter', 11579 offset: function() { 11580 return -this.adapter.outerHeight() 11581 } 11582 }], 11583 horizontal: [{ 11584 right: 'enter', 11585 left: 'exited', 11586 offset: '100%' 11587 }, { 11588 right: 'entered', 11589 left: 'exit', 11590 offset: 'right-in-view' 11591 }, { 11592 right: 'exit', 11593 left: 'entered', 11594 offset: 0 11595 }, { 11596 right: 'exited', 11597 left: 'enter', 11598 offset: function() { 11599 return -this.adapter.outerWidth() 11600 } 11601 }] 11602 } 11603 11604 for (var i = 0, end = configs[this.axis].length; i < end; i++) { 11605 var config = configs[this.axis][i] 11606 this.createWaypoint(config) 11607 } 11608 } 11609 11610 /* Private */ 11611 Inview.prototype.createWaypoint = function(config) { 11612 var self = this 11613 this.waypoints.push(new Waypoint({ 11614 context: this.options.context, 11615 element: this.options.element, 11616 enabled: this.options.enabled, 11617 handler: (function(config) { 11618 return function(direction) { 11619 self.options[config[direction]].call(self, direction) 11620 } 11621 }(config)), 11622 offset: config.offset, 11623 horizontal: this.options.horizontal 11624 })) 11625 } 11626 11627 /* Public */ 11628 Inview.prototype.destroy = function() { 11629 for (var i = 0, end = this.waypoints.length; i < end; i++) { 11630 this.waypoints[i].destroy() 11631 } 11632 this.waypoints = [] 11633 } 11634 11635 Inview.prototype.disable = function() { 11636 for (var i = 0, end = this.waypoints.length; i < end; i++) { 11637 this.waypoints[i].disable() 11638 } 11639 } 11640 11641 Inview.prototype.enable = function() { 11642 for (var i = 0, end = this.waypoints.length; i < end; i++) { 11643 this.waypoints[i].enable() 11644 } 11645 } 11646 11647 Inview.defaults = { 11648 context: window, 11649 enabled: true, 11650 enter: noop, 11651 entered: noop,
11652 exit: noop, 11653 exited: noop 11654 } 11655 11656 Waypoint.Inview = Inview 11657}()) 11658; 11659 11660/* 11661 * SmartMenus jQuery v0.9.6 11662 * http://www.smartmenus.org/ 11663 * 11664 * Copyright 2014 Vasil Dinkov, Vadikom Web Ltd. 11665 * http://vadikom.com/ 11666 * 11667 * Released under the MIT license: 11668 * http://www.opensource.org/licenses/MIT 11669 */ 11670 11671(function($) { 11672 11673 var menuTrees = [], 11674 IE = !!window.createPopup, // we need to detect it, unfortunately 11675 IElt9 = IE && !document.defaultView, 11676 IElt8 = IE && !document.querySelector, 11677 IE6 = IE && typeof document.documentElement.currentStyle.minWidth == 'undefined', 11678 mouse = false, // optimize for touch by default - we will detect for mouse input 11679 mouseDetectionEnabled = false; 11680 11681 // Handle detection for mouse input (i.e. desktop browsers, tablets with a mouse, etc.) 11682 function initMouseDetection(disable) { 11683 if (!mouseDetectionEnabled && !disable) { 11684 // if we get two consecutive mousemoves within 2 pixels from each other and within 300ms, we assume a real mouse/cursor is present 11685 // 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) 11686 var firstTime = true, 11687 lastMove = null; 11688 $(document).bind({ 11689 'mousemove.smartmenus_mouse': function(e) { 11690 var thisMove = { x: e.pageX, y: e.pageY, timeStamp: new Date().getTime() }; 11691 if (lastMove) { 11692 var deltaX = Math.abs(lastMove.x - thisMove.x), 11693 deltaY = Math.abs(lastMove.y - thisMove.y); 11694 if ((deltaX > 0 || deltaY > 0) && deltaX <= 2 && deltaY <= 2 && thisMove.timeStamp - lastMove.timeStamp <= 300) { 11695 mouse = true; 11696 // 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 11697 if (firstTime) { 11698 var $a = $(e.target).closest('a'); 11699 if ($a.is('a')) { 11700 $.each(menuTrees, function() { 11701 if ($.contains(this.$root[0], $a[0])) { 11702 this.itemEnter({ currentTarget: $a[0] }); 11703 return false; 11704 } 11705 }); 11706 } 11707 firstTime = false; 11708 } 11709 } 11710 } 11711 lastMove = thisMove; 11712 }, 11713 'touchstart.smartmenus_mouse pointerover.smartmenus_mouse MSPointerOver.smartmenus_mouse': function(e) { 11714 if (!/^(4|mouse)$/.test(e.originalEvent.pointerType)) { 11715 mouse = false; 11716 } 11717 } 11718 }); 11719 mouseDetectionEnabled = true; 11720 } else if (mouseDetectionEnabled && disable) { 11721 $(document).unbind('.smartmenus_mouse'); 11722 mouseDetectionEnabled = false; 11723 } 11724 }; 11725 11726 $.SmartMenus = function(elm, options) { 11727 this.$root = $(elm); 11728 this.opts = options; 11729 this.rootId = ''; // internal 11730 this.$subArrow = null; 11731 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) 11732 this.activatedItems = []; // stores last activated A's for each level 11733 this.visibleSubMenus = []; // stores visible sub menus UL's 11734 this.showTimeout = 0; 11735 this.hideTimeout = 0; 11736 this.scrollTimeout = 0; 11737 this.clickActivated = false; 11738 this.zIndexInc = 0; 11739 this.$firstLink = null; // we'll use these for some tests 11740 this.$firstSub = null; // at runtime so we'll cache them 11741 this.disabled = false; 11742 this.$disableOverlay = null; 11743 this.init(); 11744 }; 11745 11746 $.extend($.SmartMenus, { 11747 hideAll: function() { 11748 $.each(menuTrees, function() { 11749 this.menuHideAll(); 11750 }); 11751 }, 11752 destroy: function() { 11753 while (menuTrees.length) { 11754 menuTrees[0].destroy(); 11755 } 11756 initMouseDetection(true); 11757 }, 11758 prototype: { 11759 init: function(refresh) { 11760 var self = this; 11761 11762 if (!refresh) { 11763 menuTrees.push(this); 11764 11765 this.rootId = (new Date().getTime() + Math.random() + '').replace(/\D/g, ''); 11766 11767 if (this.$root.hasClass('sm-rtl')) { 11768 this.opts.rightToLeftSubMenus = true; 11769 } 11770 11771 // init root (main menu) 11772 this.$root 11773 .data('smartmenus', this) 11774 .attr('data-smartmenus-id', this.rootId) 11775 .dataSM('level', 1) 11776 .bind({ 11777 'mouseover.smartmenus focusin.smartmenus': $.proxy(this.rootOver, this),
11778 'mouseout.smartmenus focusout.smartmenus': $.proxy(this.rootOut, this) 11779 }) 11780 .delegate('a, div.logo-container', { 11781 'mouseenter.smartmenus': $.proxy(this.itemEnter, this), 11782 'mouseleave.smartmenus': $.proxy(this.itemLeave, this), 11783 'mousedown.smartmenus': $.proxy(this.itemDown, this), 11784 'focus.smartmenus': $.proxy(this.itemFocus, this), 11785 'blur.smartmenus': $.proxy(this.itemBlur, this), 11786 'click.smartmenus': $.proxy(this.itemClick, this), 11787 'touchend.smartmenus': $.proxy(this.itemTouchEnd, this) 11788 }); 11789 11790 var eNamespace = '.smartmenus' + this.rootId; 11791 // hide menus on tap or click outside the root UL 11792 if (this.opts.hideOnClick) { 11793 $(document).bind('touchstart' + eNamespace, $.proxy(this.docTouchStart, this)) 11794 .bind('touchmove' + eNamespace, $.proxy(this.docTouchMove, this)) 11795 .bind('touchend' + eNamespace, $.proxy(this.docTouchEnd, this)) 11796 // for Opera Mobile < 11.5, webOS browser, etc. we'll check click too 11797 .bind('click' + eNamespace, $.proxy(this.docClick, this)); 11798 } 11799 // hide sub menus on resize 11800 $(window).bind('resize' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 11801 $(window).bind('scroll' + eNamespace + ' orientationchange' + eNamespace, $.proxy(this.winResize, this)); 11802 11803 if (this.opts.subIndicators) { 11804 this.$subArrow = $('<span/>').addClass('sub-arrow'); 11805 if (this.opts.subIndicatorsText) { 11806 this.$subArrow.html(this.opts.subIndicatorsText); 11807 } 11808 } 11809 11810 // make sure mouse detection is enabled 11811 initMouseDetection(); 11812 } 11813 11814 // init sub menus 11815 this.$firstSub = this.$root.find('ul').each(function() { self.menuInit($(this)); }).eq(0); 11816 11817 this.$firstLink = this.$root.find('a').eq(0); 11818 11819 // find current item 11820 if (this.opts.markCurrentItem) { 11821 var reDefaultDoc = /(index|default)\.[^#\?\/]*/i, 11822 reHash = /#.*/, 11823 locHref = window.location.href.replace(reDefaultDoc, ''), 11824 locHrefNoHash = locHref.replace(reHash, ''); 11825 this.$root.find('a').each(function() { 11826 var href = this.href.replace(reDefaultDoc, ''), 11827 $this = $(this); 11828 if (href == locHref || href == locHrefNoHash) { 11829 $this.addClass('current'); 11830 if (self.opts.markCurrentTree) { 11831 $this.parents('li').each(function() { 11832 var $this = $(this); 11833 if ($this.dataSM('sub')) { 11834 $this.children('a').addClass('current'); 11835 } 11836 }); 11837 } 11838 } 11839 }); 11840 } 11841 }, 11842 destroy: function() { 11843 this.menuHideAll(); 11844 this.$root 11845 .removeData('smartmenus') 11846 .removeAttr('data-smartmenus-id') 11847 .removeDataSM('level') 11848 .unbind('.smartmenus') 11849 .undelegate('.smartmenus'); 11850 var eNamespace = '.smartmenus' + this.rootId; 11851 $(document).unbind(eNamespace); 11852 $(window).unbind(eNamespace); 11853 if (this.opts.subIndicators) { 11854 this.$subArrow = null; 11855 } 11856 var self = this; 11857 $.each(this.subMenus, function() { 11858 if (this.hasClass('mega-menu')) { 11859 this.find('ul').removeDataSM('in-mega'); 11860 } 11861 if (this.dataSM('shown-before')) { 11862 if (IElt8) { 11863 this.children().css({ styleFloat: '', width: '' }); 11864 } 11865 if (self.opts.subMenusMinWidth || self.opts.subMenusMaxWidth) { 11866 if (!IE6) { 11867 this.css({ width: '', minWidth: '', maxWidth: '' }).removeClass('sm-nowrap'); 11868 } else { 11869 this.css({ width: '', overflowX: '', overflowY: '' }).children().children('a').css('white-space', ''); 11870 } 11871 } 11872 if (this.dataSM('scroll-arrows')) { 11873 this.dataSM('scroll-arrows').remove(); 11874 } 11875 this.css({ zIndex: '', top: '', left: '', marginLeft: '', marginTop: '', display: '' }); 11876 } 11877 if (self.opts.subIndicators) { 11878 this.dataSM('parent-a').removeClass('has-submenu').children('span.sub-arrow').remove(); 11879 } 11880 this.removeDataSM('shown-before') 11881 .removeDataSM('ie-shim') 11882 .removeDataSM('scroll-arrows') 11883 .removeDataSM('parent-a') 11884 .removeDataSM('level') 11885 .removeDataSM('beforefirstshowfired') 11886 .parent().removeDataSM('sub'); 11887 }); 11888 if (this.opts.markCurrentItem) { 11889 this.$root.find('a.current').removeClass('current'); 11890 } 11891 this.$root = null; 11892 this.$firstLink = null; 11893 this.$firstSub = null; 11894 if (this.$disableOverlay) { 11895 this.$disableOverlay.remove(); 11896 this.$disableOverlay = null; 11897 } 11898 menuTrees.splice($.inArray(this, menuTrees), 1); 11899 }, 11900 disable: function(noOverlay) { 11901 if (!this.disabled) { 11902 this.menuHideAll(); 11903 // display overlay over the menu to prevent interaction 11904 if (!noOverlay && !this.opts.isPopup && this.$root.is(':visible')) { 11905 var pos = this.$root.offset(); 11906 this.$disableOverlay = $('<div class="sm-jquery-disable-overlay"/>').css({ 11907 position: 'absolute', 11908 top: pos.top, 11909 left: pos.left, 11910 width: this.$root.outerWidth(), 11911 height: this.$root.outerHeight(),
11912 zIndex: this.getStartZIndex() + 1, 11913 opacity: 0 11914 }).appendTo(document.body); 11915 } 11916 this.disabled = true; 11917 } 11918 }, 11919 docClick: function(e) { 11920 // hide on any click outside the menu or on a menu link 11921 if (this.visibleSubMenus.length && !$.contains(this.$root[0], e.target) || $(e.target).is('a')) { 11922 this.menuHideAll($(e.target)); 11923 } 11924 }, 11925 docTouchEnd: function(e) { 11926 if (!this.lastTouch) { 11927 return; 11928 } 11929 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))) { 11930 if (this.hideTimeout) { 11931 clearTimeout(this.hideTimeout); 11932 this.hideTimeout = 0; 11933 } 11934 // hide with a delay to prevent triggering accidental unwanted click on some page element 11935 var self = this; 11936 this.hideTimeout = setTimeout(function() { self.menuHideAll($(e.target)); }, 350); 11937 } 11938 this.lastTouch = null; 11939 }, 11940 docTouchMove: function(e) { 11941 if (!this.lastTouch) { 11942 return; 11943 } 11944 var touchPoint = e.originalEvent.touches[0]; 11945 this.lastTouch.x2 = touchPoint.pageX; 11946 this.lastTouch.y2 = touchPoint.pageY; 11947 }, 11948 docTouchStart: function(e) { 11949 var touchPoint = e.originalEvent.touches[0]; 11950 this.lastTouch = { x1: touchPoint.pageX, y1: touchPoint.pageY, target: touchPoint.target }; 11951 }, 11952 enable: function() { 11953 if (this.disabled) { 11954 if (this.$disableOverlay) { 11955 this.$disableOverlay.remove(); 11956 this.$disableOverlay = null; 11957 } 11958 this.disabled = false; 11959 } 11960 }, 11961 getHeight: function($elm) { 11962 return this.getOffset($elm, true); 11963 }, 11964 // returns precise width/height float values in IE9+, FF4+, recent WebKit 11965 // http://vadikom.com/dailies/offsetwidth-offsetheight-useless-in-ie9-firefox4/ 11966 getOffset: function($elm, height) { 11967 var old; 11968 if ($elm.css('display') == 'none') { 11969 old = { position: $elm[0].style.position, visibility: $elm[0].style.visibility }; 11970 $elm.css({ position: 'absolute', visibility: 'hidden' }).show(); 11971 } 11972 var defaultView = $elm[0].ownerDocument.defaultView, 11973 compStyle = defaultView && defaultView.getComputedStyle && defaultView.getComputedStyle($elm[0], null), 11974 val = compStyle && parseFloat(compStyle[height ? 'height' : 'width']); 11975 if (val) { 11976 val += parseFloat(compStyle[height ? 'paddingTop' : 'paddingLeft']) 11977 + parseFloat(compStyle[height ? 'paddingBottom' : 'paddingRight']) 11978 + parseInt(compStyle[height ? 'borderTopWidth' : 'borderLeftWidth']) 11979 + parseInt(compStyle[height ? 'borderBottomWidth' : 'borderRightWidth']); 11980 } else { 11981 val = height ? $elm[0].offsetHeight : $elm[0].offsetWidth; 11982 } 11983 if (old) { 11984 $elm.hide().css(old); 11985 } 11986 return val; 11987 }, 11988 getWidth: function($elm) { 11989 return this.getOffset($elm); 11990 }, 11991 getStartZIndex: function() { 11992 var zIndex = parseInt(this.$root.css('z-index')); 11993 return !isNaN(zIndex) ? zIndex : 1; 11994 }, 11995 handleEvents: function() { 11996 return !this.disabled && this.isCSSOn(); 11997 }, 11998 handleItemEvents: function($a) { 11999 return this.handleEvents() && !this.isLinkInMegaMenu($a); 12000 }, 12001 isCollapsible: function() { 12002 return this.$firstSub.css('position') == 'static'; 12003 }, 12004 isCSSOn: function() { 12005 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'; 12006 }, 12007 isFixed: function() { 12008 return this.$root.css('position') == 'fixed'; 12009 }, 12010 isLinkInMegaMenu: function($a) { 12011 return !$a.parent().parent().dataSM('level'); 12012 }, 12013 isTouchMode: function() { 12014 return !mouse || this.isCollapsible(); 12015 }, 12016 itemActivate: function($a) { 12017 var $li = $a.parent(), 12018 $ul = $li.parent(), 12019 level = $ul.dataSM('level'); 12020 // 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 12021 if (level > 1 && (!this.activatedItems[level - 2] || this.activatedItems[level - 2][0] != $ul.dataSM('parent-a')[0])) { 12022 var self = this; 12023 $($ul.parentsUntil('[data-smartmenus-id]', 'ul').get().reverse()).add($ul).each(function() { 12024 self.itemActivate($(this).dataSM('parent-a')); 12025 }); 12026 } 12027 // hide any visible deeper level sub menus 12028 if (this.visibleSubMenus.length > level) { 12029 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--) { 12030 this.menuHide(this.visibleSubMenus[i]); 12031 } 12032 } 12033 // save new active item and sub menu for this level 12034 this.activatedItems[level - 1] = $a; 12035 this.visibleSubMenus[level - 1] = $ul; 12036 if (this.$root.triggerHandler('activate.smapi', $a[0]) === false) { 12037 return; 12038 } 12039 // show the sub menu if this item has one 12040 var $sub = $li.dataSM('sub'); 12041 if ($sub && (this.isTouchMode() || (!this.opts.showOnClick || this.clickActivated))) { 12042 this.menuShow($sub); 12043 } 12044 }, 12045 itemBlur: function(e) { 12046 var $a = $(e.currentTarget); 12047 if (!this.handleItemEvents($a)) { 12048 return; 12049 } 12050 this.$root.triggerHandler('blur.smapi', $a[0]); 12051 }, 12052 itemClick: function(e) { 12053 var $a = $(e.currentTarget); 12054 12055 if (!this.handleItemEvents($a)) { 12056 return; 12057 } 12058 $a.removeDataSM('mousedown'); 12059 if (this.$root.triggerHandler('click.smapi', $a[0]) === false) { 12060 return false;
12061 } 12062 var $sub = $a.parent().dataSM('sub'); 12063 if (this.isTouchMode()) { 12064 // undo fix: prevent the address bar on iPhone from sliding down when expanding a sub menu 12065 if ($a.dataSM('href')) { 12066 $a.attr('href', $a.dataSM('href')).removeDataSM('href'); 12067 } 12068 // if the sub is not visible 12069 if ($sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 12070 // try to activate the item and show the sub 12071 this.itemActivate($a); 12072 // if "itemActivate" showed the sub, prevent the click so that the link is not loaded 12073 // 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 12074 if ($sub.is(':visible')) { 12075 return false; 12076 } 12077 } 12078 } else if (this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 && $sub) { 12079 this.clickActivated = true; 12080 this.menuShow($sub); 12081 return false; 12082 } 12083 if ($a.hasClass('disabled')) { 12084 return false; 12085 } 12086 if (this.$root.triggerHandler('select.smapi', $a[0]) === false) { 12087 return false; 12088 } 12089 }, 12090 itemDown: function(e) { 12091 var $a = $(e.currentTarget); 12092 if (!this.handleItemEvents($a)) { 12093 return; 12094 } 12095 $a.dataSM('mousedown', true); 12096 }, 12097 itemEnter: function(e) { 12098 var $a = $(e.currentTarget); 12099 if (!this.handleItemEvents($a)) { 12100 return; 12101 } 12102 if (!this.isTouchMode()) { 12103 if (this.showTimeout) { 12104 clearTimeout(this.showTimeout); 12105 this.showTimeout = 0; 12106 } 12107 var self = this; 12108 this.showTimeout = setTimeout(function() { self.itemActivate($a); }, this.opts.showOnClick && $a.parent().parent().dataSM('level') == 1 ? 1 : this.opts.showTimeout); 12109 } 12110 this.$root.triggerHandler('mouseenter.smapi', $a[0]); 12111 }, 12112 itemFocus: function(e) { 12113 var $a = $(e.currentTarget); 12114 if (!this.handleItemEvents($a)) { 12115 return; 12116 } 12117 // 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 12118 if ((!this.isTouchMode() || !$a.dataSM('mousedown')) && (!this.activatedItems.length || this.activatedItems[this.activatedItems.length - 1][0] != $a[0])) { 12119 this.itemActivate($a); 12120 } 12121 this.$root.triggerHandler('focus.smapi', $a[0]); 12122 }, 12123 itemLeave: function(e) { 12124 var $a = $(e.currentTarget); 12125 if (!this.handleItemEvents($a)) { 12126 return; 12127 } 12128 if (!this.isTouchMode()) { 12129 if ($a[0].blur) { 12130 $a[0].blur(); 12131 } 12132 if (this.showTimeout) { 12133 clearTimeout(this.showTimeout); 12134 this.showTimeout = 0; 12135 } 12136 } 12137 $a.removeDataSM('mousedown'); 12138 this.$root.triggerHandler('mouseleave.smapi', $a[0]); 12139 }, 12140 itemTouchEnd: function(e) { 12141 var $a = $(e.currentTarget); 12142 if (!this.handleItemEvents($a)) { 12143 return; 12144 } 12145 // prevent the address bar on iPhone from sliding down when expanding a sub menu 12146 var $sub = $a.parent().dataSM('sub'); 12147 if ($a.attr('href').charAt(0) !== '#' && $sub && (!$sub.dataSM('shown-before') || !$sub.is(':visible'))) { 12148 $a.dataSM('href', $a.attr('href')); 12149 $a.attr('href', '#'); 12150 } 12151 }, 12152 menuFixLayout: function($ul) { 12153 // fixes a menu that is being shown for the first time 12154 if (!$ul.dataSM('shown-before')) { 12155 $ul.hide().dataSM('shown-before', true); 12156 // fix the layout of the items in IE<8 12157 if (IElt8) { 12158 $ul.children().css({ styleFloat: 'left', width: '100%' }); 12159 } 12160 } 12161 }, 12162 menuHide: function($sub) { 12163 if (this.$root.triggerHandler('beforehide.smapi', $sub[0]) === false) { 12164 return; 12165 } 12166 $sub.stop(true, true); 12167 if ($sub.is(':visible')) { 12168 var complete = function() { 12169 // unset z-index 12170 if (IElt9) { 12171 $sub.parent().css('z-index', ''); 12172 } else { 12173 $sub.css('z-index', ''); 12174 } 12175 }; 12176 // if sub is collapsible (mobile view) 12177 if (this.isCollapsible()) { 12178 if (this.opts.collapsibleHideFunction) { 12179 this.opts.collapsibleHideFunction.call(this, $sub, complete); 12180 } else { 12181 $sub.hide(this.opts.collapsibleHideDuration, complete); 12182 } 12183 } else { 12184 if (this.opts.hideFunction) { 12185 this.opts.hideFunction.call(this, $sub, complete); 12186 } else { 12187 $sub.hide(this.opts.hideDuration, complete); 12188 } 12189 } 12190 // remove IE iframe shim 12191 if ($sub.dataSM('ie-shim')) { 12192 $sub.dataSM('ie-shim').remove(); 12193 } 12194 // deactivate scrolling if it is activated for this sub 12195 if ($sub.dataSM('scroll')) { 12196 $sub.unbind('.smartmenus_scroll').removeDataSM('scroll').dataSM('scroll-arrows').hide(); 12197 } 12198 // unhighlight parent item 12199 $sub.dataSM('parent-a').removeClass('highlighted'); 12200 var level = $sub.dataSM('level'); 12201 this.activatedItems.splice(level - 1, 1); 12202 this.visibleSubMenus.splice(level - 1, 1); 12203 this.$root.triggerHandler('hide.smapi', $sub[0]); 12204 } 12205 }, 12206 menuHideAll: function($item) { 12207 if ($item != undefined && $item.parent().hasClass('menu-item') && !$item.parent().hasClass('menu-item-has-children')) return; 12208 var $win = $(window), 12209 winW = $win.width(); 12210 if ( $('body').hasClass('vmenu') && winW >= 560 ) { 12211 return; 12212 } 12213 if (this.showTimeout) { 12214 clearTimeout(this.showTimeout); 12215 this.showTimeout = 0; 12216 } 12217 // hide all subs 12218 for (var i = this.visibleSubMenus.length - 1; i > 0; i--) { 12219 this.menuHide(this.visibleSubMenus[i]); 12220 } 12221 // hide root if it's popup 12222 if (this.opts.isPopup) { 12223 this.$root.stop(true, true); 12224 if (this.$root.is(':visible')) { 12225 if (this.opts.hideFunction) { 12226 this.opts.hideFunction.call(this, this.$root); 12227 } else { 12228 this.$root.hide(this.opts.hideDuration); 12229 } 12230 // remove IE iframe shim 12231 if (this.$root.dataSM('ie-shim')) { 12232 this.$root.dataSM('ie-shim').remove(); 12233 } 12234 } 12235 } 12236 this.activatedItems = []; 12237 this.visibleSubMenus = []; 12238 this.clickActivated = false;
12239 // reset z-index increment 12240 this.zIndexInc = 0; 12241 }, 12242 menuIframeShim: function($ul) { 12243 // create iframe shim for the menu 12244 if (IE && this.opts.overlapControlsInIE && !$ul.dataSM('ie-shim')) { 12245 $ul.dataSM('ie-shim', $('<iframe/>').attr({ src: 'javascript:0', tabindex: -9 }) 12246 .css({ position: 'absolute', top: 'auto', left: '0', opacity: 0, border: '0' }) 12247 ); 12248 } 12249 }, 12250 menuInit: function($ul) { 12251 if (!$ul.dataSM('in-mega')) { 12252 this.subMenus.push($ul); 12253 // mark UL's in mega drop downs (if any) so we can neglect them 12254 if ($ul.hasClass('mega-menu')) { 12255 $ul.find('ul').dataSM('in-mega', true); 12256 } 12257 // get level (much faster than, for example, using parentsUntil) 12258 var level = 2, 12259 par = $ul[0]; 12260 while (par != null && par.parentNode != null && ( par = par.parentNode.parentNode) != this.$root[0]) { 12261 level++; 12262 } 12263 // cache stuff 12264 $ul.dataSM('parent-a', $ul.prevAll('a').eq(-1)) 12265 .dataSM('level', level) 12266 .parent().dataSM('sub', $ul); 12267 // add sub indicator to parent item 12268 if (this.opts.subIndicators) { 12269 $ul.dataSM('parent-a').addClass('has-submenu')[this.opts.subIndicatorsPos](this.$subArrow.clone()); 12270 } 12271 } 12272 }, 12273 menuPosition: function($sub) { 12274 var fixIE = $('html.ie').length; 12275 // if (fixIE) { 12276 // var $rowParent = $($sub).closest('.main-menu-container'); 12277 // $rowParent.height($rowParent.height()); 12278 // } 12279 var $a = $sub.dataSM('parent-a'), 12280 $li = $sub.parent(), 12281 $ul = $sub.parent().parent(), 12282 // $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'), 12283 $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'), 12284 level = $sub.dataSM('level'), 12285 subW = this.getWidth($sub), 12286 subH = this.getHeight($sub), 12287 itemOffset = $a.offset(), 12288 itemX = itemOffset.left, 12289 itemY = itemOffset.top, 12290 itemW = this.getWidth($a), 12291 itemH = this.getHeight($a), 12292 $win = $(window), 12293 winX = $win.scrollLeft(), 12294 winY = $win.scrollTop(), 12295 winW = $win.width(), 12296 winH = $win.height(), 12297 containerW = $container.width(), 12298 containerOffsetX = containerW + ((winW - containerW) / 2), 12299 horizontalParent = $ul.hasClass('sm') && !$ul.hasClass('sm-vertical'), 12300 subOffsetX = level == 2 ? this.opts.mainMenuSubOffsetX : this.opts.subMenusSubOffsetX, 12301 subOffsetY = level == 2 ? this.opts.mainMenuSubOffsetY : this.opts.subMenusSubOffsetY, 12302 x, y, leftPos; 12303 12304 if (horizontalParent) { 12305 x = this.opts.rightToLeftSubMenus ? itemW - subW - subOffsetX : subOffsetX; 12306 y = this.opts.bottomToTopSubMenus ? -subH - subOffsetY : itemH + subOffsetY; 12307 } else { 12308 x = this.opts.rightToLeftSubMenus ? subOffsetX - subW : subW - subOffsetX; 12309 y = this.opts.bottomToTopSubMenus ? itemH - subOffsetY - subH : subOffsetY; 12310 } 12311 if (this.opts.keepInViewport && !this.isCollapsible()) { 12312 if (this.isFixed()) { 12313 itemX -= winX; 12314 itemY -= winY; 12315 winX = winY = 0; 12316 } 12317 var absX = itemX + x, 12318 absY = itemY + y; 12319 if (this.opts.rightToLeftSubMenus && absX < winX) { 12320 x = horizontalParent ? winX - absX + x : itemW - subOffsetX; 12321 } else if (!this.opts.rightToLeftSubMenus && absX + subW > winX + containerOffsetX ) { 12322 x = horizontalParent ? winX + containerOffsetX - subW - absX + x : subOffsetX - subW; 12323 } 12324 if (!horizontalParent) { 12325 if (subH < winH && absY + subH > winY + winH) { 12326 y += winY + winH - subH - absY; 12327 } else if (subH >= winH || absY < winY) { 12328 y += winY - absY; 12329 } 12330 } 12331 // do we need scrolling? 12332 // 0.49 added for the sake of IE9/FF4+ where we might be dealing with float numbers for "subH" 12333 if (mouse && (horizontalParent && (absY + subH > winY + winH + 0.49 || absY < winY) || !horizontalParent && subH > winH + 0.49)) { 12334 var self = this; 12335 if (!$sub.dataSM('scroll-arrows')) { 12336 $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]]) 12337 .bind({ 12338 mouseenter: function() { self.menuScroll($sub, $(this).hasClass('scroll-up')); }, 12339 mouseleave: function(e) { 12340 self.menuScrollStop($sub); 12341 self.menuScrollOut($sub, e); 12342 }, 12343 'mousewheel DOMMouseScroll': function(e) { e.preventDefault(); } 12344 }) 12345 .insertAfter($sub) 12346 ); 12347 } 12348 // bind events to show/hide arrows on hover and save scrolling data for this sub 12349 var vportY = winY - (itemY + itemH); 12350 $sub.dataSM('scroll', { 12351 vportY: vportY, 12352 subH: subH, 12353 winH: winH, 12354 step: 1 12355 }) 12356 .bind({ 12357 'mouseover.smartmenus_scroll': function(e) { self.menuScrollOver($sub, e); }, 12358 'mouseout.smartmenus_scroll': function(e) { self.menuScrollOut($sub, e); }, 12359 'mousewheel.smartmenus_scroll DOMMouseScroll.smartmenus_scroll': function(e) { self.menuScrollMousewheel($sub, e); } 12360 }) 12361 .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
12361StartZIndex() + this.zIndexInc }) 12362 .eq(0).css('margin-top', vportY).end() 12363 .eq(1).css('margin-top', vportY + winH - this.getHeight($sub.dataSM('scroll-arrows').eq(1))).end() 12364 .eq(horizontalParent && this.opts.bottomToTopSubMenus ? 0 : 1).show(); 12365 } 12366 } 12367 if ( !$sub.closest('.menu-accordion').length ) { 12368 var rightPos = 'auto'; 12369 if ( $sub.parents('.isotope-filters').length ) { 12370 if ( $sub.parents('.text-right').eq(0).length ) { 12371 leftPos = '0px'; 12372 rightPos = 'auto'; 12373 } else { 12374 leftPos = 'auto'; 12375 rightPos = '0px'; 12376 } 12377 x = 0; 12378 } else { 12379 if ( $sub.hasClass('mega-menu-inner') ) { 12380 $sub.css({ width: containerW}); 12381 leftPos = -1 * (parseFloat($sub.closest('ul.menu-smart').offset().left) - parseFloat($sub.closest('.row-menu').offset().left)); 12382 if ( ! $('body').hasClass('megamenu-side-to-side') ) { 12383 leftPos += parseFloat($sub.closest('.row-menu-inner').css('paddingLeft')); 12384 } 12385 x = 0; 12386 } else { 12387 leftPos = (level > 2 ? $li.position().left - parseFloat($li.closest('ul').css('paddingLeft')) : $li.position().left ) + 'px'; 12388 x = (level > 2 && x >= 0) ? x + 1 : x - 1; 12389 } 12390 } 12391 } 12392 12393 // $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) }); 12394 $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) }); 12395 // IE iframe shim 12396 this.menuIframeShim($sub); 12397 if ($sub.dataSM('ie-shim')) { 12398 $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) }); 12399 } 12400 }, 12401 menuScroll: function($sub, up, wheel) { 12402 var y = parseFloat($sub.css('margin-top')), 12403 scroll = $sub.dataSM('scroll'), 12404 end = scroll.vportY + (up ? 0 : scroll.winH - scroll.subH), 12405 step = wheel || !this.opts.scrollAccelerate ? this.opts.scrollStep : Math.floor($sub.dataSM('scroll').step); 12406 $sub.add($sub.dataSM('ie-shim')).css('margin-top', Math.abs(end - y) > step ? y + (up ? step : -step) : end); 12407 y = parseFloat($sub.css('margin-top')); 12408 // show opposite arrow if appropriate 12409 if (up && y + scroll.subH > scroll.vportY + scroll.winH || !up && y < scroll.vportY) { 12410 $sub.dataSM('scroll-arrows').eq(up ? 1 : 0).show(); 12411 } 12412 // accelerate when not using mousewheel to scroll 12413 if (!wheel && this.opts.scrollAccelerate && $sub.dataSM('scroll').step < this.opts.scrollStep) { 12414 $sub.dataSM('scroll').step += 0.5; 12415 } 12416 // "y" and "end" might be float numbers in IE9/FF4+ so this weird way to check is used 12417 if (Math.abs(y - end) < 1) { 12418 $sub.dataSM('scroll-arrows').eq(up ? 0 : 1).hide(); 12419 $sub.dataSM('scroll').step = 1; 12420 } else if (!wheel) { 12421 var self = this; 12422 this.scrollTimeout = setTimeout(function() { self.menuScroll($sub, up); }, this.opts.scrollInterval); 12423 } 12424 }, 12425 menuScrollMousewheel: function($sub, e) { 12426 var $closestSub = $(e.target).closest('ul'); 12427 while ($closestSub.dataSM('in-mega')) { 12428 $closestSub = $closestSub.parent().closest('ul'); 12429 } 12430 if ($closestSub[0] == $sub[0]) { 12431 var up = (e.originalEvent.wheelDelta || -e.originalEvent.detail) > 0; 12432 if ($sub.dataSM('scroll-arrows').eq(up ? 0 : 1).is(':visible')) { 12433 this.menuScroll($sub, up, true); 12434 } 12435 } 12436 e.preventDefault(); 12437 }, 12438 menuScrollOut: function($sub, e) { 12439 var reClass = /^scroll-(up|down)/, 12440 $closestSub = $(e.relatedTarget).closest('ul'); 12441 while ($closestSub.dataSM('in-mega')) { 12442 $closestSub = $closestSub.parent().closest('ul'); 12443 } 12444 if (!reClass.test((e.relatedTarget || '').className) && ($sub[0] != e.relatedTarget && !$.contains($sub[0], e.relatedTarget) || $closestSub[0] != $sub[0])) { 12445 $sub.dataSM('scroll-arrows').css('visibility', 'hidden'); 12446 } 12447 }, 12448 menuScrollOver: function($sub, e) { 12449 var reClass = /^scroll-(up|down)/, 12450 $closestSub = $(e.target).closest('ul'); 12451 while ($closestSub.dataSM('in-mega')) { 12452 $closestSub = $closestSub.parent().closest('ul'); 12453 } 12454 if (!reClass.test(e.target.className) && $closestSub[0] == $sub[0]) { 12455 $sub.dataSM('scroll-arrows').css('visibility', 'visible'); 12456 } 12457 }, 12458 menuScrollStop: function($sub) { 12459 if (this.scrollTimeout) { 12460 clearTimeout(this.scrollTimeout); 12461 this.scrollTimeout = 0; 12462 $sub.dataSM('scroll').step = 1; 12463 } 12464 }, 12465 menuShow: function($sub) { 12466 if (!$sub.dataSM('beforefirstshowfired')) { 12467 $sub.dataSM('beforefirstshowfired', true); 12468 if (this.$root.triggerHandler('beforefirstshow.smapi', $sub[0]) === false) { 12469 return; 12470 } 12471 } 12472 if (this.$root.triggerHandler('beforeshow.smapi', $sub[0]) === false) { 12473 return; 12474 } 12475 this.menuFixLayout($sub); 12476 $sub.stop(true, true); 12477 if (!$sub.is(':visible')) { 12478 $sub.css({ 12479 'visibility': 'visible', 12480 'pointer-events': 'auto', 12481 }); 12482 // set z-index - for IE < 9 set it to the parent LI
12483 var zIndex = this.getStartZIndex() + (++this.zIndexInc); 12484 if (IElt9) { 12485 $sub.parent().css('z-index', zIndex); 12486 } else { 12487 $sub.css('z-index', zIndex); 12488 } 12489 // highlight parent item 12490 if (this.opts.keepHighlighted || this.isCollapsible()) { 12491 if ($sub.dataSM('parent-a').attr('data-type') != 'title') 12492 $sub.dataSM('parent-a').addClass('highlighted'); 12493 } 12494 // min/max-width fix - no way to rely purely on CSS as all UL's are nested 12495 if (this.opts.subMenusMinWidth || this.opts.subMenusMaxWidth) { 12496 if (!IElt8) { 12497 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 12498 if (this.opts.subMenusMinWidth) { 12499 $sub.css('min-width', this.opts.subMenusMinWidth); 12500 } 12501 if (this.opts.subMenusMaxWidth) { 12502 var noMaxWidth = this.getWidth($sub); 12503 if ( ! $sub.hasClass('mega-menu-inner') ) { 12504 $sub.css('max-width', this.opts.subMenusMaxWidth); 12505 } 12506 if (noMaxWidth > this.getWidth($sub)) { 12507 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 12508 } 12509 } 12510 // IE6,7 12511 } else { 12512 $sub.children().css('styleFloat', 'none'); 12513 if (IE6) { 12514 $sub.width(this.opts.subMenusMinWidth ? this.opts.subMenusMinWidth : 1) 12515 .children().children('a').css('white-space', 'nowrap'); 12516 } else { // IE7 12517 $sub.css({ width: ($sub.hasClass('mega-menu-inner')) ? $('.box-container').outerWidth() + 'px' : 'auto', minWidth: '', maxWidth: '' }).addClass('sm-nowrap'); 12518 if (this.opts.subMenusMinWidth) { 12519 $sub.css('min-width', this.opts.subMenusMinWidth); 12520 } 12521 } 12522 if (this.opts.subMenusMaxWidth) { 12523 var noMaxWidth = $sub.width(); 12524 if (IE6) { 12525 var maxWidth = $sub.css({ width: this.opts.subMenusMaxWidth, overflowX: 'hidden', overflowY: 'hidden' }).width(); 12526 if (noMaxWidth > maxWidth) { 12527 $sub.css({ width: maxWidth, overflowX: 'visible', overflowY: 'visible' }).children().children('a').css('white-space', ''); 12528 } else { 12529 $sub.css({ width: noMaxWidth, overflowX: 'visible', overflowY: 'visible' }); 12530 } 12531 } else { // IE7 12532 if ( ! $sub.hasClass('mega-menu-inner') ) { 12533 $sub.css('max-width', this.opts.subMenusMaxWidth); 12534 } 12535 if (noMaxWidth > $sub.width()) { 12536 $sub.removeClass('sm-nowrap').css('width', this.opts.subMenusMaxWidth); 12537 } else { 12538 $sub.width(noMaxWidth); 12539 } 12540 } 12541 } else { 12542 $sub.width($sub.width()); 12543 } 12544 $sub.children().css('styleFloat', 'left'); 12545 } 12546 } 12547 this.menuPosition($sub); 12548 // insert IE iframe shim 12549 if ($sub.dataSM('ie-shim')) { 12550 $sub.dataSM('ie-shim').insertBefore($sub); 12551 } 12552 var complete = function() { 12553 // fix: "overflow: hidden;" is not reset on animation complete in jQuery < 1.9.0 in Chrome when global "box-sizing: border-box;" is used 12554 $sub.css('overflow', ''); 12555 }; 12556 // if sub is collapsible (mobile view) 12557 if (this.isCollapsible()) { 12558 if (this.opts.collapsibleShowFunction) { 12559 this.opts.collapsibleShowFunction.call(this, $sub, complete); 12560 } else { 12561 $sub.show(this.opts.collapsibleShowDuration, complete); 12562 } 12563 } else { 12564 if (this.opts.showFunction) { 12565 this.opts.showFunction.call(this, $sub, complete); 12566 } else { 12567 $sub.show(this.opts.showDuration, complete); 12568 } 12569 } 12570 // save new sub menu for this level 12571 this.visibleSubMenus[$sub.dataSM('level') - 1] = $sub; 12572 this.$root.triggerHandler('show.smapi', $sub[0]); 12573 } 12574 }, 12575 popupHide: function(noHideTimeout) { 12576 if (this.hideTimeout) { 12577 clearTimeout(this.hideTimeout); 12578 this.hideTimeout = 0; 12579 } 12580 var self = this; 12581 this.hideTimeout = setTimeout(function() { 12582 self.menuHideAll(); 12583 }, noHideTimeout ? 1 : this.opts.hideTimeout); 12584 }, 12585 popupShow: function(left, top) { 12586 if (!this.opts.isPopup) { 12587 alert('SmartMenus jQuery Error:\n\nIf you want to show this menu via the "popupShow" method, set the isPopup:true option.'); 12588 return; 12589 } 12590 if (this.hideTimeout) { 12591 clearTimeout(this.hideTimeout); 12592 this.hideTimeout = 0; 12593 } 12594 this.menuFixLayout(this.$root); 12595 this.$root.stop(true, true); 12596 if (!this.$root.is(':visible')) { 12597 this.$root.css({ left: left, top: top }); 12598 // IE iframe shim 12599 this.menuIframeShim(this.$root); 12600 if (this.$root.dataSM('ie-shim')) { 12601 this.$root.dataSM('ie-shim').css({ zIndex: this.$root.css('z-index'), width: this.getWidth(this.$root), height: this.getHeight(this.$root), left
12601: left, top: top }).insertBefore(this.$root); 12602 } 12603 // show menu 12604 if (this.opts.showFunction) { 12605 this.opts.showFunction.call(this, this.$root); 12606 } else { 12607 this.$root.show(this.opts.showDuration); 12608 } 12609 this.visibleSubMenus[0] = this.$root; 12610 } 12611 }, 12612 refresh: function() { 12613 this.menuHideAll(); 12614 this.$root.find('ul').each(function() { 12615 var $this = $(this); 12616 if ($this.dataSM('scroll-arrows')) { 12617 $this.dataSM('scroll-arrows').remove(); 12618 } 12619 }) 12620 .removeDataSM('in-mega') 12621 .removeDataSM('shown-before') 12622 .removeDataSM('ie-shim') 12623 .removeDataSM('scroll-arrows') 12624 .removeDataSM('parent-a') 12625 .removeDataSM('level') 12626 .removeDataSM('beforefirstshowfired'); 12627 this.$root.find('a.has-submenu').removeClass('has-submenu') 12628 .parent().removeDataSM('sub'); 12629 if (this.opts.subIndicators) { 12630 this.$root.find('span.sub-arrow').remove(); 12631 } 12632 if (this.opts.markCurrentItem) { 12633 this.$root.find('a.current').removeClass('current'); 12634 } 12635 this.subMenus = []; 12636 this.init(true); 12637 }, 12638 rootOut: function(e) { 12639 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 12640 return; 12641 } 12642 if (this.hideTimeout) { 12643 clearTimeout(this.hideTimeout); 12644 this.hideTimeout = 0; 12645 } 12646 if (!this.opts.showOnClick || !this.opts.hideOnClick) { 12647 var self = this; 12648 this.hideTimeout = setTimeout(function() { self.menuHideAll(); }, this.opts.hideTimeout); 12649 } 12650 }, 12651 rootOver: function(e) { 12652 if (!this.handleEvents() || this.isTouchMode() || e.target == this.$root[0]) { 12653 return; 12654 } 12655 if (this.hideTimeout) { 12656 clearTimeout(this.hideTimeout); 12657 this.hideTimeout = 0; 12658 } 12659 }, 12660 winResize: function(e) { 12661 if (!this.handleEvents()) { 12662 // we still need to resize the disable overlay if it's visible 12663 if (this.$disableOverlay) { 12664 var pos = this.$root.offset(); 12665 this.$disableOverlay.css({ 12666 top: pos.top, 12667 left: pos.left, 12668 width: this.$root.outerWidth(), 12669 height: this.$root.outerHeight() 12670 }); 12671 } 12672 return; 12673 } 12674 // hide sub menus on resize - on mobile do it only on orientation change 12675 if (!this.isCollapsible() && (!('onorientationchange' in window) || e.type == 'orientationchange')) { 12676 if (this.activatedItems.length) { 12677 this.activatedItems[this.activatedItems.length - 1][0].blur(); 12678 } 12679 this.menuHideAll(); 12680 } 12681 } 12682 } 12683 }); 12684 12685 $.fn.dataSM = function(key, val) { 12686 if (val) { 12687 return this.data(key + '_smartmenus', val); 12688 } 12689 return this.data(key + '_smartmenus'); 12690 } 12691 12692 $.fn.removeDataSM = function(key) { 12693 return this.removeData(key + '_smartmenus'); 12694 } 12695 12696 $.fn.smartmenus = function(options) { 12697 if (typeof options == 'string') { 12698 var args = arguments, 12699 method = options; 12700 Array.prototype.shift.call(args); 12701 return this.each(function() { 12702 var smartmenus = $(this).data('smartmenus'); 12703 if (smartmenus && smartmenus[method]) { 12704 smartmenus[method].apply(smartmenus, args); 12705 } 12706 }); 12707 } 12708 var opts = $.extend({}, $.fn.smartmenus.defaults, options); 12709 return this.each(function() { 12710 new $.SmartMenus(this, opts); 12711 }); 12712 } 12713 12714 // default settings 12715 $.fn.smartmenus.defaults = { 12716 isPopup: false, // is this a popup menu (can be shown via the popupShow/popupHide methods) or a permanent menu bar 12717 mainMenuSubOffsetX: 0, // pixels offset from default position
12718 mainMenuSubOffsetY: 0, // pixels offset from default position 12719 subMenusSubOffsetX: 0, // pixels offset from default position 12720 subMenusSubOffsetY: 0, // pixels offset from default position 12721 subMenusMinWidth: false, //'10em', // min-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 12722 subMenusMaxWidth: false, //'20em', // max-width for the sub menus (any CSS unit) - if set, the fixed width set in CSS will be ignored 12723 subIndicators: true, // create sub menu indicators - creates a SPAN and inserts it in the A 12724 subIndicatorsPos: 'prepend', // position of the SPAN relative to the menu item content ('prepend', 'append') 12725 subIndicatorsText: '+', // [optionally] add text in the SPAN (e.g. '+') (you may want to check the CSS for the sub indicators too) 12726 scrollStep: 30, // pixels step when scrolling long sub menus that do not fit in the viewport height 12727 scrollInterval: 30, // interval between each scrolling step 12728 scrollAccelerate: true, // accelerate scrolling or use a fixed step 12729 showTimeout: 250, // timeout before showing the sub menus 12730 hideTimeout: 500, // timeout before hiding the sub menus 12731 showDuration: 0, // duration for show animation - set to 0 for no animation - matters only if showFunction:null 12732 showFunction: null, // custom function to use when showing a sub menu (the default is the jQuery 'show') 12733 // don't forget to call complete() at the end of whatever you do 12734 // e.g.: function($ul, complete) { $ul.fadeIn(250, complete); } 12735 hideDuration: 0, // duration for hide animation - set to 0 for no animation - matters only if hideFunction:null 12736 hideFunction: function($ul, complete) { $ul.fadeOut(200, complete); }, // custom function to use when hiding a sub menu (the default is the jQuery 'hide') 12737 // don't forget to call complete() at the end of whatever you do 12738 // e.g.: function($ul, complete) { $ul.fadeOut(250, complete); } 12739 collapsibleShowDuration:0, // duration for show animation for collapsible sub menus - matters only if collapsibleShowFunction:null 12740 collapsibleShowFunction:function($ul, complete) { $ul.slideDown(200, complete); }, // custom function to use when showing a collapsible sub menu 12741 // (i.e. when mobile styles are used to make the sub menus collapsible) 12742 collapsibleHideDuration:0, // duration for hide animation for collapsible sub menus - matters only if collapsibleHideFunction:null 12743 collapsibleHideFunction:function($ul, complete) { $ul.slideUp(200, complete); }, // custom function to use when hiding a collapsible sub menu 12744 // (i.e. when mobile styles are used to make the sub menus collapsible) 12745 showOnClick: false, // show the first-level sub menus onclick instead of onmouseover (matters only for mouse input) 12746 hideOnClick: true, // hide the sub menus on click/tap anywhere on the page 12747 keepInViewport: true, // reposition the sub menus if needed to make sure they always appear inside the viewport 12748 keepHighlighted: true, // keep all ancestor items of the current sub menu highlighted (adds the 'highlighted' class to the A's) 12749 markCurrentItem: false, // automatically add the 'current' class to the A element of the item linking to the current URL 12750 markCurrentTree: true, // add the 'current' class also to the A elements of all ancestor items of the current item 12751 rightToLeftSubMenus: false, // right to left display of the sub menus (check the CSS for the sub indicators' position) 12752 bottomToTopSubMenus: false, // bottom to top display of the sub menus 12753 overlapControlsInIE: true // make sure sub menus appear on top of special OS controls in IE (i.e. SELECT, OBJECT, EMBED, etc.) 12754 }; 12755 12756})(jQuery); 12757 12758/* 12759 * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ 12760 * Open source under the BSD License. 12761 * Copyright © 2008 George McGinley Smith 12762 * All rights reserved. 12763 * https://raw.github.com/gdsmith/jquery.easing/master/LICENSE 12764*/ 12765 12766/* globals jQuery, define, module, require */ 12767(function (factory) { 12768 if (typeof define === "function" && define.amd) { 12769 define(['jquery'], function ($) { 12770 return factory($); 12771 }); 12772 } else if (typeof module === "object" && typeof module.exports === "object") { 12773 module.exports = factory(require('jquery')); 12774 } else { 12775 factory(jQuery); 12776 } 12777})(function($){ 12778 12779 // Preserve the original jQuery "swing" easing as "jswing" 12780 if (typeof $.easing !== 'undefined') { 12781 $.easing['jswing'] = $.easing['swing']; 12782 } 12783 12784 var pow = Math.pow, 12785 sqrt = Math.sqrt, 12786 sin = Math.sin, 12787 cos = Math.cos, 12788 PI = Math.PI,
12789 c1 = 1.70158, 12790 c2 = c1 * 1.525, 12791 c3 = c1 + 1, 12792 c4 = ( 2 * PI ) / 3, 12793 c5 = ( 2 * PI ) / 4.5; 12794 12795 // x is the fraction of animation progress, in the range 0..1 12796 function bounceOut(x) { 12797 var n1 = 7.5625, 12798 d1 = 2.75; 12799 if ( x < 1/d1 ) { 12800 return n1*x*x; 12801 } else if ( x < 2/d1 ) { 12802 return n1*(x-=(1.5/d1))*x + .75; 12803 } else if ( x < 2.5/d1 ) { 12804 return n1*(x-=(2.25/d1))*x + .9375; 12805 } else { 12806 return n1*(x-=(2.625/d1))*x + .984375; 12807 } 12808 } 12809 12810 $.extend( $.easing, { 12811 def: 'easeOutQuad', 12812 swing: function (x) { 12813 return $.easing[$.easing.def](x); 12814 }, 12815 easeInQuad: function (x) { 12816 return x * x; 12817 }, 12818 easeOutQuad: function (x) { 12819 return 1 - ( 1 - x ) * ( 1 - x ); 12820 }, 12821 easeInOutQuad: function (x) { 12822 return x < 0.5 ? 12823 2 * x * x : 12824 1 - pow( -2 * x + 2, 2 ) / 2; 12825 }, 12826 easeInCubic: function (x) { 12827 return x * x * x; 12828 }, 12829 easeOutCubic: function (x) { 12830 return 1 - pow( 1 - x, 3 ); 12831 }, 12832 easeInOutCubic: function (x) { 12833 return x < 0.5 ? 12834 4 * x * x * x : 12835 1 - pow( -2 * x + 2, 3 ) / 2; 12836 }, 12837 easeInQuart: function (x) { 12838 return x * x * x * x; 12839 }, 12840 easeOutQuart: function (x) { 12841 return 1 - pow( 1 - x, 4 ); 12842 }, 12843 easeInOutQuart: function (x) { 12844 return x < 0.5 ? 12845 8 * x * x * x * x : 12846 1 - pow( -2 * x + 2, 4 ) / 2; 12847 }, 12848 easeInQuint: function (x) { 12849 return x * x * x * x * x; 12850 }, 12851 easeOutQuint: function (x) { 12852 return 1 - pow( 1 - x, 5 ); 12853 }, 12854 easeInOutQuint: function (x) { 12855 return x < 0.5 ? 12856 16 * x * x * x * x * x : 12857 1 - pow( -2 * x + 2, 5 ) / 2; 12858 }, 12859 easeInSine: function (x) { 12860 return 1 - cos( x * PI/2 ); 12861 }, 12862 easeOutSine: function (x) { 12863 return sin( x * PI/2 ); 12864 }, 12865 easeInOutSine: function (x) { 12866 return -( cos( PI * x ) - 1 ) / 2; 12867 }, 12868 easeInExpo: function (x) { 12869 return x === 0 ? 0 : pow( 2, 10 * x - 10 ); 12870 }, 12871 easeOutExpo: function (x) { 12872 return x === 1 ? 1 : 1 - pow( 2, -10 * x ); 12873 }, 12874 easeInOutExpo: function (x) { 12875 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 12876 pow( 2, 20 * x - 10 ) / 2 : 12877 ( 2 - pow( 2, -20 * x + 10 ) ) / 2; 12878 }, 12879 easeInCirc: function (x) { 12880 return 1 - sqrt( 1 - pow( x, 2 ) ); 12881 }, 12882 easeOutCirc: function (x) { 12883 return sqrt( 1 - pow( x - 1, 2 ) ); 12884 }, 12885 easeInOutCirc: function (x) { 12886 return x < 0.5 ? 12887 ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : 12888 ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; 12889 }, 12890 easeInElastic: function (x) { 12891 return x === 0 ? 0 : x === 1 ? 1 : 12892 -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); 12893 }, 12894 easeOutElastic: function (x) { 12895 return x === 0 ? 0 : x === 1 ? 1 : 12896 pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; 12897 }, 12898 easeInOutElastic: function (x) { 12899 return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 12900 -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : 12901 pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; 12902 }, 12903 easeInBack: function (x) { 12904 return c3 * x * x * x - c1 * x * x; 12905 }, 12906 easeOutBack: function (x) { 12907 return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); 12908 }, 12909 easeInOutBack: function (x) { 12910 return x < 0.5 ? 12911 ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : 12912 ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; 12913 }, 12914 easeInBounce: function (x) { 12915 return 1 - bounceOut( 1 - x ); 12916 }, 12917 easeOutBounce: bounceOut, 12918 easeInOutBounce: function (x) { 12919 return x < 0.5 ? 12920 ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : 12921 ( 1 + bounceOut( 2 * x - 1 ) ) / 2; 12922 } 12923 }); 12924 return $; 12925}); 12926 12927/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) 12928 * Licensed under the MIT License (LICENSE.txt). 12929 * 12930 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 12931 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 12932 * Thanks to: Seamus Leahy for adding deltaX and deltaY 12933 * 12934 * Version: 3.0.6 12935 * 12936 * Requires: 1.2.2+ 12937 */ 12938(function($) { 12939 var types = ['DOMMouseScroll', 'mousewheel']; 12940 if ($.event.fixHooks) { 12941 for (var i = types.length; i;) { 12942 $.event.fixHooks[types[--i]] = $.event.mouseHooks; 12943 } 12944 } 12945 $.event.special.mousewheel = { 12946 setup: function() { 12947 if (this.addEventListener) { 12948 for (var i = types.length; i;) { 12949 this.addEventListener(types[--i], handler, false); 12950 } 12951 } else { 12952 this.onmousewheel = handler; 12953 } 12954 }, 12955 teardown: function() { 12956 if (this.removeEventListener) { 12957 for (var i = types.length; i;) { 12958 this.removeEventListener(types[--i], handler, false); 12959 } 12960 } else { 12961 this.onmousewheel = null; 12962 } 12963 } 12964 }; 12965 $.fn.extend({ 12966 mousewheel: function(fn) { 12967 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 12968 }, 12969 unmousewheel: function(fn) { 12970 return this.unbind("mousewheel", fn); 12971 } 12972 }); 12973 12974 function handler(event) { 12975 var orgEvent = event || window.event, 12976 args = [].slice.call(arguments, 1), 12977 delta = 0, 12978 returnValue = true, 12979 deltaX = 0, 12980 deltaY = 0; 12981 event = $.event.fix(orgEvent); 12982 event.type = "mousewheel"; 12983 // Old school scrollwheel delta 12984 if (orgEvent.wheelDelta) { 12985 delta = orgEvent.wheelDelta / 120; 12986 } 12987 if (orgEvent.detail) { 12988 delta = -orgEvent.detail / 3; 12989 } 12990 // New school multidimensional scroll (touchpads) deltas 12991 deltaY = delta; 12992 // Gecko 12993 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 12994 deltaY = 0; 12995 deltaX = -1 * delta; 12996 } 12997 // Webkit 12998 if (orgEvent.wheelDeltaY !== undefined) { 12999 deltaY = orgEvent.wheelDeltaY / 120; 13000 } 13001 if (orgEvent.wheelDeltaX !== undefined) { 13002 deltaX = -1 * orgEvent.wheelDeltaX / 120; 13003 } 13004 // Add event and delta to the front of the arguments 13005 args.unshift(event, delta, deltaX, deltaY); 13006 return ($.event.dispatch || $.event.handle).apply(this, args); 13007 } 13008})(jQuery); 13009/** 13010 * jQuery iLightBox - Revolutionary Lightbox Plugin 13011 * http://www.ilightbox.net/ 13012 * 13013 * @version: 2.2.4 - October 14, 2017 13014 * 13015 * @author: iProDev (Hemn Chawroka) 13016 * http://www.iprodev.com/ 13017 * 13018 */ 13019(function($, window, undefined) { 13020 13021 var extensions = { 13022 flash: ['swf'], 13023 image: ['bmp', 'gif', 'jpeg', 'jpg', 'png', 'tiff', 'tif', 'jfif', 'jpe', 'webp'], 13024 iframe: ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'jsp', 'php', 'pl', 'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml', 'txt'], 13025 video: ['avi', 'mov', 'mpg', 'mpeg', 'movie', 'mp4', 'webm', 'ogv', 'ogg', '3gp', 'm4v'] 13026 }, 13027 13028 // Global DOM elements 13029 $win = $(window), 13030 $doc = $(document), 13031
13032 // Support indicators 13033 browser, 13034 transform, 13035 gpuAcceleration, 13036 fullScreenApi = '', 13037 userAgent = navigator.userAgent || navigator.vendor || window.opera, 13038 supportTouch = "ontouchstart" in window || navigator.msMaxTouchPoints || (navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1), 13039 ishybrid = navigator.maxTouchPoints && navigator.userAgent.indexOf('Windows') > -1, 13040 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)), 13041 13042 // Events 13043 clickEvent = ishybrid ? "itap.iLightBox click.iLightBox" : supportTouch ? "itap.iLightBox" : "click.iLightBox", 13044 touchStartEvent = ishybrid ? "touchstart.iLightBox mousedown.iLightBox" : supportTouch ? "touchstart.iLightBox" : "mousedown.iLightBox", 13045 touchStopEvent = ishybrid ? "touchend.iLightBox mouseup.iLightBox" : supportTouch ? "touchend.iLightBox" : "mouseup.iLightBox", 13046 touchMoveEvent = ishybrid ? "touchmove.iLightBox mousemove.iLightBox" : supportTouch ? "touchmove.iLightBox" : "mousemove.iLightBox", 13047 13048 // Math shorthands 13049 abs = Math.abs, 13050 sqrt = Math.sqrt, 13051 round = Math.round, 13052 max = Math.max, 13053 min = Math.min, 13054 floor = Math.floor, 13055 random = Math.random, 13056 13057 pluginspages = { 13058 quicktime: 'http://www.apple.com/quicktime/download', 13059 flash: 'http://www.adobe.com/go/getflash' 13060 }, 13061 13062 iLightBox = function(el, options, items, instant) { 13063 var iL = this; 13064 13065 iL.options = options, 13066 iL.selector = options.selector || el, 13067 iL.context = document, 13068 iL.instant = instant; 13069 13070 if (items.length < 1) iL.attachItems(); 13071 else iL.items = items; 13072 13073 iL.vars = { 13074 total: iL.items.length, 13075 start: 0, 13076 current: null, 13077 next: null, 13078 prev: null, 13079 BODY: $('body'), 13080 loadRequests: 0, 13081 overlay: $('<div class="ilightbox-overlay"></div>'), 13082 loader: $('<div class="ilightbox-loader"><div></div></div>'), 13083 toolbar: $('<div class="ilightbox-toolbar"></div>'), 13084 innerToolbar: $('<div class="ilightbox-inner-toolbar"></div>'), 13085 title: $('<div class="ilightbox-title"></div>'), 13086 closeButton: $('<a class="ilightbox-close" title="' + iL.options.text.close + '"></a>'), 13087 fullScreenButton: $('<a class="ilightbox-fullscreen" title="' + iL.options.text.enterFullscreen + '"></a>'), 13088 innerPlayButton: $('<a class="ilightbox-play" title="' + iL.options.text.slideShow + '"></a>'), 13089 innerNextButton: $('<a class="ilightbox-next-button" title="' + iL.options.text.next + '"></a>'), 13090 innerPrevButton: $('<a class="ilightbox-prev-button" title="' + iL.options.text.previous + '"></a>'), 13091 holder: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + '" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 13092 nextPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-next" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 13093 prevPhoto: $('<div class="ilightbox-holder' + (supportTouch ? ' supportTouch' : '') + ' ilightbox-prev" ondragstart="return false;"><div class="ilightbox-container"></div></div>'), 13094 nextButton: $('<a class="ilightbox-button ilightbox-next-button" ondragstart="return false;" title="' + iL.options.text.next + '"><span></span></a>'), 13095 prevButton: $('<a class="ilightbox-button ilightbox-prev-button" ondragstart="return false;" title="' + iL.options.text.previous + '"><span></span></a>'),
13096 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>'), 13097 thumbs: false, 13098 nextLock: false, 13099 prevLock: false, 13100 hashLock: false, 13101 isMobile: false, 13102 mobileMaxWidth: 980, 13103 isInFullScreen: false, 13104 isSwipe: false, 13105 mouseID: 0, 13106 cycleID: 0, 13107 isPaused: 0, 13108 captionHeight: 39, 13109 }; 13110 13111 // Hideable elements with mousemove event 13112 iL.vars.hideableElements = iL.vars.nextButton.add(iL.vars.prevButton); 13113 13114 iL.normalizeItems(); 13115 13116 //Check necessary plugins 13117 iL.availPlugins(); 13118 13119 //Set startFrom 13120 iL.options.startFrom = (iL.options.startFrom > 0 && iL.options.startFrom >= iL.vars.total) ? iL.vars.total - 1 : iL.options.startFrom; 13121 13122 //If randomStart 13123 iL.options.startFrom = (iL.options.randomStart) ? floor(random() * iL.vars.total) : iL.options.startFrom; 13124 iL.vars.start = iL.options.startFrom; 13125 13126 if (instant) iL.instantCall(); 13127 else iL.patchItemsEvents(); 13128 13129 if (iL.options.linkId) { 13130 iL.hashChangeHandler(); 13131 $win.iLightBoxHashChange(function() { 13132 iL.hashChangeHandler(); 13133 }); 13134 } 13135 13136 if (supportTouch) { 13137 var RegExp = /(click|mouseenter|mouseleave|mouseover|mouseout)/ig, 13138 replace = "itap"; 13139 iL.options.caption.show = iL.options.caption.show.replace(RegExp, replace), 13140 iL.options.caption.hide = iL.options.caption.hide.replace(RegExp, replace), 13141 iL.options.social.show = iL.options.social.show.replace(RegExp, replace), 13142 iL.options.social.hide = iL.options.social.hide.replace(RegExp, replace); 13143 } 13144 13145 if (iL.options.controls.arrows || $(window).width() < UNCODE.mediaQuery) { 13146 $.extend(iL.options.styles, { 13147 nextOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 13148 prevOffsetX: ($(window).width() > UNCODE.mediaQuery) ? 36 : 4, 13149 nextOpacity: 0, 13150 prevOpacity: 0 13151 }); 13152 } 13153 }; 13154 13155 //iLightBox helpers 13156 iLightBox.prototype = { 13157 showLoader: function() { 13158 var iL = this; 13159 iL.vars.loadRequests += 1; 13160 if (iL.options.path.toLowerCase() == "horizontal") iL.vars.loader.addClass('ilightbox-show').stop().animate({ 13161 //top: '-30px' 13162 opacity: '1' 13163 }, iL.options.show.speed, 'easeOutCirc'); 13164 else iL.vars.loader.addClass('ilightbox-show').stop().animate({ 13165 //left: '-30px' 13166 opacity: '1' 13167 }, iL.options.show.speed, 'easeOutCirc'); 13168 }, 13169 13170 hideLoader: function() { 13171 var iL = this; 13172 iL.vars.loadRequests -= 1; 13173 iL.vars.loadRequests = (iL.vars.loadRequests < 0) ? 0 : iL.vars.loadRequests; 13174 if (iL.options.path.toLowerCase() == "horizontal") { 13175 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 13176 //top: '-192px' 13177 opacity: '0' 13178 }, iL.options.show.speed, 'easeInCirc'); 13179 } else { 13180 if (iL.vars.loadRequests <= 0) iL.vars.loader.removeClass('ilightbox-show').stop().animate({ 13181 //left: '-192px' 13182 opacity: '0' 13183 }, iL.options.show.speed, 'easeInCirc'); 13184 } 13185 }, 13186 13187 createUI: function() { 13188 var iL = this; 13189 13190 iL.ui = { 13191 currentElement: iL.vars.holder, 13192 nextElement: iL.vars.nextPhoto, 13193 prevElement: iL.vars.prevPhoto, 13194 currentItem: iL.vars.current, 13195 nextItem: iL.vars.next, 13196 prevItem: iL.vars.prev, 13197 hide: function() { 13198 iL.closeAction(); 13199 }, 13200 refresh: function() { 13201 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 13202 }, 13203 fullscreen: function() { 13204 iL.fullScreenAction(); 13205 } 13206 }; 13207 }, 13208 13209 attachItems: function() { 13210 var iL = this, 13211 itemsObject = new Array(), 13212 items = new Array(); 13213 13214 $(iL.selector, iL.context).each(function() { 13215 var t = $(this), 13216 URL = t.attr(iL.options.attr) || null, 13217 options = t.data("options") && eval("({" + t.data("options") + "})") || {}, 13218 caption = t.data('caption'), 13219 title = t.data('title'), 13220 type = t.data('type') || getTypeByExtension(URL), 13221 clone = t.data('lbox-clone') || false; 13222 13223 //Uncode addition ##START## 13224 if (type === false) { 13225 return; 13226 } 13227 //Uncode addition ##END## 13228 13229 if (t.data('lbox-clone') != undefined) return; 13230 13231 //Uncode addition ##START## 13232 if ( typeof t.attr('data-album') != 'undefined' && t.attr('data-album') != '' ) { 13233 var ALBUM_URLS = JSON.parse(t.attr('data-album')), 13234 URL_i, 13235 URLS_LENGHT = ALBUM_URLS.length; 13236 13237 for (URL_i = 0; URL_i < URLS_LENGHT; URL_i++) { 13238 if ( typeof ALBUM_URLS[URL_i].url !== 'undefined' && ALBUM_URLS[URL_i].url != '' ) { 13239 var item_opts = 'width:' + ALBUM_URLS[URL_i].width + ',height:' + ALBUM_URLS[URL_i].height + ',thumbnail: \'' + ALBUM_URLS[URL_i].thumbnail + '\''; 13240 item_opts = item_opts && eval("({" + item_opts + "})") || {}, 13241 items.push({ 13242 URL: ALBUM_URLS[URL_i].url, 13243 caption: ALBUM_URLS[URL_i].caption, 13244 title: ALBUM_URLS[URL_i].title, 13245 type: getTypeByExtension(ALBUM_URLS[URL_i].url), 13246 options: item_opts, 13247 clone: clone 13248 }); 13249 var newT = t; 13250 newT.attr('href',ALBUM_URLS[URL_i].url); 13251 if (!iL.instant) itemsObject.push(newT); 13252 } 13253 } 13254 } else { 13255 //Uncode addition ##END## 13256 items.push({ 13257 URL: URL, 13258 caption: caption, 13259 title: title, 13260 type: type, 13261 options: options, 13262 clone: clone 13263 }); 13264 } 13265 13266 13267 if (iL.vars != undefined) iL.vars.total = items.length; 13268 13269 if (!iL.instant) itemsObject.push(t); 13270 }); 13271 13272 iL.items = items, 13273 iL.itemsObject = itemsObject; 13274 13275 }, 13276 13277 normalizeItems: function() { 13278 var iL = this, 13279 newItems = new Array(); 13280 13281 $.each(iL.items, function(key, val) { 13282 13283 if (typeof val == "string") val = { 13284 url: val 13285 }; 13286 13287 var URL = val.url || val.URL || null, 13288 options = val.options || {}, 13289 caption = val.caption || null, 13290 title = val.title || null, 13291 type = (val.type) ? val.type.toLowerCase() : getTypeByExtension(URL), 13292 ext = (typeof URL != 'object') ? getExtension(URL) : ''; 13293 13294 options.thumbnail = options.thumbnail || ((type == "image") ? URL : null),
13295 options.videoType = options.videoType || null, 13296 options.skin = options.skin || iL.options.skin, 13297 options.width = options.width || null, 13298 options.height = options.height || null, 13299 options.mousewheel = (typeof options.mousewheel != 'undefined') ? options.mousewheel : true, 13300 options.swipe = (typeof options.swipe != 'undefined') ? options.swipe : true, 13301 options.social = (typeof options.social != 'undefined') ? options.social : iL.options.social.buttons && $.extend({}, {}, iL.options.social.buttons); 13302 13303 if (type == "video") { 13304 options.html5video = (typeof options.html5video != 'undefined') ? options.html5video : {}; 13305 13306 options.html5video.webm = options.html5video.webm || options.html5video.WEBM || null; 13307 options.html5video.controls = (typeof options.html5video.controls != 'undefined') ? options.html5video.controls : "controls"; 13308 options.html5video.preload = options.html5video.preload || "metadata"; 13309 options.html5video.autoplay = (typeof options.html5video.autoplay != 'undefined') ? options.html5video.autoplay : false; 13310 //UNCODE addition 13311 options.html5video.loop = (typeof options.html5video.loop != 'undefined') ? options.html5video.loop : false; 13312 } 13313 13314 if (!options.width || !options.height) { 13315 if (type == "video") options.width = 1280, options.height = 720; 13316 else if (type == "iframe") options.width = '100%', options.height = '90%'; 13317 else if (type == "flash") options.width = 1280, options.height = 720; 13318 } 13319 13320 delete val.url; 13321 val.index = key; 13322 val.URL = URL; 13323 val.caption = caption; 13324 val.title = title; 13325 val.type = type; 13326 val.options = options; 13327 val.ext = ext; 13328 13329 newItems.push(val); 13330 }); 13331 13332 iL.items = newItems; 13333 }, 13334 13335 instantCall: function() { 13336 var iL = this, 13337 key = iL.vars.start; 13338 13339 iL.vars.current = key; 13340 iL.vars.next = (iL.items[key + 1]) ? key + 1 : null; 13341 iL.vars.prev = (iL.items[key - 1]) ? key - 1 : null; 13342 13343 iL.addContents(); 13344 iL.patchEvents(); 13345 }, 13346 13347 addContents: function() { 13348 var iL = this, 13349 vars = iL.vars, 13350 opts = iL.options, 13351 viewport = getViewport(), 13352 path = opts.path.toLowerCase(), 13353 recognizingItems = vars.total > 0 && iL.items.filter(function(e, i, arr) { 13354 return ['image', 'flash', 'video'].indexOf(e.type) === -1 && typeof e.recognized === 'undefined' && (opts.smartRecognition || e.options.smartRecognition); 13355 }), 13356 needRecognition = recognizingItems.length > 0; 13357 13358 if (opts.mobileOptimizer && !opts.innerToolbar) 13359 vars.isMobile = viewport.width <= vars.mobileMaxWidth; 13360 13361 vars.overlay.addClass(opts.skin).hide().css('opacity', opts.overlay.opacity); 13362 13363 if (opts.linkId) 13364 vars.overlay[0].setAttribute('linkid', opts.linkId); 13365 13366 //Add Toolbar Buttons 13367 if (opts.controls.toolbar) { 13368 vars.toolbar.addClass(opts.skin).append(vars.closeButton); 13369 if (opts.controls.fullscreen) 13370 vars.toolbar.append(vars.fullScreenButton); 13371 if (opts.controls.slideshow) 13372 vars.toolbar.append(vars.innerPlayButton); 13373 if (vars.total > 1) 13374 vars.toolbar.append(vars.innerPrevButton).append(vars.innerNextButton); 13375 } 13376 13377 //Append elements to body 13378 vars.BODY.addClass('ilightbox-noscroll').append(vars.overlay).append(vars.loader).append(vars.holder).append(vars.nextPhoto).append(vars.prevPhoto); 13379 13380 if (!opts.innerToolbar) 13381 vars.BODY.append(vars.toolbar); 13382 if (opts.controls.arrows) 13383 vars.BODY.append(vars.nextButton).append(vars.prevButton); 13384 13385 if (opts.controls.thumbnail && vars.total > 1) { 13386 vars.BODY.append(vars.thumbnails); 13387 vars.thumbnails.addClass(opts.skin).addClass('ilightbox-' + path); 13388 $('div.ilightbox-thumbnails-grid', vars.thumbnails).empty(); 13389 vars.thumbs = true; 13390 } 13391 13392 //Configure loader and arrows 13393 var loaderCss = (opts.path.toLowerCase() == "horizontal") ? { 13394 left: parseInt((viewport.width / 2) - (vars.loader.outerWidth() / 2)) 13395 } : { 13396 top: parseInt((viewport.height / 2) - (vars.loader.outerHeight() / 2)) 13397 }; 13398 vars.loader.addClass(opts.skin).css(loaderCss); 13399 vars.nextButton.add(vars.prevButton).addClass(opts.skin); 13400 if (path == "horizontal") 13401 vars.loader.add(vars.nextButton).add(vars.prevButton).addClass('horizontal'); 13402 13403 // Configure arrow buttons 13404 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 13405 13406 if (!opts.infinite) { 13407 vars.prevButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 13408 13409 if (vars.current == 0) 13410 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 13411 if (vars.current >= vars.total - 1) 13412 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 13413 } 13414 13415 if (opts.show.effect) { 13416 vars.overlay.stop().fadeIn(opts.show.speed); 13417 vars.toolbar.stop().fadeIn(opts.show.speed); 13418 } else { 13419 vars.overlay.show(); 13420 vars.toolbar.show(); 13421 } 13422 13423 var length = recognizingItems.length; 13424 if (needRecognition) { 13425 iL.showLoader(); 13426 13427 $.each(recognizingItems, function(key, val) { 13428 var resultFnc = function(result) { 13429 var key = -1, 13430 filter = iL.items.filter(function(e, i, arr) { 13431 if (e.URL == result.url) 13432 key = i; 13433 13434 return e.URL == result.url; 13435 }), 13436 self = iL.items[key]; 13437 13438 if (result) 13439 $.extend(true, self, { 13440 URL: result.source, 13441 type: result.type, 13442 recognized: true, 13443 options: { 13444 html5video: result.html5video, 13445 width: (result.type == "image") ? 0 : (result.width || self.width), 13446 height: (result.type == "image") ? 0 : (result.height || self.height), 13447 thumbnail: self.options.thumbnail || result.thumbnail 13448 } 13449 }); 13450 13451 length--; 13452 13453 if (length == 0) { 13454 iL.hideLoader(); 13455 13456 vars.dontGenerateThumbs = false;
13457 iL.generateThumbnails(); 13458 13459 if (opts.show.effect) 13460 setTimeout(function() { 13461 iL.generateBoxes(); 13462 }, opts.show.speed); 13463 else 13464 iL.generateBoxes(); 13465 } 13466 }; 13467 13468 iL.ogpRecognition(this, resultFnc); 13469 }); 13470 } 13471 else { 13472 if (opts.show.effect) 13473 setTimeout(function() { 13474 iL.generateBoxes(); 13475 }, opts.show.speed); 13476 else 13477 iL.generateBoxes(); 13478 } 13479 13480 iL.createUI(); 13481 13482 window.iLightBox = { 13483 close: function() { 13484 iL.closeAction(); 13485 }, 13486 fullscreen: function() { 13487 iL.fullScreenAction(); 13488 }, 13489 moveNext: function() { 13490 iL.moveTo('next'); 13491 }, 13492 movePrev: function() { 13493 iL.moveTo('prev'); 13494 }, 13495 goTo: function(index) { 13496 iL.goTo(index); 13497 }, 13498 refresh: function() { 13499 iL.refresh(); 13500 }, 13501 reposition: function() { 13502 (arguments.length > 0) ? iL.repositionPhoto(true): iL.repositionPhoto(); 13503 }, 13504 setOption: function(options) { 13505 iL.setOption(options); 13506 }, 13507 destroy: function() { 13508 iL.closeAction(); 13509 iL.dispatchItemsEvents(); 13510 } 13511 }; 13512 13513 if (opts.linkId) { 13514 vars.hashLock = true; 13515 window.location.hash = opts.linkId + '/' + vars.current; 13516 setTimeout(function() { 13517 vars.hashLock = false; 13518 }, 55); 13519 } 13520 13521 if (!opts.slideshow.startPaused) { 13522 iL.resume(); 13523 vars.innerPlayButton.removeClass('ilightbox-play').addClass('ilightbox-pause'); 13524 } 13525 13526 //Trigger the onOpen callback 13527 if (typeof iL.options.callback.onOpen == 'function') iL.options.callback.onOpen.call(iL); 13528 }, 13529 13530 loadContent: function(obj, opt, speed) { 13531 var iL = this, 13532 holder, item; 13533 13534 iL.createUI(); 13535 13536 obj.speed = speed || iL.options.effects.loadedFadeSpeed; 13537 13538 if (opt == 'current') { 13539 if (!obj.options.mousewheel) iL.vars.lockWheel = true; 13540 else iL.vars.lockWheel = false; 13541 13542 if (!obj.options.swipe) iL.vars.lockSwipe = true; 13543 else iL.vars.lockSwipe = false; 13544 } 13545 13546 switch (opt) { 13547 case 'current': 13548 holder = iL.vars.holder, item = iL.vars.current; 13549 break; 13550 case 'next': 13551 holder = iL.vars.nextPhoto, item = iL.vars.next; 13552 break; 13553 case 'prev': 13554 holder = iL.vars.prevPhoto, item = iL.vars.prev; 13555 break; 13556 } 13557 13558 holder.removeAttr('style class').addClass('ilightbox-holder' + (supportTouch ? ' supportTouch' : '')).addClass(obj.options.skin); 13559 $('div.ilightbox-inner-toolbar', holder).remove(); 13560 13561 if (obj.title || iL.options.innerToolbar) { 13562 var innerToolbar = iL.vars.innerToolbar.clone(); 13563 if (obj.title && iL.options.show.title) { 13564 var title = iL.vars.title.clone(); 13565 title.empty().html(obj.title); 13566 innerToolbar.append(title); 13567 } 13568 if (iL.options.innerToolbar) { 13569 innerToolbar.append((iL.vars.total > 1) ? iL.vars.toolbar.clone() : iL.vars.toolbar); 13570 } 13571 holder.prepend(innerToolbar); 13572 } 13573 13574 //console.warn('loadContent', arguments); 13575 13576 iL.loadSwitcher(obj, holder, item, opt); 13577 }, 13578 13579 loadSwitcher: function(obj, holder, item, opt) { 13580 var iL = this, 13581 opts = iL.options, 13582 api = { 13583 element: holder, 13584 position: item 13585 }; 13586 13587 switch (obj.type) { 13588 case 'image': 13589 //Trigger the onBeforeLoad callback 13590 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13591 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13592 13593 iL.loadImage(obj.URL, function(img) { 13594 //Trigger the onAfterLoad callback 13595 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13596 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13597 13598 var width = (img) ? img.width : 400, 13599 height = (img) ? img.height : 200; 13600 13601 holder.data({ 13602 naturalWidth: width, 13603 naturalHeight: height 13604 }); 13605 13606 $('div.ilightbox-container', holder).empty().append((img) ? '<img src="' + obj.URL + '" class="ilightbox-image" />' : '<span class="ilightbox-alert">' + opts.errors.loadImage + '</span>'); 13607 13608 //Trigger the onRender callback 13609 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13610 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13611 13612 iL.configureHolder(obj, opt, holder); 13613 }); 13614 13615 break; 13616
13617 case 'video': 13618 holder.data({ 13619 naturalWidth: obj.options.width, 13620 naturalHeight: obj.options.height 13621 }); 13622 13623 if (opt === 'current') { 13624 iL.addContent(holder, obj); 13625 13626 //Trigger the onRender callback 13627 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13628 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13629 } else { 13630 $('div.ilightbox-container', holder).empty(); 13631 } 13632 13633 iL.configureHolder(obj, opt, holder); 13634 13635 break; 13636 13637 case 'iframe': 13638 //iL.showLoader(); 13639 holder.data({ 13640 naturalWidth: obj.options.width, 13641 naturalHeight: obj.options.height 13642 }); 13643 13644 iL.configureHolder(obj, opt, holder); 13645 13646 if (opt === 'current') { 13647 var el = iL.addContent(holder, obj); 13648 13649 //Trigger the onRender callback 13650 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13651 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13652 13653 //Trigger the onBeforeLoad callback 13654 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13655 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13656 13657 el.bind('load', function() { 13658 //Trigger the onAfterLoad callback 13659 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13660 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13661 13662 //iL.hideLoader(); 13663 el.unbind('load'); 13664 }); 13665 } else { 13666 $('div.ilightbox-container', holder).empty(); 13667 } 13668 13669 break; 13670 13671 case 'inline': 13672 var el = $(obj.URL), 13673 content = iL.addContent(holder, obj), 13674 images = findImageInElement(holder); 13675 13676 holder.data({ 13677 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 13678 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 13679 }); 13680 content.children().eq(0).show(); 13681 13682 //Trigger the onRender callback 13683 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13684 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13685 13686 //Trigger the onBeforeLoad callback 13687 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13688 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13689 13690 iL.loadImage(images, function() { 13691 //Trigger the onAfterLoad callback 13692 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13693 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13694 13695 iL.configureHolder(obj, opt, holder); 13696 }); 13697 13698 break; 13699 13700 case 'flash': 13701 var el = iL.addContent(holder, obj); 13702 13703 holder.data({ 13704 naturalWidth: (iL.items[item].options.width || el.outerWidth()), 13705 naturalHeight: (iL.items[item].options.height || el.outerHeight()) 13706 }); 13707 13708 //Trigger the onRender callback 13709 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13710 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13711 13712 iL.configureHolder(obj, opt, holder); 13713 13714 break; 13715 13716 case 'ajax': 13717 var ajax = obj.options.ajax || {}; 13718 //Trigger the onBeforeLoad callback 13719 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13720 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13721 13722 iL.showLoader(); 13723 $.ajax({ 13724 url: obj.URL || opts.ajaxSetup.url, 13725 data: ajax.data || null, 13726 dataType: ajax.dataType || "html", 13727 type: ajax.type || opts.ajaxSetup.type, 13728 cache: ajax.cache || opts.ajaxSetup.cache, 13729 crossDomain: ajax.crossDomain || opts.ajaxSetup.crossDomain, 13730 global: ajax.global || opts.ajaxSetup.global, 13731 ifModified: ajax.ifModified || opts.ajaxSetup.ifModified, 13732 username: ajax.username || opts.ajaxSetup.username, 13733 password: ajax.password || opts.ajaxSetup.password, 13734 beforeSend: ajax.beforeSend || opts.ajaxSetup.beforeSend, 13735 complete: ajax.complete || opts.ajaxSetup.complete, 13736 success: function(data, textStatus, jqXHR) { 13737 iL.hideLoader(); 13738 13739 var el = $(data), 13740 container = $('div.ilightbox-container', holder), 13741 elWidth = iL.items[item].options.width || parseInt(el[0].getAttribute('width')), 13742 elHeight = iL.items[item].options.height || parseInt(el[0].getAttribute('height')), 13743 css = (el[0].getAttribute('width') && el[0].getAttribute('height')) ? { 13744 'overflow': 'hidden' 13745 } : {}; 13746 13747 container.empty().append($('<div class="ilightbox-wrapper"></div>').css(css).html(el)); 13748 holder.show().data({
13749 naturalWidth: (elWidth || container.outerWidth()), 13750 naturalHeight: (elHeight || container.outerHeight()) 13751 }).hide(); 13752 13753 //Trigger the onRender callback 13754 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13755 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13756 13757 var images = findImageInElement(holder); 13758 iL.loadImage(images, function() { 13759 //Trigger the onAfterLoad callback 13760 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13761 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13762 13763 iL.configureHolder(obj, opt, holder); 13764 }); 13765 13766 opts.ajaxSetup.success(data, textStatus, jqXHR); 13767 if (typeof ajax.success == 'function') ajax.success(data, textStatus, jqXHR); 13768 }, 13769 error: function(jqXHR, textStatus, errorThrown) { 13770 //Trigger the onAfterLoad callback 13771 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13772 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13773 13774 iL.hideLoader(); 13775 $('div.ilightbox-container', holder).empty().append('<span class="ilightbox-alert">' + opts.errors.loadContents + '</span>'); 13776 iL.configureHolder(obj, opt, holder); 13777 13778 opts.ajaxSetup.error(jqXHR, textStatus, errorThrown); 13779 if (typeof ajax.error == 'function') ajax.error(jqXHR, textStatus, errorThrown); 13780 } 13781 }); 13782 13783 break; 13784 13785 case 'html': 13786 var object = obj.URL, 13787 el 13788 container = $('div.ilightbox-container', holder); 13789 13790 if (object[0].nodeName) el = object.clone(); 13791 else { 13792 var dom = $(object); 13793 if (dom.selector) el = $('<div>' + dom + '</div>'); 13794 else el = dom; 13795 } 13796 13797 var elWidth = iL.items[item].options.width || parseInt(el.attr('width')), 13798 elHeight = iL.items[item].options.height || parseInt(el.attr('height')); 13799 13800 iL.addContent(holder, obj); 13801 13802 el.appendTo(document.documentElement).hide(); 13803 13804 //Trigger the onRender callback 13805 if (typeof opts.callback.onRender == 'function') opts.callback.onRender.call(iL, iL.ui, item); 13806 if (typeof obj.options.onRender == 'function') obj.options.onRender.call(iL, api); 13807 13808 var images = findImageInElement(holder); 13809 13810 //Trigger the onBeforeLoad callback 13811 if (typeof opts.callback.onBeforeLoad == 'function') opts.callback.onBeforeLoad.call(iL, iL.ui, item); 13812 if (typeof obj.options.onBeforeLoad == 'function') obj.options.onBeforeLoad.call(iL, api); 13813 13814 iL.loadImage(images, function() { 13815 //Trigger the onAfterLoad callback 13816 if (typeof opts.callback.onAfterLoad == 'function') opts.callback.onAfterLoad.call(iL, iL.ui, item); 13817 if (typeof obj.options.onAfterLoad == 'function') obj.options.onAfterLoad.call(iL, api); 13818 13819 holder.show().data({ 13820 naturalWidth: (elWidth || container.outerWidth()), 13821 naturalHeight: (elHeight || container.outerHeight()) 13822 }).hide(); 13823 el.remove(); 13824 13825 iL.configureHolder(obj, opt, holder); 13826 }); 13827 13828 break; 13829 } 13830 }, 13831 13832 configureHolder: function(obj, opt, holder) { 13833 var iL = this, 13834 vars = iL.vars, 13835 opts = iL.options; 13836 13837 if (opt != "current")(opt == "next") ? holder.addClass('ilightbox-next') : holder.addClass('ilightbox-prev'); 13838 13839 if (opt == "current") 13840 var item = vars.current; 13841 else if (opt == "next") 13842 var opacity = opts.styles.nextOpacity, 13843 item = vars.next; 13844 else 13845 var opacity = opts.styles.prevOpacity, 13846 item = vars.prev; 13847 13848 var api = { 13849 element: holder, 13850 position: item 13851 }; 13852 13853 iL.items[item].options.width = iL.items[item].options.width || 0, 13854 iL.items[item].options.height = iL.items[item].options.height || 0; 13855 13856 if (opt == "current") { 13857 if (opts.show.effect) holder.css(transform, gpuAcceleration).fadeIn(obj.speed, function() { 13858 holder.css(transform, ''); 13859 if (obj.caption) { 13860 iL.setCaption(obj, holder); 13861 var caption = $('div.ilightbox-caption', holder), 13862 percent = parseInt((caption.outerHeight() / holder.outerHeight()) * 100); 13863 if (opts.caption.start & percent <= 50) caption.fadeIn(opts.effects.fade
13863Speed); 13864 } 13865 13866 var social = obj.options.social; 13867 if (social) { 13868 iL.setSocial(social, obj.URL, holder); 13869 if (opts.social.start) $('div.ilightbox-social', holder).fadeIn(opts.effects.fadeSpeed); 13870 } 13871 13872 //Generate thumbnails 13873 iL.generateThumbnails(); 13874 13875 //Trigger the onShow callback 13876 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13877 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13878 }); 13879 else { 13880 holder.show(); 13881 13882 //Generate thumbnails 13883 iL.generateThumbnails(); 13884 13885 //Trigger the onShow callback 13886 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13887 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13888 } 13889 } else { 13890 if (opts.show.effect) holder.fadeTo(obj.speed, opacity, function() { 13891 if (opt == "next") vars.nextLock = false; 13892 else vars.prevLock = false; 13893 13894 //Generate thumbnails 13895 iL.generateThumbnails(); 13896 13897 //Trigger the onShow callback 13898 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13899 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13900 }); 13901 else { 13902 holder.css({ 13903 opacity: opacity 13904 }).show(); 13905 if (opt == "next") vars.nextLock = false; 13906 else vars.prevLock = false; 13907 13908 //Generate thumbnails 13909 iL.generateThumbnails(); 13910 13911 //Trigger the onShow callback 13912 if (typeof opts.callback.onShow == 'function') opts.callback.onShow.call(iL, iL.ui, item); 13913 if (typeof obj.options.onShow == 'function') obj.options.onShow.call(iL, api); 13914 } 13915 } 13916 13917 setTimeout(function() { 13918 iL.repositionPhoto(); 13919 }, 0); 13920 }, 13921 13922 generateBoxes: function() { 13923 var iL = this, 13924 vars = iL.vars, 13925 opts = iL.options; 13926 13927 if (opts.infinite && vars.total >= 3) { 13928 if (vars.current == vars.total - 1) vars.next = 0; 13929 if (vars.current == 0) vars.prev = vars.total - 1; 13930 } else opts.infinite = false; 13931 13932 //UNCODE addition 13933 if ( typeof iL.items[vars.current] == 'undefined' ) 13934 vars.current = 0; 13935 13936 iL.loadContent(iL.items[vars.current], 'current', opts.show.speed); 13937 13938 if (iL.items[vars.next]) iL.loadContent(iL.items[vars.next], 'next', opts.show.speed); 13939 if (iL.items[vars.prev]) iL.loadContent(iL.items[vars.prev], 'prev', opts.show.speed); 13940 }, 13941 13942 generateThumbnails: function() { 13943 var iL = this, 13944 vars = iL.vars, 13945 opts = iL.options, 13946 timeOut = null; 13947 13948 if (vars.thumbs && !iL.vars.dontGenerateThumbs) { 13949 var thumbnails = vars.thumbnails, 13950 container = $('div.ilightbox-thumbnails-container', thumbnails), 13951 grid = $('div.ilightbox-thumbnails-grid', container), 13952 i = 0; 13953 13954 grid.removeAttr('style').empty(); 13955 13956 $.each(iL.items, function(key, val) { 13957 var isActive = (vars.current == key) ? 'ilightbox-active' : '', 13958 opacity = (vars.current == key) ? opts.thumbnails.activeOpacity : opts.thumbnails.normalOpacity, 13959 thumb = val.options.thumbnail, 13960 thumbnail = $('<div class="ilightbox-thumbnail"></div>'), 13961 icon = $('<div class="ilightbox-thumbnail-icon"></div>'); 13962 13963 thumbnail.css({ 13964 opacity: 0 13965 }).addClass(isActive); 13966 13967 if ((val.type == "video" || val.type == "flash") && typeof val.options.icon == 'undefined') { 13968 icon.addClass('ilightbox-thumbnail-video'); 13969 thumbnail.append(icon); 13970 } else if (val.options.icon) { 13971 icon.addClass('ilightbox-thumbnail-' + val.options.icon); 13972 thumbnail.append(icon); 13973 } 13974 13975 if (thumb) iL.loadImage(thumb, function(img) { 13976 i++; 13977 if (img) thumbnail.data({ 13978 naturalWidth: img.width, 13979 naturalHeight: img.height 13980 }).append('<img src="' + thumb + '" border="0" />'); 13981 else thumbnail.data({ 13982 naturalWidth: opts.thumbnails.maxWidth, 13983 naturalHeight: opts.thumbnails.maxHeight 13984 }); 13985 13986 clearTimeout(timeOut); 13987 timeOut = setTimeout(function() { 13988 iL.positionThumbnails(thumbnails, container, grid); 13989 }, 20); 13990 setTimeout(function() { 13991 thumbnail.fadeTo(opts.effects.loadedFadeSpeed, opacity); 13992 }, i * 20); 13993 }); 13994 13995 grid.append(thumbnail); 13996 }); 13997 iL.vars.dontGenerateThumbs = true; 13998 } 13999 }, 14000
14001 positionThumbnails: function(thumbnails, container, grid) { 14002 var iL = this, 14003 vars = iL.vars, 14004 opts = iL.options, 14005 viewport = getViewport(), 14006 path = opts.path.toLowerCase(); 14007 14008 if (!thumbnails) thumbnails = vars.thumbnails; 14009 if (!container) container = $('div.ilightbox-thumbnails-container', thumbnails); 14010 if (!grid) grid = $('div.ilightbox-thumbnails-grid', container); 14011 14012 var thumbs = $('.ilightbox-thumbnail', grid), 14013 widthAvail = (path == 'horizontal') ? viewport.width - opts.styles.pageOffsetX : thumbs.eq(0).outerWidth() - opts.styles.pageOffsetX, 14014 heightAvail = (path == 'horizontal') ? thumbs.eq(0).outerHeight() - opts.styles.pageOffsetY : viewport.height - opts.styles.pageOffsetY, 14015 gridWidth = (path == 'horizontal') ? 0 : widthAvail, 14016 gridHeight = (path == 'horizontal') ? heightAvail : 0, 14017 active = $('.ilightbox-active', grid), 14018 gridCss = {}, 14019 css = {}; 14020 14021 if (arguments.length < 3) { 14022 thumbs.css({ 14023 opacity: opts.thumbnails.normalOpacity 14024 }); 14025 active.css({ 14026 opacity: opts.thumbnails.activeOpacity 14027 }); 14028 } 14029 14030 thumbs.each(function(i) { 14031 var t = $(this), 14032 data = t.data(), 14033 width = (path == 'horizontal') ? 0 : opts.thumbnails.maxWidth; 14034 height = (path == 'horizontal') ? opts.thumbnails.maxHeight : 0; 14035 dims = iL.getNewDimenstions(width, height, data.naturalWidth, data.naturalHeight, true); 14036 14037 t.css({ 14038 width: dims.width, 14039 height: dims.height 14040 }); 14041 if (path == 'horizontal') t.css({ 14042 'float': 'left' 14043 }); 14044 14045 (path == 'horizontal') ? ( 14046 gridWidth += t.outerWidth() 14047 ) : ( 14048 gridHeight += t.outerHeight() 14049 ); 14050 }); 14051 14052 gridCss = { 14053 width: gridWidth, 14054 height: gridHeight 14055 }; 14056 14057 grid.css(gridCss); 14058 14059 gridCss = {}; 14060 14061 var gridOffset = grid.offset(), 14062 activeOffset = (active.length) ? active.offset() : { 14063 top: parseInt(heightAvail / 2), 14064 left: parseInt(widthAvail / 2) 14065 }; 14066 14067 gridOffset.top = (gridOffset.top - $doc.scrollTop()), 14068 gridOffset.left = (gridOffset.left - $doc.scrollLeft()), 14069 activeOffset.top = (activeOffset.top - gridOffset.top - $doc.scrollTop()), 14070 activeOffset.left = (activeOffset.left - gridOffset.left - $doc.scrollLeft()); 14071 14072 (path == 'horizontal') ? ( 14073 gridCss.top = 0, 14074 gridCss.left = parseInt((widthAvail / 2) - activeOffset.left - (active.outerWidth() / 2)) 14075 ) : ( 14076 gridCss.top = parseInt(((heightAvail / 2) - activeOffset.top - (active.outerHeight() / 2))), 14077 gridCss.left = 0 14078 ); 14079 14080 if (arguments.length < 3) grid.stop().animate(gridCss, opts.effects.repositionSpeed, 'easeOutCirc'); 14081 else grid.css(gridCss); 14082 }, 14083 14084 loadImage: function(image, callback) { 14085 if (!$.isArray(image)) image = [image]; 14086 14087 var iL = this, 14088 length = image.length; 14089 14090 if (length > 0) { 14091 iL.showLoader(); 14092 $.each(image, function(index, value) { 14093 var img = new Image(); 14094 img.onload = function() { 14095 length -= 1; 14096 if (length == 0) { 14097 iL.hideLoader(); 14098 callback(img); 14099 } 14100 }; 14101 img.onerror = img.onabort = function() { 14102 length -= 1; 14103 if (length == 0) { 14104 iL.hideLoader(); 14105 callback(false); 14106 } 14107 }; 14108 img.src = image[index]; 14109 }); 14110 } else callback(false); 14111 }, 14112 14113 patchItemsEvents: function() { 14114 var iL = this, 14115 vars = iL.vars, 14116 clickEvent = ishybrid ? "itap.iL click.iL" : supportTouch ? "itap.iL" : "click.iL", 14117 vEvent = ishybrid ? "click.iL itap.iL" : supportTouch ? "click.iL" : "itap.iL"; 14118 14119 if (iL.context && iL.selector) { 14120 var $items = $(iL.selector, iL.context); 14121 14122 $(iL.context).on(clickEvent, iL.selector, function() { 14123 var $this = $(this), 14124 //UNCODE addition 14125 key = typeof $(this).data('lb-index') !== '' && $(this).closest('.owl-item').length ? $(this).data('lb-index') : $items.index($this); 14126 if (UNCODE.isMobile) { 14127 var isCarousel = $this.closest('.owl-carousel'); 14128 if (isCarousel.length) { 14129 if (isCarousel.hasClass('owl-translating')) return false; 14130 } 14131 } 14132 14133 vars.current = key; 14134 vars.next = iL.items[key + 1] ? key + 1 : null; 14135 vars.prev = iL.items[key - 1] ? key - 1 : null; 14136 14137 //UNCODE addition 14138 if ( vars.BODY.hasClass('fp-slide-scrolling') ) 14139 return false;
14140 14141 iL.addContents(); 14142 iL.patchEvents(); 14143 14144 return false; 14145 }).on(vEvent, iL.selector, function() { 14146 return false; 14147 }); 14148 } else 14149 $.each(iL.itemsObject, function(key, val) { 14150 val.on(clickEvent, function() { 14151 vars.current = key; 14152 vars.next = iL.items[key + 1] ? key + 1 : null; 14153 vars.prev = iL.items[key - 1] ? key - 1 : null; 14154 14155 iL.addContents(); 14156 iL.patchEvents(); 14157 14158 return false; 14159 }).on(vEvent, function() { 14160 return false; 14161 }); 14162 }); 14163 }, 14164 14165 dispatchItemsEvents: function() { 14166 var iL = this, 14167 vars = iL.vars, 14168 opts = iL.options; 14169 14170 if (iL.context && iL.selector) 14171 $(iL.context).off('.iL', iL.selector); 14172 else 14173 $.each(iL.itemsObject, function(key, val) { 14174 val.off('.iL'); 14175 }); 14176 }, 14177 14178 refresh: function() { 14179 var iL = this; 14180 14181 iL.dispatchItemsEvents(); 14182 iL.attachItems(); 14183 iL.normalizeItems(); 14184 iL.patchItemsEvents(); 14185 }, 14186 14187 patchEvents: function() { 14188 var iL = this, 14189 vars = iL.vars, 14190 opts = iL.options, 14191 path = opts.path.toLowerCase(), 14192 holders = $('.ilightbox-holder'), 14193 fullscreenEvent = fullScreenApi.fullScreenEventName + '.iLightBox', 14194 durationThreshold = 1000, 14195 horizontalDistanceThreshold = 14196 verticalDistanceThreshold = 100, 14197 buttonsArray = [vars.nextButton[0], vars.prevButton[0], vars.nextButton[0].firstChild, vars.prevButton[0].firstChild]; 14198 14199 $win.bind('resize.iLightBox', function() { 14200 var viewport = getViewport(); 14201 14202 if (opts.mobileOptimizer && !opts.innerToolbar) vars.isMobile = viewport.width <= vars.mobileMaxWidth; 14203 vars.BODY[vars.isMobile ? 'addClass' : 'removeClass']('isMobile'); 14204 14205 iL.repositionPhoto(null); 14206 if (supportTouch) { 14207 clearTimeout(vars.setTime); 14208 vars.setTime = setTimeout(function() { 14209 var scrollTop = getScrollXY().y; 14210 window.scrollTo(0, scrollTop - 30); 14211 window.scrollTo(0, scrollTop + 30); 14212 window.scrollTo(0, scrollTop); 14213 }, 2000); 14214 } 14215 if (vars.thumbs) iL.positionThumbnails(); 14216 }).bind('keydown.iLightBox', function(event) { 14217 if (opts.controls.keyboard) { 14218 switch (event.keyCode) { 14219 case 13: 14220 if (event.shiftKey && opts.keyboard.shift_enter) iL.fullScreenAction(); 14221 break; 14222 case 27: 14223 if (opts.keyboard.esc) iL.closeAction(); 14224 break; 14225 case 37: 14226 if (opts.keyboard.left && !vars.lockKey) iL.moveTo('prev'); 14227 break; 14228 case 38: 14229 if (opts.keyboard.up && !vars.lockKey) iL.moveTo('prev'); 14230 break; 14231 case 39: 14232 if (opts.keyboard.right && !vars.lockKey) iL.moveTo('next'); 14233 break; 14234 case 40: 14235 if (opts.keyboard.down && !vars.lockKey) iL.moveTo('next'); 14236 break; 14237 } 14238 } 14239 }); 14240 14241 if (fullScreenApi.supportsFullScreen) $win.bind(fullscreenEvent, function() { 14242 iL.doFullscreen(); 14243 }); 14244 14245 var holderEventsArr = [opts.caption.show + '.iLightBox', opts.caption.hide + '.iLightBox', opts.social.show + '.iLightBox', opts.social.hide + '.iLightBox'].filter(function(e, i, arr) { 14246 return arr.lastIndexOf(e) === i; 14247 }), 14248 holderEvents = ""; 14249 14250 $.each(holderEventsArr, function(key, val) { 14251 if (key != 0) holderEvents += ' '; 14252 holderEvents += val; 14253 }); 14254 14255 $doc.on(clickEvent, '.ilightbox-overlay', function() { 14256 if (opts.overlay.blur) iL.closeAction(); 14257 }).on(clickEvent, '.ilightbox-next, .ilightbox-next-button', function() { 14258 iL.moveTo('next'); 14259 }).on(clickEvent, '.ilightbox-prev, .ilightbox-prev-button', function() { 14260 iL.moveTo('prev'); 14261 }).on(clickEvent, '.ilightbox-thumbnail', function() { 14262 var t = $(this), 14263 thumbs = $('.ilightbox-thumbnail', vars.thumbnails), 14264 index = thumbs.index(t); 14265 14266 if (index != vars.current) iL.goTo(index); 14267 }).on(holderEvents, '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 14268 var caption = $('div.ilightbox-caption', vars.holder), 14269 social = $('div.ilightbox-social', vars.holder), 14270 fadeSpeed = opts.effects.fadeSpeed; 14271 14272 if (vars.nextLock || vars.prevLock) { 14273 if (e.type == opts.caption.show && !caption.is(':visible')) caption.fadeIn(fadeSpeed); 14274 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.fadeOut(fadeSpeed); 14275 14276 if (e.type == opts.social.show && !social.is(':visible')) social.fadeIn(fadeSpeed); 14277 else if (e.type == opts.social.hide && social.is(':visible')) social.fadeOut(fadeSpeed); 14278 } else { 14279 if (e.type == opts.caption.show && !caption.is(':visible')) caption.stop().fadeIn(fadeSpeed); 14280 else if (e.type == opts.caption.hide && caption.is(':visible')) caption.stop().fadeOut(fadeSpeed); 14281 14282 if (e.type == opts.social.show && !social.is(':visible')) social.stop().fadeIn(fadeSpeed); 14283 else if (e.type == opts.social.hide && social.is(':visible')) social.stop().fadeOut(fadeSpeed); 14284 } 14285 }).on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-wrapper', function(e) { 14286 if (e.type == 'mouseenter') vars.lockWheel = true; 14287 else vars.lockWheel = false;
14288 }).on(clickEvent, '.ilightbox-toolbar a.ilightbox-close, .ilightbox-toolbar a.ilightbox-fullscreen, .ilightbox-toolbar a.ilightbox-play, .ilightbox-toolbar a.ilightbox-pause', function() { 14289 var t = $(this); 14290 14291 if (t.hasClass('ilightbox-fullscreen')) iL.fullScreenAction(); 14292 else if (t.hasClass('ilightbox-play')) { 14293 iL.resume(); 14294 t.addClass('ilightbox-pause').removeClass('ilightbox-play'); 14295 } else if (t.hasClass('ilightbox-pause')) { 14296 iL.pause(); 14297 t.addClass('ilightbox-play').removeClass('ilightbox-pause'); 14298 } else iL.closeAction(); 14299 }).on(touchMoveEvent, '.ilightbox-overlay, .ilightbox-thumbnails-container', function(e) { 14300 // prevent scrolling 14301 e.preventDefault(); 14302 }); 14303 14304 function mouseMoveHandler(e) { 14305 if (!vars.isMobile) { 14306 if (!vars.mouseID) { 14307 vars.hideableElements.show(); 14308 } 14309 14310 vars.mouseID = clearTimeout(vars.mouseID); 14311 14312 if (buttonsArray.indexOf(e.target) === -1) 14313 vars.mouseID = setTimeout(function() { 14314 vars.hideableElements.hide(); 14315 vars.mouseID = clearTimeout(vars.mouseID); 14316 }, 3000); 14317 } 14318 } 14319 14320 if (opts.controls.arrows && !supportTouch) $doc.on('mousemove.iLightBox', mouseMoveHandler); 14321 14322 if (opts.controls.slideshow && opts.slideshow.pauseOnHover) $doc.on('mouseenter.iLightBox mouseleave.iLightBox', '.ilightbox-holder:not(.ilightbox-next, .ilightbox-prev)', function(e) { 14323 if (e.type == 'mouseenter' && vars.cycleID) iL.pause(); 14324 else if (e.type == 'mouseleave' && vars.isPaused) iL.resume(); 14325 }); 14326 14327 var switchers = $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails'), 14328 delay = false; 14329 14330 if (opts.controls.mousewheel) switchers.on('mousewheel.iLightBox', function(event, delta) { 14331 event.preventDefault(); 14332 if (delay) return; 14333 delay = true; 14334 if (!vars.lockWheel) { 14335 event.preventDefault(); 14336 if (delta < 0) { 14337 iL.moveTo('next'); 14338 } else if (delta > 0) { 14339 iL.moveTo('prev'); 14340 } 14341 } 14342 setTimeout(function(){
14343 delay = false; 14344 }, 2000); 14345 }); 14346 14347 if (opts.controls.swipe) holders.on(touchStartEvent, function(event) { 14348 if (vars.nextLock || vars.prevLock || vars.total == 1 || vars.lockSwipe) return; 14349 14350 vars.BODY.addClass('ilightbox-closedhand'); 14351 14352 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event, 14353 scrollTop = $doc.scrollTop(), 14354 scrollLeft = $doc.scrollLeft(), 14355 offsets = [ 14356 holders.eq(0).offset(), 14357 holders.eq(1).offset(), 14358 holders.eq(2).offset() 14359 ], 14360 offSet = [{ 14361 top: offsets[0].top - scrollTop, 14362 left: offsets[0].left - scrollLeft 14363 }, { 14364 top: offsets[1].top - scrollTop, 14365 left: offsets[1].left - scrollLeft 14366 }, { 14367 top: offsets[2].top - scrollTop, 14368 left: offsets[2].left - scrollLeft 14369 }], 14370 start = { 14371 time: (new Date()).getTime(), 14372 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 14373 }, 14374 stop; 14375 14376 function moveEachHandler(i) { 14377 var t = $(this), 14378 offset = offSet[i], 14379 scroll = [(start.coords[0] - stop.coords[0]), (start.coords[1] - stop.coords[1])]; 14380 14381 t[0].style[path == "horizontal" ? 'left' : 'top'] = (path == "horizontal" ? offset.left - scroll[0] : offset.top - scroll[1]) + 'px'; 14382 } 14383 14384 function moveHandler(event) { 14385 14386 if (!start) return; 14387 14388 var data = event.originalEvent.touches ? event.originalEvent.touches[0] : event; 14389 14390 stop = { 14391 time: (new Date()).getTime(), 14392 coords: [data.pageX - scrollLeft, data.pageY - scrollTop] 14393 }; 14394 14395 holders.each(moveEachHandler); 14396 14397 // prevent scrolling 14398 event.preventDefault(); 14399 } 14400 14401 function repositionHolders() { 14402 holders.each(function() { 14403 var t = $(this), 14404 offset = t.data('offset') || { 14405 top: t.offset().top - scrollTop, 14406 left: t.offset().left - scrollLeft 14407 }, 14408 top = offset.top, 14409 left = offset.left; 14410 14411 t.css(transform, gpuAcceleration).stop().animate({ 14412 top: top, 14413 left: left 14414 }, 500, 'easeOutCirc', function() { 14415 t.css(transform, ''); 14416 }); 14417 }); 14418 } 14419 14420 holders.bind(touchMoveEvent, moveHandler); 14421 $doc.one(touchStopEvent, function(event) { 14422 holders.unbind(touchMoveEvent, moveHandler); 14423 14424 vars.BODY.removeClass('ilightbox-closedhand'); 14425 14426 if (start && stop) { 14427 if (path == "horizontal" && stop.time - start.time < durationThreshold && abs(start.coords[0] - stop.coords[0]) > horizontalDistanceThreshold && abs(start.coords[1] - stop.coords[1]) < verticalDistanceThreshold) { 14428 if (start.coords[0] > stop.coords[0]) { 14429 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 14430 else { 14431 vars.isSwipe = true; 14432 iL.moveTo('next'); 14433 } 14434 } else { 14435 if (vars.current == 0 && !opts.infinite) repositionHolders(); 14436 else { 14437 vars.isSwipe = true; 14438 iL.moveTo('prev'); 14439 } 14440 } 14441 } 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) { 14442 if (start.coords[1] > stop.coords[1]) { 14443 if (vars.current == vars.total - 1 && !opts.infinite) repositionHolders(); 14444 else { 14445 vars.isSwipe = true; 14446 iL.moveTo('next'); 14447 } 14448 } else { 14449 if (vars.current == 0 && !opts.infinite) repositionHolders(); 14450 else { 14451 vars.isSwipe = true; 14452 iL.moveTo('prev'); 14453 } 14454 } 14455 } else repositionHolders(); 14456 } 14457 start = stop = undefined; 14458 }); 14459 }); 14460 14461 }, 14462 14463 goTo: function(index) { 14464 var iL = this, 14465 vars = iL.vars, 14466 opts = iL.options, 14467 diff = (index - vars.current); 14468 14469 if (opts.infinite) { 14470 if (index == vars.total - 1 && vars.current == 0) diff = -1; 14471 if (vars.current == vars.total - 1 && index == 0) diff = 1; 14472 } 14473 14474 if (diff == 1) iL.moveTo('next'); 14475 else if (diff == -1) iL.moveTo('prev'); 14476 else { 14477 14478 if (vars.nextLock || vars.prevLock) return false; 14479 14480 //Trigger the onBeforeChange callback 14481 if (typeof opts.callback.onBeforeChange == 'function') opts.callback.onBeforeChange.call(iL, iL.ui); 14482 14483 if (opts.linkId) { 14484 vars.hashLock = true; 14485 window.location.hash = opts.linkId + '/' + index; 14486 } 14487 14488 if (iL.items[index]) { 14489 if (!iL.items[index].options.mousewheel) vars.lockWheel = true; 14490 else iL.vars.lockWheel = false;
14491 14492 if (!iL.items[index].options.swipe) vars.lockSwipe = true; 14493 else vars.lockSwipe = false; 14494 } 14495 14496 $.each([vars.holder, vars.nextPhoto, vars.prevPhoto], function(key, val) { 14497 val.css(transform, gpuAcceleration).fadeOut(opts.effects.loadedFadeSpeed); 14498 }); 14499 14500 vars.current = index; 14501 vars.next = index + 1; 14502 vars.prev = index - 1; 14503 14504 iL.createUI(); 14505 14506 setTimeout(function() { 14507 iL.generateBoxes(); 14508 }, opts.effects.loadedFadeSpeed + 50); 14509 14510 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(index).addClass('ilightbox-active'); 14511 iL.positionThumbnails(); 14512 14513 if (opts.linkId) setTimeout(function() { 14514 vars.hashLock = false; 14515 }, 55); 14516 14517 // Configure arrow buttons 14518 if (!opts.infinite) { 14519 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 14520 14521 if (vars.current == 0) { 14522 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 14523 } 14524 if (vars.current >= vars.total - 1) { 14525 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 14526 } 14527 } 14528 14529 // Reset next cycle timeout 14530 iL.resetCycle(); 14531 14532 //Trigger the onAfterChange callback 14533 if (typeof opts.callback.onAfterChange == 'function') opts.callback.onAfterChange.call(iL, iL.ui); 14534 } 14535 }, 14536 14537 moveTo: function(side) { 14538 var iL = this, 14539 vars = iL.vars, 14540 opts = iL.options, 14541 path = opts.path.toLowerCase(), 14542 viewport = getViewport(), 14543 switchSpeed = opts.effects.switchSpeed; 14544 14545 if (vars.nextLock || vars.prevLock) return false; 14546 else { 14547 14548 var item = (side == "next") ? vars.next : vars.prev; 14549 14550 if (opts.linkId) { 14551 vars.hashLock = true; 14552 window.location.hash = opts.linkId + '/' + item; 14553 } 14554 14555 if (side == "next") { 14556 if (!iL.items[item]) return false; 14557 var firstHolder = vars.nextPhoto, 14558 secondHolder = vars.holder, 14559 lastHolder = vars.prevPhoto, 14560 firstClass = 'ilightbox-prev', 14561 secondClass = 'ilightbox-next'; 14562 } else if (side == "prev") { 14563 if (!iL.items[item]) return false; 14564 var firstHolder = vars.prevPhoto, 14565 secondHolder = vars.holder, 14566 lastHolder = vars.nextPhoto, 14567 firstClass = 'ilightbox-next', 14568 secondClass = 'ilightbox-prev'; 14569 } 14570 14571 //Trigger the onBeforeChange callback 14572 if (typeof opts.callback.onBeforeChange == 'function') 14573 opts.callback.onBeforeChange.call(iL, iL.ui); 14574 14575 (side == "next") ? vars.nextLock = true: vars.prevLock = true; 14576 14577 var captionFirst = $('div.ilightbox-caption', secondHolder), 14578 socialFirst = $('div.ilightbox-social', secondHolder); 14579 14580 if (captionFirst.length) 14581 captionFirst.stop().fadeOut(switchSpeed, function() { 14582 $(this).remove(); 14583 }); 14584 if (socialFirst.length) 14585 socialFirst.stop().fadeOut(switchSpeed, function() { 14586 $(this).remove(); 14587 }); 14588 14589 if (iL.items[item].caption) { 14590 iL.setCaption(iL.items[item], firstHolder); 14591 var caption = $('div.ilightbox-caption', firstHolder), 14592 percent = parseInt((caption.outerHeight() / firstHolder.outerHeight()) * 100); 14593 if (opts.caption.start && percent <= 50) caption.fadeIn(switchSpeed); 14594 } 14595 14596 var social = iL.items[item].options.social; 14597 if (social) { 14598 iL.setSocial(social, iL.items[item].URL, firstHolder); 14599 if (opts.social.start) $('div.ilightbox-social', firstHolder).fadeIn(opts.effects.fadeSpeed); 14600 } 14601 14602 $.each([firstHolder, secondHolder, lastHolder], function(key, val) { 14603 val.removeClass('ilightbox-next ilightbox-prev'); 14604 }); 14605 14606 var firstOffset = firstHolder.data('offset'), 14607 winW = (viewport.width - (opts.styles.pageOffsetX)), 14608 winH = (viewport.height - (opts.styles.pageOffsetY)), 14609 width = firstOffset.newDims.width, 14610 height = firstOffset.newDims.height, 14611 thumbsOffset = firstOffset.thumbsOffset, 14612 diff = firstOffset.diff, 14613 top = parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)), 14614 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 14615 14616 var secondOffset = secondHolder.data('offset'), 14617 object = secondOffset.object; 14618 14619 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 14620 var objRatio = width / height; 14621 height = height - vars.captionHeight; 14622 width = height * objRatio; 14623 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top, 14624 left = parseInt((winW / 2) - (width / 2) - diff.W - (thumbsOffset.W / 2)); 14625 }*/ 14626 14627 firstHolder.show().css(transform, gpuAcceleration).animate({ 14628 top: top, 14629 left: left, 14630 opacity: 1 14631 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 14632 firstHolder.css(transform, ''); 14633 }); 14634 14635 $('div.ilightbox-container', firstHolder).animate({ 14636 width: width, 14637 height: height 14638 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 14639 14640 diff = secondOffset.diff; 14641 14642 width = secondOffset.newDims.width, 14643 height = secondOffset.newDims.height; 14644 14645 width = parseInt(width * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 14646 height = parseInt(height * opts.styles[side == 'next' ? 'prevScale' : 'nextScale']), 14647 top = (path == 'horizontal') ? parseInt((winH / 2) - object.offsetY - (height / 2) - diff.H - (thumbsOffset.H / 2)) : parseInt(winH - object.offsetX - diff.H - (thumbsOffset.H / 2)); 14648 14649 if (side == 'prev') 14650 left = (path == 'horizontal') ? parseInt(winW - object.offsetX - diff.W - (thumbsOffset.W / 2)) : parseInt((winW / 2) - (width / 2) - diff.W - object.offsetY - (thumbsOffset.W / 2)); 14651 else { 14652 top = (path == 'horizontal') ? top : parseInt(object.offsetX - diff.H - height - (thumbsOffset.H / 2)), 14653 left = (path == 'horizontal') ? parseInt(object.offsetX - diff.W - width - (thumbsOffset.W / 2)) : parseInt((winW / 2) - object.offsetY - (width / 2) - diff.W - (thumbsOffset.W / 2)); 14654 } 14655 14656 /*if (object.item.caption && !isNaN(width) && !isNaN(height) && UNCODE.wwidth > UNCODE.mediaQuery) { 14657 var objRatio = width / height; 14658 height = height - vars.captionHeight; 14659 width = height * objRatio; 14660 top = path == 'horizontal' ? parseInt((winH / 2) - (height / 2) - diff.H - (thumbsOffset.H / 2)) : top; 14661 }*/ 14662 14663 $('div.ilightbox-container', secondHolder).animate({ 14664 width: width, 14665 height: height 14666 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc'); 14667 14668 secondHolder.addClass(firstClass).css(transform, gpuAcceleration).animate({ 14669 top: top, 14670 left: left, 14671 opacity: opts.styles.prevOpacity, 14672 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 14673 secondHolder.css(transform, ''); 14674
14675 $('.ilightbox-thumbnail', vars.thumbnails).removeClass('ilightbox-active').eq(item).addClass('ilightbox-active'); 14676 iL.positionThumbnails(); 14677 14678 if (iL.items[item]) { 14679 if (!iL.items[item].options.mousewheel) vars.lockWheel = true; 14680 else vars.lockWheel = false; 14681 14682 if (!iL.items[item].options.swipe) vars.lockSwipe = true; 14683 else vars.lockSwipe = false; 14684 } 14685 14686 vars.isSwipe = false; 14687 14688 // Remove iframe & video from previous slide 14689 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 14690 $('div.ilightbox-container', secondHolder).empty(); 14691 } 14692 14693 if (side == "next") { 14694 vars.nextPhoto = lastHolder, 14695 vars.prevPhoto = secondHolder, 14696 vars.holder = firstHolder; 14697 14698 vars.nextPhoto.hide(); 14699 14700 vars.next = vars.next + 1, 14701 vars.prev = vars.current, 14702 vars.current = vars.current + 1; 14703 14704 if (opts.infinite) { 14705 if (vars.current > vars.total - 1) vars.current = 0; 14706 if (vars.current == vars.total - 1) vars.next = 0; 14707 if (vars.current == 0) vars.prev = vars.total - 1; 14708 } 14709 14710 iL.createUI(); 14711 14712 if (!iL.items[vars.next]) 14713 vars.nextLock = false; 14714 else 14715 iL.loadContent(iL.items[vars.next], 'next'); 14716 } else { 14717 vars.prevPhoto = lastHolder; 14718 vars.nextPhoto = secondHolder; 14719 vars.holder = firstHolder; 14720 14721 vars.prevPhoto.hide(); 14722 14723 vars.next = vars.current; 14724 vars.current = vars.prev; 14725 vars.prev = vars.current - 1; 14726 14727 if (opts.infinite) { 14728 if (vars.current == vars.total - 1) vars.next = 0; 14729 if (vars.current == 0) vars.prev = vars.total - 1; 14730 } 14731 14732 iL.createUI(); 14733 14734 if (!iL.items[vars.prev]) 14735 vars.prevLock = false; 14736 else 14737 iL.loadContent(iL.items[vars.prev], 'prev'); 14738 } 14739 14740 // Add iframe & video content for current slide 14741 if (['iframe', 'video'].indexOf(iL.items[vars.current].type) !== -1) { 14742 iL.loadContent(iL.items[vars.current], 'current'); 14743 } 14744 14745 if (opts.linkId) setTimeout(function() { 14746 vars.hashLock = false; 14747 }, 55); 14748 14749 // Configure arrow buttons 14750 if (!opts.infinite) { 14751 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 14752 14753 if (vars.current == 0) 14754 vars.prevButton.add(vars.innerPrevButton).addClass('disabled'); 14755 if (vars.current >= vars.total - 1) 14756 vars.nextButton.add(vars.innerNextButton).addClass('disabled'); 14757 } 14758 14759 iL.repositionPhoto(); 14760 14761 // Reset next cycle timeout 14762 iL.resetCycle(); 14763 14764 //Trigger the onAfterChange callback 14765 if (typeof opts.callback.onAfterChange == 'function') 14766 opts.callback.onAfterChange.call(iL, iL.ui); 14767 }); 14768 14769 top = (path == 'horizontal') ? getPixel(lastHolder, 'top') : ((side == "next") ? parseInt(-(winH / 2) - lastHolder.outerHeight()) : parseInt(top * 2)), 14770 left = (path == 'horizontal') ? ((side == "next") ? parseInt(-(winW / 2) - lastHolder.outerWidth()) : parseInt(left * 2)) : getPixel(lastHolder, 'left'); 14771 14772 lastHolder.css(transform, gpuAcceleration).animate({ 14773 top: top, 14774 left: left, 14775 opacity: opts.styles.nextOpacity 14776 }, switchSpeed, (vars.isSwipe) ? 'easeOutCirc' : 'easeInOutCirc', function() { 14777 lastHolder.css(transform, ''); 14778 }).addClass(secondClass); 14779 } 14780 }, 14781 14782 setCaption: function(obj, target) { 14783 var iL = this, 14784 caption = $('<div class="ilightbox-caption"></div>'); 14785 14786 if (obj.caption) { 14787 caption.html(obj.caption); 14788 $('div.ilightbox-container', target).append(caption); 14789 } 14790 }, 14791 14792 normalizeSocial: function(obj, url) { 14793 var iL = this, 14794 vars = iL.vars, 14795 opts = iL.options, 14796 baseURL = window.location.href; 14797 14798 $.each(obj, function(key, value) { 14799 if (!value) 14800 return true; 14801 14802 var item = key.toLowerCase(), 14803 source, text; 14804 14805 switch (item) { 14806 case 'facebook': 14807 source = "http://www.facebook.com/share.php?v=4&src=bm&u={URL}", 14808 text = "Share on Facebook"; 14809 break; 14810 case 'twitter': 14811 source = "http://twitter.com/home?status={URL}", 14812 text = "Share on Twitter"; 14813 break; 14814 case 'digg': 14815 source = "http://digg.com/submit?phase=2&url={URL}", 14816 text = "Share on Digg"; 14817 break; 14818 case 'reddit': 14819 source = "http://reddit.com/submit?url={URL}", 14820 text = "Share on reddit"; 14821 break; 14822 } 14823 14824 obj[key] = { 14825 URL: value.URL && absolutizeURI(baseURL, value.URL) || opts.linkId && window.location.href || typeof url !== 'string' && baseURL || url && absolutizeURI(baseURL, url) || baseURL, 14826 source: value.source || source || value.URL && absolutizeURI(baseURL, value.URL) || url && absolutizeURI(baseURL, url), 14827 text: value.text || text || "Share on " + key, 14828 width: (typeof(value.width) != 'undefined' && !isNaN(value.width)) ? parseInt(value.width) : 640, 14829 height: value.height || 360 14830 }; 14831 14832 }); 14833 14834 return obj; 14835 }, 14836 14837 setSocial: function(obj, url, target) { 14838 var iL = this, 14839 socialBar = $('<div class="ilightbox-social"></div>'), 14840 buttons = '<ul>'; 14841 14842 obj = iL.normalizeSocial(obj, url); 14843 14844 $.each(obj, function(key, value) { 14845 var item = key.toLowerCase(), 14846 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, '+')); 14847 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>'; 14848 }); 14849 14850 buttons += '</ul>'; 14851 14852 socialBar.html(buttons); 14853 $('div.ilightbox-container', target).append(socialBar); 14854 }, 14855 14856 fullScreenAction: function() { 14857 var iL = this, 14858 vars = iL.vars; 14859 14860 if (fullScreenApi.supportsFullScreen) { 14861 if (fullScreenApi.isFullScreen()) fullScreenApi.cancelFullScreen(document.documentElement); 14862 else fullScreenApi.requestFullScreen(document.documentElement); 14863 } else { 14864 iL.doFullscreen(); 14865 } 14866 }, 14867 14868 doFullscreen: function() { 14869 var iL = this, 14870 vars = iL.vars, 14871 viewport = getViewport(), 14872 opts = iL.options; 14873 14874 if (opts.fullAlone) { 14875 var currentHolder = vars.holder, 14876 current = iL.items[vars.current], 14877 windowWidth = viewport.width, 14878 windowHeight = viewport.height, 14879 elements = [currentHolder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.overlay, vars.toolbar, vars.thumbnails, vars.loader], 14880 hideElements = [vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 14881 14882 if (!vars.isInFullScreen) { 14883 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = true; 14884 vars.overlay.css({ 14885 opacity: 1 14886 }); 14887 14888 $.each(hideElements, function(i, element) { 14889 element.hide(); 14890 }); 14891 14892 vars.fullScreenButton.attr('title', opts.text.exitFullscreen); 14893 14894 if (opts.fullStretchTypes.indexOf(current.type) != -1) currentHolder.data({
14895 naturalWidthOld: currentHolder.data('naturalWidth'), 14896 naturalHeightOld: currentHolder.data('naturalHeight'), 14897 naturalWidth: windowWidth, 14898 naturalHeight: windowHeight 14899 }); 14900 else { 14901 var viewport = current.options.fullViewPort || opts.fullViewPort || '', 14902 newWidth = windowWidth, 14903 newHeight = windowHeight, 14904 width = currentHolder.data('naturalWidth'), 14905 height = currentHolder.data('naturalHeight'); 14906 14907 if (viewport.toLowerCase() == 'fill') { 14908 newHeight = (newWidth / width) * height; 14909 14910 if (newHeight < windowHeight) { 14911 newWidth = (windowHeight / height) * width, 14912 newHeight = windowHeight; 14913 } 14914 } else if (viewport.toLowerCase() == 'fit') { 14915 var dims = iL.getNewDimenstions(newWidth, newHeight, width, height, true); 14916 14917 newWidth = dims.width, 14918 newHeight = dims.height; 14919 } else if (viewport.toLowerCase() == 'stretch') { 14920 newWidth = newWidth, 14921 newHeight = newHeight; 14922 } else { 14923 var scale = (width > newWidth || height > newHeight) ? true : false, 14924 dims = iL.getNewDimenstions(newWidth, newHeight, width, height, scale); 14925 newWidth = dims.width, 14926 newHeight = dims.height; 14927 } 14928 14929 currentHolder.data({ 14930 naturalWidthOld: currentHolder.data('naturalWidth'), 14931 naturalHeightOld: currentHolder.data('naturalHeight'), 14932 naturalWidth: newWidth, 14933 naturalHeight: newHeight 14934 }); 14935 } 14936 14937 $.each(elements, function(key, val) { 14938 val.addClass('ilightbox-fullscreen'); 14939 }); 14940 14941 //Trigger the onEnterFullScreen callback 14942 if (typeof opts.callback.onEnterFullScreen == 'function') opts.callback.onEnterFullScreen.call(iL, iL.ui); 14943 } else { 14944 vars.isInFullScreen = vars.lockKey = vars.lockWheel = vars.lockSwipe = false; 14945 vars.overlay.css({ 14946 opacity: iL.options.overlay.opacity 14947 }); 14948 14949 $.each(hideElements, function(i, element) { 14950 element.show(); 14951 }); 14952 14953 vars.fullScreenButton.attr('title', opts.text.enterFullscreen); 14954 14955 currentHolder.data({ 14956 naturalWidth: currentHolder.data('naturalWidthOld'), 14957 naturalHeight: currentHolder.data('naturalHeightOld'), 14958 naturalWidthOld: null, 14959 naturalHeightOld: null 14960 }); 14961 14962 $.each(elements, function(key, val) { 14963 val.removeClass('ilightbox-fullscreen'); 14964 }); 14965 14966 //Trigger the onExitFullScreen callback 14967 if (typeof opts.callback.onExitFullScreen == 'function') opts.callback.onExitFullScreen.call(iL, iL.ui); 14968 } 14969 } else { 14970 if (!vars.isInFullScreen) vars.isInFullScreen = true; 14971 else vars.isInFullScreen = false; 14972 } 14973 iL.repositionPhoto(true); 14974 }, 14975 14976 closeAction: function() { 14977 var iL = this, 14978 vars = iL.vars, 14979 opts = iL.options; 14980 14981 $win.unbind('.iLightBox'); 14982 $doc.off('.iLightBox'); 14983 14984 if (vars.isInFullScreen) fullScreenApi.cancelFullScreen(document.documentElement); 14985 14986 $('.ilightbox-overlay, .ilightbox-holder, .ilightbox-thumbnails').off('.iLightBox'); 14987 14988 if (opts.hide.effect) vars.overlay.stop().fadeOut(opts.hide.speed, function() { 14989 vars.overlay.remove(); 14990 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 14991 }); 14992 else { 14993 vars.overlay.remove(); 14994 vars.BODY.removeClass('ilightbox-noscroll').off('.iLightBox'); 14995 } 14996 14997 var fadeOuts = [vars.toolbar, vars.holder, vars.nextPhoto, vars.prevPhoto, vars.nextButton, vars.prevButton, vars.loader, vars.thumbnails]; 14998 14999 $.each(fadeOuts, function(i, element) { 15000 element.removeAttr('style').remove(); 15001 }); 15002 15003 vars.dontGenerateThumbs = vars.isInFullScreen = false; 15004 15005 window.iLightBox = null; 15006 15007 if (opts.linkId) { 15008 vars.hashLock = true; 15009 removeHash(); 15010 setTimeout(function() { 15011 vars.hashLock = false; 15012 }, 55); 15013 } 15014 15015 vars.nextButton.add(vars.prevButton).add(vars.innerPrevButton).add(vars.innerNextButton).removeClass('disabled'); 15016 15017 //Trigger the onHide callback 15018 if (typeof opts.callback.onHide == 'function') opts.callback.onHide.call(iL, iL.ui); 15019 }, 15020 15021 repositionPhoto: function() { 15022 var iL = this, 15023 vars = iL.vars, 15024 opts = iL.options, 15025 path = opts.path.toLowerCase(), 15026 viewport = getViewport(), 15027 winWidth = viewport.width, 15028 winHeight = viewport.height; 15029 15030 if (viewport.width < UNCODE.mediaQuery) opts.styles.nextOffsetX = 0; 15031 15032 var thumbsOffsetW = (vars.isInFullScreen && opts.fullAlone || vars.isMobile) ? 0 : ((path == 'horizontal') ? 0 : vars.thumbnails.outerWidth()), 15033 thumbsOffsetH = vars.isMobile ? vars.toolbar.outerHeight() : ((vars.isInFullScreen && opts.fullAlone) ? 0 : ((path == 'horizontal') ? vars.thumbnails.outerHeight() : 0)), 15034 width = (vars.isInFullScreen && opts.fullAlone) ? winWidth : (winWidth - (opts.styles.pageOffsetX)), 15035 height = (vars.isInFullScreen && opts.fullAlone) ? winHeight : (winHeight - (opts.styles.pageOffsetY)), 15036 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, 15037 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))); 15038 15039 var elObject = { 15040 type: 'current', 15041 width: width, 15042 height: height, 15043 item: iL.items[vars.current], 15044 offsetW: offsetW, 15045 offsetH: offsetH,
15046 thumbsOffsetW: thumbsOffsetW, 15047 thumbsOffsetH: thumbsOffsetH, 15048 animate: arguments.length, 15049 holder: vars.holder 15050 }; 15051 15052 iL.repositionEl(elObject); 15053 15054 if (iL.items[vars.next]) { 15055 elObject = $.extend(elObject, { 15056 type: 'next', 15057 item: iL.items[vars.next], 15058 offsetX: opts.styles.nextOffsetX, 15059 offsetY: opts.styles.nextOffsetY, 15060 holder: vars.nextPhoto 15061 }); 15062 15063 iL.repositionEl(elObject); 15064 } 15065 15066 if (iL.items[vars.prev]) { 15067 elObject = $.extend(elObject, { 15068 type: 'prev', 15069 item: iL.items[vars.prev], 15070 offsetX: opts.styles.nextOffsetX, 15071 offsetY: opts.styles.prevOffsetY, 15072 holder: vars.prevPhoto 15073 }); 15074 15075 iL.repositionEl(elObject); 15076 } 15077 15078 var loaderCss = (path == "horizontal") ? { 15079 left: parseInt((width / 2) - (vars.loader.outerWidth() / 2)) 15080 } : { 15081 top: parseInt((height / 2) - (vars.loader.outerHeight() / 2)) 15082 }; 15083 vars.loader.css(loaderCss); 15084 }, 15085 15086 repositionEl: function(obj) { 15087 var iL = this, 15088 vars = iL.vars, 15089 opts = iL.options, 15090 path = opts.path.toLowerCase(), 15091 widthAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.width : (obj.width - obj.offsetW)) : (obj.width - obj.offsetW), 15092 heightAvail = (obj.type == 'current') ? ((vars.isInFullScreen && opts.fullAlone) ? obj.height : (obj.height - obj.offsetH)) : (obj.height - obj.offsetH), 15093 itemParent = obj.item, 15094 item = obj.item.options, 15095 holder = obj.holder, 15096 offsetX = obj.offsetX || 0, 15097 offsetY = obj.offsetY || 0, 15098 //Uncode change ##START## 15099 toolbarHeight = $('.ilightbox-inner-toolbar', holder).length ? parseInt( $('.ilightbox-inner-toolbar', holder).outerHeight() ) : 0, 15100 //Uncode change ##END## 15101 thumbsOffsetW = obj.thumbsOffsetW, 15102 thumbsOffsetH = obj.thumbsOffsetH; 15103 15104 if (obj.type == 'current') { 15105 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); 15106 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); 15107 } else { 15108 if (typeof item.width == 'number' && item.width) widthAvail = (item.width > widthAvail) ? widthAvail : item.width; 15109 if (typeof item.height == 'number' && item.height) heightAvail = (item.height > heightAvail) ? heightAvail : item.height; 15110 } 15111 15112 15113 //Uncode change ##START## 15114 heightAvail = parseInt(heightAvail - toolbarHeight); 15115 // heightAvail = parseInt(heightAvail - $('.ilightbox-inner-toolbar', holder).outerHeight()); 15116 //Uncode change ##END## 15117 15118 var width = (typeof item.width == 'string' && item.width.indexOf('%') != -1) ? percentToValue(parseInt(item.width.replace('%', '')), obj.width) : holder.data('naturalWidth'), 15119 height = (typeof item.height == 'string' && item.height.indexOf('%') != -1) ? percentToValue(parseInt(item.height.replace('%', '')), obj.height) : holder.data('naturalHeight'); 15120 15121 var dims = ((typeof item.width == 'string' && item.width.indexOf('%') != -1 || typeof item.height == 'string' && item.height.indexOf('%') != -1) ? { 15122 width: width, 15123 height: height 15124 } : iL.getNewDimenstions(widthAvail, heightAvail, width, height)), 15125 newDims = $.extend({}, dims, {}); 15126 15127 if (obj.type == 'prev' || obj.type == 'next') 15128 width = parseInt(dims.width * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)), 15129 height = parseInt(dims.height * ((obj.type == 'next') ? opts.styles.nextScale : opts.styles.prevScale)); 15130 else 15131 width = dims.width, 15132 height = dims.height; 15133 15134 var widthDiff = parseInt((getPixel(holder, 'padding-left') + getPixel(holder, 'padding-right') + getPixel(holder, 'border-left-width') + getPixel(holder, 'border-right-width')) / 2), 15135 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); 15136 15137 switch (obj.type) { 15138 case 'current': 15139 var top = parseInt((obj.height / 2) - (height / 2) - heightDiff - (thumbsOffsetH / 2)), 15140 left = parseInt((obj.width / 2) - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 15141 break; 15142
15143 case 'next': 15144 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(obj.height - offsetX - heightDiff - (thumbsOffsetH / 2)), 15145 left = (path == 'horizontal') ? parseInt(obj.width - offsetX - widthDiff - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - (width / 2) - widthDiff - offsetY - (thumbsOffsetW / 2)); 15146 break; 15147 15148 case 'prev': 15149 var top = (path == 'horizontal') ? parseInt((obj.height / 2) - offsetY - (height / 2) - heightDiff - (thumbsOffsetH / 2)) : parseInt(offsetX - heightDiff - height - (thumbsOffsetH / 2)), 15150 left = (path == 'horizontal') ? parseInt(offsetX - widthDiff - width - (thumbsOffsetW / 2)) : parseInt((obj.width / 2) - offsetY - (width / 2) - widthDiff - (thumbsOffsetW / 2)); 15151 break; 15152 } 15153 15154 holder.data('offset', { 15155 top: top, 15156 left: left, 15157 newDims: newDims, 15158 diff: { 15159 W: widthDiff, 15160 H: heightDiff 15161 }, 15162 thumbsOffset: { 15163 W: thumbsOffsetW, 15164 H: thumbsOffsetH 15165 }, 15166 object: obj 15167 }); 15168 15169 var opacityMobile; 15170 if ( isMobile ) { 15171 opacityMobile = { 15172 opacity: 1, 15173 top: top, 15174 left: left 15175 }; 15176 } else { 15177 opacityMobile = { 15178 top: top, 15179 left: left 15180 }; 15181 } 15182 15183 if (obj.animate > 0 && opts.effects.reposition) { 15184 holder.css(transform, gpuAcceleration).stop().animate( 15185 opacityMobile, 15186 opts.effects.repositionSpeed, 'easeOutCirc', function() { 15187 holder.css(transform, ''); 15188 }); 15189 $('div.ilightbox-container', holder).stop().animate({ 15190 width: width, 15191 height: height 15192 }, opts.effects.repositionSpeed, 'easeOutCirc'); 15193 $('div.ilightbox-inner-toolbar', holder).stop().animate({ 15194 width: width 15195 }, opts.effects.repositionSpeed, 'easeOutCirc', function() { 15196 $(this).css('overflow', 'visible'); 15197 }); 15198 } else { 15199 holder.css(opacityMobile); 15200 $('div.ilightbox-container', holder).css({ 15201 width: width, 15202 height: height 15203 }); 15204 $('div.ilightbox-inner-toolbar', holder).css({ 15205 width: width 15206 }); 15207 } 15208 }, 15209 15210 15211 resume: function(priority) { 15212 var iL = this, 15213 vars = iL.vars, 15214 opts = iL.options; 15215 15216 if (!opts.slideshow.pauseTime || opts.controls.slideshow && vars.total <= 1 || priority < vars.isPaused) { 15217 return; 15218 } 15219 15220 vars.isPaused = 0; 15221 15222 if (vars.cycleID) { 15223 vars.cycleID = clearTimeout(vars.cycleID); 15224 } 15225 15226 vars.cycleID = setTimeout(function() { 15227 if (vars.current == vars.total - 1) iL.goTo(0); 15228 else iL.moveTo('next'); 15229 }, opts.slideshow.pauseTime); 15230 }, 15231 15232 pause: function(priority) { 15233 var iL = this, 15234 vars = iL.vars, 15235 opts = iL.options; 15236 15237 if (priority < vars.isPaused) { 15238 return; 15239 } 15240 15241 vars.isPaused = priority || 100; 15242 15243 if (vars.cycleID) { 15244 vars.cycleID = clearTimeout(vars.cycleID); 15245 } 15246 }, 15247 15248 resetCycle: function() { 15249 var iL = this, 15250 vars = iL.vars, 15251 opts = iL.options; 15252 15253 if (opts.controls.slideshow && vars.cycleID && !vars.isPaused) { 15254 iL.resume(); 15255 } 15256 }, 15257 15258 getNewDimenstions: function(width, height, width_old, height_old, thumb) { 15259 var iL = this; 15260 15261 if (!width) factor = height / height_old; 15262 else if (!height) factor = width / width_old; 15263 else factor = min(width / width_old, height / height_old); 15264 15265 if (!thumb) { 15266 if (factor > iL.options.maxScale) factor = iL.options.maxScale; 15267 else if (factor < iL.options.minScale) factor = iL.options.minScale; 15268 } 15269 15270 var final_width = (iL.options.keepAspectRatio) ? round(width_old * factor) : width, 15271 final_height = (iL.options.keepAspectRatio) ? round(height_old * factor) : height; 15272 15273 return { 15274 width: final_width, 15275 height: final_height, 15276 ratio: factor 15277 }; 15278 }, 15279 15280 setOption: function(options) { 15281 var iL = this; 15282 15283 iL.options = $.extend(true, iL.options, options || {}); 15284 iL.refresh(); 15285 }, 15286 15287 availPlugins: function() { 15288 var iL = this, 15289 testEl = document.createElement("video"); 15290 15291 iL.plugins = { 15292 flash: !isMobile, 15293 quicktime: (parseInt(PluginDetect.getVersion("QuickTime")) >= 0) ? true : false, 15294 html5H264: !!(testEl.canPlayType && testEl.canPlayType('video/mp4').replace(/no/, '')), 15295 html5WebM: !!(testEl.canPlayType && testEl.canPlayType('video/webm').replace(/no/, '')), 15296 html5Vorbis: !!(testEl.canPlayType && testEl.canPlayType('video/ogg').replace(/no/, '')), 15297 html5QuickTime: !!(testEl.canPlayType && testEl.canPlayType('video/quicktime').replace(/no/, '')) 15298 }; 15299 }, 15300 15301 addContent: function(element, obj) { 15302 var iL = this, 15303 el; 15304 15305 switch (obj.type) { 15306 case 'video': 15307 var HTML5 = false, 15308 videoType = obj.videoType, 15309 html5video = obj.options.html5video; 15310 15311 if (((videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v') || html5video.h264) && iL.plugins.html5H264) 15312 obj.ext = 'mp4', 15313 obj.URL = html5video.h264 || obj.URL; 15314 else if (html5video.webm && iL.plugins.html5WebM) 15315 obj.ext = 'webm', 15316 obj.URL = html5video.webm || obj.URL; 15317 else if (html5video.ogg && iL.plugins.html5Vorbis) 15318 obj.ext = 'ogv', 15319 obj.URL = html5video.ogg || obj.URL; 15320 15321 if (iL.plugins.html5H264 && (videoType == 'video/mp4' || obj.ext == 'mp4' || obj.ext == 'm4v')) HTML5 = true, videoType = "video/mp4"; 15322 else if (iL.plugins.html5WebM && (videoType == 'video/webm' || obj.ext == 'webm')) HTML5 = true, videoType = "video/webm"; 15323 else if (iL.plugins.html5Vorbis && (videoType == 'video/ogg' || obj.ext == 'ogv')) HTML5 = true, videoType = "video/ogg"; 15324 else if (iL.plugins.html5QuickTime && (videoType == 'video/quicktime' || obj.ext == 'mov' || obj.ext == 'qt')) HTML5 = true, videoType = "video/quicktime"; 15325 15326 if (HTML5) { 15327 el = $('<video />
15327', { 15328 "width": "100%", 15329 "height": "100%", 15330 "preload": html5video.preload, 15331 "autoplay": html5video.autoplay, 15332 "loop": html5video.loop, 15333 "poster": html5video.poster, 15334 "controls": html5video.controls, 15335 "controlslist": "nodownload" 15336 }).append($('<source />', { 15337 "src": obj.URL, 15338 "type": videoType 15339 })); 15340 } else { 15341 if (!iL.plugins.quicktime) el = $('<span />', { 15342 "class": "ilightbox-alert", 15343 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.quicktime).replace('{type}', 'QuickTime') 15344 }); 15345 else { 15346 15347 el = $('<object />', { 15348 "type": "video/quicktime", 15349 "pluginspage": pluginspages.quicktime 15350 }).attr({ 15351 "data": obj.URL, 15352 "width": "100%", 15353 "height": "100%" 15354 }).append($('<param />', { 15355 "name": "src", 15356 "value": obj.URL 15357 })).append($('<param />', { 15358 "name": "autoplay", 15359 "value": "false" 15360 })).append($('<param />', { 15361 "name": "loop", 15362 "value": "false" 15363 })).append($('<param />', { 15364 "name": "scale", 15365 "value": "tofit" 15366 })); 15367 15368 if (browser.msie) el = QT_GenerateOBJECTText(obj.URL, '100%', '100%', '', 'SCALE', 'tofit', 'AUTOPLAY', 'false', 'LOOP', 'false'); 15369 } 15370 } 15371 15372 break; 15373 15374 case 'flash': 15375 if (!iL.plugins.flash) el = $('<span />', { 15376 "class": "ilightbox-alert", 15377 html: iL.options.errors.missingPlugin.replace('{pluginspage}', pluginspages.flash).replace('{type}', 'Adobe Flash player') 15378 }); 15379 else { 15380 var flashvars = "", 15381 i = 0; 15382 15383 if (obj.options.flashvars) $.each(obj.options.flashvars, function(k, v) { 15384 if (i != 0) flashvars += "&"; 15385 flashvars += k + "=" + encodeURIComponent(v); 15386 i++; 15387 }); 15388 else flashvars = null; 15389 15390 el = $('<embed />').attr({ 15391 "type": "application/x-shockwave-flash", 15392 "src": obj.URL, 15393 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 15394 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 15395 "quality": "high", 15396 "bgcolor": "#000000", 15397 "play": "true", 15398 "loop": "true", 15399 "menu": "true", 15400 "wmode": "transparent", 15401 "scale": "showall", 15402 "allowScriptAccess": "always", 15403 "allowFullScreen": "true", 15404 "flashvars": flashvars, 15405 "fullscreen": "yes" 15406 }); 15407 } 15408 15409 break; 15410 15411 case 'iframe': 15412 el = $('<iframe />').attr({ 15413 "width": (typeof obj.options.width == 'number' && obj.options.width && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.width : "100%", 15414 "height": (typeof obj.options.height == 'number' && obj.options.height && iL.options.minScale == '1' && iL.options.maxScale == '1') ? obj.options.height : "100%", 15415 src: obj.URL, 15416 frameborder: 0, 15417 'hspace': 0, 15418 'vspace': 0, 15419 'scrolling': supportTouch ? 'auto' : 'scroll', 15420 'webkitAllowFullScreen': '', 15421 'mozallowfullscreen': '', 15422 'allowFullScreen': '' 15423 }); 15424 15425 break; 15426 15427 case 'inline': 15428 el = $('<div class="ilightbox-wrapper"></div>').html($(obj.URL).clone(true)); 15429 15430 break; 15431 15432 case 'html': 15433 var object = obj.URL, 15434 el; 15435 15436 if (object[0].nodeName) { 15437 el = $('<div class="ilightbox-wrapper"></div>').html(object); 15438 } else { 15439 var dom = $(obj.URL), 15440 html = (dom.selector) ? $('<div>' + dom + '</div>') : dom; 15441 el = $('<div class="ilightbox-wrapper"></div>').html(html); 15442 } 15443 15444 break; 15445 } 15446 15447 $('div.ilightbox-container', element).empty().html(el); 15448 15449 // For fixing Chrome about just playing the video for first time 15450 if (el[0].tagName.toLowerCase() === 'video' && browser.webkit) setTimeout(function() { 15451 var src = el[0].currentSrc + '?' + floor(random() * 30000); 15452 el[0].currentSrc = src; 15453 el[0].src = src; 15454 }); 15455 15456 return el; 15457 }, 15458 15459 ogpRecognition: function(obj, callback) { 15460 var iL = this, 15461 url = obj.URL; 15462 15463 iL.showLoader(); 15464 doAjax(url, function(data) { 15465 iL.hideLoader(); 15466 if (data) { 15467 var object = new Object(); 15468 15469 object.length = false, 15470 object.url = data.url; 15471 15472 if (data.status == 200) { 15473 var result = data.results, 15474 type = result.type, 15475 source = result.source; 15476 15477 object.source = source.src, 15478 object.width = source.width && parseInt(source.width) || 0, 15479 object.height = source.height && parseInt(source.height) || 0, 15480 object.type = type, 15481 object.thumbnail = source.thumbnail || result.images && result.images[0], 15482 object.html5video = result.html5video || {}, 15483 object.length = true; 15484 15485 if (source.type == 'application/x-shockwave-flash') object.type = "flash"; 15486 else if (source.type.indexOf("video/") != -1) object.type = "video"; 15487 else if (source.type.indexOf("/html") != -1) object.type = "iframe"; 15488 else if (source.type.indexOf("image/") != -1) object.type = "image"; 15489 15490 } else if (typeof data.response != 'undefined') 15491 throw data.response; 15492 15493 callback.call(this, object.length ? object : false); 15494 } 15495 }); 15496 }, 15497 15498 hashChangeHandler: function(url) { 15499 var iL = this, 15500 vars = iL.vars, 15501 opts = iL.options, 15502 URL = url || window.location.href, 15503 hash = parseURI(URL).hash, 15504 split = hash.split('/'), 15505 index = split[1]; 15506 15507 if (vars.hashLock || ('#' + opts.linkId != split[0] && hash.length > 1)) return; 15508 15509 if (index) { 15510 var target = split[1] || 0; 15511 if (iL.items[target]) {
15512 var overlay = $('.ilightbox-overlay'); 15513 if (overlay.length && overlay.attr('linkid') == opts.linkId) { 15514 iL.goTo(target); 15515 } else { 15516 iL.itemsObject[target].trigger(ishybrid ? "itap click" : supportTouch ? 'itap' : 'click'); 15517 //iL.goTo(target); 15518 } 15519 } else { 15520 var overlay = $('.ilightbox-overlay'); 15521 if (overlay.length) iL.closeAction(); 15522 } 15523 } else { 15524 var overlay = $('.ilightbox-overlay'); 15525 if (overlay.length) iL.closeAction(); 15526 } 15527 } 15528 }; 15529 15530 /** 15531 * Parse style to pixels. 15532 * 15533 * @param {Object} $element jQuery object with element. 15534 * @param {Property} property CSS property to get the pixels from. 15535 * 15536 * @return {Int} 15537 */ 15538 function getPixel($element, property) { 15539 return parseInt($element.css(property), 10) || 0; 15540 } 15541 15542 /** 15543 * Make sure that number is within the limits. 15544 * 15545 * @param {Number} number 15546 * @param {Number} min 15547 * @param {Number} max 15548 * 15549 * @return {Number} 15550 */ 15551 function within(number, min, max) { 15552 return number < min ? min : number > max ? max : number; 15553 } 15554 15555 /** 15556 * Get viewport/window size (width and height). 15557 * 15558 * @return {Object} 15559 */ 15560 function getViewport() { 15561 var e = window, 15562 a = 'inner'; 15563 if (!('innerWidth' in window)) { 15564 a = 'client'; 15565 e = document.documentElement || document.body; 15566 } 15567 return { 15568 width: e[a + 'Width'], 15569 height: e[a + 'Height'] 15570 } 15571 } 15572 15573 /** 15574 * Remove hash tag from the URL 15575 * 15576 * @return {Void} 15577 */ 15578 function removeHash() { 15579 var scroll = getScrollXY(); 15580 15581 //UNCODE change 15582 // window.location.hash = ""; 15583 // history.pushState("", document.title, window.location.pathname + window.location.search); 15584 history.replaceState({}, document.title, window.location.pathname + window.location.search); 15585 15586 // Restore the scroll offset, should be flicker free 15587 window.scrollTo(scroll.x, scroll.y); 15588 } 15589 15590 /** 15591 * Do the ajax requests with callback. 15592 * 15593 * @param {String} url 15594 * @param {Function} callback 15595 * 15596 * @return {Void} 15597 */ 15598 function doAjax(url, callback) { 15599 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'); 15600 $.ajax({ 15601 url: url, 15602 dataType: 'jsonp' 15603 }); 15604 15605 iLCallback = function(data) { 15606 callback.call(this, data); 15607 }; 15608 } 15609 15610 /** 15611 * Find image from DOM elements 15612 * 15613 * @param {Element} element 15614 * 15615 * @return {Void} 15616 */ 15617 function findImageInElement(element) { 15618 var elements = $('*', element), 15619 imagesArr = new Array(); 15620 15621 elements.each(function() { 15622 var url = "", 15623 element = this; 15624 15625 if ($(element).css("background-image") != "none") { 15626 url = $(element).css("background-image"); 15627 } else if (typeof($(element).attr("src")) != "undefined" && element.nodeName.toLowerCase() == "img") { 15628 url = $(element).attr("src"); 15629 } 15630 15631 if (url.indexOf("gradient") == -1) { 15632 url = url.replace(/url\(\"/g, ""); 15633 url = url.replace(/url\(/g, ""); 15634 url = url.replace(/\"\)/g, ""); 15635 url = url.replace(/\)/g, ""); 15636 15637 var urls = url.split(","); 15638 15639 for (var i = 0; i < urls.length; i++) { 15640 if (urls[i].length > 0 && $.inArray(urls[i], imagesArr) == -1) { 15641 var extra = ""; 15642 if (browser.msie && browser.version < 9) { 15643 extra = "?" + floor(random() * 3000); 15644 } 15645 imagesArr.push(urls[i] + extra); 15646 } 15647 } 15648 } 15649 }); 15650 15651 return imagesArr; 15652 } 15653 15654 /** 15655 * Get file extension. 15656 * 15657 * @param {String} URL 15658 * 15659 * @return {String} 15660 */ 15661 function getExtension(URL) { 15662 if (URL !== null) { 15663 //UNCODE: fix issue to detect media type with query strings 15664 var ext = URL.indexOf('?') !== -1 ? URL.split('?')[0] : URL; 15665 ext = ext.split('.').pop().toLowerCase(); 15666 15667 return ext; 15668 } 15669 } 15670 15671 /** 15672 * Get type via extension. 15673 * 15674 * @param {String} URL 15675 * 15676 * @return {String} 15677 */ 15678 function getTypeByExtension(URL) { 15679 var type, 15680 ext = getExtension(URL); 15681 15682 //Uncode addition ##START## 15683 if (URL == undefined) { 15684 return false; 15685 } 15686 //Uncode addition ##END## 15687 15688 if (extensions.image.indexOf(ext) !== -1) type = 'image'; 15689 else if (extensions.flash.indexOf(ext) !== -1) type = 'flash'; 15690 else if (extensions.video.indexOf(ext) !== -1) type = 'video'; 15691 else if (ext.substring(0, 1) == "#") type = 'inline'; //Uncode addition 15692 else type = 'iframe'; 15693 15694 return type; 15695 } 15696 15697 /** 15698 * Return value from percent of a number. 15699 * 15700 * @param {Number} percent 15701 * @param {Number} total 15702 * 15703 * @return {Number} 15704 */ 15705 function percentToValue(percent, total) { 15706 return parseInt((total / 100) * percent); 15707 } 15708 15709 /** 15710 * A JavaScript equivalent of PHPâs parse_url. 15711 * 15712 * @param {String} url The URL to parse. 15713 * 15714 * @return {Mixed} 15715 */ 15716 function parseURI(url) { 15717 var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); 15718 // authority = '//' + user + ':' + pass '@' + hostname + ':' port 15719 return (m ? { 15720 href: m[0] || '', 15721 protocol: m[1] || '', 15722 authority: m[2] || '', 15723 host: m[3] || '', 15724 hostname: m[4] || '', 15725 port: m[5] || '', 15726 pathname: m[6] || '', 15727 search: m[7] || '', 15728 hash: m[8] || '' 15729 } : null); 15730 } 15731 15732 /** 15733 * Gets the absolute URI. 15734 * 15735 * @param {String} href The relative URL. 15736 * @param {String} base The base URL. 15737 * 15738 * @return {String} The absolute URL. 15739 */ 15740 function absolutizeURI(base, href) { // RFC 3986 15741 var iL = this; 15742 15743 function removeDotSegments(input) { 15744 var output = []; 15745 input.replace(/^(\.\.?(\/|$))+/, '') 15746 .replace(/\/(\.(\/|$))+/g, '/') 15747 .replace(/\/\.\.$/, '/../') 15748 .replace(/\/?[^\/]*/g, function(p) { 15749 if (p === '/..') { 15750 output.pop(); 15751 } else { 15752 output.push(p); 15753 } 15754 }); 15755 return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); 15756 } 15757 15758 href = parseURI(href || ''); 15759 base = parseURI(base || ''); 15760 15761 return !href || !base ? null : (href.protocol || base.protocol) + 15762 (href.protocol || href.authority ? href.authority : base.authority) + 15763 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)) + 15764 (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + 15765 href.hash; 15766 } 15767 15768 /** 15769 * A JavaScript equivalent of PHPâs version_compare. 15770 * 15771 * @param {String} v1 15772 * @param {String} v2 15773 * @param {String} operator
15774 * 15775 * @return {Boolean} 15776 */ 15777 function version_compare(v1, v2, operator) { 15778 this.php_js = this.php_js || {}; 15779 this.php_js.ENV = this.php_js.ENV || {}; 15780 var i = 0, 15781 x = 0, 15782 compare = 0, 15783 vm = { 15784 'dev': -6, 15785 'alpha': -5, 15786 'a': -5, 15787 'beta': -4, 15788 'b': -4, 15789 'RC': -3, 15790 'rc': -3, 15791 '#': -2, 15792 'p': 1, 15793 'pl': 1 15794 }, 15795 prepVersion = function(v) { 15796 v = ('' + v).replace(/[_\-+]/g, '.'); 15797 v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.'); 15798 return (!v.length ? [-8] : v.split('.')); 15799 }, 15800 numVersion = function(v) { 15801 return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10)); 15802 }; 15803 v1 = prepVersion(v1); 15804 v2 = prepVersion(v2); 15805 x = max(v1.length, v2.length); 15806 for (i = 0; i < x; i++) { 15807 if (v1[i] == v2[i]) { 15808 continue; 15809 } 15810 v1[i] = numVersion(v1[i]); 15811 v2[i] = numVersion(v2[i]); 15812 if (v1[i] < v2[i]) { 15813 compare = -1; 15814 break; 15815 } else if (v1[i] > v2[i]) { 15816 compare = 1; 15817 break; 15818 } 15819 } 15820 if (!operator) { 15821 return compare; 15822 } 15823 15824 switch (operator) { 15825 case '>': 15826 case 'gt': 15827 return (compare > 0); 15828 case '>=': 15829 case 'ge': 15830 return (compare >= 0); 15831 case '<=': 15832 case 'le': 15833 return (compare <= 0); 15834 case '==': 15835 case '=': 15836 case 'eq': 15837 return (compare === 0); 15838 case '<>': 15839 case '!=': 15840 case 'ne': 15841 return (compare !== 0); 15842 case '': 15843 case '<': 15844 case 'lt': 15845 return (compare < 0); 15846 default: 15847 return null; 15848 } 15849 } 15850 15851 15852 // Begin the iLightBox plugin 15853 $.fn.iLightBox = function() { 15854 15855 var args = arguments, 15856 opt = ($.isPlainObject(args[0])) ? args[0] : args[1], 15857 items = ($.isArray(args[0]) || typeof args[0] == 'string') ? args[0] : args[1]; 15858 15859 if (!opt) opt = {}; 15860 15861 // Default options. Play carefully. 15862 var options = $.extend(true, { 15863 attr: 'href', 15864 path: 'vertical', 15865 skin: 'dark', 15866 linkId: false, 15867 infinite: false, 15868 startFrom: 0, 15869 randomStart: false, 15870 keepAspectRatio: true, 15871 maxScale: 1, 15872 minScale: .2, 15873 innerToolbar: false, 15874 smartRecognition: false, 15875 mobileOptimizer: true, 15876 fullAlone: true, 15877 fullViewPort: null, 15878 fullStretchTypes: 'flash, video', 15879 overlay: { 15880 blur: true, 15881 opacity: .85 15882 }, 15883 controls: { 15884 arrows: false, 15885 slideshow: false, 15886 toolbar: true, 15887 fullscreen: true, 15888 thumbnail: true, 15889 keyboard: true, 15890 mousewheel: true, 15891 swipe: true 15892 }, 15893 keyboard: { 15894 left: true, // previous 15895 right: true, // next 15896 up: true, // previous 15897 down: true, // next 15898 esc: true, // close 15899 shift_enter: true // fullscreen 15900 }, 15901 show: { 15902 effect: true, 15903 speed: 300, 15904 title: true 15905 }, 15906 hide: { 15907 effect: true, 15908 speed: 300 15909 }, 15910 caption: { 15911 start: true, 15912 show: 'mouseenter', 15913 hide: 'mouseleave' 15914 }, 15915 social: { 15916 start: true, 15917 show: 'mouseenter', 15918 hide: 'mouseleave',
15919 buttons: false 15920 }, 15921 styles: { 15922 pageOffsetX: 0, 15923 pageOffsetY: 0, 15924 nextOffsetX: 45, 15925 nextOffsetY: 0, 15926 nextOpacity: 1, 15927 nextScale: 1, 15928 prevOffsetX: 45, 15929 prevOffsetY: 0, 15930 prevOpacity: 1, 15931 prevScale: 1 15932 }, 15933 thumbnails: { 15934 maxWidth: 120, 15935 maxHeight: 80, 15936 normalOpacity: 1, 15937 activeOpacity: .6 15938 }, 15939 effects: { 15940 reposition: true, 15941 repositionSpeed: 200, 15942 switchSpeed: 500, 15943 loadedFadeSpeed: 180, 15944 fadeSpeed: 200 15945 }, 15946 slideshow: { 15947 pauseTime: 5000, 15948 pauseOnHover: false, 15949 startPaused: true 15950 }, 15951 text: { 15952 close: "Press Esc to close", 15953 enterFullscreen: "Enter Fullscreen (Shift+Enter)", 15954 exitFullscreen: "Exit Fullscreen (Shift+Enter)", 15955 slideShow: "Slideshow", 15956 next: "Next", 15957 previous: "Previous" 15958 }, 15959 errors: { 15960 loadImage: "An error occurred when trying to load photo.", 15961 loadContents: "An error occurred when trying to load contents.", 15962 missingPlugin: "The content your are attempting to view requires the <a href='{pluginspage}' target='_blank'>{type} plugin<\/a>." 15963 }, 15964 ajaxSetup: { 15965 url: '', 15966 beforeSend: function(jqXHR, settings) {}, 15967 cache: false, 15968 complete: function(jqXHR, textStatus) {}, 15969 crossDomain: false, 15970 error: function(jqXHR, textStatus, errorThrown) {}, 15971 success: function(data, textStatus, jqXHR) {}, 15972 global: true, 15973 ifModified: false, 15974 username: null, 15975 password: null, 15976 type: 'GET' 15977 }, 15978 callback: {} 15979 }, opt); 15980 15981 var instant = ($.isArray(items) || typeof items == 'string') ? true : false; 15982 15983 items = $.isArray(items) ? items : new Array(); 15984 15985 if (typeof args[0] == 'string') items[0] = args[0]; 15986 15987 if (version_compare($.fn.jquery, '1.8', '>=')) { 15988 var iLB = new iLightBox($(this), options, items, instant); 15989 return { 15990 close: function() { 15991 iLB.closeAction(); 15992 }, 15993 fullscreen: function() { 15994 iLB.fullScreenAction(); 15995 }, 15996 moveNext: function() { 15997 iLB.moveTo('next'); 15998 }, 15999 movePrev: function() { 16000 iLB.moveTo('prev'); 16001 }, 16002 goTo: function(index) { 16003 iLB.goTo(index); 16004 }, 16005 refresh: function() { 16006 iLB.refresh(); 16007 }, 16008 reposition: function() { 16009 (arguments.length > 0) ? iLB.repositionPhoto(true): iLB.repositionPhoto(); 16010 }, 16011 setOption: function(options) { 16012 iLB.setOption(options); 16013 }, 16014 destroy: function() { 16015 iLB.closeAction(); 16016 iLB.dispatchItemsEvents(); 16017 } 16018 }; 16019 } else { 16020 throw "The jQuery version that was loaded is too old. iLightBox requires jQuery 1.8+"; 16021 } 16022 16023 }; 16024 16025 16026 $.iLightBox = function() { 16027 return $.fn.iLightBox(arguments[0], arguments[1]); 16028 }; 16029 16030 function getScrollXY() { 16031 var scrOfX = 0, 16032 scrOfY = 0; 16033 if (typeof(window.pageYOffset) == 'number') { 16034 //Netscape compliant 16035 scrOfY = window.pageYOffset; 16036 scrOfX = window.pageXOffset; 16037 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { 16038 //DOM compliant 16039 scrOfY = document.body.scrollTop; 16040 scrOfX = document.body.scrollLeft; 16041 } else if (document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) { 16042 //IE6 standards compliant mode 16043 scrOfY = document.documentElement.scrollTop; 16044 scrOfX = document.documentElement.scrollLeft; 16045 } 16046 return { 16047 x: scrOfX, 16048 y: scrOfY 16049 }; 16050 } 16051 16052 (function() { 16053 // add new event shortcuts 16054 $.each(("touchstart touchmove touchend " + 16055 "tap taphold " + 16056 "swipe swipeleft swiperight " + 16057 "scrollstart scrollstop").split(" "), function(i, name) { 16058 16059 $.fn[name] = function(fn) { 16060 return fn ? this.bind(name, fn) : this.trigger(name); 16061 }; 16062 16063 // jQuery < 1.8 16064 // if ($.attrFn) { 16065 // $.attrFn[name] = true; 16066 // } 16067 }); 16068 16069 var tapSettings = { 16070 startEvent: 'touchstart.iTap', 16071 endEvent: 'touchend.iTap' 16072 }; 16073 16074 // tap Event: 16075 $.event.special.itap = { 16076 setup: function() { 16077 16078 var self = this, 16079 $self = $(this), 16080 start, stop; 16081 16082 $self.bind(tapSettings.startEvent, function(event) { 16083 start = getScrollXY(); 16084 16085 $self.one(tapSettings.endEvent, function(event) { 16086 stop = getScrollXY(); 16087 16088 var orgEvent = event || window.event; 16089 event = $.event.fix(orgEvent); 16090 event.type = "itap"; 16091 16092 if ((start && stop) && (start.x == stop.x && start.y == stop.y))($.event.dispatch || $.event.handle).call(self, event); 16093 16094 start = stop = undefined; 16095 }); 16096 }); 16097 }, 16098 16099 teardown: function() { 16100 $(this).unbind(tapSettings.startEvent); 16101 } 16102 }; 16103 }()); 16104 16105 16106 //Fullscreen API 16107 (function() { 16108 fullScreenApi = { 16109 supportsFullScreen: false, 16110 isFullScreen: function() { 16111 return false;
16112 }, 16113 requestFullScreen: function() {}, 16114 cancelFullScreen: function() {}, 16115 fullScreenEventName: '', 16116 prefix: '' 16117 }, 16118 browserPrefixes = 'webkit moz o ms khtml'.split(' '); 16119 16120 // check for native support 16121 if (typeof document.cancelFullScreen != 'undefined') { 16122 fullScreenApi.supportsFullScreen = true; 16123 } else { 16124 // check for fullscreen support by vendor prefix 16125 for (var i = 0, il = browserPrefixes.length; i < il; i++) { 16126 fullScreenApi.prefix = browserPrefixes[i]; 16127 16128 if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] != 'undefined') { 16129 fullScreenApi.supportsFullScreen = true; 16130 16131 break; 16132 } 16133 } 16134 } 16135 16136 // update methods to do something useful 16137 if (fullScreenApi.supportsFullScreen) { 16138 fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; 16139 16140 fullScreenApi.isFullScreen = function() { 16141 switch (this.prefix) { 16142 case '': 16143 return document.fullScreen; 16144 case 'webkit': 16145 return document.webkitIsFullScreen; 16146 default: 16147 return document[this.prefix + 'FullScreen']; 16148 } 16149 } 16150 fullScreenApi.requestFullScreen = function(el) { 16151 return (this.prefix === '') ? el.requestFullScreen() : el[this.prefix + 'RequestFullScreen'](); 16152 } 16153 fullScreenApi.cancelFullScreen = function(el) { 16154 return (this.prefix === '') ? document.cancelFullScreen() : document[this.prefix + 'CancelFullScreen'](); 16155 } 16156 } 16157 }()); 16158 16159 // Browser detect 16160 (function() { 16161 function uaMatch(ua) { 16162 ua = ua.toLowerCase(); 16163 16164 var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || 16165 /(webkit)[ \/]([\w.]+)/.exec(ua) || 16166 /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || 16167 /(msie) ([\w.]+)/.exec(ua) || 16168 ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || []; 16169 16170 return { 16171 browser: match[1] || "", 16172 version: match[2] || "0" 16173 }; 16174 } 16175 16176 var matched = uaMatch(navigator.userAgent); 16177 browser = {}; 16178 16179 if (matched.browser) { 16180 browser[matched.browser] = true; 16181 browser.version = matched.version; 16182 } 16183 16184 // Chrome is Webkit, but Webkit is also Safari. 16185 if (browser.chrome) { 16186 browser.webkit = true; 16187 } else if (browser.webkit) { 16188 browser.safari = true; 16189 } 16190 }()); 16191 16192 // Feature detects 16193 (function() { 16194 var prefixes = ['', 'webkit', 'moz', 'ms', 'o']; 16195 var el = document.createElement('div'); 16196 16197 function testProp(prop) { 16198 for (var p = 0, pl = prefixes.length; p < pl; p++) { 16199 var prefixedProp = prefixes[p] ? prefixes[p] + prop.charAt(0).toUpperCase() + prop.slice(1) : prop; 16200 if (el.style[prefixedProp] !== undefined) { 16201 return prefixedProp; 16202 } 16203 } 16204 } 16205 16206 // Global support indicators 16207 transform = testProp('transform') || ''; 16208 gpuAcceleration = testProp('perspective') ? 'translateZ(0) ' : ''; 16209 }()); 16210 16211 16212 /* 16213 PluginDetect v0.7.9 16214 www.pinlady.net/PluginDetect/license/ 16215 [ getVersion onWindowLoaded BetterIE ] 16216 [ Flash QuickTime Shockwave ] 16217 */ 16218 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;
16218d++){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);
16218d.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)}
16218c.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;
16218if(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(); 16219 16220 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)}; 16221 16222 16223 /* 16224 jQuery hashchange event v1.3 16225 https://github.com/cowboy/jquery-hashchange 16226 Copyright (c) 2010 "Cowboy" Ben Alman 16227 Dual licensed under the MIT and GPL licenses. 16228 */ 16229 (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= 16230 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|| 16231 "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;
16231a!==d&&(b.title=k.title,b.open(),e&&b.write('<script>document.domain="'+e+'"\x3c/script>'),b.close(),c.location.hash=a)}}();return h}()})(); 16232 16233 if (!Array.prototype.filter) { 16234 Array.prototype.filter = function(fun /*, thisp */ ) { 16235 "use strict"; 16236 16237 if (this == null) 16238 throw new TypeError(); 16239 16240 var t = Object(this); 16241 var len = t.length >>> 0; 16242 if (typeof fun != "function") 16243 throw new TypeError(); 16244 16245 var res = []; 16246 var thisp = arguments[1]; 16247 for (var i = 0; i < len; i++) { 16248 if (i in t) { 16249 var val = t[i]; // in case fun mutates this 16250 if (fun.call(thisp, val, i, t)) 16251 res.push(val); 16252 } 16253 } 16254 16255 return res; 16256 }; 16257 } 16258 16259 if (!Array.prototype.indexOf) { 16260 Array.prototype.indexOf = function(searchElement, fromIndex) { 16261 var k; 16262 16263 if (this == null) { 16264 throw new TypeError('"this" is null or not defined'); 16265 } 16266 16267 var O = Object(this); 16268 16269 var len = O.length >>> 0; 16270 16271 if (len === 0) { 16272 return -1; 16273 } 16274 16275 var n = +fromIndex || 0; 16276 16277 if (abs(n) === Infinity) { 16278 n = 0; 16279 } 16280 16281 if (n >= len) { 16282 return -1; 16283 } 16284 16285 k = max(n >= 0 ? n : len - abs(n), 0); 16286 16287 while (k < len) { 16288 var kValue; 16289 if (k in O && O[k] === searchElement) { 16290 return k; 16291 } 16292 k++; 16293 } 16294 return -1; 16295 }; 16296 } 16297 16298 if (!Array.prototype.lastIndexOf) { 16299 Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/ ) { 16300 "use strict"; 16301 16302 if (this == null) 16303 throw new TypeError(); 16304 16305 var t = Object(this); 16306 var len = t.length >>> 0; 16307 if (len === 0) 16308 return -1; 16309 16310 var n = len; 16311 if (arguments.length > 1) { 16312 n = Number(arguments[1]); 16313 if (n != n) 16314 n = 0; 16315 else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) 16316 n = (n > 0 || -1) * floor(abs(n)); 16317 } 16318 16319 var k = n >= 0 ? min(n, len - 1) : len - abs(n); 16320 16321 for (; k >= 0; k--) { 16322 if (k in t && t[k] === searchElement) 16323 return k; 16324 } 16325 return -1; 16326 }; 16327 } 16328})(jQuery, this); 16329 16330/*! 16331 * lightgallery | 2.4.0 | January 29th 2022 16332 * http://www.lightgalleryjs.com/ 16333 * Copyright (c) 2020 Sachin Neravath; 16334 * @license GPLv3 16335 */ 16336 16337(function (global, factory) { 16338 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 16339 typeof define === 'function' && define.amd ? define(factory) : 16340 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lightGallery = factory()); 16341}(this, (function () { 'use strict'; 16342 16343 /*! ***************************************************************************** 16344 Copyright (c) Microsoft Corporation. 16345 16346 Permission to use, copy, modify, and/or distribute this software for any 16347 purpose with or without fee is hereby granted. 16348 16349 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 16350 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 16351 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 16352 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 16353 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 16354 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16355 PERFORMANCE OF THIS SOFTWARE. 16356 ***************************************************************************** */ 16357 16358 var __assign = function() { 16359 __assign = Object.assign || function __assign(t) { 16360 for (var s, i = 1, n = arguments.length; i < n; i++) { 16361 s = arguments[i]; 16362 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 16363 } 16364 return t; 16365 }; 16366 return __assign.apply(this, arguments); 16367 }; 16368 16369 function __spreadArrays() { 16370 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 16371 for (var r = Array(s), k = 0, i = 0; i < il; i++) 16372 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 16373 r[k] = a[j]; 16374 return r; 16375 } 16376 16377 /** 16378 * List of lightGallery events 16379 * All events should be documented here 16380 * Below interfaces are used to build the website documentations 16381 * */ 16382 var lGEvents = { 16383 afterAppendSlide: 'lgAfterAppendSlide', 16384 init: 'lgInit', 16385 hasVideo: 'lgHasVideo', 16386 containerResize: 'lgContainerResize', 16387 updateSlides: 'lgUpdateSlides', 16388 afterAppendSubHtml: 'lgAfterAppendSubHtml', 16389 beforeOpen: 'lgBeforeOpen', 16390 afterOpen: 'lgAfterOpen', 16391 slideItemLoad: 'lgSlideItemLoad', 16392 beforeSlide: 'lgBeforeSlide', 16393 afterSlide: 'lgAfterSlide', 16394 posterClick: 'lgPosterClick', 16395 dragStart: 'lgDragStart', 16396 dragMove: 'lgDragMove', 16397 dragEnd: 'lgDragEnd', 16398 beforeNextSlide: 'lgBeforeNextSlide', 16399 beforePrevSlide: 'lgBeforePrevSlide', 16400 beforeClose: 'lgBeforeClose', 16401 afterClose: 'lgAfterClose', 16402 rotateLeft: 'lgRotateLeft', 16403 rotateRight: 'lgRotateRight', 16404 flipHorizontal: 'lgFlipHorizontal', 16405 flipVertical: 'lgFlipVertical', 16406 autoplay: 'lgAutoplay', 16407 autoplayStart: 'lgAutoplayStart', 16408 autoplayStop: 'lgAutoplayStop', 16409 }; 16410 16411 var lightGalleryCoreSettings = { 16412 mode: 'lg-slide', 16413 easing: 'ease', 16414 speed: 400, 16415 licenseKey: '0000-0000-000-0000', 16416 height: '100%', 16417 width: '100%', 16418 addClass: '', 16419 startClass: 'lg-start-zoom', 16420 backdropDuration: 300, 16421 container: '', 16422 startAnimationDuration: 400, 16423 zoomFromOrigin: true, 16424 hideBarsDelay: 0, 16425 showBarsAfter: 10000, 16426 slideDelay: 0, 16427 supportLegacyBrowser: true, 16428 allowMediaOverlap: false, 16429 videoMaxSize: '1280-720', 16430 loadYouTubePoster: true, 16431 defaultCaptionHeight: 0, 16432 ariaLabelledby: '', 16433 ariaDescribedby: '', 16434 closable: true, 16435 swipeToClose: true, 16436 closeOnTap: true, 16437 showCloseIcon: true, 16438 showMaximizeIcon: false, 16439 loop: true, 16440 escKey: true, 16441 keyPress: true, 16442 controls: true, 16443 slideEndAnimation: true, 16444 hideControlOnEnd: false, 16445 mousewheel: false, 16446 getCaptionFromTitleOrAlt: true, 16447 appendSubHtmlTo: '.lg-sub-html', 16448 subHtmlSelectorRelative: false, 16449 preload: 2, 16450 numberOfSlideItemsInDom: 10, 16451 selector: '', 16452 selectWithin: '', 16453 nextHtml: '', 16454 prevHtml: '', 16455 index: 0, 16456 iframeWidth: '100%', 16457 iframeHeight: '100%', 16458 iframeMaxWidth: '100%', 16459 iframeMaxHeight: '100%', 16460 download: true, 16461 counter: true, 16462 appendCounterTo: '.lg-toolbar', 16463 swipeThreshold: 50, 16464 enableSwipe: true, 16465 enableDrag: true,
vendor: 59,996 bytes, lines 16466-17818
16466 dynamic: false, 16467 dynamicEl: [], 16468 extraProps: [], 16469 exThumbImage: '', 16470 isMobile: undefined, 16471 mobileSettings: { 16472 controls: false, 16473 showCloseIcon: false, 16474 download: false, 16475 }, 16476 plugins: [], 16477 strings: { 16478 closeGallery: 'Close gallery', 16479 toggleMaximize: 'Toggle maximize', 16480 previousSlide: 'Previous slide', 16481 nextSlide: 'Next slide', 16482 download: 'Download', 16483 playVideo: 'Play video', 16484 }, 16485 }; 16486 16487 function initLgPolyfills() { 16488 (function () { 16489 if (typeof window.CustomEvent === 'function') 16490 return false; 16491 function CustomEvent(event, params) { 16492 params = params || { 16493 bubbles: false, 16494 cancelable: false, 16495 detail: null, 16496 }; 16497 var evt = document.createEvent('CustomEvent'); 16498 evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); 16499 return evt; 16500 } 16501 window.CustomEvent = CustomEvent; 16502 })(); 16503 (function () { 16504 if (!Element.prototype.matches) { 16505 Element.prototype.matches = 16506 Element.prototype.msMatchesSelector || 16507 Element.prototype.webkitMatchesSelector; 16508 } 16509 })(); 16510 } 16511 var lgQuery = /** @class */ (function () { 16512 function lgQuery(selector) { 16513 this.cssVenderPrefixes = [ 16514 'TransitionDuration', 16515 'TransitionTimingFunction', 16516 'Transform', 16517 'Transition', 16518 ]; 16519 this.selector = this._getSelector(selector); 16520 this.firstElement = this._getFirstEl(); 16521 return this; 16522 } 16523 lgQuery.generateUUID = function () { 16524 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { 16525 var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; 16526 return v.toString(16); 16527 }); 16528 }; 16529 lgQuery.prototype._getSelector = function (selector, context) { 16530 if (context === void 0) { context = document; } 16531 if ( typeof selector === 'object' ) { 16532 return selector; 16533 } else { 16534 if (typeof selector !== 'string') { 16535 return selector; 16536 } 16537 } 16538 context = context || document; 16539 var fl = selector.substring(0, 1); 16540 if (fl === '#') { 16541 return context.querySelector(selector); 16542 } 16543 else { 16544 return context.querySelectorAll(selector); 16545 } 16546 }; 16547 lgQuery.prototype._each = function (func) { 16548 if (!this.selector) { 16549 return this; 16550 } 16551 if (this.selector.length !== undefined) { 16552 [].forEach.call(this.selector, func); 16553 } 16554 else { 16555 func(this.selector, 0); 16556 } 16557 return this; 16558 }; 16559 lgQuery.prototype._setCssVendorPrefix = function (el, cssProperty, value) { 16560 // prettier-ignore 16561 var property = cssProperty.replace(/-([a-z])/gi, function (s, group1) { 16562 return group1.toUpperCase(); 16563 }); 16564 if (this.cssVenderPrefixes.indexOf(property) !== -1) { 16565 el.style[property.charAt(0).toLowerCase() + property.slice(1)] = value; 16566 el.style['webkit' + property] = value; 16567 el.style['moz' + property] = value; 16568 el.style['ms' + property] = value; 16569 el.style['o' + property] = value; 16570 } 16571 else { 16572 el.style[property] = value; 16573 } 16574 }; 16575 lgQuery.prototype._getFirstEl = function () { 16576 if (this.selector && this.selector.length !== undefined) { 16577 return this.selector[0]; 16578 } 16579 else { 16580 return this.selector; 16581 } 16582 }; 16583 lgQuery.prototype.isEventMatched = function (event, eventName) { 16584 var eventNamespace = eventName.split('.'); 16585 return event 16586 .split('.') 16587 .filter(function (e) { return e; }) 16588 .every(function (e) { 16589 return eventNamespace.indexOf(e) !== -1; 16590 }); 16591 }; 16592 lgQuery.prototype.attr = function (attr, value) { 16593 if (value === undefined) { 16594 if (!this.firstElement) { 16595 return ''; 16596 } 16597 return this.firstElement.getAttribute(attr); 16598 } 16599 this._each(function (el) { 16600 el.setAttribute(attr, value); 16601 }); 16602 return this; 16603 }; 16604 lgQuery.prototype.find = function (selector) { 16605 return $LG(this._getSelector(selector, this.selector)); 16606 }; 16607 lgQuery.prototype.first = function () { 16608 if (this.selector && this.selector.length !== undefined) { 16609 return $LG(this.selector[0]); 16610 } 16611 else { 16612 return $LG(this.selector); 16613 } 16614 }; 16615 lgQuery.prototype.eq = function (index) { 16616 return $LG(this.selector[index]); 16617 }; 16618 lgQuery.prototype.parent = function () { 16619 return $LG(this.selector.parentElement); 16620 }; 16621 lgQuery.prototype.get = function () { 16622 return this._getFirstEl(); 16623 }; 16624 lgQuery.prototype.removeAttr = function (attributes) { 16625 var attrs = attributes.split(' '); 16626 this._each(function (el) { 16627 attrs.forEach(function (attr) { return el.removeAttribute(attr); }); 16628 }); 16629 return this; 16630 }; 16631 lgQuery.prototype.wrap = function (className) { 16632 if (!this.firstElement) { 16633 return this; 16634 } 16635 var wrapper = document.createElement('div'); 16636 wrapper.className = className; 16637 this.firstElement.parentNode.insertBefore(wrapper, this.firstElement); 16638 this.firstElement.parentNode.removeChild(this.firstElement); 16639 wrapper.appendChild(this.firstElement); 16640 return this; 16641 }; 16642 lgQuery.prototype.addClass = function (classNames) { 16643 if (classNames === void 0) { classNames = ''; } 16644 this._each(function (el) { 16645 // IE doesn't support multiple arguments 16646 classNames.split(' ').forEach(function (className) { 16647 if (className) { 16648 el.classList.add(className); 16649 } 16650 }); 16651 }); 16652 return this; 16653 }; 16654 lgQuery.prototype.removeClass = function (classNames) { 16655 this._each(function (el) { 16656 // IE doesn't support multiple arguments 16657 classNames.split(' ').forEach(function (className) { 16658 if (className) { 16659 el.classList.remove(className); 16660 } 16661 }); 16662 }); 16663 return this; 16664 }; 16665 lgQuery.prototype.hasClass = function (className) { 16666 if (!this.firstElement) { 16667 return false; 16668 } 16669 return this.firstElement.classList.contains(className); 16670 }; 16671 lgQuery.prototype.hasAttribute = function (attribute) { 16672 if (!this.firstElement) { 16673 return false; 16674 } 16675 return this.firstElement.hasAttribute(attribute); 16676 }; 16677 lgQuery.prototype.toggleClass = function (className) { 16678 if (!this.firstElement) { 16679 return this; 16680 } 16681 if (this.hasClass(className)) { 16682 this.removeClass(className); 16683 } 16684 else { 16685 this.addClass(className); 16686 } 16687 return this; 16688 }; 16689 lgQuery.prototype.css = function (property, value) { 16690 var _this = this; 16691 this._each(function (el) { 16692 _this._setCssVendorPrefix(el, property, value); 16693 }); 16694 return this; 16695 }; 16696 // Need to pass separate namespaces for separate elements 16697 lgQuery.prototype.on = function (events, listener) { 16698 var _this = this; 16699 if (!this.selector) { 16700 return this; 16701 } 16702 events.split(' ').forEach(function (event) { 16703 if (!Array.isArray(lgQuery.eventListeners[event])) { 16704 lgQuery.eventListeners[event] = []; 16705 } 16706 lgQuery.eventListeners[event].push(listener); 16707 _this.selector.addEventListener(event.split('.')[0], listener); 16708 }); 16709 return this; 16710 }; 16711 // @todo - test this 16712 lgQuery.prototype.once = function (event, listener) { 16713 var _this = this; 16714 this.on(event, function () { 16715 _this.off(event); 16716 listener(event); 16717 }); 16718 return this; 16719 }; 16720 lgQuery.prototype.off = function (event) { 16721 var _this = this; 16722 if (!this.selector) { 16723 return this; 16724 } 16725 Object.keys(lgQuery.eventListeners).forEach(function (eventName) { 16726 if (_this.isEventMatched(event, eventName)) { 16727 lgQuery.eventListeners[eventName].forEach(function (listener) { 16728 _this.selector.removeEventListener(eventName.split('.')[0], listener); 16729 }); 16730 lgQuery.eventListeners[eventName] = []; 16731 } 16732 }); 16733 return this; 16734 }; 16735 lgQuery.prototype.trigger = function (event, detail) { 16736 if (!this.firstElement) { 16737 return this; 16738 } 16739 var customEvent = new CustomEvent(event.split('.')[0], { 16740 detail: detail || null, 16741 }); 16742 this.firstElement.dispatchEvent(customEvent); 16743 return this; 16744 }; 16745 // Does not support IE 16746 lgQuery.prototype.load = function (url) { 16747 var _this = this; 16748 fetch(url) 16749 .then(function (res) { return res.text(); }) 16750 .then(function (html) { 16751 _this.selector.innerHTML = html; 16752 }); 16753 return this; 16754 }; 16755 lgQuery.prototype.html = function (html) { 16756 if (html === undefined) { 16757 if (!this.firstElement) { 16758 return ''; 16759 } 16760 return this.firstElement.innerHTML; 16761 } 16762 this._each(function (el) { 16763 el.innerHTML = html; 16764 }); 16765 return this; 16766 }; 16767 lgQuery.prototype.append = function (html) { 16768 this._each(function (el) { 16769 if (typeof html === 'string') { 16770 el.insertAdjacentHTML('beforeend', html); 16771 } 16772 else { 16773 el.appendChild(html); 16774 } 16775 }); 16776 return this; 16777 }; 16778 lgQuery.prototype.prepend = function (html) { 16779 this._each(function (el) { 16780 el.insertAdjacentHTML('afterbegin', html); 16781 }); 16782 return this; 16783 }; 16784 lgQuery.prototype.remove = function () { 16785 this._each(function (el) { 16786 el.parentNode.removeChild(el); 16787 }); 16788 return this; 16789 }; 16790 lgQuery.prototype.empty = function () { 16791 this._each(function (el) { 16792 el.innerHTML = ''; 16793 }); 16794 return this; 16795 }; 16796 lgQuery.prototype.scrollTop = function (scrollTop) { 16797 if (scrollTop !== undefined) { 16798 document.body.scrollTop = scrollTop; 16799 document.documentElement.scrollTop = scrollTop; 16800 return this; 16801 } 16802 else { 16803 return (window.pageYOffset || 16804 document.documentElement.scrollTop || 16805 document.body.scrollTop || 16806 0); 16807 } 16808 }; 16809 lgQuery.prototype.scrollLeft = function (scrollLeft) { 16810 if (scrollLeft !== undefined) { 16811 document.body.scrollLeft = scrollLeft; 16812 document.documentElement.scrollLeft = scrollLeft; 16813 return this; 16814 } 16815 else { 16816 return (window.pageXOffset || 16817 document.documentElement.scrollLeft || 16818 document.body.scrollLeft || 16819 0); 16820 } 16821 }; 16822 lgQuery.prototype.offset = function () { 16823 if (!this.firstElement) { 16824 return { 16825 left: 0, 16826 top: 0, 16827 }; 16828 } 16829 var rect = this.firstElement.getBoundingClientRect(); 16830 var bodyMarginLeft = $LG('body').style().marginLeft; 16831 // Minus body margin - https://stackoverflow.com/questions/30711548/is-getboundingclientrect-left-returning-a-wrong-value 16832 return { 16833 left: rect.left - parseFloat(bodyMarginLeft) + this.scrollLeft(), 16834 top: rect.top + this.scrollTop(), 16835 }; 16836 }; 16837 lgQuery.prototype.style = function () { 16838 if (!this.firstElement) { 16839 return {}; 16840 } 16841 return (this.firstElement.currentStyle || 16842 window.getComputedStyle(this.firstElement)); 16843 }; 16844 // Width without padding and border even if box-sizing is used. 16845 lgQuery.prototype.width = function () { 16846 var style = this.style(); 16847 return (this.firstElement.clientWidth - 16848 parseFloat(style.paddingLeft) - 16849 parseFloat(style.paddingRight)); 16850 }; 16851 // Height without padding and border even if box-sizing is used. 16852 lgQuery.prototype.height = function () { 16853 var style = this.style(); 16854 return (this.firstElement.clientHeight - 16855 parseFloat(style.paddingTop) - 16856 parseFloat(style.paddingBottom)); 16857 }; 16858 lgQuery.eventListeners = {}; 16859 return lgQuery; 16860 }()); 16861 function $LG(selector) { 16862 initLgPolyfills(); 16863 return new lgQuery(selector); 16864 } 16865 16866 var defaultDynamicOptions = [ 16867 'src', 16868 'sources', 16869 'subHtml', 16870 'subHtmlUrl', 16871 'html', 16872 'video', 16873 'poster', 16874 'slideName', 16875 'responsive', 16876 'srcset', 16877 'sizes', 16878 'iframe', 16879 'downloadUrl', 16880 'download', 16881 'width', 16882 'facebookShareUrl', 16883 'tweetText', 16884 'iframeTitle', 16885 'twitterShareUrl', 16886 'pinterestShareUrl', 16887 'pinterestText', 16888 'fbHtml', 16889 'disqusIdentifier', 16890 'disqusUrl', 16891 ]; 16892 // Convert html data-attribute to camalcase 16893 function convertToData(attr) { 16894 // FInd a way for lgsize 16895 if (attr === 'href') { 16896 return 'src'; 16897 } 16898 attr = attr.replace('data-', ''); 16899 attr = attr.charAt(0).toLowerCase() + attr.slice(1); 16900 attr = attr.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); 16901 return attr; 16902 } 16903 var utils = { 16904 /** 16905 * get possible width and height from the lgSize attribute. Used for ZoomFromOrigin option 16906 */ 16907 //Uncode edit ##START## 16908 getSize: function (el, container, spacing, defaultLgSize, galleryItem) { 16909 // getSize: function (el, container, spacing, defaultLgSize) { 16910 //Uncode edit ##END## 16911 if (spacing === void 0) { spacing = 0; } 16912 var LGel = $LG(el); 16913 var lgSize = LGel.attr('data-lg-size') || defaultLgSize; 16914 //Uncode edit ##START## 16915 if ( typeof galleryItem.size && galleryItem.size != null ) { 16916 lgSize = galleryItem.size; 16917 } 16918 //Uncode edit ##END## 16919 if (!lgSize) { 16920 return; 16921 } 16922 var isResponsiveSizes = lgSize.split(','); 16923 // if at-least two viewport sizes are available 16924 if (isResponsiveSizes[1]) { 16925 var wWidth = window.innerWidth; 16926 for (var i = 0; i < isResponsiveSizes.length; i++) { 16927 var size_1 = isResponsiveSizes[i]; 16928 var responsiveWidth = parseInt(size_1.split('-')[2], 10); 16929 if (responsiveWidth > wWidth) { 16930 lgSize = size_1; 16931 break; 16932 } 16933 // take last item as last option 16934 if (i === isResponsiveSizes.length - 1) { 16935 lgSize = size_1; 16936 } 16937 } 16938 } 16939 var size = lgSize.split('-'); 16940 var width = parseInt(size[0], 10); 16941 var height = parseInt(size[1], 10); 16942 var cWidth = container.width(); 16943 var cHeight = container.height() - spacing; 16944 var maxWidth = Math.min(cWidth, width); 16945 var maxHeight = Math.min(cHeight, height); 16946 var ratio = Math.min(maxWidth / width, maxHeight / height); 16947 return { width: width * ratio, height: height * ratio }; 16948 }, 16949 /** 16950 * @desc Get transform value based on the imageSize. Used for ZoomFromOrigin option 16951 * @param {jQuery Element} 16952 * @returns {String} Transform CSS string 16953 */ 16954 getTransform: function (el, container, top, bottom, imageSize) { 16955 if (!imageSize) { 16956 return; 16957 } 16958 var LGel = $LG(el).find('img').first(); 16959 if (!LGel.get()) { 16960 return; 16961 } 16962 var containerRect = container.get().getBoundingClientRect(); 16963 var wWidth = containerRect.width; 16964 // using innerWidth to include mobile safari bottom bar 16965 var wHeight = container.height() - (top + bottom); 16966 var elWidth = LGel.width(); 16967 var elHeight = LGel.height(); 16968 var elStyle = LGel.style(); 16969 var x = (wWidth - elWidth) / 2 - 16970 LGel.offset().left + 16971 (parseFloat(elStyle.paddingLeft) || 0) + 16972 (parseFloat(elStyle.borderLeft) || 0) + 16973 $LG(window).scrollLeft() + 16974 containerRect.left; 16975 var y = (wHeight - elHeight) / 2 - 16976 LGel.offset().top + 16977 (parseFloat(elStyle.paddingTop) || 0) + 16978 (parseFloat(elStyle.borderTop) || 0) + 16979 $LG(window).scrollTop() + 16980 top; 16981 var scX = elWidth / imageSize.width; 16982 var scY = elHeight / imageSize.height; 16983 var transform = 'translate3d(' + 16984 (x *= -1) + 16985 'px, ' + 16986 (y *= -1) + 16987 'px, 0) scale3d(' + 16988 scX + 16989 ', ' + 16990 scY + 16991 ', 1)'; 16992 return transform; 16993 }, 16994 getIframeMarkup: function (iframeWidth, iframeHeight, iframeMaxWidth, iframeMaxHeight, src, iframeTitle) { 16995 var title = iframeTitle ? 'title="' + iframeTitle + '"' : ''; 16996 return "<div class=\"lg-video-cont lg-has-iframe\" style=\"width:" + iframeWidth + "; max-width:" + iframeMaxWidth + "; height: " + iframeHeight + "; max-height:" + iframeMaxHeight + "\">\n <iframe class=\"lg-object\" frameborder=\"0\" " + title + " src=\"" + src + "\" allowfullscreen=\"true\"></iframe>\n </div>"; 16997 }, 16998 getImgMarkup: function (index, src, altAttr, srcset, sizes, sources) { 16999 var srcsetAttr = srcset ? "srcset=\"" + srcset + "\"" : ''; 17000 var sizesAttr = sizes ? "sizes=\"" + sizes + "\"" : ''; 17001 var imgMarkup = "<img " + altAttr + " " + srcsetAttr + " " + sizesAttr + " class=\"lg-object lg-image\" data-index=\"" + index + "\" src=\"" + src + "\" />"; 17002 var sourceTag = ''; 17003 if (sources) { 17004 var sourceObj = typeof sources === 'string' ? JSON.parse(sources) : sources; 17005 sourceTag = sourceObj.map(function (source) { 17006 var attrs = ''; 17007 Object.keys(source).forEach(function (key) { 17008 // Do not remove the first space as it is required to separate the attributes 17009 attrs += " " + key + "=\"" + source[key] + "\""; 17010 }); 17011 return "<source " + attrs + "></source>"; 17012 }); 17013 } 17014 return "" + sourceTag + imgMarkup; 17015 }, 17016 // Get src from responsive src 17017 getResponsiveSrc: function (srcItms) { 17018 var rsWidth = []; 17019 var rsSrc = []; 17020 var src = ''; 17021 for (var i = 0; i < srcItms.length; i++) { 17022 var _src = srcItms[i].split(' '); 17023 // Manage empty space 17024 if (_src[0] === '') { 17025 _src.splice(0, 1); 17026 } 17027 rsSrc.push(_src[0]); 17028 rsWidth.push(_src[1]); 17029 } 17030 var wWidth = window.innerWidth; 17031 for (var j = 0; j < rsWidth.length; j++) { 17032 if (parseInt(rsWidth[j], 10) > wWidth) { 17033 src = rsSrc[j]; 17034 break; 17035 } 17036 } 17037 return src; 17038 }, 17039 isImageLoaded: function (img) { 17040 if (!img) 17041 return false; 17042 // During the onload event, IE correctly identifies any images that 17043 // werenât downloaded as not complete. Others should too. Gecko-based 17044 // browsers act like NS4 in that they report this incorrectly. 17045 if (!img.complete) { 17046 return false; 17047 } 17048 // However, they do have two very useful properties: naturalWidth and 17049 // naturalHeight. These give the true size of the image. If it failed 17050 // to load, either of these should be zero. 17051 if (img.naturalWidth === 0) { 17052 return false; 17053 } 17054 // No other way of checking: assume itâs ok. 17055 return true; 17056 }, 17057 getVideoPosterMarkup: function (_poster, dummyImg, videoContStyle, playVideoString, _isVideo) { 17058 var videoClass = ''; 17059 if (_isVideo && _isVideo.youtube) { 17060 videoClass = 'lg-has-youtube'; 17061 } 17062 else if (_isVideo && _isVideo.vimeo) { 17063 videoClass = 'lg-has-vimeo'; 17064 } 17065 else { 17066 videoClass = 'lg-has-html5'; 17067 } 17068 return "<div class=\"lg-video-cont " + videoClass + "\" style=\"" + videoContStyle + "\">\n <div class=\"lg-video-play-button\">\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>"; 17069 }, 17070 /** 17071 * @desc Create dynamic elements array from gallery items when dynamic option is false 17072 * It helps to avoid frequent DOM interaction 17073 * and avoid multiple checks for dynamic elments 17074 * 17075 * @returns {Array} dynamicEl 17076 */ 17077 getDynamicOptions: function (items, extraProps, getCaptionFromTitleOrAlt, exThumbImage) { 17078 var dynamicElements = []; 17079 var availableDynamicOptions = __spreadArrays(defaultDynamicOptions, extraProps); 17080 [].forEach.call(items, function (item) { 17081 var dynamicEl = {}; 17082 for (var i = 0; i < item.attributes.length; i++) { 17083 var attr = item.attributes[i]; 17084 if (attr.specified) { 17085 var dynamicAttr = convertToData(attr.name); 17086 var label = ''; 17087 if (availableDynamicOptions.indexOf(dynamicAttr) > -1) { 17088 label = dynamicAttr; 17089 } 17090 if (label) { 17091 dynamicEl[label] = attr.value; 17092 } 17093 } 17094 } 17095 var currentItem = $LG(item); 17096 var alt = currentItem.find('img').first().attr('alt'); 17097 var title = currentItem.attr('title'); 17098 //Uncode edit ##START## 17099 // var thumb = exThumbImage 17100 var thumb = exThumbImage && currentItem.attr(exThumbImage) 17101 //Uncode edit ##END## 17102 ? currentItem.attr(exThumbImage) 17103 : currentItem.find('img').first().attr('src'); 17104 dynamicEl.thumb = thumb; 17105 //Uncode edit ##START## 17106 if (getCaptionFromTitleOrAlt && !dynamicEl.subHtml) { 17107 // dynamicEl.subHtml = title || alt || ''; 17108 dynamicEl.subHtml = title || ''; 17109 } 17110 // dynamicEl.alt = alt || title || ''; 17111 dynamicEl.alt = title || ''; 17112 var inlineType = currentItem.attr('data-type'); 17113 dynamicEl.type = inlineType; 17114 //Uncode edit ##END## 17115 dynamicElements.push(dynamicEl); 17116 }); 17117 return dynamicElements; 17118 }, 17119 isMobile: function () { 17120 return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent); 17121 }, 17122 /** 17123 * @desc Check the given src is video 17124 * @param {String} src 17125 * @return {Object} video type 17126 * Ex:{ youtube : ["//www.youtube.com/watch?v=c0asJgSyxcY", "c0asJgSyxcY"] } 17127 * 17128 * @todo - this information can be moved to dynamicEl to avoid frequent calls 17129 */ 17130 isVideo: function (src, isHTML5VIdeo, index) { 17131 if (!src) { 17132 if (isHTML5VIdeo) { 17133 return { 17134 html5: true, 17135 }; 17136 } 17137 else { 17138 console.warn('lightGallery :- data-src is not provided on slide item ' + 17139 (index + 1) + 17140 '. Please make sure the selector property is properly configured. More info - https://www.lightgalleryjs.com/demos/html-markup/'); 17141 return; 17142 } 17143 } 17144 var youtube = src.match(/\/\/(?:www\.)?youtu(?:\.be|be\.com|be-nocookie\.com)\/(?:watch\?v=|embed\/)?([a-z0-9\-\_\%]+)([\&|?][\S]*)*/i); 17145 var vimeo = src.match(/\/\/(?:www\.)?(?:player\.)?vimeo.com\/(?:video\/)?([0-9a-z\-_]+)(.*)?/i); 17146 var wistia = src.match(/https?:\/\/(.+)?(wistia\.com|wi\.st)\/(medias|embed)\/([0-9a-z\-_]+)(.*)/); 17147 if (youtube) { 17148 return { 17149 youtube: youtube, 17150 }; 17151 } 17152 else if (vimeo) { 17153 return { 17154 vimeo: vimeo, 17155 }; 17156 } 17157 else if (wistia) { 17158 return { 17159 wistia: wistia, 17160 }; 17161 } 17162 }, 17163 }; 17164 17165 // @ref - https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio 17166 // @ref - https://2ality.com/2017/04/setting-up-multi-platform-packages.html 17167 // Unique id for each gallery 17168 var lgId = 0; 17169 var LightGallery = /** @class */ (function () { 17170 function LightGallery(element, options) { 17171 this.lgOpened = false; 17172 this.index = 0; 17173 // lightGallery modules 17174 this.plugins = []; 17175 // false when lightGallery load first slide content; 17176 this.lGalleryOn = false; 17177 // True when a slide animation is in progress 17178 this.lgBusy = false; 17179 this.currentItemsInDom = []; 17180 // Scroll top value before lightGallery is opened 17181 this.prevScrollTop = 0; 17182 this.isDummyImageRemoved = false; 17183 this.dragOrSwipeEnabled = false; 17184 this.mediaContainerPosition = { 17185 top: 0, 17186 bottom: 0, 17187 }; 17188 if (!element) { 17189 return this; 17190 } 17191 lgId++; 17192 this.lgId = lgId; 17193 this.el = element; 17194 this.LGel = $LG(element); 17195 this.generateSettings(options); 17196 this.buildModules(); 17197 // When using dynamic mode, ensure dynamicEl is an array 17198 if (this.settings.dynamic && 17199 this.settings.dynamicEl !== undefined && 17200 !Array.isArray(this.settings.dynamicEl)) { 17201 throw 'When using dynamic mode, you must also define dynamicEl as an Array.'; 17202 } 17203 this.galleryItems = this.getItems(); 17204 this.normalizeSettings(); 17205 // Gallery items 17206 this.init(); 17207 //Uncode edit ##START## 17208 // this.validateLicense(); 17209 //Uncode edit ##END## 17210 return this; 17211 } 17212 LightGallery.prototype.generateSettings = function (options) { 17213 // lightGallery settings 17214 this.settings = __assign(__assign({}, lightGalleryCoreSettings), options); 17215 if (this.settings.isMobile && 17216 typeof this.settings.isMobile === 'function' 17217 ? this.settings.isMobile() 17218 : utils.isMobile()) { 17219 var mobileSettings = __assign(__assign({}, this.settings.mobileSettings), this.settings.mobileSettings); 17220 this.settings = __assign(__assign({}, this.settings), mobileSettings); 17221 } 17222 }; 17223 LightGallery.prototype.normalizeSettings = function () { 17224 if (this.settings.slideEndAnimation) { 17225 this.settings.hideControlOnEnd = false; 17226 } 17227 if (!this.settings.closable) { 17228 this.settings.swipeToClose = false; 17229 } 17230 // And reset it on close to get the correct value next time 17231 this.zoomFromOrigin = this.settings.zoomFromOrigin; 17232 // At the moment, Zoom from image doesn't support dynamic options 17233 // @todo add zoomFromOrigin support for dynamic images 17234 if (this.settings.dynamic) { 17235 this.zoomFromOrigin = false; 17236 } 17237 if (!this.settings.container) { 17238 this.settings.container = document.body; 17239 } 17240 // settings.preload should not be grater than $item.length 17241 this.settings.preload = Math.min(this.settings.preload, this.galleryItems.length); 17242 }; 17243 LightGallery.prototype.init = function () { 17244 var _this = this; 17245 this.addSlideVideoInfo(this.galleryItems); 17246 this.buildStructure(); 17247 this.LGel.trigger(lGEvents.init, { 17248 instance: this, 17249 }); 17250 if (this.settings.keyPress) { 17251 this.keyPress(); 17252 } 17253 setTimeout(function () { 17254 _this.enableDrag(); 17255 _this.enableSwipe(); 17256 _this.triggerPosterClick(); 17257 }, 50); 17258 this.arrow(); 17259 if (this.settings.mousewheel) { 17260 this.mousewheel(); 17261 } 17262 if (!this.settings.dynamic) { 17263 this.openGalleryOnItemClick(); 17264 } 17265 }; 17266 LightGallery.prototype.openGalleryOnItemClick = function () { 17267 var _this = this; 17268 var _loop_1 = function (index) { 17269 var element = this_1.items[index]; 17270 var $element = $LG(element); 17271 // Using different namespace for click because click event should not unbind if selector is same object('this') 17272 // @todo manage all event listners - should have namespace that represent element 17273 var uuid = lgQuery.generateUUID(); 17274 $element 17275 .attr('data-lg-id', uuid) 17276 .on("click.lgcustom-item-" + uuid, function (e) { 17277 e.preventDefault(); 17278 var currentItemIndex = _this.settings.index || index; 17279 _this.openGallery(currentItemIndex, element); 17280 }); 17281 }; 17282 var this_1 = this; 17283 // Using for loop instead of using bubbling as the items can be any html element. 17284 for (var index = 0; index < this.items.length; index++) { 17285 _loop_1(index); 17286 } 17287 }; 17288 /** 17289 * Module constructor 17290 * Modules are build incrementally. 17291 * Gallery should be opened only once all the modules are initialized. 17292 * use moduleBuildTimeout to make sure this 17293 */ 17294 LightGallery.prototype.buildModules = function () { 17295 var _this = this; 17296 this.settings.plugins.forEach(function (plugin) { 17297 _this.plugins.push(new plugin(_this, $LG)); 17298 }); 17299 }; 17300 LightGallery.prototype.validateLicense = function () { 17301 if (!this.settings.licenseKey) { 17302 console.warn('Please provide a valid license key'); 17303 } 17304 else if (this.settings.licenseKey === '0000-0000-000-0000') { 17305 console.warn("lightGallery: " + this.settings.licenseKey + " license key is not valid for production use"); 17306 } 17307 }; 17308 LightGallery.prototype.getSlideItem = function (index) { 17309 return $LG(this.getSlideItemId(index)); 17310 }; 17311 LightGallery.prototype.getSlideItemId = function (index) { 17312 return "#lg-item-" + this.lgId + "-" + index; 17313 }; 17314 LightGallery.prototype.getIdName = function (id) { 17315 return id + "-" + this.lgId; 17316 }; 17317 LightGallery.prototype.getElementById = function (id) { 17318 return $LG("#" + this.getIdName(id)); 17319 }; 17320 LightGallery.prototype.manageSingleSlideClassName = function () { 17321 if (this.galleryItems.length < 2) { 17322 this.outer.addClass('lg-single-item'); 17323 } 17324 else { 17325 this.outer.removeClass('lg-single-item'); 17326 } 17327 }; 17328 LightGallery.prototype.buildStructure = function () { 17329 var _this = this; 17330 var container = this.$container && this.$container.get(); 17331 if (container) { 17332 return; 17333 } 17334 var controls = ''; 17335 var subHtmlCont = ''; 17336 // Create controls 17337 if (this.settings.controls) { 17338 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>"; 17339 } 17340 if (this.settings.appendSubHtmlTo !== '.lg-item') { 17341 subHtmlCont = 17342 '<div class="lg-sub-html" role="status" aria-live="polite"></div>'; 17343 } 17344 var addClasses = ''; 17345 if (this.settings.allowMediaOverlap) { 17346 // Do not remove space before last single quote 17347 addClasses += 'lg-media-overlap '; 17348 } 17349 var ariaLabelledby = this.settings.ariaLabelledby 17350 ? 'aria-labelledby="' + this.settings.ariaLabelledby + '"' 17351 : ''; 17352 var ariaDescribedby = this.settings.ariaDescribedby 17353 ? 'aria-describedby="' + this.settings.ariaDescribedby + '"' 17354 : ''; 17355 var containerClassName = "lg-container " + this.settings.addClass + " " + (document.body !== this.settings.container ? 'lg-inline' : ''); 17356 var closeIcon = this.settings.closable && this.settings.showCloseIcon 17357 ? "<button type=\"button\" aria-label=\"" + this.settings.strings['closeGallery'] + "\" id=\"" + this.getIdName('lg-close') + "\" class=\"lg-close lg-icon\"></button>" 17358 : ''; 17359 var maximizeIcon = this.settings.showMaximizeIcon 17360 ? "<button type=\"button\" aria-label=\"" + this.settings.strings['toggleMaximize'] + "\" id=\"" + this.getIdName('lg-maximize') + "\" class=\"lg-maximize lg-icon\"></button>" 17361 : ''; 17362 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' 17363 ? subHtmlCont 17364 : '') + "\n <div id=\"" + this.getIdName('lg-components') + "\" class=\"lg-components\">\n " + (this.settings.appendSubHtmlTo === '.lg-sub-html' 17365 ? subHtmlCont 17366 : '') + "\n </div>\n </div>\n </div>\n "; 17367 $LG(this.settings.container).append(template); 17368 if (document.body !== this.settings.container) { 17369 $LG(this.settings.container).css('position', 'relative'); 17370 } 17371 this.outer = this.getElementById('lg-outer'); 17372 this.$lgComponents = this.getElementById('lg-components'); 17373 this.$backdrop = this.getElementById('lg-backdrop'); 17374 this.$container = this.getElementById('lg-container'); 17375 this.$inner = this.getElementById('lg-inner'); 17376 this.$content = this.getElementById('lg-content'); 17377 this.$toolbar = this.getElementById('lg-toolbar'); 17378 this.$backdrop.css('transition-duration', this.settings.backdropDuration + 'ms'); 17379 var outerClassNames = this.settings.mode + " "; 17380 this.manageSingleSlideClassName(); 17381 if (this.settings.enableDrag) { 17382 outerClassNames += 'lg-grab '; 17383 } 17384 this.outer.addClass(outerClassNames); 17385 this.$inner.css('transition-timing-function', this.settings.easing); 17386 this.$inner.css('transition-duration', this.settings.speed + 'ms'); 17387 if (this.settings.download) { 17388 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>"); 17389 } 17390 this.counter(); 17391 $LG(window).on("resize.lg.global" + this.lgId + " orientationchange.lg.global" + this.lgId, function () { 17392 _this.refreshOnResize(); 17393 }); 17394 this.hideBars(); 17395 this.manageCloseGallery(); 17396 this.toggleMaximize(); 17397 this.initModules(); 17398 }; 17399 LightGallery.prototype.refreshOnResize = function () { 17400 if (this.lgOpened) { 17401 var currentGalleryItem = this.galleryItems[this.index]; 17402 var __slideVideoInfo = currentGalleryItem.__slideVideoInfo; 17403 this.mediaContainerPosition = this.getMediaContainerPosition(); 17404 var _a = this.mediaContainerPosition, top_1 = _a.top, bottom = _a.bottom; 17405 //Uncode edit ##START## 17406 this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 17407 // this.currentImageSize = utils.getSize(this.items[this.index], this.outer, top_1 + bottom, __slideVideoInfo && this.settings.videoMaxSize); 17408 //Uncode edit ##END## 17409 if (__slideVideoInfo) { 17410 this.resizeVideoSlide(this.index, this.currentImageSize); 17411 } 17412 if (this.zoomFromOrigin && !this.isDummyImageRemoved) { 17413 var imgStyle = this.getDummyImgStyles(this.currentImageSize); 17414 this.outer 17415 .find('.lg-current .lg-dummy-img') 17416 .first() 17417 .attr('style', imgStyle); 17418 } 17419 this.LGel.trigger(lGEvents.containerResize); 17420 } 17421 }; 17422 LightGallery.prototype.resizeVideoSlide = function (index, imageSize) { 17423 var lgVideoStyle = this.getVideoContStyle(imageSize); 17424 var currentSlide = this.getSlideItem(index); 17425 currentSlide.find('.lg-video-cont').attr('style', lgVideoStyle); 17426 }; 17427 /** 17428 * Update slides dynamically. 17429 * Add, edit or delete slides dynamically when lightGallery is opened. 17430 * Modify the current gallery items and pass it via updateSlides method 17431 * @note 17432 * - Do not mutate existing lightGallery items directly. 17433 * - Always pass new list of gallery items 17434 * - You need to take care of thumbnails outside the gallery if any 17435 * - user this method only if you want to update slides when the gallery is opened. Otherwise, use `refresh()` method. 17436 * @param items Gallery items 17437 * @param index After the update operation, which slide gallery should navigate to 17438 * @category lGPublicMethods 17439 * @example 17440 * const plugin = lightGallery(); 17441 * 17442 * // Adding slides dynamically 17443 * let galleryItems = [ 17444 * // Access existing lightGallery items 17445 * // galleryItems are automatically generated internally from the gallery HTML markup 17446 * // or directly from galleryItems when dynamic gallery is used 17447 * ...plugin.galleryItems, 17448 * ...[ 17449 * { 17450 * src: 'img/img-1.png', 17451 * thumb: 'img/thumb1.png', 17452 * }, 17453 * ], 17454 * ]; 17455 * plugin.updateSlides( 17456 * galleryItems, 17457 * plugin.index, 17458 * ); 17459 * 17460 * 17461 * // Remove slides dynamically 17462 * galleryItems = JSON.parse( 17463 * JSON.stringify(updateSlideInstance.galleryItems), 17464 * ); 17465 * galleryItems.shift(); 17466 * updateSlideInstance.updateSlides(galleryItems, 1); 17467 * @see <a href="/demos/update-slides/">Demo</a> 17468 */ 17469 LightGallery.prototype.updateSlides = function (items, index) { 17470 if (this.index > items.length - 1) { 17471 this.index = items.length - 1; 17472 } 17473 if (items.length === 1) { 17474 this.index = 0; 17475 } 17476 if (!items.length) { 17477 this.closeGallery(); 17478 return; 17479 } 17480 var currentSrc = this.galleryItems[index].src; 17481 this.galleryItems = items; 17482 this.updateControls(); 17483 this.$inner.empty(); 17484 this.currentItemsInDom = []; 17485 var _index = 0; 17486 // Find the current index based on source value of the slide 17487 this.galleryItems.some(function (galleryItem, itemIndex) { 17488 if (galleryItem.src === currentSrc) { 17489 _index = itemIndex; 17490 return true; 17491 } 17492 return false; 17493 }); 17494 this.currentItemsInDom = this.organizeSlideItems(_index, -1); 17495 this.loadContent(_index, true); 17496 this.getSlideItem(_index).addClass('lg-current'); 17497 this.index = _index; 17498 this.updateCurrentCounter(_index); 17499 this.LGel.trigger(lGEvents.updateSlides); 17500 }; 17501 // Get gallery items based on multiple conditions 17502 LightGallery.prototype.getItems = function () { 17503 // Gallery items 17504 this.items = []; 17505 if (!this.settings.dynamic) { 17506 if (this.settings.selector === 'this') { 17507 this.items.push(this.el); 17508 } 17509 else if (this.settings.selector) { 17510 if (typeof this.settings.selector === 'string') { 17511 if (this.settings.selectWithin) { 17512 var selectWithin = $LG(this.settings.selectWithin); 17513 this.items = selectWithin 17514 .find(this.settings.selector) 17515 .get(); 17516 } 17517 else { 17518 this.items = this.el.querySelectorAll(this.settings.selector); 17519 } 17520 } 17521 else { 17522 this.items = this.settings.selector; 17523 } 17524 } 17525 else { 17526 this.items = this.el.children; 17527 } 17528 return utils.getDynamicOptions(this.items, this.settings.extraProps, this.settings.getCaptionFromTitleOrAlt, this.settings.exThumbImage); 17529 } 17530 else { 17531 return this.settings.dynamicEl || []; 17532 } 17533 }; 17534 /** 17535 * Open lightGallery. 17536 * Open gallery with specific slide by passing index of the slide as parameter. 17537 * @category lGPublicMethods 17538 * @param {Number} index - index of the slide 17539 * @param {HTMLElement} element - Which image lightGallery should zoom from 17540 * 17541 * @example 17542 * const $dynamicGallery = document.getElementById('dynamic-gallery-demo'); 17543 * const dynamicGallery = lightGallery($dynamicGallery, { 17544 * dynamic: true, 17545 * dynamicEl: [ 17546 * { 17547 * src: 'img/1.jpg', 17548 * thumb: 'img/thumb-1.jpg', 17549 * subHtml: '<h4>Image 1 title</h4><p>Image 1 descriptions.</p>', 17550 * }, 17551 * ... 17552 * ], 17553 * }); 17554 * $dynamicGallery.addEventListener('click', function () { 17555 * // Starts with third item.(Optional). 17556 * // This is useful if you want use dynamic mode with 17557 * // custom thumbnails (thumbnails outside gallery), 17558 * dynamicGallery.openGallery(2); 17559 * }); 17560 * 17561 */ 17562 LightGallery.prototype.openGallery = function (index, element) { 17563 var _this = this; 17564 if (index === void 0) { index = this.settings.index; } 17565 // prevent accidental double execution 17566 if (this.lgOpened) 17567 return; 17568 this.lgOpened = true; 17569 this.outer.get().focus(); 17570 this.outer.removeClass('lg-hide-items'); 17571 // Add display block, but still has opacity 0 17572 this.$container.addClass('lg-show'); 17573 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, index); 17574 this.currentItemsInDom = itemsToBeInsertedToDom; 17575 var items = ''; 17576 itemsToBeInsertedToDom.forEach(function (item) { 17577 items = items + ("<div id=\"" + item + "\" class=\"lg-item\"></div>"); 17578 }); 17579 this.$inner.append(items); 17580 this.addHtml(index); 17581 var transform = ''; 17582 this.mediaContainerPosition = this.getMediaContainerPosition(); 17583 var _a = this.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 17584 if (!this.settings.allowMediaOverlap) { 17585 this.setMediaContainerPosition(top, bottom); 17586 } 17587 var __slideVideoInfo = this.galleryItems[index].__slideVideoInfo; 17588 if (this.zoomFromOrigin && element) { 17589 //Uncode edit ##START## 17590 this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 17591 // this.currentImageSize = utils.getSize(element, this.outer, top + bottom, __slideVideoInfo && this.settings.videoMaxSize); 17592 //Uncode edit ##END## 17593 transform = utils.getTransform(element, this.outer, top, bottom, this.currentImageSize); 17594 } 17595 if (!this.zoomFromOrigin || !transform) { 17596 this.outer.addClass(this.settings.startClass); 17597 this.getSlideItem(index).removeClass('lg-complete'); 17598 } 17599 var timeout = this.settings.zoomFromOrigin 17600 ? 100 17601 : this.settings.backdropDuration; 17602 setTimeout(function () { 17603 _this.outer.addClass('lg-components-open'); 17604 }, timeout); 17605 this.index = index; 17606 //Uncode edit ##START## 17607 // this.LGel.trigger(lGEvents.beforeOpen); 17608 this.LGel.trigger(lGEvents.beforeOpen, { 17609 galleryItems: this.galleryItems, 17610 items: this.items, 17611 outer: this.outer, 17612 }); 17613 //Uncode edit ##END## 17614 // add class lg-current to remove initial transition 17615 this.getSlideItem(index).addClass('lg-current'); 17616 this.lGalleryOn = false; 17617 // Store the current scroll top value to scroll back after closing the gallery.. 17618 this.prevScrollTop = $LG(window).scrollTop(); 17619 setTimeout(function () { 17620 // Need to check both zoomFromOrigin and transform values as we need to set set the 17621 // default opening animation if user missed to add the lg-size attribute 17622 if (_this.zoomFromOrigin && transform) { 17623 var currentSlide_1 = _this.getSlideItem(index); 17624 currentSlide_1.css('transform', transform); 17625 setTimeout(function () { 17626 currentSlide_1 17627 .addClass('lg-start-progress lg-start-end-progress') 17628 .css('transition-duration', _this.settings.startAnimationDuration + 'ms'); 17629 _this.outer.addClass('lg-zoom-from-image'); 17630 }); 17631 setTimeout(function () { 17632 currentSlide_1.css('transform', 'translate3d(0, 0, 0)'); 17633 }, 100); 17634 } 17635 setTimeout(function () { 17636 _this.$backdrop.addClass('in'); 17637 _this.$container.addClass('lg-show-in'); 17638 }, 10); 17639 // lg-visible class resets gallery opacity to 1 17640 if (!_this.zoomFromOrigin || !transform) { 17641 setTimeout(function () { 17642 _this.outer.addClass('lg-visible'); 17643 }, _this.settings.backdropDuration); 17644 } 17645 // initiate slide function 17646 _this.slide(index, false, false, false); 17647 _this.LGel.trigger(lGEvents.afterOpen); 17648 }); 17649 if (document.body === this.settings.container) { 17650 $LG('html').addClass('lg-on'); 17651 } 17652 }; 17653 /** 17654 * Note - Changing the position of the media on every slide transition creates a flickering effect. 17655 * Therefore, The height of the caption is calculated dynamically, only once based on the first slide caption. 17656 * if you have dynamic captions for each media, 17657 * you can provide an appropriate height for the captions via allowMediaOverlap option 17658 */ 17659 LightGallery.prototype.getMediaContainerPosition = function () { 17660 if (this.settings.allowMediaOverlap) { 17661 return { 17662 top: 0, 17663 bottom: 0, 17664 }; 17665 } 17666 var top = this.$toolbar.get().clientHeight || 0; 17667 var subHtml = this.outer.find('.lg-components .lg-sub-html').get(); 17668 var captionHeight = this.settings.defaultCaptionHeight || 17669 (subHtml && subHtml.clientHeight) || 17670 0; 17671 var thumbContainer = this.outer.find('.lg-thumb-outer').get(); 17672 var thumbHeight = thumbContainer ? thumbContainer.clientHeight : 0; 17673 var bottom = thumbHeight + captionHeight; 17674 //Uncode edit ##START## 17675 bottom = bottom < 55 ? 55 : bottom; 17676 //Uncode edit ##END## 17677 return { 17678 top: top, 17679 bottom: bottom, 17680 }; 17681 }; 17682 LightGallery.prototype.setMediaContainerPosition = function (top, bottom) { 17683 if (top === void 0) { top = 0; } 17684 if (bottom === void 0) { bottom = 0; } 17685 this.$content.css('top', top + 'px').css('bottom', bottom + 'px'); 17686 }; 17687 LightGallery.prototype.hideBars = function () { 17688 var _this = this; 17689 // Hide controllers if mouse doesn't move for some period 17690 setTimeout(function () { 17691 _this.outer.removeClass('lg-hide-items'); 17692 if (_this.settings.hideBarsDelay > 0) { 17693 _this.outer.on('mousemove.lg click.lg touchstart.lg', function () { 17694 _this.outer.removeClass('lg-hide-items'); 17695 clearTimeout(_this.hideBarTimeout); 17696 // Timeout will be cleared on each slide movement also 17697 _this.hideBarTimeout = setTimeout(function () { 17698 _this.outer.addClass('lg-hide-items'); 17699 }, _this.settings.hideBarsDelay); 17700 }); 17701 _this.outer.trigger('mousemove.lg'); 17702 } 17703 }, this.settings.showBarsAfter); 17704 }; 17705 LightGallery.prototype.initPictureFill = function ($img) { 17706 if (this.settings.supportLegacyBrowser) { 17707 try { 17708 picturefill({ 17709 elements: [$img.get()], 17710 }); 17711 } 17712 catch (e) { 17713 console.warn('lightGallery :- If you want srcset or picture tag to be supported for older browser please include picturefil javascript library in your document.'); 17714 } 17715 } 17716 }; 17717 /** 17718 * @desc Create image counter 17719 * Ex: 1/10 17720 */ 17721 LightGallery.prototype.counter = function () { 17722 if (this.settings.counter) { 17723 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>"; 17724 this.outer.find(this.settings.appendCounterTo).append(counterHtml); 17725 } 17726 }; 17727 /** 17728 * @desc add sub-html into the slide 17729 * @param {Number} index - index of the slide 17730 */ 17731 LightGallery.prototype.addHtml = function (index) { 17732 var subHtml; 17733 var subHtmlUrl; 17734 if (this.galleryItems[index].subHtmlUrl) { 17735 subHtmlUrl = this.galleryItems[index].subHtmlUrl; 17736 } 17737 else { 17738 subHtml = this.galleryItems[index].subHtml; 17739 } 17740 if (!subHtmlUrl) { 17741 if (subHtml) { 17742 // get first letter of sub-html 17743 // if first letter starts with . or # get the html form the jQuery object 17744 var fL = subHtml.substring(0, 1); 17745 if (fL === '.' || fL === '#') { 17746 if (this.settings.subHtmlSelectorRelative && 17747 !this.settings.dynamic) { 17748 subHtml = $LG(this.items) 17749 .eq(index) 17750 .find(subHtml) 17751 .first() 17752 .html(); 17753 } 17754 else { 17755 subHtml = $LG(subHtml).first().html(); 17756 } 17757 } 17758 } 17759 else { 17760 subHtml = ''; 17761 } 17762 } 17763 if (this.settings.appendSubHtmlTo !== '.lg-item') { 17764 if (subHtmlUrl) { 17765 this.outer.find('.lg-sub-html').load(subHtmlUrl); 17766 } 17767 else { 17768 this.outer.find('.lg-sub-html').html(subHtml); 17769 } 17770 } 17771 else { 17772 var currentSlide = $LG(this.getSlideItemId(index)); 17773 if (subHtmlUrl) { 17774 currentSlide.load(subHtmlUrl); 17775 } 17776 else { 17777 currentSlide.append("<div class=\"lg-sub-html\">" + subHtml + "</div>"); 17778 } 17779 } 17780 // Add lg-empty-html class if title doesn't exist 17781 if (typeof subHtml !== 'undefined' && subHtml !== null) { 17782 if (subHtml === '') { 17783 this.outer 17784 .find(this.settings.appendSubHtmlTo) 17785 .addClass('lg-empty-html'); 17786 } 17787 else { 17788 this.outer 17789 .find(this.settings.appendSubHtmlTo) 17790 .removeClass('lg-empty-html'); 17791 } 17792 } 17793 this.LGel.trigger(lGEvents.afterAppendSubHtml, { 17794 index: index, 17795 }); 17796 }; 17797 /** 17798 * @desc Preload slides 17799 * @param {Number} index - index of the slide 17800 * @todo preload not working for the first slide, Also, should work for the first and last slide as well 17801 */ 17802 LightGallery.prototype.preload = function (index) { 17803 for (var i = 1; i <= this.settings.preload; i++) { 17804 if (i >= this.galleryItems.length - index) { 17805 break; 17806 } 17807 this.loadContent(index + i, false); 17808 } 17809 for (var j = 1; j <= this.settings.preload; j++) { 17810 if (index - j < 0) { 17811 break; 17812 } 17813 this.loadContent(index - j, false); 17814 } 17815 }; 17816 LightGallery.prototype.getDummyImgStyles = function (imageSize) { 17817 if (!imageSize) 17818 return '';
17819 return "width:" + imageSize.width + "px;\n margin-left: -" + imageSize.width / 2 + "px;\n margin-top: -" + imageSize.height / 2 + "px;\n height:" + imageSize.height + "px"; 17820 }; 17821 LightGallery.prototype.getVideoContStyle = function (imageSize) { 17822 if (!imageSize) 17823 return ''; 17824 return "width:" + imageSize.width + "px;\n height:" + imageSize.height + "px"; 17825 }; 17826 LightGallery.prototype.getDummyImageContent = function ($currentSlide, index, alt) { 17827 var $currentItem; 17828 if (!this.settings.dynamic) { 17829 $currentItem = $LG(this.items).eq(index); 17830 } 17831 if ($currentItem) { 17832 var _dummyImgSrc = void 0; 17833 if (!this.settings.exThumbImage) { 17834 _dummyImgSrc = $currentItem.find('img').first().attr('src'); 17835 } 17836 else { 17837 _dummyImgSrc = $currentItem.attr(this.settings.exThumbImage); 17838 } 17839 if (!_dummyImgSrc) 17840 return ''; 17841 var imgStyle = this.getDummyImgStyles(this.currentImageSize); 17842 var dummyImgContent = "<img " + alt + " style=\"" + imgStyle + "\" class=\"lg-dummy-img\" src=\"" + _dummyImgSrc + "\" />"; 17843 $currentSlide.addClass('lg-first-slide'); 17844 this.outer.addClass('lg-first-slide-loading'); 17845 return dummyImgContent; 17846 } 17847 return ''; 17848 }; 17849 LightGallery.prototype.setImgMarkup = function (src, $currentSlide, index) { 17850 var currentGalleryItem = this.galleryItems[index]; 17851 var alt = currentGalleryItem.alt, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources; 17852 // Use the thumbnail as dummy image which will be resized to actual image size and 17853 // displayed on top of actual image 17854 var imgContent = ''; 17855 var altAttr = alt ? 'alt="' + alt + '"' : ''; 17856 if (this.isFirstSlideWithZoomAnimation()) { 17857 imgContent = this.getDummyImageContent($currentSlide, index, altAttr); 17858 } 17859 else { 17860 imgContent = utils.getImgMarkup(index, src, altAttr, srcset, sizes, sources); 17861 } 17862 var imgMarkup = "<picture class=\"lg-img-wrap\"> " + imgContent + "</picture>"; 17863 $currentSlide.prepend(imgMarkup); 17864 }; 17865 LightGallery.prototype.onSlideObjectLoad = function ($slide, isHTML5VideoWithoutPoster, onLoad, onError) { 17866 var mediaObject = $slide.find('.lg-object').first(); 17867 if (utils.isImageLoaded(mediaObject.get()) || 17868 isHTML5VideoWithoutPoster) { 17869 onLoad(); 17870 } 17871 else { 17872 mediaObject.on('load.lg error.lg', function () { 17873 onLoad && onLoad(); 17874 }); 17875 mediaObject.on('error.lg', function () { 17876 onError && onError(); 17877 }); 17878 } 17879 }; 17880 /** 17881 * 17882 * @param $el Current slide item 17883 * @param index 17884 * @param delay Delay is 0 except first time 17885 * @param speed Speed is same as delay, except it is 0 if gallery is opened via hash plugin 17886 * @param isFirstSlide 17887 */ 17888 LightGallery.prototype.onLgObjectLoad = function (currentSlide, index, delay, speed, isFirstSlide, isHTML5VideoWithoutPoster) { 17889 var _this = this; 17890 //Uncode edit ##START## 17891 var $item = _this.galleryItems[index], 17892 type = $item.type; 17893 17894 if ( typeof $item.src !== 'undefined' ) { 17895 var inline_id = $item.src.replace('#', ''), 17896 $inline = document.getElementById(inline_id), 17897 inline_html; 17898 17899 if ( type === 'inline' && inline_id != null && typeof $inline !== 'undefined' ) { 17900 inline_html = $inline.innerHTML; 17901 } else { 17902 inline_html = ''; 17903 } 17904 } 17905 //Uncode edit ##END## 17906 this.onSlideObjectLoad(currentSlide, isHTML5VideoWithoutPoster, function () { 17907 _this.triggerSlideItemLoad(currentSlide, index, delay, speed, isFirstSlide); 17908 }, function () { 17909 currentSlide.addClass('lg-complete lg-complete_'); 17910 //Uncode edit ##START## 17911 // currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>'); 17912 if ( inline_html !== '' ) { 17913 currentSlide.html(inline_html); 17914 } else { 17915 currentSlide.html('<span class="lg-error-msg">Oops... Failed to load content...</span>'); 17916 } 17917 //Uncode edit ##END## 17918 }); 17919 }; 17920 LightGallery.prototype.triggerSlideItemLoad = function ($currentSlide, index, delay, speed, isFirstSlide) { 17921 var _this = this; 17922 var currentGalleryItem = this.galleryItems[index]; 17923 // Adding delay for video slides without poster for better performance and user experience 17924 // Videos should start playing once once the gallery is completely loaded 17925 var _speed = isFirstSlide &&
vendor: 49,644 bytes, lines 17926-18972
17926 this.getSlideType(currentGalleryItem) === 'video' && 17927 !currentGalleryItem.poster 17928 ? speed 17929 : 0; 17930 setTimeout(function () { 17931 $currentSlide.addClass('lg-complete lg-complete_'); 17932 _this.LGel.trigger(lGEvents.slideItemLoad, { 17933 index: index, 17934 delay: delay || 0, 17935 isFirstSlide: isFirstSlide, 17936 }); 17937 }, _speed); 17938 }; 17939 LightGallery.prototype.isFirstSlideWithZoomAnimation = function () { 17940 return !!(!this.lGalleryOn && 17941 this.zoomFromOrigin && 17942 this.currentImageSize); 17943 }; 17944 // Add video slideInfo 17945 LightGallery.prototype.addSlideVideoInfo = function (items) { 17946 var _this = this; 17947 items.forEach(function (element, index) { 17948 element.__slideVideoInfo = utils.isVideo(element.src, !!element.video, index); 17949 if (element.__slideVideoInfo && 17950 _this.settings.loadYouTubePoster && 17951 !element.poster && 17952 element.__slideVideoInfo.youtube) { 17953 element.poster = "//img.youtube.com/vi/" + element.__slideVideoInfo.youtube[1] + "/maxresdefault.jpg"; 17954 } 17955 }); 17956 }; 17957 /** 17958 * Load slide content into slide. 17959 * This is used to load content into slides that is not visible too 17960 * @param {Number} index - index of the slide. 17961 * @param {Boolean} rec - if true call loadcontent() function again. 17962 */ 17963 LightGallery.prototype.loadContent = function (index, rec) { 17964 var _this = this; 17965 var currentGalleryItem = this.galleryItems[index]; 17966 var $currentSlide = $LG(this.getSlideItemId(index)); 17967 var poster = currentGalleryItem.poster, srcset = currentGalleryItem.srcset, sizes = currentGalleryItem.sizes, sources = currentGalleryItem.sources; 17968 var src = currentGalleryItem.src; 17969 var video = currentGalleryItem.video; 17970 var _html5Video = video && typeof video === 'string' ? JSON.parse(video) : video; 17971 if (currentGalleryItem.responsive) { 17972 var srcDyItms = currentGalleryItem.responsive.split(','); 17973 src = utils.getResponsiveSrc(srcDyItms) || src; 17974 } 17975 var videoInfo = currentGalleryItem.__slideVideoInfo; 17976 var lgVideoStyle = ''; 17977 var iframe = !!currentGalleryItem.iframe; 17978 var isFirstSlide = !this.lGalleryOn; 17979 // delay for adding complete class. it is 0 except first time. 17980 var delay = 0; 17981 if (isFirstSlide) { 17982 if (this.zoomFromOrigin && this.currentImageSize) { 17983 delay = this.settings.startAnimationDuration + 10; 17984 } 17985 else { 17986 delay = this.settings.backdropDuration + 10; 17987 } 17988 } 17989 if (!$currentSlide.hasClass('lg-loaded')) { 17990 if (videoInfo) { 17991 var _a = this.mediaContainerPosition, top_2 = _a.top, bottom = _a.bottom; 17992 //Uncode edit ##START## 17993 var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 17994 // var videoSize = utils.getSize(this.items[index], this.outer, top_2 + bottom, videoInfo && this.settings.videoMaxSize); 17995 //Uncode edit ##END## 17996 lgVideoStyle = this.getVideoContStyle(videoSize); 17997 } 17998 if (iframe) { 17999 var markup = utils.getIframeMarkup(this.settings.iframeWidth, this.settings.iframeHeight, this.settings.iframeMaxWidth, this.settings.iframeMaxHeight, src, currentGalleryItem.iframeTitle); 18000 $currentSlide.prepend(markup); 18001 } 18002 else if (poster) { 18003 var dummyImg = ''; 18004 var hasStartAnimation = isFirstSlide && 18005 this.zoomFromOrigin && 18006 this.currentImageSize; 18007 if (hasStartAnimation) { 18008 dummyImg = this.getDummyImageContent($currentSlide, index, ''); 18009 } 18010 var markup = utils.getVideoPosterMarkup(poster, dummyImg || '', lgVideoStyle, this.settings.strings['playVideo'], videoInfo); 18011 $currentSlide.prepend(markup); 18012 } 18013 //Uncode edit ##START## 18014 // else if (videoInfo) { 18015 else if (videoInfo || this.getSlideType(currentGalleryItem) === 'audio') { 18016 if (! _html5Video) { 18017 var markup = "<div class=\"lg-video-cont \" style=\"" + lgVideoStyle + "\"></div>"; 18018 } 18019 //Uncode edit ##END## 18020 $currentSlide.prepend(markup); 18021 } 18022 else { 18023 this.setImgMarkup(src, $currentSlide, index); 18024 if (srcset || sources) { 18025 var $img = $currentSlide.find('.lg-object'); 18026 this.initPictureFill($img); 18027 } 18028 } 18029 if (poster || videoInfo) { 18030 this.LGel.trigger(lGEvents.hasVideo, { 18031 index: index, 18032 src: src, 18033 html5Video: _html5Video, 18034 hasPoster: !!poster, 18035 }); 18036 } 18037 this.LGel.trigger(lGEvents.afterAppendSlide, { index: index }); 18038 if (this.lGalleryOn && 18039 this.settings.appendSubHtmlTo === '.lg-item') { 18040 this.addHtml(index); 18041 } 18042 } 18043 // For first time add some delay for displaying the start animation. 18044 var _speed = 0; 18045 // Do not change the delay value because it is required for zoom plugin. 18046 // If gallery opened from direct url (hash) speed value should be 0 18047 if (delay && !$LG(document.body).hasClass('lg-from-hash')) { 18048 _speed = delay; 18049 } 18050 // Only for first slide and zoomFromOrigin is enabled 18051 if (this.isFirstSlideWithZoomAnimation()) { 18052 setTimeout(function () { 18053 $currentSlide 18054 .removeClass('lg-start-end-progress lg-start-progress') 18055 .removeAttr('style'); 18056 }, this.settings.startAnimationDuration + 100); 18057 if (!$currentSlide.hasClass('lg-loaded')) { 18058 setTimeout(function () { 18059 if (_this.getSlideType(currentGalleryItem) === 'image') { 18060 $currentSlide 18061 .find('.lg-img-wrap') 18062 .append(utils.getImgMarkup(index, src, '', srcset, sizes, currentGalleryItem.sources)); 18063 if (srcset || sources) { 18064 var $img = $currentSlide.find('.lg-object'); 18065 _this.initPictureFill($img); 18066 } 18067 } 18068 if (_this.getSlideType(currentGalleryItem) === 'image' || 18069 (_this.getSlideType(currentGalleryItem) === 'video' && 18070 poster)) { 18071 _this.onLgObjectLoad($currentSlide, index, delay, _speed, true, false); 18072 // load remaining slides once the slide is completely loaded 18073 _this.onSlideObjectLoad($currentSlide, !!(videoInfo && videoInfo.html5 && !poster), function () { 18074 _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed); 18075 }, function () { 18076 _this.loadContentOnFirstSlideLoad(index, $currentSlide, _speed); 18077 }); 18078 } 18079 }, this.settings.startAnimationDuration + 100); 18080 } 18081 } 18082 // SLide content has been added to dom 18083 $currentSlide.addClass('lg-loaded'); 18084 if (!this.isFirstSlideWithZoomAnimation() || 18085 (this.getSlideType(currentGalleryItem) === 'video' && !poster)) { 18086 //Uncode edit ##START## 18087 // this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!(videoInfo && videoInfo.html5 && !poster)); 18088 this.onLgObjectLoad($currentSlide, index, delay, _speed, isFirstSlide, !!( (videoInfo && videoInfo.html5 && !poster) || this.getSlideType(currentGalleryItem) === 'audio')); 18089 //Uncode edit ##END## 18090 } 18091 // When gallery is opened once content is loaded (second time) need to add lg-complete class for css styling 18092 if ((!this.zoomFromOrigin || !this.currentImageSize) && 18093 $currentSlide.hasClass('lg-complete_') && 18094 !this.lGalleryOn) { 18095 setTimeout(function () { 18096 $currentSlide.addClass('lg-complete'); 18097 }, this.settings.backdropDuration); 18098 } 18099 // Content loaded 18100 // Need to set lGalleryOn before calling preload function 18101 this.lGalleryOn = true; 18102 if (rec === true) { 18103 if (!$currentSlide.hasClass('lg-complete_')) { 18104 $currentSlide 18105 .find('.lg-object') 18106 .first() 18107 .on('load.lg error.lg', function () { 18108 _this.preload(index); 18109 }); 18110 } 18111 else { 18112 this.preload(index); 18113 } 18114 } 18115 }; 18116 /** 18117 * @desc Remove dummy image content and load next slides 18118 * Called only for the first time if zoomFromOrigin animation is enabled 18119 * @param index 18120 * @param $currentSlide 18121 * @param speed 18122 */ 18123 LightGallery.prototype.loadContentOnFirstSlideLoad = function (index, $currentSlide, speed) { 18124 var _this = this; 18125 setTimeout(function () { 18126 $currentSlide.find('.lg-dummy-img').remove(); 18127 $currentSlide.removeClass('lg-first-slide'); 18128 _this.outer.removeClass('lg-first-slide-loading'); 18129 _this.isDummyImageRemoved = true; 18130 _this.preload(index); 18131 }, speed + 300); 18132 }; 18133 LightGallery.prototype.getItemsToBeInsertedToDom = function (index, prevIndex, numberOfItems) { 18134 var _this = this; 18135 if (numberOfItems === void 0) { numberOfItems = 0; } 18136 var itemsToBeInsertedToDom = []; 18137 // Minimum 2 items should be there 18138 var possibleNumberOfItems = Math.max(numberOfItems, 3); 18139 possibleNumberOfItems = Math.min(possibleNumberOfItems, this.galleryItems.length); 18140 var prevIndexItem = "lg-item-" + this.lgId + "-" + prevIndex; 18141 if (this.galleryItems.length <= 3) { 18142 this.galleryItems.forEach(function (_element, index) { 18143 itemsToBeInsertedToDom.push("lg-item-" + _this.lgId + "-" + index); 18144 }); 18145 return itemsToBeInsertedToDom; 18146 } 18147 if (index < (this.galleryItems.length - 1) / 2) { 18148 for (var idx = index; idx > index - possibleNumberOfItems / 2 && idx >= 0; idx--) { 18149 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx); 18150 } 18151 var numberOfExistingItems = itemsToBeInsertedToDom.length; 18152 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) { 18153 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index + idx + 1)); 18154 } 18155 } 18156 else { 18157 for (var idx = index; idx <= this.galleryItems.length - 1 && 18158 idx < index + possibleNumberOfItems / 2; idx++) { 18159 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + idx); 18160 } 18161 var numberOfExistingItems = itemsToBeInsertedToDom.length; 18162 for (var idx = 0; idx < possibleNumberOfItems - numberOfExistingItems; idx++) { 18163 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (index - idx - 1)); 18164 } 18165 } 18166 if (this.settings.loop) { 18167 if (index === this.galleryItems.length - 1) { 18168 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + 0); 18169 } 18170 else if (index === 0) { 18171 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + (this.galleryItems.length - 1)); 18172 } 18173 } 18174 if (itemsToBeInsertedToDom.indexOf(prevIndexItem) === -1) { 18175 itemsToBeInsertedToDom.push("lg-item-" + this.lgId + "-" + prevIndex); 18176 } 18177 return itemsToBeInsertedToDom; 18178 }; 18179 LightGallery.prototype.organizeSlideItems = function (index, prevIndex) { 18180 var _this = this; 18181 var itemsToBeInsertedToDom = this.getItemsToBeInsertedToDom(index, prevIndex, this.settings.numberOfSlideItemsInDom); 18182 itemsToBeInsertedToDom.forEach(function (item) { 18183 if (_this.currentItemsInDom.indexOf(item) === -1) { 18184 _this.$inner.append("<div id=\"" + item + "\" class=\"lg-item\"></div>"); 18185 } 18186 }); 18187 this.currentItemsInDom.forEach(function (item) { 18188 if (itemsToBeInsertedToDom.indexOf(item) === -1) { 18189 $LG("#" + item).remove(); 18190 } 18191 }); 18192 return itemsToBeInsertedToDom; 18193 }; 18194 /** 18195 * Get previous index of the slide 18196 */ 18197 LightGallery.prototype.getPreviousSlideIndex = function () { 18198 var prevIndex = 0; 18199 try { 18200 var currentItemId = this.outer 18201 .find('.lg-current') 18202 .first() 18203 .attr('id'); 18204 prevIndex = parseInt(currentItemId.split('-')[3]) || 0; 18205 } 18206 catch (error) { 18207 prevIndex = 0; 18208 } 18209 return prevIndex; 18210 }; 18211 LightGallery.prototype.setDownloadValue = function (index) { 18212 if (this.settings.download) { 18213 var currentGalleryItem = this.galleryItems[index]; 18214 var hideDownloadBtn = currentGalleryItem.downloadUrl === false || 18215 currentGalleryItem.downloadUrl === 'false'; 18216 if (hideDownloadBtn) { 18217 this.outer.addClass('lg-hide-download'); 18218 } 18219 else { 18220 var $download = this.getElementById('lg-download'); 18221 this.outer.removeClass('lg-hide-download'); 18222 $download.attr('href', currentGalleryItem.downloadUrl || 18223 currentGalleryItem.src); 18224 if (currentGalleryItem.download) { 18225 //Uncode edit ##START## 18226 var download_url = currentGalleryItem.downloadUrl || currentGalleryItem.src, 18227 download_name = download_url.substring(download_url.lastIndexOf('/')+1); 18228 $download.attr('download', download_name); 18229 // $download.attr('download', currentGalleryItem.download); 18230 //Uncode edit ##END## 18231 } 18232 } 18233 } 18234 }; 18235 LightGallery.prototype.makeSlideAnimation = function (direction, currentSlideItem, previousSlideItem) { 18236 var _this = this; 18237 if (this.lGalleryOn) { 18238 previousSlideItem.addClass('lg-slide-progress'); 18239 } 18240 setTimeout(function () { 18241 // remove all transitions 18242 _this.outer.addClass('lg-no-trans'); 18243 _this.outer 18244 .find('.lg-item') 18245 .removeClass('lg-prev-slide lg-next-slide'); 18246 if (direction === 'prev') { 18247 //prevslide 18248 currentSlideItem.addClass('lg-prev-slide'); 18249 previousSlideItem.addClass('lg-next-slide'); 18250 } 18251 else { 18252 // next slide 18253 currentSlideItem.addClass('lg-next-slide'); 18254 previousSlideItem.addClass('lg-prev-slide'); 18255 } 18256 // give 50 ms for browser to add/remove class 18257 setTimeout(function () { 18258 _this.outer.find('.lg-item').removeClass('lg-current'); 18259 currentSlideItem.addClass('lg-current'); 18260 // reset all transitions 18261 _this.outer.removeClass('lg-no-trans'); 18262 }, 50); 18263 }, this.lGalleryOn ? this.settings.slideDelay : 0); 18264 }; 18265 /** 18266 * Goto a specific slide. 18267 * @param {Number} index - index of the slide 18268 * @param {Boolean} fromTouch - true if slide function called via touch event or mouse drag 18269 * @param {Boolean} fromThumb - true if slide function called via thumbnail click 18270 * @param {String} direction - Direction of the slide(next/prev) 18271 * @category lGPublicMethods 18272 * @example 18273 * const plugin = lightGallery(); 18274 * // to go to 3rd slide 18275 * plugin.slide(2); 18276 * 18277 */ 18278 LightGallery.prototype.slide = function (index, fromTouch, fromThumb, direction) { 18279 var _this = this; 18280 var prevIndex = this.getPreviousSlideIndex(); 18281 this.currentItemsInDom = this.organizeSlideItems(index, prevIndex); 18282 // Prevent multiple call, Required for hsh plugin 18283 if (this.lGalleryOn && prevIndex === index) { 18284 return; 18285 } 18286 var numberOfGalleryItems = this.galleryItems.length; 18287 if (!this.lgBusy) { 18288 if (this.settings.counter) { 18289 this.updateCurrentCounter(index); 18290 } 18291 var currentSlideItem = this.getSlideItem(index); 18292 var previousSlideItem_1 = this.getSlideItem(prevIndex); 18293 var currentGalleryItem = this.galleryItems[index]; 18294 var videoInfo = currentGalleryItem.__slideVideoInfo; 18295 this.outer.attr('data-lg-slide-type', this.getSlideType(currentGalleryItem)); 18296 this.setDownloadValue(index); 18297 if (videoInfo) { 18298 var _a = this.mediaContainerPosition, top_3 = _a.top, bottom = _a.bottom; 18299 //Uncode edit ##START## 18300 var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize, this.galleryItems[this.index]); 18301 // var videoSize = utils.getSize(this.items[index], this.outer, top_3 + bottom, videoInfo && this.settings.videoMaxSize); 18302 //Uncode edit ##END## 18303 this.resizeVideoSlide(index, videoSize); 18304 } 18305 this.LGel.trigger(lGEvents.beforeSlide, { 18306 prevIndex: prevIndex, 18307 index: index, 18308 fromTouch: !!fromTouch, 18309 fromThumb: !!fromThumb, 18310 //Uncode edit ##START## 18311 currentSlide: currentSlideItem, 18312 previousSlide: previousSlideItem_1, 18313 info: currentGalleryItem, 18314 item: this.items[index] 18315 //Uncode edit ##END## 18316 }); 18317 this.lgBusy = true; 18318 clearTimeout(this.hideBarTimeout); 18319 this.arrowDisable(index); 18320 if (!direction) { 18321 if (index < prevIndex) { 18322 direction = 'prev'; 18323 } 18324 else if (index > prevIndex) { 18325 direction = 'next'; 18326 } 18327 } 18328 if (!fromTouch) { 18329 this.makeSlideAnimation(direction, currentSlideItem, previousSlideItem_1); 18330 } 18331 else { 18332 this.outer 18333 .find('.lg-item') 18334 .removeClass('lg-prev-slide lg-current lg-next-slide'); 18335 var touchPrev = void 0; 18336 var touchNext = void 0; 18337 if (numberOfGalleryItems > 2) { 18338 touchPrev = index - 1; 18339 touchNext = index + 1; 18340 if (index === 0 && prevIndex === numberOfGalleryItems - 1) { 18341 // next slide 18342 touchNext = 0; 18343 touchPrev = numberOfGalleryItems - 1; 18344 } 18345 else if (index === numberOfGalleryItems - 1 && 18346 prevIndex === 0) { 18347 // prev slide 18348 touchNext = 0; 18349 touchPrev = numberOfGalleryItems - 1; 18350 } 18351 } 18352 else { 18353 touchPrev = 0; 18354 touchNext = 1; 18355 } 18356 if (direction === 'prev') { 18357 this.getSlideItem(touchNext).addClass('lg-next-slide'); 18358 } 18359 else { 18360 this.getSlideItem(touchPrev).addClass('lg-prev-slide'); 18361 } 18362 currentSlideItem.addClass('lg-current'); 18363 } 18364 // Do not put load content in set timeout as it needs to load immediately when the gallery is opened 18365 if (!this.lGalleryOn) { 18366 this.loadContent(index, true); 18367 } 18368 else { 18369 setTimeout(function () { 18370 _this.loadContent(index, true); 18371 // Add title if this.settings.appendSubHtmlTo === lg-sub-html 18372 if (_this.settings.appendSubHtmlTo !== '.lg-item') { 18373 _this.addHtml(index); 18374 } 18375 }, this.settings.speed + 50 + (fromTouch ? 0 : this.settings.slideDelay)); 18376 } 18377 setTimeout(function () { 18378 _this.lgBusy = false; 18379 previousSlideItem_1.removeClass('lg-slide-progress'); 18380 _this.LGel.trigger(lGEvents.afterSlide, { 18381 prevIndex: prevIndex, 18382 index: index, 18383 fromTouch: fromTouch, 18384 fromThumb: fromThumb, 18385 }); 18386 }, (this.lGalleryOn ? this.settings.speed + 100 : 100) + (fromTouch ? 0 : this.settings.slideDelay)); 18387 } 18388 this.index = index; 18389 }; 18390 LightGallery.prototype.updateCurrentCounter = function (index) { 18391 this.getElementById('lg-counter-current').html(index + 1 + ''); 18392 }; 18393 LightGallery.prototype.updateCounterTotal = function () { 18394 this.getElementById('lg-counter-all').html(this.galleryItems.length + ''); 18395 }; 18396 LightGallery.prototype.getSlideType = function (item) { 18397 if (item.__slideVideoInfo) { 18398 return 'video'; 18399 } 18400 else if (item.iframe) { 18401 return 'iframe'; 18402 } 18403 //Uncode edit ##START## 18404 else if (typeof item.src !== '' && item.src.search(/.mp3|.m4a/i) > -1) { 18405 return 'audio'; 18406 } 18407 //Uncode edit ##END## 18408 else { 18409 return 'image'; 18410 } 18411 }; 18412 LightGallery.prototype.touchMove = function (startCoords, endCoords, e) { 18413 var distanceX = endCoords.pageX - startCoords.pageX; 18414 var distanceY = endCoords.pageY - startCoords.pageY; 18415 var allowSwipe = false; 18416 if (this.swipeDirection) { 18417 allowSwipe = true; 18418 } 18419 else { 18420 if (Math.abs(distanceX) > 15) { 18421 this.swipeDirection = 'horizontal'; 18422 allowSwipe = true; 18423 } 18424 else if (Math.abs(distanceY) > 15) { 18425 this.swipeDirection = 'vertical'; 18426 allowSwipe = true; 18427 } 18428 } 18429 if (!allowSwipe) { 18430 return; 18431 } 18432 var $currentSlide = this.getSlideItem(this.index); 18433 if (this.swipeDirection === 'horizontal') { 18434 e === null || e === void 0 ? void 0 : e.preventDefault(); 18435 // reset opacity and transition duration 18436 this.outer.addClass('lg-dragging'); 18437 // move current slide 18438 this.setTranslate($currentSlide, distanceX, 0); 18439 // move next and prev slide with current slide 18440 var width = $currentSlide.get().offsetWidth; 18441 var slideWidthAmount = (width * 15) / 100; 18442 var gutter = slideWidthAmount - Math.abs((distanceX * 10) / 100); 18443 this.setTranslate(this.outer.find('.lg-prev-slide').first(), -width + distanceX - gutter, 0); 18444 this.setTranslate(this.outer.find('.lg-next-slide').first(), width + distanceX + gutter, 0); 18445 } 18446 else if (this.swipeDirection === 'vertical') { 18447 if (this.settings.swipeToClose) { 18448 e === null || e === void 0 ? void 0 : e.preventDefault(); 18449 this.$container.addClass('lg-dragging-vertical'); 18450 var opacity = 1 - Math.abs(distanceY) / window.innerHeight; 18451 this.$backdrop.css('opacity', opacity); 18452 var scale = 1 - Math.abs(distanceY) / (window.innerWidth * 2); 18453 this.setTranslate($currentSlide, 0, distanceY, scale, scale); 18454 if (Math.abs(distanceY) > 100) { 18455 this.outer 18456 .addClass('lg-hide-items') 18457 .removeClass('lg-components-open'); 18458 } 18459 } 18460 } 18461 }; 18462 LightGallery.prototype.touchEnd = function (endCoords, startCoords, event) { 18463 var _this = this; 18464 var distance; 18465 // keep slide animation for any mode while dragg/swipe 18466 if (this.settings.mode !== 'lg-slide') { 18467 this.outer.addClass('lg-slide'); 18468 } 18469 // set transition duration 18470 setTimeout(function () { 18471 _this.$container.removeClass('lg-dragging-vertical'); 18472 _this.outer 18473 .removeClass('lg-dragging lg-hide-items') 18474 .addClass('lg-components-open'); 18475 var triggerClick = true; 18476 if (_this.swipeDirection === 'horizontal') { 18477 distance = endCoords.pageX - startCoords.pageX; 18478 var distanceAbs = Math.abs(endCoords.pageX - startCoords.pageX); 18479 if (distance < 0 && 18480 distanceAbs > _this.settings.swipeThreshold) { 18481 _this.goToNextSlide(true); 18482 triggerClick = false; 18483 } 18484 else if (distance > 0 && 18485 distanceAbs > _this.settings.swipeThreshold) { 18486 _this.goToPrevSlide(true); 18487 triggerClick = false; 18488 } 18489 } 18490 else if (_this.swipeDirection === 'vertical') { 18491 distance = Math.abs(endCoords.pageY - startCoords.pageY); 18492 if (_this.settings.closable && 18493 _this.settings.swipeToClose && 18494 distance > 100) { 18495 _this.closeGallery(); 18496 return; 18497 } 18498 else { 18499 _this.$backdrop.css('opacity', 1); 18500 } 18501 } 18502 _this.outer.find('.lg-item').removeAttr('style'); 18503 if (triggerClick && 18504 Math.abs(endCoords.pageX - startCoords.pageX) < 5) { 18505 // Trigger click if distance is less than 5 pix 18506 var target = $LG(event.target); 18507 if (_this.isPosterElement(target)) { 18508 _this.LGel.trigger(lGEvents.posterClick); 18509 } 18510 } 18511 _this.swipeDirection = undefined; 18512 }); 18513 // remove slide class once drag/swipe is completed if mode is not slide 18514 setTimeout(function () { 18515 if (!_this.outer.hasClass('lg-dragging') && 18516 _this.settings.mode !== 'lg-slide') { 18517 _this.outer.removeClass('lg-slide'); 18518 } 18519 }, this.settings.speed + 100); 18520 }; 18521 LightGallery.prototype.enableSwipe = function () { 18522 var _this = this; 18523 var startCoords = {}; 18524 var endCoords = {}; 18525 var isMoved = false; 18526 var isSwiping = false; 18527 if (this.settings.enableSwipe) { 18528 this.$inner.on('touchstart.lg', function (e) { 18529 _this.dragOrSwipeEnabled = true; 18530 var $item = _this.getSlideItem(_this.index); 18531 if (($LG(e.target).hasClass('lg-item') || 18532 $item.get().contains(e.target)) && 18533 !_this.outer.hasClass('lg-zoomed') && 18534 !_this.lgBusy && 18535 e.targetTouches.length === 1) { 18536 isSwiping = true; 18537 _this.touchAction = 'swipe'; 18538 _this.manageSwipeClass(); 18539 startCoords = { 18540 pageX: e.targetTouches[0].pageX, 18541 pageY: e.targetTouches[0].pageY, 18542 }; 18543 } 18544 }); 18545 this.$inner.on('touchmove.lg', function (e) { 18546 if (isSwiping && 18547 _this.touchAction === 'swipe' && 18548 e.targetTouches.length === 1) { 18549 endCoords = { 18550 pageX: e.targetTouches[0].pageX, 18551 pageY: e.targetTouches[0].pageY, 18552 }; 18553 _this.touchMove(startCoords, endCoords, e); 18554 isMoved = true; 18555 } 18556 }); 18557 this.$inner.on('touchend.lg', function (event) { 18558 if (_this.touchAction === 'swipe') { 18559 if (isMoved) { 18560 isMoved = false; 18561 _this.touchEnd(endCoords, startCoords, event); 18562 } 18563 else if (isSwiping) { 18564 var target = $LG(event.target); 18565 if (_this.isPosterElement(target)) { 18566 _this.LGel.trigger(lGEvents.posterClick); 18567 } 18568 } 18569 _this.touchAction = undefined; 18570 isSwiping = false; 18571 } 18572 }); 18573 } 18574 }; 18575 LightGallery.prototype.enableDrag = function () { 18576 var _this = this; 18577 var startCoords = {}; 18578 var endCoords = {}; 18579 var isDraging = false; 18580 var isMoved = false; 18581 if (this.settings.enableDrag) { 18582 this.outer.on('mousedown.lg', function (e) { 18583 _this.dragOrSwipeEnabled = true; 18584 var $item = _this.getSlideItem(_this.index); 18585 if ($LG(e.target).hasClass('lg-item') || 18586 $item.get().contains(e.target)) { 18587 if (!_this.outer.hasClass('lg-zoomed') && !_this.lgBusy) { 18588 e.preventDefault(); 18589 if (!_this.lgBusy) { 18590 _this.manageSwipeClass(); 18591 startCoords = { 18592 pageX: e.pageX, 18593 pageY: e.pageY, 18594 }; 18595 isDraging = true; 18596 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 18597 _this.outer.get().scrollLeft += 1; 18598 _this.outer.get().scrollLeft -= 1; 18599 // * 18600 _this.outer 18601 .removeClass('lg-grab') 18602 .addClass('lg-grabbing'); 18603 _this.LGel.trigger(lGEvents.dragStart); 18604 } 18605 } 18606 } 18607 }); 18608 $LG(window).on("mousemove.lg.global" + this.lgId, function (e) { 18609 if (isDraging && _this.lgOpened) { 18610 isMoved = true; 18611 endCoords = { 18612 pageX: e.pageX, 18613 pageY: e.pageY, 18614 }; 18615 _this.touchMove(startCoords, endCoords); 18616 _this.LGel.trigger(lGEvents.dragMove); 18617 } 18618 }); 18619 $LG(window).on("mouseup.lg.global" + this.lgId, function (event) { 18620 if (!_this.lgOpened) { 18621 return; 18622 } 18623 var target = $LG(event.target); 18624 if (isMoved) { 18625 isMoved = false; 18626 _this.touchEnd(endCoords, startCoords, event); 18627 _this.LGel.trigger(lGEvents.dragEnd); 18628 } 18629 else if (_this.isPosterElement(target)) { 18630 _this.LGel.trigger(lGEvents.posterClick); 18631 } 18632 // Prevent execution on click 18633 if (isDraging) { 18634 isDraging = false; 18635 _this.outer.removeClass('lg-grabbing').addClass('lg-grab'); 18636 } 18637 }); 18638 } 18639 }; 18640 LightGallery.prototype.triggerPosterClick = function () { 18641 var _this = this; 18642 this.$inner.on('click.lg', function (event) { 18643 if (!_this.dragOrSwipeEnabled && 18644 _this.isPosterElement($LG(event.target))) { 18645 _this.LGel.trigger(lGEvents.posterClick); 18646 } 18647 }); 18648 }; 18649 LightGallery.prototype.manageSwipeClass = function () { 18650 var _touchNext = this.index + 1; 18651 var _touchPrev = this.index - 1; 18652 if (this.settings.loop && this.galleryItems.length > 2) { 18653 if (this.index === 0) { 18654 _touchPrev = this.galleryItems.length - 1; 18655 } 18656 else if (this.index === this.galleryItems.length - 1) { 18657 _touchNext = 0; 18658 } 18659 } 18660 this.outer.find('.lg-item').removeClass('lg-next-slide lg-prev-slide'); 18661 if (_touchPrev > -1) { 18662 this.getSlideItem(_touchPrev).addClass('lg-prev-slide'); 18663 } 18664 this.getSlideItem(_touchNext).addClass('lg-next-slide'); 18665 }; 18666 /** 18667 * Go to next slide 18668 * @param {Boolean} fromTouch - true if slide function called via touch event 18669 * @category lGPublicMethods 18670 * @example 18671 * const plugin = lightGallery(); 18672 * plugin.goToNextSlide(); 18673 * @see <a href="/demos/methods/">Demo</a> 18674 */ 18675 LightGallery.prototype.goToNextSlide = function (fromTouch) { 18676 var _this = this; 18677 var _loop = this.settings.loop; 18678 if (fromTouch && this.galleryItems.length < 3) { 18679 _loop = false; 18680 } 18681 if (!this.lgBusy) { 18682 if (this.index + 1 < this.galleryItems.length) { 18683 this.index++; 18684 this.LGel.trigger(lGEvents.beforeNextSlide, { 18685 index: this.index, 18686 }); 18687 this.slide(this.index, !!fromTouch, false, 'next'); 18688 } 18689 else { 18690 if (_loop) { 18691 this.index = 0; 18692 this.LGel.trigger(lGEvents.beforeNextSlide, { 18693 index: this.index, 18694 }); 18695 this.slide(this.index, !!fromTouch, false, 'next'); 18696 } 18697 else if (this.settings.slideEndAnimation && !fromTouch) { 18698 this.outer.addClass('lg-right-end'); 18699 setTimeout(function () { 18700 _this.outer.removeClass('lg-right-end'); 18701 }, 400); 18702 } 18703 } 18704 } 18705 }; 18706 /** 18707 * Go to previous slides 18708 * @param {Boolean} fromTouch - true if slide function called via touch event 18709 * @category lGPublicMethods 18710 * @example 18711 * const plugin = lightGallery({}); 18712 * plugin.goToPrevSlide(); 18713 * @see <a href="/demos/methods/">Demo</a> 18714 * 18715 */ 18716 LightGallery.prototype.goToPrevSlide = function (fromTouch) { 18717 var _this = this; 18718 var _loop = this.settings.loop; 18719 if (fromTouch && this.galleryItems.length < 3) { 18720 _loop = false; 18721 } 18722 if (!this.lgBusy) { 18723 if (this.index > 0) { 18724 this.index--; 18725 this.LGel.trigger(lGEvents.beforePrevSlide, { 18726 index: this.index, 18727 fromTouch: fromTouch, 18728 }); 18729 this.slide(this.index, !!fromTouch, false, 'prev'); 18730 } 18731 else { 18732 if (_loop) { 18733 this.index = this.galleryItems.length - 1; 18734 this.LGel.trigger(lGEvents.beforePrevSlide, { 18735 index: this.index, 18736 fromTouch: fromTouch, 18737 }); 18738 this.slide(this.index, !!fromTouch, false, 'prev'); 18739 } 18740 else if (this.settings.slideEndAnimation && !fromTouch) { 18741 this.outer.addClass('lg-left-end'); 18742 setTimeout(function () { 18743 _this.outer.removeClass('lg-left-end'); 18744 }, 400); 18745 } 18746 } 18747 } 18748 }; 18749 LightGallery.prototype.keyPress = function () { 18750 var _this = this; 18751 $LG(window).on("keydown.lg.global" + this.lgId, function (e) { 18752 if (_this.lgOpened && 18753 _this.settings.escKey === true && 18754 e.keyCode === 27) { 18755 e.preventDefault(); 18756 if (_this.settings.allowMediaOverlap && 18757 _this.outer.hasClass('lg-can-toggle') && 18758 _this.outer.hasClass('lg-components-open')) { 18759 _this.outer.removeClass('lg-components-open'); 18760 } 18761 else { 18762 _this.closeGallery(); 18763 } 18764 } 18765 if (_this.lgOpened && _this.galleryItems.length > 1) { 18766 if (e.keyCode === 37) { 18767 e.preventDefault(); 18768 _this.goToPrevSlide(); 18769 } 18770 if (e.keyCode === 39) { 18771 e.preventDefault(); 18772 _this.goToNextSlide(); 18773 } 18774 } 18775 }); 18776 }; 18777 LightGallery.prototype.arrow = function () { 18778 var _this = this; 18779 this.getElementById('lg-prev').on('click.lg', function () { 18780 _this.goToPrevSlide(); 18781 }); 18782 this.getElementById('lg-next').on('click.lg', function () { 18783 _this.goToNextSlide(); 18784 }); 18785 }; 18786 LightGallery.prototype.arrowDisable = function (index) { 18787 // Disable arrows if settings.hideControlOnEnd is true 18788 if (!this.settings.loop && this.settings.hideControlOnEnd) { 18789 var $prev = this.getElementById('lg-prev'); 18790 var $next = this.getElementById('lg-next'); 18791 if (index + 1 === this.galleryItems.length) { 18792 $next.attr('disabled', 'disabled').addClass('disabled'); 18793 } 18794 else { 18795 $next.removeAttr('disabled').removeClass('disabled'); 18796 } 18797 if (index === 0) { 18798 $prev.attr('disabled', 'disabled').addClass('disabled'); 18799 } 18800 else { 18801 $prev.removeAttr('disabled').removeClass('disabled'); 18802 } 18803 } 18804 }; 18805 LightGallery.prototype.setTranslate = function ($el, xValue, yValue, scaleX, scaleY) { 18806 if (scaleX === void 0) { scaleX = 1; } 18807 if (scaleY === void 0) { scaleY = 1; } 18808 $el.css('transform', 'translate3d(' + 18809 xValue + 18810 'px, ' + 18811 yValue + 18812 'px, 0px) scale3d(' + 18813 scaleX + 18814 ', ' + 18815 scaleY + 18816 ', 1)'); 18817 }; 18818 LightGallery.prototype.mousewheel = function () { 18819 var _this = this; 18820 var lastCall = 0; 18821 this.outer.on('wheel.lg', function (e) { 18822 if (!e.deltaY || _this.galleryItems.length < 2) { 18823 return; 18824 } 18825 e.preventDefault(); 18826 var now = new Date().getTime(); 18827 if (now - lastCall < 1000) { 18828 return; 18829 } 18830 lastCall = now; 18831 if (e.deltaY > 0) { 18832 _this.goToNextSlide(); 18833 } 18834 else if (e.deltaY < 0) { 18835 _this.goToPrevSlide(); 18836 } 18837 }); 18838 }; 18839 LightGallery.prototype.isSlideElement = function (target) { 18840 return (target.hasClass('lg-outer') || 18841 target.hasClass('lg-item') || 18842 target.hasClass('lg-img-wrap')); 18843 }; 18844 LightGallery.prototype.isPosterElement = function (target) { 18845 var playButton = this.getSlideItem(this.index) 18846 .find('.lg-video-play-button') 18847 .get(); 18848 return (target.hasClass('lg-video-poster') || 18849 target.hasClass('lg-video-play-button') || 18850 (playButton && playButton.contains(target.get()))); 18851 }; 18852 /** 18853 * Maximize minimize inline gallery. 18854 * @category lGPublicMethods 18855 */ 18856 LightGallery.prototype.toggleMaximize = function () { 18857 var _this = this; 18858 this.getElementById('lg-maximize').on('click.lg', function () { 18859 _this.$container.toggleClass('lg-inline'); 18860 _this.refreshOnResize(); 18861 }); 18862 }; 18863 LightGallery.prototype.invalidateItems = function () { 18864 for (var index = 0; index < this.items.length; index++) { 18865 var element = this.items[index]; 18866 var $element = $LG(element); 18867 $element.off("click.lgcustom-item-" + $element.attr('data-lg-id')); 18868 } 18869 }; 18870 LightGallery.prototype.manageCloseGallery = function () { 18871 var _this = this; 18872 if (!this.settings.closable) 18873 return; 18874 var mousedown = false; 18875 this.getElementById('lg-close').on('click.lg', function () { 18876 _this.closeGallery(); 18877 }); 18878 if (this.settings.closeOnTap) { 18879 // If you drag the slide and release outside gallery gets close on chrome 18880 // for preventing this check mousedown and mouseup happened on .lg-item or lg-outer 18881 this.outer.on('mousedown.lg', function (e) { 18882 var target = $LG(e.target); 18883 if (_this.isSlideElement(target)) { 18884 mousedown = true; 18885 } 18886 else { 18887 mousedown = false; 18888 } 18889 }); 18890 this.outer.on('mousemove.lg', function () { 18891 mousedown = false; 18892 }); 18893 this.outer.on('mouseup.lg', function (e) { 18894 var target = $LG(e.target); 18895 if (_this.isSlideElement(target) && mousedown) { 18896 if (!_this.outer.hasClass('lg-dragging')) { 18897 _this.closeGallery(); 18898 } 18899 } 18900 }); 18901 } 18902 }; 18903 /** 18904 * Close lightGallery if it is opened. 18905 * 18906 * @description If closable is false in the settings, you need to pass true via closeGallery method to force close gallery 18907 * @return returns the estimated time to close gallery completely including the close animation duration 18908 * @category lGPublicMethods 18909 * @example 18910 * const plugin = lightGallery(); 18911 * plugin.closeGallery(); 18912 * 18913 */ 18914 LightGallery.prototype.closeGallery = function (force) { 18915 var _this = this; 18916 if (!this.lgOpened || (!this.settings.closable && !force)) { 18917 return 0; 18918 } 18919 this.LGel.trigger(lGEvents.beforeClose); 18920 $LG(window).scrollTop(this.prevScrollTop); 18921 var currentItem = this.items[this.index]; 18922 var transform; 18923 if (this.zoomFromOrigin && currentItem) { 18924 var _a = this.mediaContainerPosition, top_4 = _a.top, bottom = _a.bottom; 18925 var _b = this.galleryItems[this.index], __slideVideoInfo = _b.__slideVideoInfo, poster = _b.poster; 18926 //Uncode edit ##START## 18927 var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize, this.galleryItems[this.index]); 18928 // var imageSize = utils.getSize(currentItem, this.outer, top_4 + bottom, __slideVideoInfo && poster && this.settings.videoMaxSize); 18929 //Uncode edit ##END## 18930 transform = utils.getTransform(currentItem, this.outer, top_4, bottom, imageSize); 18931 } 18932 if (this.zoomFromOrigin && transform) { 18933 this.outer.addClass('lg-closing lg-zoom-from-image'); 18934 this.getSlideItem(this.index) 18935 .addClass('lg-start-end-progress') 18936 .css('transition-duration', this.settings.startAnimationDuration + 'ms') 18937 .css('transform', transform); 18938 } 18939 else { 18940 this.outer.addClass('lg-hide-items'); 18941 // lg-zoom-from-image is used for setting the opacity to 1 if zoomFromOrigin is true 18942 // If the closing item doesn't have the lg-size attribute, remove this class to avoid the closing css conflicts 18943 this.outer.removeClass('lg-zoom-from-image'); 18944 } 18945 // Unbind all events added by lightGallery 18946 // @todo 18947 //this.$el.off('.lg.tm'); 18948 this.destroyModules(); 18949 this.lGalleryOn = false; 18950 this.isDummyImageRemoved = false; 18951 this.zoomFromOrigin = this.settings.zoomFromOrigin; 18952 clearTimeout(this.hideBarTimeout); 18953 this.hideBarTimeout = false; 18954 $LG('html').removeClass('lg-on'); 18955 this.outer.removeClass('lg-visible lg-components-open'); 18956 // Resetting opacity to 0 isd required as vertical swipe to close function adds inline opacity. 18957 this.$backdrop.removeClass('in').css('opacity', 0); 18958 var removeTimeout = this.zoomFromOrigin && transform 18959 ? Math.max(this.settings.startAnimationDuration, this.settings.backdropDuration) 18960 : this.settings.backdropDuration; 18961 this.$container.removeClass('lg-show-in'); 18962 // Once the closign animation is completed and gallery is invisible 18963 setTimeout(function () { 18964 if (_this.zoomFromOrigin && transform) { 18965 _this.outer.removeClass('lg-zoom-from-image'); 18966 } 18967 _this.$container.removeClass('lg-show'); 18968 // Need to remove inline opacity as it is used in the stylesheet as well 18969 _this.$backdrop 18970 .removeAttr('style') 18971 .css('transition-duration', _this.settings.backdropDuration + 'ms'); 18972 _this.outer.removeClass("lg-closing " + _this.settings.startClass);
18973 _this.getSlideItem(_this.index).removeClass('lg-start-end-progress'); 18974 _this.$inner.empty(); 18975 if (_this.lgOpened) { 18976 _this.LGel.trigger(lGEvents.afterClose, { 18977 instance: _this, 18978 }); 18979 } 18980 if (_this.outer.get()) { 18981 _this.outer.get().blur(); 18982 } 18983 _this.lgOpened = false; 18984 }, removeTimeout + 100); 18985 return removeTimeout + 100; 18986 }; 18987 LightGallery.prototype.initModules = function () { 18988 this.plugins.forEach(function (module) { 18989 try { 18990 module.init(); 18991 } 18992 catch (err) { 18993 console.warn("lightGallery:- make sure lightGallery module is properly initiated"); 18994 } 18995 }); 18996 }; 18997 LightGallery.prototype.destroyModules = function (destroy) { 18998 this.plugins.forEach(function (module) { 18999 try { 19000 if (destroy) { 19001 module.destroy(); 19002 } 19003 else { 19004 module.closeGallery && module.closeGallery(); 19005 } 19006 } 19007 catch (err) { 19008 console.warn("lightGallery:- make sure lightGallery module is properly destroyed"); 19009 } 19010 }); 19011 }; 19012 /** 19013 * Refresh lightGallery with new set of children. 19014 * 19015 * @description This is useful to update the gallery when the child elements are changed without calling destroy method. 19016 * 19017 * If you are using dynamic mode, you can pass the modified array of dynamicEl as the first parameter to refresh the dynamic gallery 19018 * @see <a href="/demos/dynamic-mode/">Demo</a> 19019 * @category lGPublicMethods 19020 * @example 19021 * const plugin = lightGallery(); 19022 * // Delete or add children, then call 19023 * plugin.refresh(); 19024 * 19025 */ 19026 LightGallery.prototype.refresh = function (galleryItems) { 19027 if (!this.settings.dynamic) { 19028 this.invalidateItems(); 19029 } 19030 if (galleryItems) { 19031 this.galleryItems = galleryItems; 19032 } 19033 else { 19034 this.galleryItems = this.getItems(); 19035 } 19036 this.updateControls(); 19037 this.openGalleryOnItemClick(); 19038 this.LGel.trigger(lGEvents.updateSlides); 19039 }; 19040 LightGallery.prototype.updateControls = function () { 19041 this.addSlideVideoInfo(this.galleryItems); 19042 this.updateCounterTotal(); 19043 this.manageSingleSlideClassName(); 19044 }; 19045 /** 19046 * Destroy lightGallery. 19047 * Destroy lightGallery and its plugin instances completely 19048 * 19049 * @description This method also calls CloseGallery function internally. Returns the time takes to completely close and destroy the instance. 19050 * In case if you want to re-initialize lightGallery right after destroying it, initialize it only once the destroy process is completed. 19051 * You can use refresh method most of the times. 19052 * @category lGPublicMethods 19053 * @example 19054 * const plugin = lightGallery(); 19055 * plugin.destroy(); 19056 * 19057 */ 19058 LightGallery.prototype.destroy = function () { 19059 var _this = this; 19060 var closeTimeout = this.closeGallery(true); 19061 setTimeout(function () { 19062 _this.destroyModules(true); 19063 if (!_this.settings.dynamic) { 19064 _this.invalidateItems(); 19065 } 19066 $LG(window).off(".lg.global" + _this.lgId); 19067 _this.LGel.off('.lg'); 19068 _this.$container.remove(); 19069 }, closeTimeout); 19070 return closeTimeout; 19071 }; 19072 return LightGallery; 19073 }()); 19074 19075 function lightGallery(el, options) { 19076 return new LightGallery(el, options); 19077 } 19078 19079 return lightGallery; 19080 19081}))); 19082//# sourceMappingURL=lightgallery.umd.js.map 19083 19084/*! 19085 * lightgallery | 2.4.0 | January 29th 2022 19086 * http://www.lightgalleryjs.com/ 19087 * Copyright (c) 2020 Sachin Neravath; 19088 * @license GPLv3 19089 */ 19090 19091(function (global, factory) { 19092 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 19093 typeof define === 'function' && define.amd ? define(factory) : 19094 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgZoom = factory()); 19095}(this, (function () { 'use strict'; 19096 19097 /*! ***************************************************************************** 19098 Copyright (c) Microsoft Corporation. 19099 19100 Permission to use, copy, modify, and/or distribute this software for any 19101 purpose with or without fee is hereby granted. 19102 19103 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 19104 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 19105 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 19106 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 19107 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 19108 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 19109 PERFORMANCE OF THIS SOFTWARE. 19110 ***************************************************************************** */ 19111 19112 var __assign = function() { 19113 __assign = Object.assign || function __assign(t) { 19114 for (var s, i = 1, n = arguments.length; i < n; i++) { 19115 s = arguments[i]; 19116 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 19117 } 19118 return t; 19119 }; 19120 return __assign.apply(this, arguments); 19121 }; 19122 19123 var zoomSettings = { 19124 scale: 1, 19125 zoom: true, 19126 actualSize: true, 19127 showZoomInOutIcons: false, 19128 actualSizeIcons: { 19129 zoomIn: 'lg-zoom-in', 19130 zoomOut: 'lg-zoom-out', 19131 }, 19132 enableZoomAfter: 300, 19133 zoomPluginStrings: { 19134 zoomIn: 'Zoom in', 19135 zoomOut: 'Zoom out', 19136 viewActualSize: 'View actual size', 19137 }, 19138 }; 19139 19140 /** 19141 * List of lightGallery events 19142 * All events should be documented here 19143 * Below interfaces are used to build the website documentations 19144 * */ 19145 var lGEvents = { 19146 afterAppendSlide: 'lgAfterAppendSlide', 19147 init: 'lgInit', 19148 hasVideo: 'lgHasVideo', 19149 containerResize: 'lgContainerResize', 19150 updateSlides: 'lgUpdateSlides', 19151 afterAppendSubHtml: 'lgAfterAppendSubHtml', 19152 beforeOpen: 'lgBeforeOpen', 19153 afterOpen: 'lgAfterOpen', 19154 slideItemLoad: 'lgSlideItemLoad', 19155 beforeSlide: 'lgBeforeSlide', 19156 afterSlide: 'lgAfterSlide', 19157 posterClick: 'lgPosterClick', 19158 dragStart: 'lgDragStart', 19159 dragMove: 'lgDragMove', 19160 dragEnd: 'lgDragEnd', 19161 beforeNextSlide: 'lgBeforeNextSlide', 19162 beforePrevSlide: 'lgBeforePrevSlide', 19163 beforeClose: 'lgBeforeClose', 19164 afterClose: 'lgAfterClose', 19165 rotateLeft: 'lgRotateLeft', 19166 rotateRight: 'lgRotateRight', 19167 flipHorizontal: 'lgFlipHorizontal', 19168 flipVertical: 'lgFlipVertical', 19169 autoplay: 'lgAutoplay', 19170 autoplayStart: 'lgAutoplayStart', 19171 autoplayStop: 'lgAutoplayStop', 19172 }; 19173 19174 var Zoom = /** @class */ (function () { 19175 function Zoom(instance, $LG) { 19176 // get lightGallery core plugin instance 19177 this.core = instance;
19178 this.$LG = $LG; 19179 this.settings = __assign(__assign({}, zoomSettings), this.core.settings); 19180 return this; 19181 } 19182 // Append Zoom controls. Actual size, Zoom-in, Zoom-out 19183 Zoom.prototype.buildTemplates = function () { 19184 var zoomIcons = this.settings.showZoomInOutIcons 19185 ? "<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>" 19186 : ''; 19187 if (this.settings.actualSize) { 19188 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>"; 19189 } 19190 this.core.outer.addClass('lg-use-transition-for-zoom'); 19191 this.core.$toolbar.first().append(zoomIcons); 19192 }; 19193 /** 19194 * @desc Enable zoom option only once the image is completely loaded 19195 * If zoomFromOrigin is true, Zoom is enabled once the dummy image has been inserted 19196 * 19197 * Zoom styles are defined under lg-zoomable CSS class. 19198 */ 19199 Zoom.prototype.enableZoom = function (event) { 19200 var _this = this; 19201 // delay will be 0 except first time 19202 var _speed = this.settings.enableZoomAfter + event.detail.delay; 19203 // set _speed value 0 if gallery opened from direct url and if it is first slide 19204 if (this.$LG('body').first().hasClass('lg-from-hash') && 19205 event.detail.delay) { 19206 // will execute only once 19207 _speed = 0; 19208 } 19209 else { 19210 // Remove lg-from-hash to enable starting animation. 19211 this.$LG('body').first().removeClass('lg-from-hash'); 19212 } 19213 this.zoomableTimeout = setTimeout(function () { 19214 if (!_this.isImageSlide()) { 19215 return; 19216 } 19217 _this.core.getSlideItem(event.detail.index).addClass('lg-zoomable'); 19218 if (event.detail.index === _this.core.index) { 19219 _this.setZoomEssentials(); 19220 } 19221 }, _speed + 30); 19222 }; 19223 Zoom.prototype.enableZoomOnSlideItemLoad = function () { 19224 // Add zoomable class 19225 this.core.LGel.on(lGEvents.slideItemLoad + ".zoom", this.enableZoom.bind(this)); 19226 }; 19227 Zoom.prototype.getModifier = function (rotateValue, axis, el) { 19228 var originalRotate = rotateValue; 19229 rotateValue = Math.abs(rotateValue); 19230 var transformValues = this.getCurrentTransform(el); 19231 if (!transformValues) { 19232 return 1; 19233 } 19234 var modifier = 1; 19235 if (axis === 'X') { 19236 var flipHorizontalValue = Math.sign(parseFloat(transformValues[0])); 19237 if (rotateValue === 0 || rotateValue === 180) { 19238 modifier = 1; 19239 } 19240 else if (rotateValue === 90) { 19241 if ((originalRotate === -90 && flipHorizontalValue === 1) || 19242 (originalRotate === 90 && flipHorizontalValue === -1)) { 19243 modifier = -1; 19244 } 19245 else { 19246 modifier = 1; 19247 } 19248 } 19249 modifier = modifier * flipHorizontalValue; 19250 } 19251 else { 19252 var flipVerticalValue = Math.sign(parseFloat(transformValues[3])); 19253 if (rotateValue === 0 || rotateValue === 180) { 19254 modifier = 1; 19255 } 19256 else if (rotateValue === 90) { 19257 var sinX = parseFloat(transformValues[1]);
19258 var sinMinusX = parseFloat(transformValues[2]); 19259 modifier = Math.sign(sinX * sinMinusX * originalRotate * flipVerticalValue); 19260 } 19261 modifier = modifier * flipVerticalValue; 19262 } 19263 return modifier; 19264 }; 19265 Zoom.prototype.getImageSize = function ($image, rotateValue, axis) { 19266 var imageSizes = { 19267 y: 'offsetHeight', 19268 x: 'offsetWidth', 19269 }; 19270 if (Math.abs(rotateValue) === 90) { 19271 // Swap axis 19272 if (axis === 'x') { 19273 axis = 'y'; 19274 } 19275 else { 19276 axis = 'x'; 19277 } 19278 } 19279 return $image[imageSizes[axis]]; 19280 }; 19281 Zoom.prototype.getDragCords = function (e, rotateValue) { 19282 if (rotateValue === 90) { 19283 return { 19284 x: e.pageY, 19285 y: e.pageX, 19286 }; 19287 } 19288 else { 19289 return { 19290 x: e.pageX, 19291 y: e.pageY, 19292 }; 19293 } 19294 }; 19295 Zoom.prototype.getSwipeCords = function (e, rotateValue) { 19296 var x = e.targetTouches[0].pageX; 19297 var y = e.targetTouches[0].pageY; 19298 if (rotateValue === 90) { 19299 return { 19300 x: y, 19301 y: x, 19302 }; 19303 } 19304 else { 19305 return { 19306 x: x, 19307 y: y, 19308 }; 19309 } 19310 }; 19311 Zoom.prototype.getDragAllowedAxises = function (rotateValue, scale) { 19312 scale = scale || this.scale || 1; 19313 var allowY = this.imageYSize * scale > this.containerRect.height; 19314 var allowX = this.imageXSize * scale > this.containerRect.width; 19315 if (rotateValue === 90) { 19316 return { 19317 allowX: allowY, 19318 allowY: allowX, 19319 }; 19320 } 19321 else { 19322 return { 19323 allowX: allowX, 19324 allowY: allowY, 19325 }; 19326 } 19327 }; 19328 /** 19329 * 19330 * @param {Element} el 19331 * @return matrix(cos(X), sin(X), -sin(X), cos(X), 0, 0); 19332 * Get the current transform value 19333 */ 19334 Zoom.prototype.getCurrentTransform = function (el) { 19335 if (!el) { 19336 return; 19337 } 19338 var st = window.getComputedStyle(el, null); 19339 var tm = st.getPropertyValue('-webkit-transform') || 19340 st.getPropertyValue('-moz-transform') || 19341 st.getPropertyValue('-ms-transform') || 19342 st.getPropertyValue('-o-transform') || 19343 st.getPropertyValue('transform') || 19344 'none'; 19345 if (tm !== 'none') { 19346 return tm.split('(')[1].split(')')[0].split(','); 19347 } 19348 return; 19349 }; 19350 Zoom.prototype.getCurrentRotation = function (el) { 19351 if (!el) { 19352 return 0; 19353 } 19354 var values = this.getCurrentTransform(el); 19355 if (values) { 19356 return Math.round(Math.atan2(parseFloat(values[1]), parseFloat(values[0])) * 19357 (180 / Math.PI)); 19358 // If you want rotate in 360 19359 //return (angle < 0 ? angle + 360 : angle); 19360 } 19361 return 0; 19362 }; 19363 Zoom.prototype.setZoomEssentials = function () { 19364 var $image = this.core 19365 .getSlideItem(this.core.index) 19366 .find('.lg-image') 19367 .first(); 19368 var rotateEl = this.core 19369 .getSlideItem(this.core.index) 19370 .find('.lg-img-rotate') 19371 .first() 19372 .get(); 19373 this.rotateValue = this.getCurrentRotation(rotateEl); 19374 this.imageYSize = this.getImageSize($image.get(), this.rotateValue, 'y'); 19375 this.imageXSize = this.getImageSize($image.get(), this.rotateValue, 'x'); 19376 this.containerRect = this.core.outer.get().getBoundingClientRect(); 19377 this.modifierX = this.getModifier(this.rotateValue, 'X', rotateEl); 19378 this.modifierY = this.getModifier(this.rotateValue, 'Y', rotateEl); 19379 }; 19380 /**
19381 * @desc Image zoom 19382 * Translate the wrap and scale the image to get better user experience 19383 * 19384 * @param {String} scale - Zoom decrement/increment value 19385 */ 19386 Zoom.prototype.zoomImage = function (scale) { 19387 // Find offset manually to avoid issue after zoom 19388 var offsetX = (this.containerRect.width - this.imageXSize) / 2 + 19389 this.containerRect.left; 19390 var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 19391 var topBottomSpacing = Math.abs(top - bottom) / 2; 19392 var offsetY = (this.containerRect.height - 19393 this.imageYSize - 19394 topBottomSpacing * this.modifierX) / 19395 2 + 19396 this.scrollTop + 19397 this.containerRect.top; 19398 var originalX; 19399 var originalY; 19400 if (scale === 1) { 19401 this.positionChanged = false; 19402 } 19403 var dragAllowedAxises = this.getDragAllowedAxises(Math.abs(this.rotateValue), scale); 19404 var allowY = dragAllowedAxises.allowY, allowX = dragAllowedAxises.allowX; 19405 if (this.positionChanged) { 19406 originalX = this.left / (this.scale - 1); 19407 originalY = this.top / (this.scale - 1); 19408 this.pageX = Math.abs(originalX) + offsetX; 19409 this.pageY = Math.abs(originalY) + offsetY; 19410 this.positionChanged = false; 19411 } 19412 var possibleSwipeCords = this.getPossibleSwipeDragCords(this.rotateValue, scale); 19413 var _x = offsetX - this.pageX; 19414 var _y = offsetY - this.pageY; 19415 var x = (scale - 1) * _x; 19416 var y = (scale - 1) * _y; 19417 if (allowX) { 19418 if (this.isBeyondPossibleLeft(x, possibleSwipeCords.minX)) { 19419 x = possibleSwipeCords.minX; 19420 } 19421 else if (this.isBeyondPossibleRight(x, possibleSwipeCords.maxX)) { 19422 x = possibleSwipeCords.maxX; 19423 } 19424 } 19425 else { 19426 if (scale > 1) { 19427 if (x < possibleSwipeCords.minX) { 19428 x = possibleSwipeCords.minX; 19429 } 19430 else if (x > possibleSwipeCords.maxX) { 19431 x = possibleSwipeCords.maxX; 19432 } 19433 } 19434 } 19435 if (allowY) { 19436 if (this.isBeyondPossibleTop(y, possibleSwipeCords.minY)) { 19437 y = possibleSwipeCords.minY; 19438 } 19439 else if (this.isBeyondPossibleBottom(y, possibleSwipeCords.maxY)) { 19440 y = possibleSwipeCords.maxY; 19441 } 19442 } 19443 else { 19444 // If the translate value based on index of beyond the viewport, utilize the available space to prevent image being cut out 19445 if (scale > 1) { 19446 //If image goes beyond viewport top, use the minim possible translate value 19447 if (y < possibleSwipeCords.minY) { 19448 y = possibleSwipeCords.minY; 19449 } 19450 else if (y > possibleSwipeCords.maxY) { 19451 y = possibleSwipeCords.maxY; 19452 } 19453 } 19454 } 19455 this.setZoomStyles({ 19456 x: x, 19457 y: y, 19458 scale: scale, 19459 }); 19460 }; 19461 /** 19462 * @desc apply scale3d to image and translate to image wrap 19463 * @param {style} X,Y and scale 19464 */ 19465 Zoom.prototype.setZoomStyles = function (style) { 19466 var $image = this.core 19467 .getSlideItem(this.core.index) 19468 .find('.lg-image') 19469 .first(); 19470 var $dummyImage = this.core.outer 19471 .find('.lg-current .lg-dummy-img') 19472 .first(); 19473 var $imageWrap = $image.parent(); 19474 this.scale = style.scale; 19475 $image.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)'); 19476 $dummyImage.css('transform', 'scale3d(' + style.scale + ', ' + style.scale + ', 1)'); 19477 var transform = 'translate3d(' + style.x + 'px, ' + style.y + 'px, 0)'; 19478 $imageWrap.css('transform', transform); 19479 this.left = style.x; 19480 this.top = style.y; 19481 }; 19482 /** 19483 * @param index - Index of the current slide 19484 * @param event - event will be available only if the function is called on clicking/taping the imags 19485 */ 19486 Zoom.prototype.setActualSize = function (index, event) { 19487 var _this = this; 19488 // Allow zoom only on image 19489 if (!this.isImageSlide() || 19490 this.core.outer.hasClass('lg-first-slide-loading')) { 19491 return; 19492 } 19493 var scale = this.getCurrentImageActualSizeScale(); 19494 if (this.core.outer.hasClass('lg-zoomed')) { 19495 this.scale = 1; 19496 } 19497 else {
19498 this.scale = this.getScale(scale); 19499 } 19500 this.setPageCords(event); 19501 this.beginZoom(this.scale); 19502 this.zoomImage(this.scale); 19503 setTimeout(function () { 19504 _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab'); 19505 }, 10); 19506 }; 19507 Zoom.prototype.getNaturalWidth = function (index) { 19508 var $image = this.core.getSlideItem(index).find('.lg-image').first(); 19509 var naturalWidth = this.core.galleryItems[index].width; 19510 return naturalWidth 19511 ? parseFloat(naturalWidth) 19512 : $image.get().naturalWidth; 19513 }; 19514 Zoom.prototype.getActualSizeScale = function (naturalWidth, width) { 19515 var _scale; 19516 var scale; 19517 if (naturalWidth > width) { 19518 _scale = naturalWidth / width; 19519 scale = _scale || 2; 19520 } 19521 else { 19522 scale = 1; 19523 } 19524 return scale; 19525 }; 19526 Zoom.prototype.getCurrentImageActualSizeScale = function () { 19527 var $image = this.core 19528 .getSlideItem(this.core.index) 19529 .find('.lg-image') 19530 .first(); 19531 var width = $image.get().offsetWidth; 19532 var naturalWidth = this.getNaturalWidth(this.core.index) || width; 19533 return this.getActualSizeScale(naturalWidth, width); 19534 }; 19535 Zoom.prototype.getPageCords = function (event) { 19536 var cords = {}; 19537 if (event) { 19538 cords.x = event.pageX || event.targetTouches[0].pageX; 19539 cords.y = event.pageY || event.targetTouches[0].pageY; 19540 } 19541 else { 19542 var containerRect = this.core.outer.get().getBoundingClientRect(); 19543 cords.x = containerRect.width / 2 + containerRect.left; 19544 cords.y = 19545 containerRect.height / 2 + this.scrollTop + containerRect.top; 19546 } 19547 return cords; 19548 }; 19549 Zoom.prototype.setPageCords = function (event) { 19550 var pageCords = this.getPageCords(event); 19551 this.pageX = pageCords.x; 19552 this.pageY = pageCords.y; 19553 }; 19554 // If true, zoomed - in else zoomed out 19555 Zoom.prototype.beginZoom = function (scale) { 19556 this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging'); 19557 if (scale > 1) { 19558 this.core.outer.addClass('lg-zoomed'); 19559 var $actualSize = this.core.getElementById('lg-actual-size'); 19560 $actualSize 19561 .removeClass(this.settings.actualSizeIcons.zoomIn) 19562 .addClass(this.settings.actualSizeIcons.zoomOut); 19563 } 19564 else { 19565 this.resetZoom(); 19566 } 19567 return scale > 1; 19568 }; 19569 Zoom.prototype.getScale = function (scale) { 19570 var actualSizeScale = this.getCurrentImageActualSizeScale(); 19571 if (scale < 1) { 19572 scale = 1; 19573 } 19574 else if (scale > actualSizeScale) { 19575 scale = actualSizeScale; 19576 } 19577 return scale; 19578 }; 19579 Zoom.prototype.init = function () { 19580 var _this = this; 19581 if (!this.settings.zoom) { 19582 return; 19583 } 19584 this.buildTemplates(); 19585 this.enableZoomOnSlideItemLoad(); 19586 var tapped = null; 19587 this.core.outer.on('dblclick.lg', function (event) { 19588 if (!_this.$LG(event.target).hasClass('lg-image')) { 19589 return; 19590 } 19591 _this.setActualSize(_this.core.index, event); 19592 }); 19593 this.core.outer.on('touchstart.lg', function (event) { 19594 var $target = _this.$LG(event.target); 19595 if (event.targetTouches.length === 1 && 19596 $target.hasClass('lg-image')) { 19597 if (!tapped) { 19598 tapped = setTimeout(function () { 19599 tapped = null; 19600 }, 300); 19601 } 19602 else { 19603 clearTimeout(tapped); 19604 tapped = null; 19605 event.preventDefault(); 19606 _this.setActualSize(_this.core.index, event); 19607 } 19608 } 19609 }); 19610 // Update zoom on resize and orientationchange 19611 this.core.LGel.on(lGEvents.containerResize + ".zoom " + lGEvents.rotateRight + ".zoom " + lGEvents.rotateLeft + ".zoom " + lGEvents.flipHorizontal + ".zoom " + lGEvents.flipVertical + ".zoom", function () { 19612 if (!_this.core.lgOpened || !_this.isImageSlide()) 19613 return; 19614 _this.setPageCords(); 19615 _this.setZoomEssentials(); 19616 _this.zoomImage(_this.scale); 19617 }); 19618 // Update zoom on resize and orientationchange 19619 this.$LG(window).on("scroll.lg.zoom.global" + this.core.lgId, function () { 19620 if (!_this.core.lgOpened) 19621 return; 19622 _this.scrollTop = _this.$LG(window).scrollTop(); 19623 }); 19624 this.core.getElementById('lg-zoom-out').on('click.lg', function () { 19625 if (_this.core.outer.find('.lg-current .lg-image').get()) { 19626 _this.scale -= _this.settings.scale;
19627 _this.scale = _this.getScale(_this.scale); 19628 _this.beginZoom(_this.scale); 19629 _this.zoomImage(_this.scale); 19630 } 19631 }); 19632 this.core.getElementById('lg-zoom-in').on('click.lg', function () { 19633 _this.zoomIn(); 19634 }); 19635 this.core.getElementById('lg-actual-size').on('click.lg', function () { 19636 _this.setActualSize(_this.core.index); 19637 }); 19638 this.core.LGel.on(lGEvents.beforeOpen + ".zoom", function () { 19639 _this.core.outer.find('.lg-item').removeClass('lg-zoomable'); 19640 }); 19641 this.core.LGel.on(lGEvents.afterOpen + ".zoom", function () { 19642 _this.scrollTop = _this.$LG(window).scrollTop(); 19643 // Set the initial value center 19644 _this.pageX = _this.core.outer.width() / 2; 19645 _this.pageY = _this.core.outer.height() / 2 + _this.scrollTop; 19646 _this.scale = 1; 19647 }); 19648 // Reset zoom on slide change 19649 this.core.LGel.on(lGEvents.afterSlide + ".zoom", function (event) { 19650 var prevIndex = event.detail.prevIndex; 19651 _this.scale = 1; 19652 _this.positionChanged = false; 19653 _this.resetZoom(prevIndex); 19654 if (_this.isImageSlide()) { 19655 _this.setZoomEssentials(); 19656 } 19657 }); 19658 // Drag option after zoom 19659 this.zoomDrag(); 19660 this.pinchZoom(); 19661 this.zoomSwipe(); 19662 // Store the zoomable timeout value just to clear it while closing 19663 this.zoomableTimeout = false; 19664 this.positionChanged = false; 19665 }; 19666 Zoom.prototype.zoomIn = function (scale) { 19667 // Allow zoom only on image 19668 if (!this.isImageSlide()) { 19669 return; 19670 } 19671 if (scale) { 19672 this.scale = scale; 19673 } 19674 else { 19675 this.scale += this.settings.scale; 19676 } 19677 this.scale = this.getScale(this.scale); 19678 this.beginZoom(this.scale); 19679 this.zoomImage(this.scale); 19680 }; 19681 // Reset zoom effect 19682 Zoom.prototype.resetZoom = function (index) { 19683 this.core.outer.removeClass('lg-zoomed lg-zoom-drag-transition'); 19684 var $actualSize = this.core.getElementById('lg-actual-size'); 19685 var $item = this.core.getSlideItem(index !== undefined ? index : this.core.index); 19686 $actualSize 19687 .removeClass(this.settings.actualSizeIcons.zoomOut) 19688 .addClass(this.settings.actualSizeIcons.zoomIn); 19689 $item.find('.lg-img-wrap').first().removeAttr('style'); 19690 $item.find('.lg-image').first().removeAttr('style'); 19691 this.scale = 1; 19692 this.left = 0; 19693 this.top = 0; 19694 // Reset pagx pagy values to center 19695 this.setPageCords(); 19696 }; 19697 Zoom.prototype.getTouchDistance = function (e) { 19698 return Math.sqrt((e.targetTouches[0].pageX - e.targetTouches[1].pageX) * 19699 (e.targetTouches[0].pageX - e.targetTouches[1].pageX) + 19700 (e.targetTouches[0].pageY - e.targetTouches[1].pageY) * 19701 (e.targetTouches[0].pageY - e.targetTouches[1].pageY)); 19702 }; 19703 Zoom.prototype.pinchZoom = function () { 19704 var _this = this; 19705 var startDist = 0; 19706 var pinchStarted = false; 19707 var initScale = 1; 19708 var $item = this.core.getSlideItem(this.core.index); 19709 this.core.$inner.on('touchstart.lg', function (e) { 19710 $item = _this.core.getSlideItem(_this.core.index); 19711 if (!_this.isImageSlide()) { 19712 return; 19713 } 19714 if (e.targetTouches.length === 2 && 19715 !_this.core.outer.hasClass('lg-first-slide-loading') && 19716 (_this.$LG(e.target).hasClass('lg-item') || 19717 $item.get().contains(e.target))) { 19718 initScale = _this.scale || 1; 19719 _this.core.outer.removeClass('lg-zoom-drag-transition lg-zoom-dragging'); 19720 _this.core.touchAction = 'pinch'; 19721 startDist = _this.getTouchDistance(e); 19722 } 19723 }); 19724 this.core.$inner.on('touchmove.lg', function (e) { 19725 if (e.targetTouches.length === 2 && 19726 _this.core.touchAction === 'pinch' && 19727 (_this.$LG(e.target).hasClass('lg-item') || 19728 $item.get().contains(e.target))) { 19729 e.preventDefault(); 19730 var endDist = _this.getTouchDistance(e); 19731 var distance = startDist - endDist; 19732 if (!pinchStarted && Math.abs(distance) > 5) { 19733 pinchStarted = true; 19734 } 19735 if (pinchStarted) { 19736 _this.scale = Math.max(1, initScale + -distance * 0.008); 19737 _this.zoomImage(_this.scale); 19738 } 19739 } 19740 }); 19741 this.core.$inner.on('touchend.lg', function (e) { 19742 if (_this.core.touchAction === 'pinch' && 19743 (_this.$LG(e.target).hasClass('lg-item') || 19744 $item.get().contains(e.target))) { 19745 pinchStarted = false;
19746 startDist = 0; 19747 if (_this.scale <= 1) { 19748 _this.resetZoom(); 19749 } 19750 else { 19751 _this.scale = _this.getScale(_this.scale); 19752 _this.zoomImage(_this.scale); 19753 _this.core.outer.addClass('lg-zoomed'); 19754 } 19755 _this.core.touchAction = undefined; 19756 } 19757 }); 19758 }; 19759 Zoom.prototype.touchendZoom = function (startCoords, endCoords, allowX, allowY, touchDuration, rotateValue) { 19760 var distanceXnew = endCoords.x - startCoords.x; 19761 var distanceYnew = endCoords.y - startCoords.y; 19762 var speedX = Math.abs(distanceXnew) / touchDuration + 1; 19763 var speedY = Math.abs(distanceYnew) / touchDuration + 1; 19764 if (speedX > 2) { 19765 speedX += 1; 19766 } 19767 if (speedY > 2) { 19768 speedY += 1; 19769 } 19770 distanceXnew = distanceXnew * speedX; 19771 distanceYnew = distanceYnew * speedY; 19772 var _LGel = this.core 19773 .getSlideItem(this.core.index) 19774 .find('.lg-img-wrap') 19775 .first(); 19776 var distance = {}; 19777 distance.x = this.left + distanceXnew * this.modifierX; 19778 distance.y = this.top + distanceYnew * this.modifierY; 19779 var possibleSwipeCords = this.getPossibleSwipeDragCords(rotateValue); 19780 if (Math.abs(distanceXnew) > 15 || Math.abs(distanceYnew) > 15) { 19781 if (allowY) { 19782 if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) { 19783 distance.y = possibleSwipeCords.minY; 19784 } 19785 else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) { 19786 distance.y = possibleSwipeCords.maxY; 19787 } 19788 } 19789 if (allowX) { 19790 if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) { 19791 distance.x = possibleSwipeCords.minX; 19792 } 19793 else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) { 19794 distance.x = possibleSwipeCords.maxX; 19795 } 19796 } 19797 if (allowY) { 19798 this.top = distance.y; 19799 } 19800 else { 19801 distance.y = this.top; 19802 } 19803 if (allowX) { 19804 this.left = distance.x; 19805 } 19806 else { 19807 distance.x = this.left; 19808 } 19809 this.setZoomSwipeStyles(_LGel, distance); 19810 this.positionChanged = true; 19811 } 19812 }; 19813 Zoom.prototype.getZoomSwipeCords = function (startCoords, endCoords, allowX, allowY, possibleSwipeCords) { 19814 var distance = {}; 19815 if (allowY) { 19816 distance.y = 19817 this.top + (endCoords.y - startCoords.y) * this.modifierY; 19818 if (this.isBeyondPossibleTop(distance.y, possibleSwipeCords.minY)) { 19819 var diffMinY = possibleSwipeCords.minY - distance.y; 19820 distance.y = possibleSwipeCords.minY - diffMinY / 6; 19821 } 19822 else if (this.isBeyondPossibleBottom(distance.y, possibleSwipeCords.maxY)) { 19823 var diffMaxY = distance.y - possibleSwipeCords.maxY; 19824 distance.y = possibleSwipeCords.maxY + diffMaxY / 6; 19825 } 19826 } 19827 else { 19828 distance.y = this.top; 19829 } 19830 if (allowX) { 19831 distance.x = 19832 this.left + (endCoords.x - startCoords.x) * this.modifierX; 19833 if (this.isBeyondPossibleLeft(distance.x, possibleSwipeCords.minX)) { 19834 var diffMinX = possibleSwipeCords.minX - distance.x; 19835 distance.x = possibleSwipeCords.minX - diffMinX / 6; 19836 } 19837 else if (this.isBeyondPossibleRight(distance.x, possibleSwipeCords.maxX)) { 19838 var difMaxX = distance.x - possibleSwipeCords.maxX; 19839 distance.x = possibleSwipeCords.maxX + difMaxX / 6; 19840 } 19841 } 19842 else { 19843 distance.x = this.left; 19844 } 19845 return distance; 19846 }; 19847 Zoom.prototype.isBeyondPossibleLeft = function (x, minX) { 19848 return x >= minX; 19849 }; 19850 Zoom.prototype.isBeyondPossibleRight = function (x, maxX) { 19851 return x <= maxX; 19852 }; 19853 Zoom.prototype.isBeyondPossibleTop = function (y, minY) { 19854 return y >= minY; 19855 }; 19856 Zoom.prototype.isBeyondPossibleBottom = function (y, maxY) { 19857 return y <= maxY; 19858 }; 19859 Zoom.prototype.isImageSlide = function () { 19860 var currentItem = this.core.galleryItems[this.core.index];
19861 return this.core.getSlideType(currentItem) === 'image'; 19862 }; 19863 Zoom.prototype.getPossibleSwipeDragCords = function (rotateValue, scale) { 19864 var dataScale = scale || this.scale || 1; 19865 var elDataScale = Math.abs(dataScale); 19866 var _a = this.core.mediaContainerPosition, top = _a.top, bottom = _a.bottom; 19867 var topBottomSpacing = Math.abs(top - bottom) / 2; 19868 var minY = (this.imageYSize - this.containerRect.height) / 2 + 19869 topBottomSpacing * this.modifierX; 19870 var maxY = this.containerRect.height - this.imageYSize * elDataScale + minY; 19871 var minX = (this.imageXSize - this.containerRect.width) / 2; 19872 var maxX = this.containerRect.width - this.imageXSize * elDataScale + minX; 19873 var possibleSwipeCords = { 19874 minY: minY, 19875 maxY: maxY, 19876 minX: minX, 19877 maxX: maxX, 19878 }; 19879 if (Math.abs(rotateValue) === 90) { 19880 possibleSwipeCords = { 19881 minY: minX, 19882 maxY: maxX, 19883 minX: minY, 19884 maxX: maxY, 19885 }; 19886 } 19887 return possibleSwipeCords; 19888 }; 19889 Zoom.prototype.setZoomSwipeStyles = function (LGel, distance) { 19890 LGel.css('transform', 'translate3d(' + distance.x + 'px, ' + distance.y + 'px, 0)'); 19891 }; 19892 Zoom.prototype.zoomSwipe = function () { 19893 var _this = this; 19894 var startCoords = {}; 19895 var endCoords = {}; 19896 var isMoved = false; 19897 // Allow x direction drag 19898 var allowX = false; 19899 // Allow Y direction drag 19900 var allowY = false; 19901 var startTime = new Date(); 19902 var endTime = new Date(); 19903 var possibleSwipeCords; 19904 var _LGel; 19905 var $item = this.core.getSlideItem(this.core.index); 19906 this.core.$inner.on('touchstart.lg', function (e) { 19907 // Allow zoom only on image 19908 if (!_this.isImageSlide()) { 19909 return; 19910 } 19911 $item = _this.core.getSlideItem(_this.core.index); 19912 if ((_this.$LG(e.target).hasClass('lg-item') || 19913 $item.get().contains(e.target)) && 19914 e.targetTouches.length === 1 && 19915 _this.core.outer.hasClass('lg-zoomed')) { 19916 e.preventDefault(); 19917 startTime = new Date(); 19918 _this.core.touchAction = 'zoomSwipe'; 19919 _LGel = _this.core 19920 .getSlideItem(_this.core.index) 19921 .find('.lg-img-wrap') 19922 .first(); 19923 var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue)); 19924 allowY = dragAllowedAxises.allowY; 19925 allowX = dragAllowedAxises.allowX; 19926 if (allowX || allowY) { 19927 startCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue)); 19928 } 19929 possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue); 19930 // reset opacity and transition duration 19931 _this.core.outer.addClass('lg-zoom-dragging lg-zoom-drag-transition'); 19932 } 19933 }); 19934 this.core.$inner.on('touchmove.lg', function (e) { 19935 if (e.targetTouches.length === 1 && 19936 _this.core.touchAction === 'zoomSwipe' && 19937 (_this.$LG(e.target).hasClass('lg-item') || 19938 $item.get().contains(e.target))) { 19939 e.preventDefault(); 19940 _this.core.touchAction = 'zoomSwipe'; 19941 endCoords = _this.getSwipeCords(e, Math.abs(_this.rotateValue)); 19942 var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords); 19943 if (Math.abs(endCoords.x - startCoords.x) > 15 || 19944 Math.abs(endCoords.y - startCoords.y) > 15) { 19945 isMoved = true; 19946 _this.setZoomSwipeStyles(_LGel, distance); 19947 } 19948 } 19949 }); 19950 this.core.$inner.on('touchend.lg', function (e) { 19951 if (_this.core.touchAction === 'zoomSwipe' && 19952 (_this.$LG(e.target).hasClass('lg-item') || 19953 $item.get().contains(e.target))) { 19954 _this.core.touchAction = undefined; 19955 _this.core.outer.removeClass('lg-zoom-dragging'); 19956 if (!isMoved) { 19957 return; 19958 } 19959 isMoved = false;
19960 endTime = new Date(); 19961 var touchDuration = endTime.valueOf() - startTime.valueOf(); 19962 _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue); 19963 } 19964 }); 19965 }; 19966 Zoom.prototype.zoomDrag = function () { 19967 var _this = this; 19968 var startCoords = {}; 19969 var endCoords = {}; 19970 var isDragging = false; 19971 var isMoved = false; 19972 // Allow x direction drag 19973 var allowX = false; 19974 // Allow Y direction drag 19975 var allowY = false; 19976 var startTime; 19977 var endTime; 19978 var possibleSwipeCords; 19979 var _LGel; 19980 this.core.outer.on('mousedown.lg.zoom', function (e) { 19981 // Allow zoom only on image 19982 if (!_this.isImageSlide()) { 19983 return; 19984 } 19985 var $item = _this.core.getSlideItem(_this.core.index); 19986 if (_this.$LG(e.target).hasClass('lg-item') || 19987 $item.get().contains(e.target)) { 19988 startTime = new Date(); 19989 _LGel = _this.core 19990 .getSlideItem(_this.core.index) 19991 .find('.lg-img-wrap') 19992 .first(); 19993 var dragAllowedAxises = _this.getDragAllowedAxises(Math.abs(_this.rotateValue)); 19994 allowY = dragAllowedAxises.allowY; 19995 allowX = dragAllowedAxises.allowX; 19996 if (_this.core.outer.hasClass('lg-zoomed')) { 19997 if (_this.$LG(e.target).hasClass('lg-object') && 19998 (allowX || allowY)) { 19999 e.preventDefault(); 20000 startCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 20001 possibleSwipeCords = _this.getPossibleSwipeDragCords(_this.rotateValue); 20002 isDragging = true; 20003 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 20004 _this.core.outer.get().scrollLeft += 1; 20005 _this.core.outer.get().scrollLeft -= 1; 20006 _this.core.outer 20007 .removeClass('lg-grab') 20008 .addClass('lg-grabbing lg-zoom-drag-transition lg-zoom-dragging'); 20009 // reset opacity and transition duration 20010 } 20011 } 20012 } 20013 }); 20014 this.$LG(window).on("mousemove.lg.zoom.global" + this.core.lgId, function (e) { 20015 if (isDragging) { 20016 isMoved = true; 20017 endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 20018 var distance = _this.getZoomSwipeCords(startCoords, endCoords, allowX, allowY, possibleSwipeCords); 20019 _this.setZoomSwipeStyles(_LGel, distance); 20020 } 20021 }); 20022 this.$LG(window).on("mouseup.lg.zoom.global" + this.core.lgId, function (e) { 20023 if (isDragging) { 20024 endTime = new Date(); 20025 isDragging = false; 20026 _this.core.outer.removeClass('lg-zoom-dragging'); 20027 // Fix for chrome mouse move on click 20028 if (isMoved && 20029 (startCoords.x !== endCoords.x || 20030 startCoords.y !== endCoords.y)) { 20031 endCoords = _this.getDragCords(e, Math.abs(_this.rotateValue)); 20032 var touchDuration = endTime.valueOf() - startTime.valueOf(); 20033 _this.touchendZoom(startCoords, endCoords, allowX, allowY, touchDuration, _this.rotateValue); 20034 } 20035 isMoved = false; 20036 } 20037 _this.core.outer.removeClass('lg-grabbing').addClass('lg-grab'); 20038 }); 20039 }; 20040 Zoom.prototype.closeGallery = function () { 20041 this.resetZoom(); 20042 }; 20043 Zoom.prototype.destroy = function () { 20044 // Unbind all events added by lightGallery zoom plugin 20045 this.$LG(window).off(".lg.zoom.global" + this.core.lgId); 20046 this.core.LGel.off('.lg.zoom'); 20047 this.core.LGel.off('.zoom'); 20048 clearTimeout(this.zoomableTimeout); 20049 this.zoomableTimeout = false;
20050 }; 20051 return Zoom; 20052 }()); 20053 20054 return Zoom; 20055 20056}))); 20057//# sourceMappingURL=lg-zoom.umd.js.map 20058 20059/*! 20060 * lightgallery | 2.4.0 | January 29th 2022 20061 * http://www.lightgalleryjs.com/ 20062 * Copyright (c) 2020 Sachin Neravath; 20063 * @license GPLv3 20064 */ 20065 20066(function (global, factory) { 20067 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 20068 typeof define === 'function' && define.amd ? define(factory) : 20069 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgFullscreen = factory()); 20070}(this, (function () { 'use strict'; 20071 20072 /*! ***************************************************************************** 20073 Copyright (c) Microsoft Corporation. 20074 20075 Permission to use, copy, modify, and/or distribute this software for any 20076 purpose with or without fee is hereby granted. 20077 20078 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 20079 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 20080 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 20081 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20082 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20083 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20084 PERFORMANCE OF THIS SOFTWARE. 20085 ***************************************************************************** */ 20086 20087 var __assign = function() { 20088 __assign = Object.assign || function __assign(t) { 20089 for (var s, i = 1, n = arguments.length; i < n; i++) { 20090 s = arguments[i]; 20091 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 20092 } 20093 return t; 20094 }; 20095 return __assign.apply(this, arguments); 20096 }; 20097 20098 var fullscreenSettings = { 20099 fullScreen: true, 20100 fullscreenPluginStrings: { 20101 toggleFullscreen: 'Toggle Fullscreen', 20102 }, 20103 }; 20104 20105 var FullScreen = /** @class */ (function () { 20106 function FullScreen(instance, $LG) { 20107 // get lightGallery core plugin instance 20108 this.core = instance; 20109 this.$LG = $LG; 20110 // extend module default settings with lightGallery core settings 20111 this.settings = __assign(__assign({}, fullscreenSettings), this.core.settings); 20112 return this; 20113 } 20114 FullScreen.prototype.init = function () { 20115 var fullScreen = ''; 20116 if (this.settings.fullScreen) { 20117 // check for fullscreen browser support 20118 if (!document.fullscreenEnabled && 20119 !document.webkitFullscreenEnabled && 20120 !document.mozFullScreenEnabled && 20121 !document.msFullscreenEnabled) { 20122 return; 20123 } 20124 else { 20125 fullScreen = "<button type=\"button\" aria-label=\"" + this.settings.fullscreenPluginStrings['toggleFullscreen'] + "\" class=\"lg-fullscreen lg-icon\"></button>"; 20126 this.core.$toolbar.append(fullScreen); 20127 this.fullScreen(); 20128 } 20129 } 20130 }; 20131 FullScreen.prototype.isFullScreen = function () { 20132 return (document.fullscreenElement || 20133 document.mozFullScreenElement || 20134 document.webkitFullscreenElement || 20135 document.msFullscreenElement); 20136 }; 20137 FullScreen.prototype.requestFullscreen = function () { 20138 var el = document.documentElement; 20139 if (el.requestFullscreen) { 20140 el.requestFullscreen(); 20141 } 20142 else if (el.msRequestFullscreen) { 20143 el.msRequestFullscreen(); 20144 } 20145 else if (el.mozRequestFullScreen) { 20146 el.mozRequestFullScreen(); 20147 } 20148 else if (el.webkitRequestFullscreen) { 20149 el.webkitRequestFullscreen(); 20150 } 20151 }; 20152 FullScreen.prototype.exitFullscreen = function () { 20153 if (document.exitFullscreen) { 20154 document.exitFullscreen(); 20155 } 20156 else if (document.msExitFullscreen) { 20157 document.msExitFullscreen(); 20158 } 20159 else if (document.mozCancelFullScreen) { 20160 document.mozCancelFullScreen(); 20161 } 20162 else if (document.webkitExitFullscreen) { 20163 document.webkitExitFullscreen(); 20164 } 20165 }; 20166 // https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode 20167 FullScreen.prototype.fullScreen = function () { 20168 var _this = this; 20169 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 () { 20170 if (!_this.core.lgOpened) 20171 return; 20172 _this.core.outer.toggleClass('lg-fullscreen-on'); 20173 }); 20174 this.core.outer 20175 .find('.lg-fullscreen') 20176 .first() 20177 .on('click.lg', function () { 20178 if (_this.isFullScreen()) { 20179 _this.exitFullscreen(); 20180 } 20181 else { 20182 _this.requestFullscreen(); 20183 } 20184 }); 20185 }; 20186 FullScreen.prototype.closeGallery = function () { 20187 // exit from fullscreen if activated 20188 if (this.isFullScreen()) { 20189 this.exitFullscreen(); 20190 } 20191 }; 20192 FullScreen.prototype.destroy = function () { 20193 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); 20194 }; 20195 return FullScreen; 20196 }()); 20197 20198 return FullScreen; 20199 20200}))); 20201//# sourceMappingURL=lg-fullscreen.umd.js.map 20202 20203/*! 20204 * lightgallery | 2.4.0 | January 29th 2022 20205 * http://www.lightgalleryjs.com/ 20206 * Copyright (c) 2020 Sachin Neravath; 20207 * @license GPLv3 20208 */ 20209 20210(function (global, factory) { 20211 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 20212 typeof define === 'function' && define.amd ? define(factory) : 20213 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgHash = factory()); 20214}(this, (function () { 'use strict'; 20215 20216 /*! ***************************************************************************** 20217 Copyright (c) Microsoft Corporation. 20218 20219 Permission to use, copy, modify, and/or distribute this software for any 20220 purpose with or without fee is hereby granted. 20221 20222 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 20223 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 20224 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 20225 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20226 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20227 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20228 PERFORMANCE OF THIS SOFTWARE. 20229 ***************************************************************************** */ 20230 20231 var __assign = function() { 20232 __assign = Object.assign || function __assign(t) { 20233 for (var s, i = 1, n = arguments.length; i < n; i++) { 20234 s = arguments[i]; 20235 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 20236 } 20237 return t; 20238 }; 20239 return __assign.apply(this, arguments); 20240 }; 20241 20242 /** 20243 * List of lightGallery events 20244 * All events should be documented here 20245 * Below interfaces are used to build the website documentations 20246 * */ 20247 var lGEvents = { 20248 afterAppendSlide: 'lgAfterAppendSlide', 20249 init: 'lgInit', 20250 hasVideo: 'lgHasVideo', 20251 containerResize: 'lgContainerResize', 20252 updateSlides: 'lgUpdateSlides', 20253 afterAppendSubHtml: 'lgAfterAppendSubHtml', 20254 beforeOpen: 'lgBeforeOpen', 20255 afterOpen: 'lgAfterOpen', 20256 slideItemLoad: 'lgSlideItemLoad', 20257 beforeSlide: 'lgBeforeSlide', 20258 afterSlide: 'lgAfterSlide', 20259 posterClick: 'lgPosterClick', 20260 dragStart: 'lgDragStart', 20261 dragMove: 'lgDragMove', 20262 dragEnd: 'lgDragEnd', 20263 beforeNextSlide: 'lgBeforeNextSlide', 20264 beforePrevSlide: 'lgBeforePrevSlide', 20265 beforeClose: 'lgBeforeClose', 20266 afterClose: 'lgAfterClose', 20267 rotateLeft: 'lgRotateLeft', 20268 rotateRight: 'lgRotateRight', 20269 flipHorizontal: 'lgFlipHorizontal', 20270 flipVertical: 'lgFlipVertical', 20271 autoplay: 'lgAutoplay', 20272 autoplayStart: 'lgAutoplayStart', 20273 autoplayStop: 'lgAutoplayStop', 20274 }; 20275 20276 var hashSettings = { 20277 hash: true, 20278 galleryId: '1', 20279 customSlideName: false, 20280 }; 20281 20282 var Hash = /** @class */ (function () { 20283 function Hash(instance, $LG) { 20284 // get lightGallery core plugin instance 20285 this.core = instance;
20286 this.$LG = $LG; 20287 // extend module default settings with lightGallery core settings 20288 this.settings = __assign(__assign({}, hashSettings), this.core.settings); 20289 return this; 20290 } 20291 Hash.prototype.init = function () { 20292 var _this = this; 20293 if (!this.settings.hash) { 20294 return; 20295 } 20296 this.oldHash = window.location.hash; 20297 setTimeout(function () { 20298 _this.buildFromHash(); 20299 }, 100); 20300 // Change hash value on after each slide transition 20301 this.core.LGel.on(lGEvents.afterSlide + ".hash", this.onAfterSlide.bind(this)); 20302 this.core.LGel.on(lGEvents.afterClose + ".hash", this.onCloseAfter.bind(this)); 20303 // Listen hash change and change the slide according to slide value 20304 this.$LG(window).on("hashchange.lg.hash.global" + this.core.lgId, this.onHashchange.bind(this)); 20305 }; 20306 Hash.prototype.onAfterSlide = function (event) { 20307 var slideName = this.core.galleryItems[event.detail.index].slideName; 20308 slideName = this.settings.customSlideName 20309 ? slideName || event.detail.index 20310 : event.detail.index; 20311 if (history.replaceState) { 20312 history.replaceState(null, '', window.location.pathname + 20313 window.location.search + 20314 '#lg=' + 20315 this.settings.galleryId + 20316 '&slide=' + 20317 slideName); 20318 } 20319 else { 20320 window.location.hash = 20321 'lg=' + this.settings.galleryId + '&slide=' + slideName; 20322 } 20323 }; 20324 /** 20325 * Get index of the slide from custom slideName. Has to be a public method. Used in hash plugin 20326 * @param {String} hash 20327 * @returns {Number} Index of the slide. 20328 */ 20329 Hash.prototype.getIndexFromUrl = function (hash) { 20330 if (hash === void 0) { hash = window.location.hash; } 20331 var slideName = hash.split('&slide=')[1]; 20332 var _idx = 0; 20333 if (this.settings.customSlideName) { 20334 for (var index = 0; index < this.core.galleryItems.length; index++) { 20335 var dynamicEl = this.core.galleryItems[index]; 20336 if (dynamicEl.slideName === slideName) { 20337 _idx = index; 20338 break; 20339 } 20340 } 20341 } 20342 else { 20343 _idx = parseInt(slideName, 10); 20344 } 20345 return isNaN(_idx) ? 0 : _idx; 20346 }; 20347 // Build Gallery if gallery id exist in the URL 20348 Hash.prototype.buildFromHash = function () { 20349 // if dynamic option is enabled execute immediately 20350 var _hash = window.location.hash; 20351 //Uncode edit ##START## 20352 // if (_hash.indexOf('lg=' + this.settings.galleryId) > 0) { 20353 if (_hash.indexOf('lg=' + this.settings.galleryId + '&') > 0) { 20354 //Uncode edit ##END## 20355 // This class is used to remove the initial animation if galleryId present in the URL 20356 this.$LG(document.body).addClass('lg-from-hash'); 20357 var index = this.getIndexFromUrl(_hash); 20358 this.core.openGallery(index); 20359 return true; 20360 } 20361 }; 20362 Hash.prototype.onCloseAfter = function () { 20363 // Reset to old hash value 20364 if (this.oldHash && 20365 this.oldHash.indexOf('lg=' + this.settings.galleryId) < 0) { 20366 if (history.replaceState) { 20367 history.replaceState(null, '', this.oldHash); 20368 } 20369 else { 20370 window.location.hash = this.oldHash; 20371 } 20372 } 20373 else { 20374 if (history.replaceState) { 20375 history.replaceState(null, document.title, window.location.pathname + window.location.search); 20376 } 20377 else { 20378 window.location.hash = ''; 20379 } 20380 } 20381 }; 20382 Hash.prototype.onHashchange = function () { 20383 if (!this.core.lgOpened) 20384 return; 20385 var _hash = window.location.hash; 20386 var index = this.getIndexFromUrl(_hash); 20387 // it galleryId doesn't exist in the url close the gallery 20388 if (_hash.indexOf('lg=' + this.settings.galleryId) > -1) { 20389 this.core.slide(index, false, false); 20390 } 20391 else if (this.core.lGalleryOn) { 20392 this.core.closeGallery(); 20393 } 20394 }; 20395 Hash.prototype.closeGallery = function () { 20396 if (this.settings.hash) { 20397 this.$LG(document.body).removeClass('lg-from-hash'); 20398 } 20399 }; 20400 Hash.prototype.destroy = function () { 20401 this.core.LGel.off('.lg.hash'); 20402 this.core.LGel.off('.hash'); 20403 this.$LG(window).off("hashchange.lg.hash.global" + this.core.lgId); 20404 }; 20405 return Hash; 20406 }()); 20407 20408 return Hash; 20409 20410}))); 20411//# sourceMappingURL=lg-hash.umd.js.map 20412 20413/*! 20414 * lightgallery | 2.4.0 | January 29th 2022 20415 * http://www.lightgalleryjs.com/ 20416 * Copyright (c) 2020 Sachin Neravath; 20417 * @license GPLv3 20418 */ 20419 20420(function (global, factory) { 20421 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 20422 typeof define === 'function' && define.amd ? define(factory) : 20423 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgShare = factory()); 20424}(this, (function () { 'use strict'; 20425 20426 /*! ***************************************************************************** 20427 Copyright (c) Microsoft Corporation. 20428 20429 Permission to use, copy, modify, and/or distribute this software for any 20430 purpose with or without fee is hereby granted. 20431 20432 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 20433 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 20434 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 20435 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20436 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20437 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20438 PERFORMANCE OF THIS SOFTWARE. 20439 ***************************************************************************** */ 20440 20441 var __assign = function() { 20442 __assign = Object.assign || function __assign(t) { 20443 for (var s, i = 1, n = arguments.length; i < n; i++) { 20444 s = arguments[i]; 20445 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 20446 } 20447 return t; 20448 }; 20449 return __assign.apply(this, arguments); 20450 }; 20451 20452 function __spreadArrays() { 20453 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; 20454 for (var r = Array(s), k = 0, i = 0; i < il; i++) 20455 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) 20456 r[k] = a[j]; 20457 return r; 20458 } 20459 20460 var shareSettings = { 20461 share: true, 20462 facebook: true, 20463 facebookDropdownText: 'Facebook', 20464 twitter: true, 20465 twitterDropdownText: 'Twitter', 20466 pinterest: true, 20467 pinterestDropdownText: 'Pinterest', 20468 additionalShareOptions: [], 20469 sharePluginStrings: { share: 'Share' }, 20470 }; 20471 20472 function getFacebookShareLink(galleryItem) { 20473 var facebookBaseUrl = '//www.facebook.com/sharer/sharer.php?u='; 20474 return (facebookBaseUrl + 20475 encodeURIComponent(galleryItem.facebookShareUrl || window.location.href)); 20476 } 20477 20478 function getTwitterShareLink(galleryItem) { 20479 var twitterBaseUrl = '//twitter.com/intent/tweet?text='; 20480 var url = encodeURIComponent(galleryItem.twitterShareUrl || window.location.href); 20481 var text = galleryItem.tweetText;
20482 return twitterBaseUrl + text + '&url=' + url; 20483 } 20484 20485 function getPinterestShareLink(galleryItem) { 20486 var pinterestBaseUrl = 'http://www.pinterest.com/pin/create/button/?url='; 20487 var description = galleryItem.pinterestText; 20488 var media = encodeURIComponent(galleryItem.src); 20489 var url = encodeURIComponent(galleryItem.pinterestShareUrl || window.location.href); 20490 return (pinterestBaseUrl + 20491 url + 20492 '&media=' + 20493 media + 20494 '&description=' + 20495 description); 20496 } 20497 20498 /** 20499 * List of lightGallery events 20500 * All events should be documented here 20501 * Below interfaces are used to build the website documentations 20502 * */ 20503 var lGEvents = { 20504 afterAppendSlide: 'lgAfterAppendSlide', 20505 init: 'lgInit', 20506 hasVideo: 'lgHasVideo', 20507 containerResize: 'lgContainerResize', 20508 updateSlides: 'lgUpdateSlides', 20509 afterAppendSubHtml: 'lgAfterAppendSubHtml', 20510 beforeOpen: 'lgBeforeOpen', 20511 afterOpen: 'lgAfterOpen', 20512 slideItemLoad: 'lgSlideItemLoad', 20513 beforeSlide: 'lgBeforeSlide', 20514 afterSlide: 'lgAfterSlide', 20515 posterClick: 'lgPosterClick', 20516 dragStart: 'lgDragStart', 20517 dragMove: 'lgDragMove', 20518 dragEnd: 'lgDragEnd', 20519 beforeNextSlide: 'lgBeforeNextSlide', 20520 beforePrevSlide: 'lgBeforePrevSlide', 20521 beforeClose: 'lgBeforeClose', 20522 afterClose: 'lgAfterClose', 20523 rotateLeft: 'lgRotateLeft', 20524 rotateRight: 'lgRotateRight', 20525 flipHorizontal: 'lgFlipHorizontal', 20526 flipVertical: 'lgFlipVertical', 20527 autoplay: 'lgAutoplay', 20528 autoplayStart: 'lgAutoplayStart', 20529 autoplayStop: 'lgAutoplayStop', 20530 }; 20531 20532 var Share = /** @class */ (function () { 20533 function Share(instance) { 20534 this.shareOptions = []; 20535 // get lightGallery core plugin instance 20536 this.core = instance; 20537 // extend module default settings with lightGallery core settings 20538 this.settings = __assign(__assign({}, shareSettings), this.core.settings); 20539 return this; 20540 } 20541 Share.prototype.init = function () { 20542 if (!this.settings.share) { 20543 return; 20544 } 20545 this.shareOptions = __spreadArrays(this.getDefaultShareOptions(), this.settings.additionalShareOptions); 20546 this.setLgShareMarkup(); 20547 this.core.outer 20548 .find('.lg-share .lg-dropdown') 20549 .append(this.getShareListHtml()); 20550 this.core.LGel.on(lGEvents.afterSlide + ".share", this.onAfterSlide.bind(this)); 20551 }; 20552 Share.prototype.getShareListHtml = function () { 20553 var shareHtml = ''; 20554 this.shareOptions.forEach(function (shareOption) { 20555 shareHtml += shareOption.dropdownHTML; 20556 }); 20557 return shareHtml; 20558 }; 20559 Share.prototype.setLgShareMarkup = function () { 20560 var _this = this; 20561 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>"); 20562 this.core.outer.append('<div class="lg-dropdown-overlay"></div>'); 20563 var $shareButton = this.core.outer.find('.lg-share'); 20564 $shareButton.first().on('click.lg', function () { 20565 _this.core.outer.toggleClass('lg-dropdown-active'); 20566 if (_this.core.outer.hasClass('lg-dropdown-active')) { 20567 _this.core.outer.attr('aria-expanded', true); 20568 } 20569 else { 20570 _this.core.outer.attr('aria-expanded', false); 20571 } 20572 }); 20573 this.core.outer 20574 .find('.lg-dropdown-overlay') 20575 .first() 20576 .on('click.lg', function () { 20577 _this.core.outer.removeClass('lg-dropdown-active'); 20578 _this.core.outer.attr('aria-expanded', false); 20579 }); 20580 }; 20581 Share.prototype.onAfterSlide = function (event) { 20582 var _this = this; 20583 var index = event.detail.index; 20584 var currentItem = this.core.galleryItems[index]; 20585 setTimeout(function () { 20586 _this.shareOptions.forEach(function (shareOption) { 20587 var selector = shareOption.selector; 20588 _this.core.outer 20589 .find(selector) 20590 .attr('href', shareOption.generateLink(currentItem)); 20591 }); 20592 }, 100); 20593 }; 20594 Share.prototype.getShareListItemHTML = function (type, text) { 20595 return "<li><a class=\"lg-share-" + type + "\" rel=\"noopener\" target=\"_blank\"><span class=\"lg-icon\"></span><span class=\"lg-dropdown-text\">
20595" + text + "</span></a></li>"; 20596 }; 20597 Share.prototype.getDefaultShareOptions = function () { 20598 return __spreadArrays((this.settings.facebook 20599 ? [ 20600 { 20601 type: 'facebook', 20602 generateLink: getFacebookShareLink, 20603 dropdownHTML: this.getShareListItemHTML('facebook', this.settings.facebookDropdownText), 20604 selector: '.lg-share-facebook', 20605 }, 20606 ] 20607 : []), (this.settings.twitter 20608 ? [ 20609 { 20610 type: 'twitter', 20611 generateLink: getTwitterShareLink, 20612 dropdownHTML: this.getShareListItemHTML('twitter', this.settings.twitterDropdownText), 20613 selector: '.lg-share-twitter', 20614 }, 20615 ] 20616 : []), (this.settings.pinterest 20617 ? [ 20618 { 20619 type: 'pinterest', 20620 generateLink: getPinterestShareLink, 20621 dropdownHTML: this.getShareListItemHTML('pinterest', this.settings.pinterestDropdownText), 20622 selector: '.lg-share-pinterest', 20623 }, 20624 ] 20625 : [])); 20626 }; 20627 Share.prototype.destroy = function () { 20628 this.core.outer.find('.lg-dropdown-overlay').remove(); 20629 this.core.outer.find('.lg-share').remove(); 20630 this.core.LGel.off('.lg.share'); 20631 this.core.LGel.off('.share'); 20632 }; 20633 return Share; 20634 }()); 20635 20636 return Share; 20637 20638}))); 20639//# sourceMappingURL=lg-share.umd.js.map 20640 20641/*! 20642 * lightgallery | 2.4.0 | January 29th 2022 20643 * http://www.lightgalleryjs.com/ 20644 * Copyright (c) 2020 Sachin Neravath; 20645 * @license GPLv3 20646 */ 20647 20648(function (global, factory) { 20649 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 20650 typeof define === 'function' && define.amd ? define(factory) : 20651 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgThumbnail = factory()); 20652}(this, (function () { 'use strict'; 20653 20654 /*! ***************************************************************************** 20655 Copyright (c) Microsoft Corporation. 20656 20657 Permission to use, copy, modify, and/or distribute this software for any 20658 purpose with or without fee is hereby granted. 20659 20660 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 20661 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 20662 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 20663 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 20664 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 20665 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20666 PERFORMANCE OF THIS SOFTWARE. 20667 ***************************************************************************** */ 20668 20669 var __assign = function() { 20670 __assign = Object.assign || function __assign(t) { 20671 for (var s, i = 1, n = arguments.length; i < n; i++) { 20672 s = arguments[i]; 20673 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 20674 } 20675 return t; 20676 }; 20677 return __assign.apply(this, arguments); 20678 }; 20679 20680 var thumbnailsSettings = { 20681 thumbnail: true, 20682 animateThumb: true, 20683 currentPagerPosition: 'middle', 20684 alignThumbnails: 'middle', 20685 thumbWidth: 100, 20686 thumbHeight: '80px', 20687 thumbMargin: 5, 20688 appendThumbnailsTo: '.lg-components', 20689 toggleThumb: false, 20690 enableThumbDrag: true, 20691 enableThumbSwipe: true, 20692 thumbnailSwipeThreshold: 10, 20693 loadYouTubeThumbnail: true, 20694 youTubeThumbSize: 1, 20695 thumbnailPluginStrings: { 20696 toggleThumbnails: 'Toggle thumbnails', 20697 }, 20698 }; 20699 20700 /** 20701 * List of lightGallery events 20702 * All events should be documented here 20703 * Below interfaces are used to build the website documentations 20704 * */ 20705 var lGEvents = { 20706 afterAppendSlide: 'lgAfterAppendSlide', 20707 init: 'lgInit', 20708 hasVideo: 'lgHasVideo', 20709 containerResize: 'lgContainerResize', 20710 updateSlides: 'lgUpdateSlides', 20711 afterAppendSubHtml: 'lgAfterAppendSubHtml', 20712 beforeOpen: 'lgBeforeOpen', 20713 afterOpen: 'lgAfterOpen', 20714 slideItemLoad: 'lgSlideItemLoad', 20715 beforeSlide: 'lgBeforeSlide', 20716 afterSlide: 'lgAfterSlide', 20717 posterClick: 'lgPosterClick', 20718 dragStart: 'lgDragStart', 20719 dragMove: 'lgDragMove', 20720 dragEnd: 'lgDragEnd', 20721 beforeNextSlide: 'lgBeforeNextSlide', 20722 beforePrevSlide: 'lgBeforePrevSlide', 20723 beforeClose: 'lgBeforeClose', 20724 afterClose: 'lgAfterClose', 20725 rotateLeft: 'lgRotateLeft', 20726 rotateRight: 'lgRotateRight', 20727 flipHorizontal: 'lgFlipHorizontal', 20728 flipVertical: 'lgFlipVertical', 20729 autoplay: 'lgAutoplay', 20730 autoplayStart: 'lgAutoplayStart', 20731 autoplayStop: 'lgAutoplayStop', 20732 }; 20733 20734 var Thumbnail = /** @class */ (function () { 20735 function Thumbnail(instance, $LG) { 20736 this.thumbOuterWidth = 0; 20737 this.thumbTotalWidth = 0; 20738 this.translateX = 0; 20739 this.thumbClickable = false;
20740 // get lightGallery core plugin instance 20741 this.core = instance; 20742 this.$LG = $LG; 20743 return this; 20744 } 20745 Thumbnail.prototype.init = function () { 20746 // extend module default settings with lightGallery core settings 20747 this.settings = __assign(__assign({}, thumbnailsSettings), this.core.settings); 20748 this.thumbOuterWidth = 0; 20749 this.thumbTotalWidth = 20750 this.core.galleryItems.length * 20751 (this.settings.thumbWidth + this.settings.thumbMargin); 20752 // Thumbnail animation value 20753 this.translateX = 0; 20754 this.setAnimateThumbStyles(); 20755 if (!this.core.settings.allowMediaOverlap) { 20756 this.settings.toggleThumb = false; 20757 } 20758 if (this.settings.thumbnail) { 20759 this.build(); 20760 if (this.settings.animateThumb) { 20761 if (this.settings.enableThumbDrag) { 20762 this.enableThumbDrag(); 20763 } 20764 if (this.settings.enableThumbSwipe) { 20765 this.enableThumbSwipe(); 20766 } 20767 this.thumbClickable = false; 20768 } 20769 else { 20770 this.thumbClickable = true; 20771 } 20772 this.toggleThumbBar(); 20773 this.thumbKeyPress(); 20774 } 20775 }; 20776 Thumbnail.prototype.build = function () { 20777 var _this = this; 20778 this.setThumbMarkup(); 20779 this.manageActiveClassOnSlideChange(); 20780 this.$lgThumb.first().on('click.lg touchend.lg', function (e) { 20781 var $target = _this.$LG(e.target); 20782 if (!$target.hasAttribute('data-lg-item-id')) { 20783 return; 20784 } 20785 setTimeout(function () { 20786 // In IE9 and bellow touch does not support 20787 // Go to slide if browser does not support css transitions 20788 if (_this.thumbClickable && !_this.core.lgBusy) { 20789 var index = parseInt($target.attr('data-lg-item-id')); 20790 _this.core.slide(index, false, true, false); 20791 } 20792 }, 50); 20793 }); 20794 //Uncode edit ##START## 20795 // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) { 20796 this.core.LGel.on(lGEvents.beforeSlide, function (event) { 20797 //Uncode edit ##END## 20798 var index = event.detail.index; 20799 _this.animateThumb(index); 20800 }); 20801 //Uncode edit ##START## 20802 // this.core.LGel.on(lGEvents.beforeOpen + ".thumb", function () { 20803 this.core.LGel.on(lGEvents.beforeOpen, function () { 20804 //Uncode edit ##END## 20805 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 20806 }); 20807 //Uncode edit ##START## 20808 // this.core.LGel.on(lGEvents.updateSlides + ".thumb", function () { 20809 this.core.LGel.on(lGEvents.updateSlides, function () { 20810 //Uncode edit ##END## 20811 _this.rebuildThumbnails(); 20812 }); 20813 //Uncode edit ##START## 20814 // this.core.LGel.on(lGEvents.containerResize + ".thumb", function () { 20815 this.core.LGel.on(lGEvents.containerResize, function () { 20816 //Uncode edit ##END## 20817 if (!_this.core.lgOpened) 20818 return; 20819 setTimeout(function () { 20820 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 20821 _this.animateThumb(_this.core.index); 20822 _this.thumbOuterWidth = _this.core.outer.get().offsetWidth; 20823 }, 50); 20824 }); 20825 }; 20826 Thumbnail.prototype.setThumbMarkup = function () { 20827 var thumbOuterClassNames = 'lg-thumb-outer '; 20828 if (this.settings.alignThumbnails) { 20829 thumbOuterClassNames += "lg-thumb-align-" + this.settings.alignThumbnails; 20830 } 20831 var html = "<div class=\"" + thumbOuterClassNames + "\">\n <div class=\"lg-thumb lg-group\">\n </div>\n </div>"; 20832 this.core.outer.addClass('lg-has-thumb'); 20833 if (this.settings.appendThumbnailsTo === '.lg-components') { 20834 this.core.$lgComponents.append(html); 20835 } 20836 else { 20837 this.core.outer.append(html); 20838 } 20839 this.$thumbOuter = this.core.outer.find('.lg-thumb-outer').first(); 20840 this.$lgThumb = this.core.outer.find('.lg-thumb').first(); 20841 if (this.settings.animateThumb) { 20842 this.core.outer 20843 .find('.lg-thumb') 20844 .css('transition-duration', this.core.settings.speed + 'ms') 20845 .css('width', this.thumbTotalWidth + 'px') 20846 .css('position', 'relative'); 20847 } 20848 this.setThumbItemHtml(this.core.galleryItems); 20849 }; 20850 Thumbnail.prototype.enableThumbDrag = function () { 20851 var _this = this; 20852 var thumbDragUtils = { 20853 cords: { 20854 startX: 0, 20855 endX: 0, 20856 }, 20857 isMoved: false, 20858 newTranslateX: 0, 20859 startTime: new Date(), 20860 endTime: new Date(), 20861 touchMoveTime: 0, 20862 }; 20863 var isDragging = false;
20864 this.$thumbOuter.addClass('lg-grab'); 20865 this.core.outer 20866 .find('.lg-thumb') 20867 .first() 20868 .on('mousedown.lg.thumb', function (e) { 20869 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 20870 // execute only on .lg-object 20871 e.preventDefault(); 20872 thumbDragUtils.cords.startX = e.pageX; 20873 thumbDragUtils.startTime = new Date(); 20874 _this.thumbClickable = false; 20875 isDragging = true; 20876 // ** Fix for webkit cursor issue https://code.google.com/p/chromium/issues/detail?id=26723 20877 _this.core.outer.get().scrollLeft += 1; 20878 _this.core.outer.get().scrollLeft -= 1; 20879 // * 20880 _this.$thumbOuter 20881 .removeClass('lg-grab') 20882 .addClass('lg-grabbing'); 20883 } 20884 }); 20885 this.$LG(window).on("mousemove.lg.thumb.global" + this.core.lgId, function (e) { 20886 if (!_this.core.lgOpened) 20887 return; 20888 if (isDragging) { 20889 thumbDragUtils.cords.endX = e.pageX; 20890 thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils); 20891 } 20892 }); 20893 this.$LG(window).on("mouseup.lg.thumb.global" + this.core.lgId, function () { 20894 if (!_this.core.lgOpened) 20895 return; 20896 if (thumbDragUtils.isMoved) { 20897 thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils); 20898 } 20899 else { 20900 _this.thumbClickable = true; 20901 } 20902 if (isDragging) { 20903 isDragging = false; 20904 _this.$thumbOuter.removeClass('lg-grabbing').addClass('lg-grab'); 20905 } 20906 }); 20907 }; 20908 Thumbnail.prototype.enableThumbSwipe = function () { 20909 var _this = this; 20910 var thumbDragUtils = { 20911 cords: { 20912 startX: 0, 20913 endX: 0, 20914 }, 20915 isMoved: false, 20916 newTranslateX: 0, 20917 startTime: new Date(), 20918 endTime: new Date(), 20919 touchMoveTime: 0, 20920 }; 20921 this.$lgThumb.on('touchstart.lg', function (e) { 20922 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 20923 e.preventDefault(); 20924 thumbDragUtils.cords.startX = e.targetTouches[0].pageX; 20925 _this.thumbClickable = false; 20926 thumbDragUtils.startTime = new Date(); 20927 } 20928 }); 20929 this.$lgThumb.on('touchmove.lg', function (e) { 20930 if (_this.thumbTotalWidth > _this.thumbOuterWidth) { 20931 e.preventDefault(); 20932 thumbDragUtils.cords.endX = e.targetTouches[0].pageX; 20933 thumbDragUtils = _this.onThumbTouchMove(thumbDragUtils); 20934 } 20935 }); 20936 this.$lgThumb.on('touchend.lg', function () { 20937 if (thumbDragUtils.isMoved) { 20938 thumbDragUtils = _this.onThumbTouchEnd(thumbDragUtils); 20939 } 20940 else { 20941 _this.thumbClickable = true; 20942 } 20943 }); 20944 }; 20945 // Rebuild thumbnails 20946 Thumbnail.prototype.rebuildThumbnails = function () { 20947 var _this = this; 20948 // Remove transitions 20949 this.$thumbOuter.addClass('lg-rebuilding-thumbnails'); 20950 setTimeout(function () { 20951 _this.thumbTotalWidth = 20952 _this.core.galleryItems.length * 20953 (_this.settings.thumbWidth + _this.settings.thumbMargin); 20954 _this.$lgThumb.css('width', _this.thumbTotalWidth + 'px'); 20955 _this.$lgThumb.empty(); 20956 _this.setThumbItemHtml(_this.core.galleryItems); 20957 _this.animateThumb(_this.core.index); 20958 }, 50); 20959 setTimeout(function () { 20960 _this.$thumbOuter.removeClass('lg-rebuilding-thumbnails'); 20961 }, 200); 20962 }; 20963 // @ts-check 20964 Thumbnail.prototype.setTranslate = function (value) { 20965 this.$lgThumb.css('transform', 'translate3d(-' + value + 'px, 0px, 0px)'); 20966 }; 20967 Thumbnail.prototype.getPossibleTransformX = function (left) { 20968 if (left > this.thumbTotalWidth - this.thumbOuterWidth) { 20969 left = this.thumbTotalWidth - this.thumbOuterWidth; 20970 } 20971 if (left < 0) { 20972 left = 0; 20973 } 20974 return left; 20975 }; 20976 Thumbnail.prototype.animateThumb = function (index) { 20977 this.$lgThumb.css('transition-duration', this.core.settings.speed + 'ms'); 20978 if (this.settings.animateThumb) { 20979 var position = 0; 20980 switch (this.settings.currentPagerPosition) { 20981 case 'left': 20982 position = 0; 20983 break; 20984 case 'middle': 20985 position = 20986 this.thumbOuterWidth / 2 - this.settings.thumbWidth / 2; 20987 break; 20988 case 'right': 20989 position = this.thumbOuterWidth - this.settings.thumbWidth; 20990 } 20991 this.translateX = 20992 (this.settings.thumbWidth + this.settings.thumbMargin) * index - 20993 1 - 20994 position; 20995 if (this.translateX > this.thumbTotalWidth - this.thumbOuterWidth) { 20996 this.translateX = this.thumbTotalWidth - this.thumbOuterWidth; 20997 } 20998 if (this.translateX < 0) { 20999 this.translateX = 0; 21000 } 21001 this.setTranslate(this.translateX); 21002 } 21003 }; 21004 Thumbnail.prototype.onThumbTouchMove = function (thumbDragUtils) { 21005 thumbDragUtils.newTranslateX = this.translateX; 21006 thumbDragUtils.isMoved = true; 21007 thumbDragUtils.touchMoveTime = new Date().valueOf(); 21008 thumbDragUtils.newTranslateX -= 21009 thumbDragUtils.cords.endX - thumbDragUtils.cords.startX; 21010 thumbDragUtils.newTranslateX = this.getPossibleTransformX(thumbDragUtils.newTranslateX); 21011 // move current slide 21012 this.setTranslate(thumbDragUtils.newTranslateX); 21013 this.$thumbOuter.addClass('lg-dragging'); 21014 return thumbDragUtils; 21015 }; 21016 Thumbnail.prototype.onThumbTouchEnd = function (thumbDragUtils) { 21017 thumbDragUtils.isMoved = false;
21018 thumbDragUtils.endTime = new Date(); 21019 this.$thumbOuter.removeClass('lg-dragging'); 21020 var touchDuration = thumbDragUtils.endTime.valueOf() - 21021 thumbDragUtils.startTime.valueOf(); 21022 var distanceXnew = thumbDragUtils.cords.endX - thumbDragUtils.cords.startX; 21023 var speedX = Math.abs(distanceXnew) / touchDuration; 21024 // Some magical numbers 21025 // Can be improved 21026 if (speedX > 0.15 && 21027 thumbDragUtils.endTime.valueOf() - thumbDragUtils.touchMoveTime < 30) { 21028 speedX += 1; 21029 if (speedX > 2) { 21030 speedX += 1; 21031 } 21032 speedX = 21033 speedX + 21034 speedX * (Math.abs(distanceXnew) / this.thumbOuterWidth); 21035 this.$lgThumb.css('transition-duration', Math.min(speedX - 1, 2) + 'settings'); 21036 distanceXnew = distanceXnew * speedX; 21037 this.translateX = this.getPossibleTransformX(this.translateX - distanceXnew); 21038 this.setTranslate(this.translateX); 21039 } 21040 else { 21041 this.translateX = thumbDragUtils.newTranslateX; 21042 } 21043 if (Math.abs(thumbDragUtils.cords.endX - thumbDragUtils.cords.startX) < 21044 this.settings.thumbnailSwipeThreshold) { 21045 this.thumbClickable = true; 21046 } 21047 return thumbDragUtils; 21048 }; 21049 Thumbnail.prototype.getThumbHtml = function (thumb, index) { 21050 var slideVideoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 21051 var thumbImg; 21052 if (slideVideoInfo.youtube) { 21053 if (this.settings.loadYouTubeThumbnail) { 21054 thumbImg = 21055 '//img.youtube.com/vi/' + 21056 slideVideoInfo.youtube[1] + 21057 '/' + 21058 this.settings.youTubeThumbSize + 21059 '.jpg'; 21060 } 21061 else { 21062 thumbImg = thumb; 21063 } 21064 } 21065 else { 21066 thumbImg = thumb; 21067 } 21068 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>"; 21069 }; 21070 Thumbnail.prototype.getThumbItemHtml = function (items) { 21071 var thumbList = ''; 21072 for (var i = 0; i < items.length; i++) { 21073 thumbList += this.getThumbHtml(items[i].thumb, i); 21074 } 21075 return thumbList; 21076 }; 21077 Thumbnail.prototype.setThumbItemHtml = function (items) { 21078 var thumbList = this.getThumbItemHtml(items); 21079 this.$lgThumb.html(thumbList); 21080 }; 21081 Thumbnail.prototype.setAnimateThumbStyles = function () { 21082 if (this.settings.animateThumb) { 21083 this.core.outer.addClass('lg-animate-thumb'); 21084 } 21085 }; 21086 // Manage thumbnail active calss 21087 Thumbnail.prototype.manageActiveClassOnSlideChange = function () { 21088 var _this = this; 21089 // manage active class for thumbnail 21090 //Uncode edit ##START## 21091 // this.core.LGel.on(lGEvents.beforeSlide + ".thumb", function (event) { 21092 this.core.LGel.on(lGEvents.beforeSlide, function (event) { 21093 //Uncode edit ##END## 21094 var $thumb = _this.core.outer.find('.lg-thumb-item'); 21095 var index = event.detail.index; 21096 $thumb.removeClass('active'); 21097 $thumb.eq(index).addClass('active'); 21098 }); 21099 }; 21100 // Toggle thumbnail bar 21101 Thumbnail.prototype.toggleThumbBar = function () { 21102 var _this = this; 21103 if (this.settings.toggleThumb) { 21104 this.core.outer.addClass('lg-can-toggle'); 21105 this.core.$toolbar.append('<button type="button" aria-label="' + 21106 this.settings.thumbnailPluginStrings['toggleThumbnails'] + 21107 '" class="lg-toggle-thumb lg-icon"></button>'); 21108 this.core.outer 21109 .find('.lg-toggle-thumb') 21110 .first() 21111 .on('click.lg', function () { 21112 _this.core.outer.toggleClass('lg-components-open'); 21113 }); 21114 } 21115 }; 21116 Thumbnail.prototype.thumbKeyPress = function () { 21117 var _this = this; 21118 this.$LG(window).on("keydown.lg.thumb.global" + this.core.lgId, function (e) { 21119 if (!_this.core.lgOpened || !_this.settings.toggleThumb) 21120 return; 21121 if (e.keyCode === 38) { 21122 e.preventDefault(); 21123 _this.core.outer.addClass('lg-components-open'); 21124 } 21125 else if (e.keyCode === 40) { 21126 e.preventDefault(); 21127 _this.core.outer.removeClass('lg-components-open'); 21128 } 21129 }); 21130 }; 21131 Thumbnail.prototype.destroy = function () { 21132 if (this.settings.thumbnail) { 21133 this.$LG(window).off(".lg.thumb.global" + this.core.lgId); 21134 this.core.LGel.off('.lg.thumb'); 21135 this.core.LGel.off('.thumb'); 21136 this.$thumbOuter.remove(); 21137 this.core.outer.removeClass('lg-has-thumb'); 21138 } 21139 }; 21140 return Thumbnail; 21141 }()); 21142 21143 return Thumbnail; 21144 21145}))); 21146//# sourceMappingURL=lg-thumbnail.umd.js.map 21147 21148/*! 21149 * lightgallery | 2.4.0 | January 29th 2022 21150 * http://www.lightgalleryjs.com/ 21151 * Copyright (c) 2020 Sachin Neravath; 21152 * @license GPLv3 21153 */ 21154 21155(function (global, factory) { 21156 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 21157 typeof define === 'function' && define.amd ? define(factory) : 21158 (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.lgVideo = factory()); 21159}(this, (function () { 'use strict'; 21160 21161 /*! ***************************************************************************** 21162 Copyright (c) Microsoft Corporation. 21163 21164 Permission to use, copy, modify, and/or distribute this software for any 21165 purpose with or without fee is hereby granted. 21166 21167 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 21168 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 21169 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 21170 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 21171 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21172 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21173 PERFORMANCE OF THIS SOFTWARE. 21174 ***************************************************************************** */ 21175 21176 var __assign = function() { 21177 __assign = Object.assign || function __assign(t) { 21178 for (var s, i = 1, n = arguments.length; i < n; i++) { 21179 s = arguments[i]; 21180 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; 21181 } 21182 return t; 21183 }; 21184 return __assign.apply(this, arguments); 21185 }; 21186 21187 var videoSettings = { 21188 autoplayFirstVideo: true, 21189 youTubePlayerParams: false, 21190 vimeoPlayerParams: false, 21191 wistiaPlayerParams: false, 21192 gotoNextSlideOnVideoEnd: true, 21193 autoplayVideoOnSlide: false,
21194 videojs: false, 21195 videojsOptions: {}, 21196 }; 21197 21198 /** 21199 * List of lightGallery events 21200 * All events should be documented here 21201 * Below interfaces are used to build the website documentations 21202 * */ 21203 var lGEvents = { 21204 afterAppendSlide: 'lgAfterAppendSlide', 21205 init: 'lgInit', 21206 hasVideo: 'lgHasVideo', 21207 containerResize: 'lgContainerResize', 21208 updateSlides: 'lgUpdateSlides', 21209 afterAppendSubHtml: 'lgAfterAppendSubHtml', 21210 beforeOpen: 'lgBeforeOpen', 21211 afterOpen: 'lgAfterOpen', 21212 slideItemLoad: 'lgSlideItemLoad', 21213 beforeSlide: 'lgBeforeSlide', 21214 afterSlide: 'lgAfterSlide', 21215 posterClick: 'lgPosterClick', 21216 dragStart: 'lgDragStart', 21217 dragMove: 'lgDragMove', 21218 dragEnd: 'lgDragEnd', 21219 beforeNextSlide: 'lgBeforeNextSlide', 21220 beforePrevSlide: 'lgBeforePrevSlide', 21221 beforeClose: 'lgBeforeClose', 21222 afterClose: 'lgAfterClose', 21223 rotateLeft: 'lgRotateLeft', 21224 rotateRight: 'lgRotateRight', 21225 flipHorizontal: 'lgFlipHorizontal', 21226 flipVertical: 'lgFlipVertical', 21227 autoplay: 'lgAutoplay', 21228 autoplayStart: 'lgAutoplayStart', 21229 autoplayStop: 'lgAutoplayStop', 21230 }; 21231 21232 var param = function (obj) { 21233 return Object.keys(obj) 21234 .map(function (k) { 21235 return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); 21236 }) 21237 .join('&'); 21238 }; 21239 var getVimeoURLParams = function (defaultParams, videoInfo) { 21240 if (!videoInfo || !videoInfo.vimeo) 21241 return ''; 21242 var urlParams = videoInfo.vimeo[2] || ''; 21243 urlParams = 21244 urlParams[0] == '?' ? '&' + urlParams.slice(1) : urlParams || ''; 21245 var defaultPlayerParams = defaultParams 21246 ? '&' + param(defaultParams) 21247 : ''; 21248 // For vimeo last parms gets priority if duplicates found 21249 var vimeoPlayerParams = "?autoplay=0&muted=1" + defaultPlayerParams + urlParams; 21250 return vimeoPlayerParams; 21251 }; 21252 21253 /** 21254 * Video module for lightGallery 21255 * Supports HTML5, YouTube, Vimeo, wistia videos 21256 * 21257 * 21258 * @ref Wistia 21259 * https://wistia.com/support/integrations/wordpress(How to get url) 21260 * https://wistia.com/support/developers/embed-options#using-embed-options 21261 * https://wistia.com/support/developers/player-api 21262 * https://wistia.com/support/developers/construct-an-embed-code 21263 * http://jsfiddle.net/xvnm7xLm/ 21264 * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video 21265 * https://wistia.com/support/embed-and-share/sharing-videos 21266 * https://private-sharing.wistia.com/medias/mwhrulrucj 21267 * 21268 * @ref Youtube 21269 * https://developers.google.com/youtube/player_parameters#enablejsapi 21270 * https://developers.google.com/youtube/iframe_api_reference 21271 * https://developer.chrome.com/blog/autoplay/#iframe-delegation 21272 * 21273 * @ref Vimeo 21274 * https://stackoverflow.com/questions/10488943/easy-way-to-get-vimeo-id-from-a-vimeo-url 21275 * https://vimeo.zendesk.com/hc/en-us/articles/360000121668-Starting-playback-at-a-specific-timecode 21276 * https://vimeo.zendesk.com/hc/en-us/articles/360001494447-Using-Player-Parameters 21277 */ 21278 var Video = /** @class */ (function () { 21279 function Video(instance) { 21280 // get lightGallery core plugin instance 21281 this.core = instance; 21282 this.settings = __assign(__assign({}, videoSettings), this.core.settings); 21283 return this; 21284 } 21285 Video.prototype.init = function () { 21286 var _this = this; 21287 /** 21288 * Event triggered when video url found without poster 21289 * Append video HTML 21290 * Play if autoplayFirstVideo is true 21291 */ 21292 this.core.LGel.on(lGEvents.hasVideo + ".video", this.onHasVideo.bind(this)); 21293 this.core.LGel.on(lGEvents.posterClick + ".video", function () { 21294 var $el = _this.core.getSlideItem(_this.core.index); 21295 _this.loadVideoOnPosterClick($el); 21296 }); 21297 this.core.LGel.on(lGEvents.slideItemLoad + ".video", this.onSlideItemLoad.bind(this)); 21298 // @desc fired immediately before each slide transition. 21299 this.core.LGel.on(lGEvents.beforeSlide + ".video", this.onBeforeSlide.bind(this)); 21300 // @desc fired immediately after each slide transition. 21301 this.core.LGel.on(lGEvents.afterSlide + ".video", this.onAfterSlide.bind(this)); 21302 }; 21303 /**
21304 * @desc Event triggered when a slide is completely loaded 21305 * 21306 * @param {Event} event - lightGalley custom event 21307 */ 21308 Video.prototype.onSlideItemLoad = function (event) { 21309 var _this = this; 21310 var _a = event.detail, isFirstSlide = _a.isFirstSlide, index = _a.index; 21311 // Should check the active slide as well as user may have moved to different slide before the first slide is loaded 21312 if (this.settings.autoplayFirstVideo && 21313 isFirstSlide && 21314 index === this.core.index) { 21315 // Delay is just for the transition effect on video load 21316 setTimeout(function () { 21317 _this.loadAndPlayVideo(index); 21318 }, 200); 21319 } 21320 // Should not call on first slide. should check only if the slide is active 21321 if (!isFirstSlide && 21322 this.settings.autoplayVideoOnSlide && 21323 index === this.core.index) { 21324 this.loadAndPlayVideo(index); 21325 } 21326 }; 21327 /** 21328 * @desc Event triggered when video url or poster found 21329 * Append video HTML is poster is not given 21330 * Play if autoplayFirstVideo is true 21331 * 21332 * @param {Event} event - Javascript Event object. 21333 */ 21334 Video.prototype.onHasVideo = function (event) { 21335 var _a = event.detail, index = _a.index, src = _a.src, html5Video = _a.html5Video, hasPoster = _a.hasPoster; 21336 if (!hasPoster) { 21337 // All functions are called separately if poster exist in loadVideoOnPosterClick function 21338 this.appendVideos(this.core.getSlideItem(index), { 21339 src: src, 21340 addClass: 'lg-object', 21341 index: index, 21342 html5Video: html5Video, 21343 }); 21344 // Automatically navigate to next slide once video reaches the end. 21345 this.gotoNextSlideOnVideoEnd(src, index); 21346 } 21347 }; 21348 /** 21349 * @desc fired immediately before each slide transition. 21350 * Pause the previous video 21351 * Hide the download button if the slide contains YouTube, Vimeo, or Wistia videos. 21352 * 21353 * @param {Event} event - Javascript Event object. 21354 * @param {number} prevIndex - Previous index of the slide. 21355 * @param {number} index - Current index of the slide 21356 */ 21357 Video.prototype.onBeforeSlide = function (event) { 21358 if (this.core.lGalleryOn) { 21359 var prevIndex = event.detail.prevIndex; 21360 this.pauseVideo(prevIndex); 21361 } 21362 // Uncode edit ##START## 21363 var _a = event.detail, index = _a.index, src = _a.info.src; 21364 if ( typeof src !== 'undefined' && src.indexOf("autoplay") > -1 ) { 21365 this.loadAndPlayVideo(index); 21366 21367 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}, 21368 $videoElement = this.core.getSlideItem(index).find('.lg-video-object').first(); 21369 if (videoInfo.vimeo) { 21370 var vimeoPlayer = new Vimeo.Player($videoElement.get()); 21371 vimeoPlayer.on('play', function () { 21372 vimeoPlayer.setCurrentTime(0); 21373 }); 21374 } else if ( videoInfo.youtube ) { 21375 try { 21376 $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"seekTo\",\"args\":[0, true]}", '*'); 21377 } 21378 catch (e) { 21379 console.warn(e); 21380 } 21381 } 21382 } 21383 // Uncode edit ##END## 21384 }; 21385 /** 21386 * @desc fired immediately after each slide transition. 21387 * Play video if autoplayVideoOnSlide option is enabled. 21388 * 21389 * @param {Event} event - Javascript Event object. 21390 * @param {number} prevIndex - Previous index of the slide. 21391 * @param {number} index - Current index of the slide 21392 * @todo should check on onSlideLoad as well if video is not loaded on after slide 21393 */ 21394 Video.prototype.onAfterSlide = function (event) { 21395 var _this = this; 21396 var _a = event.detail, index = _a.index, prevIndex = _a.prevIndex;
21397 // Do not call on first slide 21398 var $slide = this.core.getSlideItem(index); 21399 if (this.settings.autoplayVideoOnSlide && index !== prevIndex) { 21400 if ($slide.hasClass('lg-complete')) { 21401 setTimeout(function () { 21402 _this.loadAndPlayVideo(index); 21403 }, 100); 21404 } 21405 } 21406 }; 21407 Video.prototype.loadAndPlayVideo = function (index) { 21408 var $slide = this.core.getSlideItem(index); 21409 var currentGalleryItem = this.core.galleryItems[index]; 21410 if (currentGalleryItem.poster) { 21411 this.loadVideoOnPosterClick($slide, true); 21412 } 21413 else { 21414 //Uncode edit ##START## 21415 // this.playVideo(index); 21416 var src = currentGalleryItem.src; 21417 if ( typeof src !== 'undefined' && src.indexOf("autoplay") > -1) { 21418 if ( this.core.index == index ) { 21419 this.playVideo(index); 21420 } else { 21421 this.pauseVideo(index); 21422 } 21423 } 21424 //Uncode edit ##END## 21425 } 21426 }; 21427 /** 21428 * Play HTML5, Youtube, Vimeo or Wistia videos in a particular slide. 21429 * @param {number} index - Index of the slide 21430 */ 21431 Video.prototype.playVideo = function (index) { 21432 this.controlVideo(index, 'play'); 21433 }; 21434 /** 21435 * Pause HTML5, Youtube, Vimeo or Wistia videos in a particular slide. 21436 * @param {number} index - Index of the slide 21437 */ 21438 Video.prototype.pauseVideo = function (index) { 21439 this.controlVideo(index, 'pause'); 21440 }; 21441 Video.prototype.getVideoHtml = function (src, addClass, index, html5Video) { 21442 var video = ''; 21443 var videoInfo = this.core.galleryItems[index] 21444 .__slideVideoInfo || {}; 21445 var currentGalleryItem = this.core.galleryItems[index]; 21446 var videoTitle = currentGalleryItem.title || currentGalleryItem.alt; 21447 videoTitle = videoTitle ? 'title="' + videoTitle + '"' : ''; 21448 var commonIframeProps = "allowtransparency=\"true\"\n frameborder=\"0\"\n scrolling=\"no\"\n allowfullscreen\n mozallowfullscreen\n webkitallowfullscreen\n oallowfullscreen\n msallowfullscreen"; 21449 if (videoInfo.youtube) { 21450 var videoId = 'lg-youtube' + index; 21451 var slideUrlParams = videoInfo.youtube[2] 21452 ? videoInfo.youtube[2] + '&' 21453 : ''; 21454 // For youtube first parms gets priority if duplicates found 21455 var youTubePlayerParams = "?" + slideUrlParams + "wmode=opaque&autoplay=0&mute=1&enablejsapi=1"; 21456 var playerParams = youTubePlayerParams + 21457 (this.settings.youTubePlayerParams 21458 ? '&' + param(this.settings.youTubePlayerParams) 21459 : ''); 21460 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>"; 21461 } 21462 else if (videoInfo.vimeo) { 21463 var videoId = 'lg-vimeo' + index; 21464 var playerParams = getVimeoURLParams(this.settings.vimeoPlayerParams, videoInfo); 21465 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>"; 21466 } 21467 else if (videoInfo.wistia) { 21468 var wistiaId = 'lg-wistia' + index; 21469 var playerParams = param(this.settings.wistiaPlayerParams); 21470 playerParams = playerParams ? '?' + playerParams : ''; 21471 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>"; 21472 } 21473 else if (videoInfo.html5) { 21474 var html5VideoMarkup = ''; 21475 for (var i = 0; i < html5Video.source.length; i++) { 21476 html5VideoMarkup += "<source src=\"" + html5Video.source[i].src + "\" type=\"" + html5Video.source[i].type + "\">"; 21477 } 21478 if (html5Video.tracks) { 21479 var _loop_1 = function (i) { 21480 var trackAttributes = ''; 21481 var track = html5Video.tracks[i]; 21482 Object.keys(track || {}
21482).forEach(function (key) { 21483 trackAttributes += key + "=\"" + track[key] + "\" "; 21484 }); 21485 html5VideoMarkup += "<track " + trackAttributes + ">"; 21486 }; 21487 for (var i = 0; i < html5Video.tracks.length; i++) { 21488 _loop_1(i); 21489 } 21490 } 21491 var html5VideoAttrs_1 = ''; 21492 var videoAttributes_1 = html5Video.attributes || {}; 21493 Object.keys(videoAttributes_1 || {}).forEach(function (key) { 21494 html5VideoAttrs_1 += key + "=\"" + videoAttributes_1[key] + "\" "; 21495 }); 21496 video = "<video class=\"lg-video-object lg-html5 " + (this.settings.videojs ? 'video-js' : '') + "\" " + html5VideoAttrs_1 + ">\n " + html5VideoMarkup + "\n Your browser does not support HTML5 video.\n </video>"; 21497 } 21498 return video; 21499 }; 21500 /** 21501 * @desc - Append videos to the slide 21502 * 21503 * @param {HTMLElement} el - slide element 21504 * @param {Object} videoParams - Video parameters, Contains src, class, index, htmlVideo 21505 */ 21506 Video.prototype.appendVideos = function (el, videoParams) { 21507 var _a; 21508 var videoHtml = this.getVideoHtml(videoParams.src, videoParams.addClass, videoParams.index, videoParams.html5Video); 21509 el.find('.lg-video-cont').append(videoHtml); 21510 var $videoElement = el.find('.lg-video-object').first(); 21511 if (videoParams.html5Video) { 21512 $videoElement.on('mousedown.lg.video', function (e) { 21513 e.stopPropagation(); 21514 }); 21515 } 21516 if (this.settings.videojs && ((_a = this.core.galleryItems[videoParams.index].__slideVideoInfo) === null || _a === void 0 ? void 0 : _a.html5)) { 21517 try { 21518 return videojs($videoElement.get(), this.settings.videojsOptions); 21519 } 21520 catch (e) { 21521 console.warn('lightGallery:- Make sure you have included videojs'); 21522 } 21523 } 21524 }; 21525 Video.prototype.gotoNextSlideOnVideoEnd = function (src, index) { 21526 var _this = this; 21527 var $videoElement = this.core 21528 .getSlideItem(index) 21529 .find('.lg-video-object') 21530 .first(); 21531 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 21532 if (this.settings.gotoNextSlideOnVideoEnd) { 21533 if (videoInfo.html5) { 21534 $videoElement.on('ended', function () { 21535 _this.core.goToNextSlide(); 21536 }); 21537 } 21538 else if (videoInfo.vimeo) { 21539 try { 21540 // https://github.com/vimeo/player.js/#ended 21541 new Vimeo.Player($videoElement.get()).on('ended', function () { 21542 _this.core.goToNextSlide(); 21543 }); 21544 } 21545 catch (e) { 21546 console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js'); 21547 } 21548 } 21549 else if (videoInfo.wistia) { 21550 try { 21551 window._wq = window._wq || []; 21552 // @todo Event is gettign triggered multiple times 21553 window._wq.push({ 21554 id: $videoElement.attr('id'), 21555 onReady: function (video) { 21556 video.bind('end', function () { 21557 _this.core.goToNextSlide(); 21558 }); 21559 }, 21560 }); 21561 } 21562 catch (e) { 21563 console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js'); 21564 } 21565 } 21566 } 21567 }; 21568 Video.prototype.controlVideo = function (index, action) { 21569 var $videoElement = this.core 21570 .getSlideItem(index) 21571 .find('.lg-video-object') 21572 .first(); 21573 var videoInfo = this.core.galleryItems[index].__slideVideoInfo || {}; 21574 if (!$videoElement.get()) 21575 return; 21576 if (videoInfo.youtube) { 21577 try { 21578 $videoElement.get().contentWindow.postMessage("{\"event\":\"command\",\"func\":\"" + action + "Video\",\"args\":\"\"}", '*'); 21579 } 21580 catch (e) { 21581 console.warn("lightGallery:- " + e); 21582 } 21583 } 21584 else if (videoInfo.vimeo) { 21585 try { 21586 new Vimeo.Player($videoElement.get())[action](); 21587 } 21588 catch (e) { 21589 console.warn('lightGallery:- Make sure you have included //github.com/vimeo/player.js'); 21590 } 21591 } 21592 else if (videoInfo.html5) { 21593 if (this.settings.videojs) { 21594 try { 21595 videojs($videoElement.get())[action](); 21596 } 21597 catch (e) { 21598 console.warn('lightGallery:- Make sure you have included videojs'); 21599 } 21600 } 21601 else { 21602 $videoElement.get()[action](); 21603 } 21604 } 21605 else if (videoInfo.wistia) { 21606 try { 21607 window._wq = window._wq || []; 21608 // @todo Find a way to destroy wistia player instance 21609 window._wq.push({ 21610 id: $videoElement.attr('id'), 21611 onReady: function (video) { 21612 video[action](); 21613 }, 21614 }); 21615 } 21616 catch (e) { 21617 console.warn('lightGallery:- Make sure you have included //fast.wistia.com/assets/external/E-v1.js'); 21618 } 21619 } 21620 }; 21621 Video.prototype.loadVideoOnPosterClick = function ($el, forcePlay) { 21622 var _this = this; 21623 // check slide has poster 21624 if (!$el.hasClass('lg-video-loaded')) { 21625 // check already video element present
21626 if (!$el.hasClass('lg-has-video')) { 21627 $el.addClass('lg-has-video'); 21628 var _html = void 0; 21629 var _src = this.core.galleryItems[this.core.index].src; 21630 var video = this.core.galleryItems[this.core.index].video; 21631 if (video) { 21632 _html = 21633 typeof video === 'string' ? JSON.parse(video) : video; 21634 } 21635 var videoJsPlayer_1 = this.appendVideos($el, { 21636 src: _src, 21637 addClass: '', 21638 index: this.core.index, 21639 html5Video: _html, 21640 }); 21641 this.gotoNextSlideOnVideoEnd(_src, this.core.index); 21642 var $tempImg = $el.find('.lg-object').first().get(); 21643 // @todo make sure it is working 21644 $el.find('.lg-video-cont').first().append($tempImg); 21645 $el.addClass('lg-video-loading'); 21646 videoJsPlayer_1 && 21647 videoJsPlayer_1.ready(function () { 21648 videoJsPlayer_1.on('loadedmetadata', function () { 21649 _this.onVideoLoadAfterPosterClick($el, _this.core.index); 21650 }); 21651 }); 21652 $el.find('.lg-video-object') 21653 .first() 21654 .on('load.lg error.lg loadedmetadata.lg', function () { 21655 setTimeout(function () { 21656 _this.onVideoLoadAfterPosterClick($el, _this.core.index); 21657 }, 50); 21658 }); 21659 } 21660 else { 21661 this.playVideo(this.core.index); 21662 } 21663 } 21664 else if (forcePlay) { 21665 this.playVideo(this.core.index); 21666 } 21667 }; 21668 Video.prototype.onVideoLoadAfterPosterClick = function ($el, index) { 21669 $el.addClass('lg-video-loaded'); 21670 this.playVideo(index); 21671 }; 21672 Video.prototype.destroy = function () { 21673 this.core.LGel.off('.lg.video'); 21674 this.core.LGel.off('.video'); 21675 }; 21676 return Video; 21677 }()); 21678 21679 return Video; 21680 21681}))); 21682//# sourceMappingURL=lg-video.umd.js.map 21683 21684 21685/*! @vimeo/player v2.16.3 | (c) 2022 Vimeo | MIT License | https://github.com/vimeo/player.js */ 21686!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 l(e){return/^(https?:)?\/\/((player|www)\.)?vimeo\.com(?=$|\/)/.test(e)}function u(e){var t=0<arguments.length&&void 0!==e?e:{},n=t.id,e=t.url,t=n||e;if(!t)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(e=t,!isNaN(parseFloat(e))&&isFinite(e)&&Math.floor(e)==e)return"https://vimeo.com/".concat(t);if(l(t))return t.replace("http:","https:");if(n)throw new TypeError("â".concat(n,"â is not a valid video id."));throw new TypeError("â".concat(t,"â is not a vimeo.com url."))}var t=void 0!==Array.prototype.indexOf,Player="undefined"!=typeof window&&void 0!==window.postMessage;if(!(e||t&&Player))throw new Error("Sorry, the Vimeo Player API is not available in this browser.");var n,o,a="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function c(){if(void 0===this)throw new TypeError("Constructor WeakMap requires 'new'");if(o(this,"_id","_WeakMap_"+f()+"."+f()),0<arguments.length)throw new TypeError("WeakMap iterable is not supported")}function s(e,t){if(!d(e)||!n.call(e,"_id"))throw new TypeError(t+" method called on incompatible receiver "+typeof e)}function f(){return Math.random().toString().substring(2)}function d(e){return Object(e)===e}(Player="undefined"!=typeof self?self:"undefined"!=typeof window?window:a).WeakMap||(n=Object.prototype.hasOwnProperty,Player.WeakMap=((o=function(e,t,n){Object.defineProperty?Object.defineProperty(e,t,{configurable:!0,writable:!0,value:n}):e[t]=n})(c.prototype,"delete",function(e){if(s(this,"delete"),!d(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)&&(delete e[this._id],!0)}),o(c.prototype,"get",function(e){if(s(this,"get"),d(e)){var t=e[this._id];return t&&t[0]===e?t[1]:void 0}}),o(c.prototype,"has",function(e){if(s(this,"has"),!d(e))return!1;var t=e[this._id];return!(!t||t[0]!==e)}),o(c.prototype,"set",function(e,t){if(s(this,"set"),!d(e))throw new TypeError("Invalid value used as weak map key");var n=e[this._id];return n&&n[0]===e?n[1]=t:o(e,this._id,[e,t]),this}),o(c,"_polyfill",!0),c));var h,m=(function(e){var t,n,r;r=function(){var t,n,r,o,i,e=Object.prototype.toString,a="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 u(e,t){this.fn=e,this.self=t,this.next=void 0}function l(e,t){y.add(e,t),n=n||a(y.drain)}function c(e){var t,n=typeof e;return"function"==typeof(t=null!=e&&("object"==n||"function"==n)?e.then:t)&&t}function s(){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=c(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 f(e){var n,r=this;if(!r.triggered){r.triggered=!0,r.def&&(r=r.def);try{(n=c(e))?l(function(){var t=new m(r);try{n.call(e,function(){f.apply(t,arguments)},function(){d.apply(t,arguments)})}catch(e){d.call(t,e)}}):(r.msg=e,r.state=1,0<r.chain.length&&l(s,r))}catch(e){d.call(new m(r),e)}}}function d(e){var t=this;t.triggered||(t.triggered=!0,(t=t.def?t.def:t).msg=e,t.state=2,0<t.chain.length&&l(s,t))}function h(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 v(e){this.promise=e,this.state=0,this.triggered=!1,this.chain=[],this.msg=void 0}function p(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 v(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&&l(s,r),n.promise},this.catch=function(e){return this.then(void 0,e)};try{e.call(void 0,function(e){f.call(r,e)},function(e){d.call(r,e)})}catch(e){d.call(r,e)}}var y={add:function(e,t){i=new u(e,t),o?o.next=i:r=i,o=i,i=void 0},drain:function(){var e=r;
vendor: 14,752 bytes, lines 21686-21689
21686for(r=o=n=void 0;e;)e.fn.call(e.self),e=e.next}},g=t({},"constructor",p,!1);return t(p.prototype=g,"__NPO__",0,!1),t(p,"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(p,"reject",function(n){return new this(function(e,t){if("function"!=typeof e||"function"!=typeof t)throw TypeError("Not a function");t(n)})}),t(p,"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;h(a,t,function(e,t){o[e]=t,++i===r&&n(o)},e)})}),t(p,"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");h(r,t,function(e,t){n(t)},e)})}),p},(n=a)[t="Promise"]=n[t]||r(),e.exports&&(e.exports=n[t])}(h={exports:{}}),h.exports),v=new WeakMap;function p(e,t,n){var r=v.get(e.element)||{};t in r||(r[t]=[]),r[t].push(n),v.set(e.element,r)}function y(e,t){return(v.get(e.element)||{})[t]||[]}function g(e,t,n){var r=v.get(e.element)||{};if(!r[t])return!0;if(!n)return r[t]=[],v.set(e.element,r),!0;n=r[t].indexOf(n);return-1!==n&&r[t].splice(n,1),v.set(e.element,r),r[t]&&0===r[t].length}var w=["autopause","autoplay","background","byline","color","controls","dnt","height","id","interactiveparams","keyboard","loop","maxheight","maxwidth","muted","playsinline","portrait","responsive","speed","texttrack","title","transparent","url","width"];function b(r,e){return w.reduce(function(e,t){var n=r.getAttribute("data-vimeo-".concat(t));return!n&&""!==n||(e[t]=""===n?1:n),e},1<arguments.length&&void 0!==e?e:{})}function k(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");e=document.createElement("div");return e.innerHTML=n,t.appendChild(e.firstChild),t.setAttribute("data-vimeo-initialized","true"),t.querySelector("iframe")}function E(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(!l(i))throw new TypeError("â".concat(i,"â is not a vimeo.com url."));var e,r="https://vimeo.com/api/oembed.json?url=".concat(encodeURIComponent(i));for(e in a)a.hasOwnProperty(e)&&(r+="&".concat(e,"=").concat(encodeURIComponent(a[e])));var o=new("XDomainRequest"in window?XDomainRequest:XMLHttpRequest);o.open("GET",r,!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 k(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()})}function T(e){function n(e){"console"in window&&console.warn&&console.warn("There was an error creating an embed: ".concat(e))}e=0<arguments.length&&void 0!==e?e:document,e=[].slice.call(e.querySelectorAll("[data-vimeo-id], [data-vimeo-url]"));e.forEach(function(t){try{if(null!==t.getAttribute("data-vimeo-defer"))return;var e=b(t);E(u(e),e,t).then(function(e){return k(e,t)}).catch(n)}catch(e){n(e)}})}function P(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){return console.warn(e),{}}return e}function _(e,t,n){e.element.contentWindow&&e.element.contentWindow.postMessage&&(t={method:t},void 0!==n&&(t.value=n),8<=(n=parseFloat(navigator.userAgent.toLowerCase().replace(/^.*msie (\d+).*$/,"$1")))&&n<10&&(t=JSON.stringify(t)),e.element.contentWindow.postMessage(t,e.origin))}function M(n,r){var t,e,o,i,a=[];(r=P(r)).event?("error"===r.event&&y(n,r.data.method).forEach(function(e){var t=new Error(r.data.message);t.name=r.data.name,e.reject(t),g(n,r.data.method,e)}),a=y(n,"event:".concat(r.event)),t=r.data):r.method&&(e=n,o=r.method,(i=!((i=y(e,o)).length<1)&&(i=i.shift(),g(e,o,i),i))&&(a.push(i),t=r.value)),a.forEach(function(e){try{if("function"==typeof e)return void e.call(n,t);e.resolve(t)}catch(e){}})}var N,F,x,C=new WeakMap,j=new WeakMap,A={},Player=function(){function Player(i){var e,a=this,t=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&&i instanceof jQuery&&(1<i.length&&window.console&&console.warn&&console.warn("A jQuery object with multiple elements was passed, using the first element."),i=i[0]),"undefined"!=typeof document&&"string"==typeof i&&(i=document.getElementById(i)),e=i,!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"===i.nodeName||(r=i.querySelector("iframe"))&&(i=r),"IFRAME"===i.nodeName&&!l(i.getAttribute("src")||""))throw new Error("The player element passed isnât a Vimeo embed.");if(C.has(i))return C.get(i);this._window=i.ownerDocument.defaultView,this.element=i,this.origin="*";var n,r=new m(function(r,o){var e;a._onMessage=function(e){if(l(e.origin)&&a.element.contentWindow===e.source){"*"===a.origin&&(a.origin=e.origin);var t=P(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 o(n)}e=t&&"ready"===t.event,n=t&&"ping"===t.method;if(e||n)return a.element.setAttribute("data-ready","true"),void r();M(a,t)}},a._window.addEventListener("message",a._onMessage),"IFRAME"!==a.element.nodeName&&E(u(e=b(i,t)),e,i).then(function(e){var t,n,r=k(e,i);return a.element=r,a._originalElement=i,t=i,n=r,r=v.get(t),v.set(n,r),v.delete(t),C.set(a.element,a),e}).catch(o)});return j.set(this,r),C.set(this.element,this),"IFRAME"===this.element.nodeName&&_(this,"ping"),A.isEnabled&&(n=function(){return A.exit()},this.fullscreenchangeHandler=function(){(A.isFullscreen?p:g)(a,"event:exitFullscreen",n),a.ready().then(function(){_(a,"fullscreenchange",A.isFullscreen)})},A.on("fullscreenchange",this.fullscreenchangeHandler)),this}var e,t,n;return e=Player,(t=[{key:"callMethod",value:function(n){var r=this,o=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};return new m(function(e,t){return r.ready().then(function(){p(r,n,{resolve:e,reject:t}),_(r,n,o)}).catch(t)})}},{key:"get",value:function(n){var r=this;return new m(function(e,t){return n=i(n,"get"),r.ready().then(function(){p(r,n,{resolve:e,reject:t}),_(r,n)}).catch(t)})}},{key:"set",value:function(n,r){var o=this;return new m(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(){p(o,n,{resolve:e,reject: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===y(this,"event:".concat(e)).length&&this.callMethod("addEventListener",e).catch(function(){}),p(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.");g(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=j.get(this)||new m(function(e,t){t(new Error("Unknown player. Probably unloaded."))});return m.resolve(e)}},{key:"addCuePoint",value:function(e){return this.callMethod("addCuePoint",{time:e,data:1<arguments.length&&void 0!==arguments[1]?arguments[1]:{}})}},{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 A.isEnabled?A.request(this.element):this.callMethod("requestFullscreen")}},{key:"exitFullscreen",value:function(){return A.isEnabled?A.exit():this.callMethod("exitFullscreen")}},{key:"getFullscreen",value:function(){return A.isEnabled?m.resolve(A.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 m(function(e){var t;j.delete(n),C.delete(n.element),n._originalElement&&(C.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),A.isEnabled&&A.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)}},{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||(N=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}(),F={fullscreenchange:N.fullscreenchange,fullscreenerror:N.fullscreenerror},x={request:function(o){return new Promise(function(e,t){function n(){x.off("fullscreenchange",n),e()}x.on("fullscreenchange",n);var r=(o=o||document.documentElement)[N.requestFullscreen]();r instanceof Promise&&r.then(n).catch(t)})},exit:function(){return new Promise(function(t,e){var n,r;x.isFullscreen?(n=function e(){x.off("fullscreenchange",e),t()},x.on("fullscreenchange",n),(r=document[N.exitFullscreen]())instanceof Promise&&r.then(n).catch(e)):t()})},on:function(e,t){e=F[e];e&&document.addEventListener(e,t)},off:function(e,t){e=F[e];e&&document.removeEventListener(e,t)}},Object.defineProperties(x,{isFullscreen:{get:function(){return Boolean(document[N.fullscreenElement])}},element:{enumerable:!0,get:function(){return document[N.fullscreenElement]}},isEnabled:{enumerable:!0,get:function(){return Boolean(document[N.fullscreenEnabled])}}}),A=x,T(),function(e){var r=0<arguments.length&&void 0!==e?e:document;window.VimeoPlayerResizeEmbeds_||(window.VimeoPlayerResizeEmbeds_=!0,window.addEventListener("message",function(e){if(l(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}}))}()),Player}); 21687 21688/** 21689 * Owl carousel
vendor: 31,483 bytes, lines 21690-22893
21690 * @version 2.0.0-beta.3 21691 * @author Bartosz Wojciechowski 21692 * @license The MIT License (MIT) 21693 * @todo Lazy Load Icon 21694 * @todo prevent animationend bubling 21695 * @todo itemsScaleUp 21696 * @todo Test Zepto 21697 * @todo stagePadding calculate wrong active classes 21698 */ 21699;(function($, window, document, undefined) { 21700 21701 /** 21702 * Creates a carousel. 21703 * @class The Owl Carousel. 21704 * @public 21705 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 21706 * @param {Object} [options] - The options 21707 */ 21708 function Owl(element, options) { 21709 21710 /** 21711 * Current settings for the carousel. 21712 * @public 21713 */ 21714 this.settings = null; 21715 21716 /** 21717 * Current options set by the caller including defaults. 21718 * @public 21719 */ 21720 this.options = $.extend({}, Owl.Defaults, options); 21721 21722 /** 21723 * Plugin element. 21724 * @public 21725 */ 21726 this.$element = $(element); 21727 21728 /** 21729 * Proxied event handlers. 21730 * @protected 21731 */ 21732 this._handlers = {}; 21733 21734 /** 21735 * References to the running plugins of this carousel. 21736 * @protected 21737 */ 21738 this._plugins = {}; 21739 21740 /** 21741 * Currently suppressed events to prevent them from beeing retriggered. 21742 * @protected 21743 */ 21744 this._supress = {}; 21745 21746 /** 21747 * Absolute current position. 21748 * @protected 21749 */ 21750 this._current = null; 21751 21752 /** 21753 * Animation speed in milliseconds. 21754 * @protected 21755 */ 21756 this._speed = null; 21757 21758 /** 21759 * Coordinates of all items in pixel. 21760 * @todo The name of this member is missleading. 21761 * @protected 21762 */ 21763 this._coordinates = []; 21764 21765 /** 21766 * Current breakpoint. 21767 * @todo Real media queries would be nice. 21768 * @protected 21769 */ 21770 this._breakpoint = null; 21771 21772 /** 21773 * Current width of the plugin element. 21774 */ 21775 this._width = null; 21776 21777 /** 21778 * All real items. 21779 * @protected 21780 */ 21781 this._items = []; 21782 21783 /** 21784 * All cloned items. 21785 * @protected 21786 */ 21787 this._clones = []; 21788 21789 /** 21790 * Merge values of all items. 21791 * @todo Maybe this could be part of a plugin. 21792 * @protected 21793 */ 21794 this._mergers = []; 21795 21796 /** 21797 * Widths of all items. 21798 */ 21799 this._widths = []; 21800 21801 /** 21802 * Invalidated parts within the update process. 21803 * @protected 21804 */ 21805 this._invalidated = {}; 21806 21807 /** 21808 * Ordered list of workers for the update process. 21809 * @protected 21810 */ 21811 this._pipe = []; 21812 21813 /** 21814 * Current state information for the drag operation. 21815 * @todo #261 21816 * @protected 21817 */ 21818 this._drag = { 21819 time: null, 21820 target: null, 21821 pointer: null, 21822 stage: { 21823 start: null, 21824 current: null 21825 }, 21826 direction: null 21827 }; 21828 21829 /** 21830 * Current state information and their tags. 21831 * @type {Object} 21832 * @protected 21833 */ 21834 this._states = { 21835 current: {}, 21836 tags: { 21837 'initializing': [ 'busy' ], 21838 'animating': [ 'busy' ], 21839 'dragging': [ 'interacting' ] 21840 } 21841 }; 21842 21843 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 21844 this._handlers[handler] = $.proxy(this[handler], this); 21845 }, this)); 21846 21847 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 21848 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 21849 = new plugin(this); 21850 }, this)); 21851 21852 $.each(Owl.Workers, $.proxy(function(priority, worker) { 21853 this._pipe.push({ 21854 'filter': worker.filter, 21855 'run': $.proxy(worker.run, this) 21856 }); 21857 }, this)); 21858 21859 this.setup(); 21860 this.initialize(); 21861 } 21862 21863 /** 21864 * Default options for the carousel. 21865 * @public 21866 */ 21867 Owl.Defaults = { 21868 items: 3, 21869 loop: false, 21870 center: false, 21871 rewind: false, 21872 21873 mouseDrag: true, 21874 touchDrag: true, 21875 pullDrag: true, 21876 freeDrag: false, 21877 21878 margin: 0, 21879 stagePadding: 0, 21880 21881 merge: false, 21882 mergeFit: true, 21883 autoWidth: false, 21884 21885 startPosition: 0, 21886 rtl: false, 21887 21888 smartSpeed: 250, 21889 fluidSpeed: false, 21890 dragEndSpeed: false, 21891 21892 responsive: {}, 21893 responsiveRefreshRate: 200, 21894 responsiveBaseElement: window, 21895 21896 fallbackEasing: 'swing', 21897 21898 info: false, 21899 21900 nestedItemSelector: false, 21901 itemElement: 'div', 21902 stageElement: 'div', 21903 21904 refreshClass: 'owl-refresh', 21905 loadedClass: 'owl-loaded', 21906 loadingClass: 'owl-loading', 21907 rtlClass: 'owl-rtl', 21908 responsiveClass: 'owl-responsive', 21909 dragClass: 'owl-drag', 21910 itemClass: 'owl-item', 21911 stageClass: 'owl-stage', 21912 stageOuterClass: 'owl-stage-outer', 21913 grabClass: 'owl-grab' 21914 }; 21915 21916 /** 21917 * Enumeration for width. 21918 * @public 21919 * @readonly 21920 * @enum {String} 21921 */ 21922 Owl.Width = { 21923 Default: 'default', 21924 Inner: 'inner', 21925 Outer: 'outer' 21926 }; 21927 21928 /** 21929 * Enumeration for types. 21930 * @public 21931 * @readonly 21932 * @enum {String} 21933 */ 21934 Owl.Type = { 21935 Event: 'event', 21936 State: 'state' 21937 }; 21938 21939 /** 21940 * Contains all registered plugins. 21941 * @public 21942 */ 21943 Owl.Plugins = {}; 21944 21945 /** 21946 * List of workers involved in the update process. 21947 */ 21948 Owl.Workers = [ { 21949 filter: [ 'width', 'settings' ], 21950 run: function() { 21951 this._width = (this.$element.closest('.px-gutter').length) ? 12 * Math.ceil(this.$element.width() / 12) : this.$element.width(); 21952 //this._width = (UNCODE.isMobile) ? this.$element.width() : 12 * Math.ceil(this.$element.width() / 12); 21953 } 21954 }, { 21955 filter: [ 'width', 'items', 'settings' ], 21956 run: function(cache) { 21957 cache.current = this._items && this._items[this.relative(this._current)]; 21958 } 21959 }, { 21960 filter: [ 'items', 'settings' ], 21961 run: function() { 21962 this.$stage.children('.cloned').remove(); 21963 } 21964 }, { 21965 filter: [ 'width', 'items', 'settings' ], 21966 run: function(cache) { 21967 var margin = this.settings.margin || '', 21968 grid = !this.settings.autoWidth, 21969 rtl = this.settings.rtl, 21970 css = { 21971 'width': 'auto', 21972 'margin-left': rtl ? margin : '', 21973 'margin-right': rtl ? '' : margin 21974 }; 21975 21976 !grid && this.$stage.children().css(css); 21977 21978 cache.css = css; 21979 } 21980 }, { 21981 filter: [ 'width', 'items', 'settings' ], 21982 run: function(cache) { 21983 //UNCODE edit to fix Chrome stage padding issue 21984 var width = Math.round((this.width() / this.settings.items).toFixed(3) - this.settings.margin), 21985 merge = null, 21986 iterator = this._items.length, 21987 grid = !this.settings.autoWidth, 21988 widths = []; 21989 21990 cache.items = { 21991 merge: false, 21992 width: width 21993 }; 21994 21995 while (iterator--) { 21996 merge = this._mergers[iterator]; 21997 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 21998 21999 cache.items.merge = merge > 1 || cache.items.merge; 22000 22001 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 22002 } 22003 22004 this._widths = widths; 22005 } 22006 }, { 22007 filter: [ 'items', 'settings' ], 22008 run: function() { 22009 var clones = [], 22010 items = this._items, 22011 settings = this.settings, 22012 view = Math.max(settings.items * 2, 4), 22013 size = Math.ceil(items.length / 2) * 2, 22014 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 22015 append = '', 22016 prepend = ''; 22017 22018 repeat /= 2; 22019 22020 while (repeat--) { 22021 clones.push(this.normalize(clones.length / 2, true)); 22022 append = append + items[clones[clones.length - 1]][0].outerHTML; 22023 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 22024 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 22025 } 22026 22027 this._clones = clones; 22028 22029 // var appendVideo = $(append).find('.uncode-video-container'); 22030 // if (appendVideo.length) { 22031 // appendVideo.attr('data-id', Math.round(Math.random() * 100000)); 22032 // } 22033 // var prependVideo = $(prepend).find('.uncode-video-container'); 22034 // if (prependVideo.length) { 22035 // prependVideo.attr('data-id', Math.round(Math.random() * 100000)); 22036 // } 22037 $(append).addClass('cloned').appendTo(this.$stage); 22038 $(prepend).addClass('cloned').prependTo(this.$stage); 22039 } 22040 }, { 22041 filter: [ 'width', 'items', 'settings' ], 22042 run: function() { 22043 var rtl = this.settings.rtl ? 1 : -1, 22044 size = this._clones.length + this._items.length, 22045 iterator = -1, 22046 previous = 0, 22047 current = 0, 22048 coordinates = []; 22049 22050 while (++iterator < size) { 22051 previous = coordinates[iterator - 1] || 0; 22052 current = this._widths[this.relative(iterator)] + this.settings.margin; 22053 coordinates.push(previous + current * rtl); 22054 } 22055 22056 this._coordinates = coordinates; 22057 } 22058 }, { 22059 filter: [ 'width', 'items', 'settings' ], 22060 run: function() { 22061 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 22062 padding = stagePadding, 22063 coordinates = this._coordinates, 22064 css = { 22065 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 22066 'padding-left': padding || '', 22067 'padding-right': padding || '' 22068 }; 22069 22070 this.$stage.css(css); 22071 } 22072 }, { 22073 filter: [ 'width', 'items', 'settings' ], 22074 run: function(cache) { 22075 var iterator = this._coordinates.length, 22076 grid = !this.settings.autoWidth, 22077 items = this.$stage.children(); 22078 22079 if (grid && cache.items.merge) { 22080 while (iterator--) { 22081 cache.css.width = this._widths[this.relative(iterator)]; 22082 items.eq(iterator).css(cache.css); 22083 } 22084 } else if (grid) { 22085 cache.css.width = cache.items.width; 22086 items.css(cache.css); 22087 } 22088 } 22089 }, { 22090 filter: [ 'items' ], 22091 run: function() { 22092 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 22093 } 22094 }, { 22095 filter: [ 'width', 'items', 'settings' ], 22096 run: function(cache) { 22097 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 22098 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 22099 this.reset(cache.current); 22100 } 22101 }, { 22102 filter: [ 'position' ], 22103 run: function() { 22104 this.animate(this.coordinates(this._current)); 22105 } 22106 }, { 22107 filter: [ 'width', 'position', 'items', 'settings' ], 22108 run: function() { 22109 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200, 22110 rtl = this.settings.rtl ? 1 : -1, 22111 padding = this.settings.stagePadding * 2, 22112 begin = this.coordinates(this.current()) + padding, 22113 end = begin + this.width() * rtl, 22114 inner, outer, matches = [], i, n; 22115 22116 for (i = 0, n = this._coordinates.length; i < n; i++) { 22117 inner = this._coordinates[i - 1] || 0; 22118 outer = Math.abs(this._coordinates[i]) + padding * rtl; 22119 22120 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 22121 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 22122 matches.push(i); 22123 } 22124 } 22125 22126 this.$stage.children('.active').removeClass('active'); 22127 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 22128 22129 if (this.settings.center) { 22130 this.$stage.children('.center').removeClass('center'); 22131 this.$stage.children().eq(this.current()).addClass('center'); 22132 } 22133 } 22134 } ]; 22135 22136 /** 22137 * Initializes the carousel. 22138 * @protected 22139 */ 22140 Owl.prototype.initialize = function() { 22141 this.enter('initializing'); 22142 this.trigger('initialize'); 22143 22144 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 22145 22146 if (this.settings.autoWidth && !this.is('pre-loading')) { 22147 var imgs, nestedSelector, width; 22148 imgs = this.$element.find('img'); 22149 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 22150 width = this.$element.children(nestedSelector).width(); 22151 22152 if (imgs.length && width <= 0) { 22153 this.preloadAutoWidthImages(imgs); 22154 } 22155 } 22156 22157 this.$element.addClass(this.options.loadingClass); 22158 22159 // create stage 22160 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 22161 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 22162 22163 // append stage 22164 this.$element.append(this.$stage.parent()); 22165 22166 // append content 22167 this.replace(this.$element.children().not(this.$stage.parent())); 22168 22169 // check visibility 22170 if (this.$element.is(':visible')) { 22171 // update view 22172 this.refresh(); 22173 } else { 22174 // invalidate width 22175 this.invalidate('width'); 22176 } 22177 22178 this.$element 22179 .removeClass(this.options.loadingClass) 22180 .addClass(this.options.loadedClass); 22181 22182 // register event handlers 22183 this.registerEventHandlers(); 22184 22185 this.leave('initializing'); 22186 this.trigger('initialized'); 22187 }; 22188 22189 /** 22190 * Setups the current settings. 22191 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 22192 * @todo Support for media queries by using `matchMedia` would be nice. 22193 * @public 22194 */ 22195 Owl.prototype.setup = function() { 22196 var viewport = this.viewport(), 22197 overwrites = this.options.responsive, 22198 match = -1, 22199 settings = null; 22200 22201 if (!overwrites) { 22202 settings = $.extend({}, this.options); 22203 } else { 22204 $.each(overwrites, function(breakpoint) { 22205 if (breakpoint <= viewport && breakpoint > match) { 22206 match = Number(breakpoint); 22207 } 22208 }); 22209 22210 settings = $.extend({}, this.options, overwrites[match]); 22211 delete settings.responsive; 22212 22213 // responsive class 22214 if (settings.responsiveClass) { 22215 this.$element.attr('class', 22216 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 22217 ); 22218 } 22219 } 22220 22221 if (this.settings === null || this._breakpoint !== match) { 22222 this.trigger('change', { property: { name: 'settings', value: settings } }); 22223 this._breakpoint = match; 22224 this.settings = settings; 22225 this.invalidate('settings'); 22226 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 22227 } 22228 }; 22229 22230 /** 22231 * Updates option logic if necessery. 22232 * @protected 22233 */ 22234 Owl.prototype.optionsLogic = function() { 22235 if (this.settings.autoWidth) { 22236 this.settings.stagePadding = false; 22237 this.settings.merge = false; 22238 } 22239 }; 22240 22241 /** 22242 * Prepares an item before add. 22243 * @todo Rename event parameter `content` to `item`. 22244 * @protected 22245 * @returns {jQuery|HTMLElement} - The item container. 22246 */ 22247 Owl.prototype.prepare = function(item, index) { 22248 var event = this.trigger('prepare', { content: item }); 22249 if (!event.data) { 22250 event.data = $('<' + this.settings.itemElement + '/>') 22251 .addClass(this.options.itemClass).attr('data-index', index + 1).append(item) 22252 } 22253 22254 this.trigger('prepared', { content: event.data }); 22255 22256 return event.data; 22257 }; 22258 22259 /** 22260 * Updates the view. 22261 * @public 22262 */ 22263 Owl.prototype.update = function() { 22264 var i = 0, 22265 n = this._pipe.length, 22266 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 22267 cache = {}; 22268 22269 while (i < n) { 22270 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 22271 this._pipe[i].run(cache); 22272 } 22273 i++; 22274 } 22275 22276 this._invalidated = {}; 22277 22278 !this.is('valid') && this.enter('valid'); 22279 }; 22280 22281 /** 22282 * Gets the width of the view. 22283 * @public 22284 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 22285 * @returns {Number} - The width of the view in pixel. 22286 */ 22287 Owl.prototype.width = function(dimension) { 22288 dimension = dimension || Owl.Width.Default; 22289 var stagePadding = (this._width < 480 && this.settings.stagePadding > 0) ? 41 : (this._width * this.settings.stagePadding) / 200; 22290 switch (dimension) { 22291 case Owl.Width.Inner: 22292 case Owl.Width.Outer: 22293 return this._width; 22294 default: 22295 return this._width - stagePadding * 2 + this.settings.margin; 22296 } 22297 }; 22298 22299 /** 22300 * Refreshes the carousel primarily for adaptive purposes. 22301 * @public 22302 */ 22303 Owl.prototype.refresh = function() { 22304 this.enter('refreshing'); 22305 this.trigger('refresh'); 22306 22307 this.setup(); 22308 22309 this.optionsLogic(); 22310 22311 this.$element.addClass(this.options.refreshClass); 22312 22313 this.update(); 22314 22315 this.$element.removeClass(this.options.refreshClass); 22316 22317 this.leave('refreshing'); 22318 this.trigger('refreshed'); 22319 }; 22320 22321 /** 22322 * Checks window `resize` event. 22323 * @protected 22324 */ 22325 Owl.prototype.onThrottledResize = function() { 22326 window.clearTimeout(this.resizeTimer); 22327 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 22328 }; 22329 22330 /** 22331 * Checks window `resize` event. 22332 * @protected 22333 */ 22334 Owl.prototype.onResize = function() { 22335 if (!this._items.length) { 22336 return false; 22337 } 22338 22339 if (this._width === this.$element.width()) { 22340 return false; 22341 } 22342 22343 if (!this.$element.is(':visible')) { 22344 return false; 22345 } 22346 22347 this.enter('resizing'); 22348 22349 if (this.trigger('resize').isDefaultPrevented()) { 22350 this.leave('resizing'); 22351 return false; 22352 } 22353 22354 this.invalidate('width'); 22355 22356 this.refresh(); 22357 22358 this.leave('resizing'); 22359 this.trigger('resized'); 22360 }; 22361 22362 /** 22363 * Registers event handlers. 22364 * @todo Check `msPointerEnabled` 22365 * @todo #261 22366 * @protected 22367 */ 22368 Owl.prototype.registerEventHandlers = function() { 22369 if ($.support.transition) { 22370 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 22371 } 22372 22373 if (this.settings.responsive !== false) { 22374 this.on(window, 'resize', this._handlers.onThrottledResize); 22375 } 22376 22377 if (this.settings.mouseDrag) { 22378 this.$element.addClass(this.options.dragClass); 22379 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 22380 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 22381 } 22382 22383 if (this.settings.touchDrag){ 22384 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 22385 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 22386 } 22387 }; 22388 22389 /** 22390 * Handles `touchstart` and `mousedown` events. 22391 * @todo Horizontal swipe threshold as option 22392 * @todo #261 22393 * @protected 22394 * @param {Event} event - The event arguments. 22395 */ 22396 Owl.prototype.onDragStart = function(event) { 22397 var stage = null; 22398 22399 if (event.which === 3) { 22400 return; 22401 } 22402 22403 if ($.support.transform) { 22404 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 22405 stage = { 22406 x: stage[stage.length === 16 ? 12 : 4], 22407 y: stage[stage.length === 16 ? 13 : 5] 22408 }; 22409 } else { 22410 stage = this.$stage.position(); 22411 stage = { 22412 x: this.settings.rtl ? 22413 stage.left + this.$stage.width() - this.width() + this.settings.margin : 22414 stage.left, 22415 y: stage.top 22416 }; 22417 } 22418 22419 if (this.is('animating')) { 22420 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 22421 this.invalidate('position'); 22422 } 22423 22424 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 22425 22426 this.speed(0); 22427 22428 this._drag.time = new Date().getTime(); 22429 this._drag.target = $(event.target); 22430 this._drag.stage.start = stage; 22431 this._drag.stage.current = stage; 22432 this._drag.pointer = this.pointer(event); 22433 22434 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 22435 22436 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 22437 var delta = this.difference(this._drag.pointer, this.pointer(event)); 22438 22439 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 22440 22441 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 22442 return; 22443 } 22444 22445 event.preventDefault(); 22446 22447 this.enter('dragging'); 22448 this.trigger('drag'); 22449 }, this)); 22450 }; 22451 22452 /** 22453 * Handles the `touchmove` and `mousemove` events. 22454 * @todo #261 22455 * @protected 22456 * @param {Event} event - The event arguments. 22457 */ 22458 Owl.prototype.onDragMove = function(event) { 22459 var minimum = null, 22460 maximum = null, 22461 pull = null, 22462 delta = this.difference(this._drag.pointer, this.pointer(event)), 22463 stage = this.difference(this._drag.stage.start, delta); 22464 22465 if (!this.is('dragging')) { 22466 return; 22467 } 22468 22469 event.preventDefault(); 22470 22471 if (this.settings.loop) { 22472 minimum = this.coordinates(this.minimum()); 22473 maximum = this.coordinates(this.maximum() + 1) - minimum; 22474 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 22475 } else { 22476 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 22477 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 22478 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 22479 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 22480 } 22481 22482 this._drag.stage.current = stage; 22483 22484 this.animate(stage.x); 22485 }; 22486 22487 /** 22488 * Handles the `touchend` and `mouseup` events. 22489 * @todo #261 22490 * @todo Threshold for click event 22491 * @protected 22492 * @param {Event} event - The event arguments. 22493 */ 22494 Owl.prototype.onDragEnd = function(event) { 22495 var delta = this.difference(this._drag.pointer, this.pointer(event)), 22496 stage = this._drag.stage.current, 22497 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 22498 22499 $(document).off('.owl.core'); 22500 22501 this.$element.removeClass(this.options.grabClass); 22502 22503 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 22504 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 22505 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 22506 this.invalidate('position'); 22507 this.update(); 22508 22509 this._drag.direction = direction; 22510 22511 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 22512 this._drag.target.one('click.owl.core', function() { return false; }); 22513 } 22514 } 22515 22516 if (!this.is('dragging')) { 22517 return; 22518 } 22519 22520 this.leave('dragging'); 22521 this.trigger('dragged'); 22522 }; 22523 22524 /** 22525 * Gets absolute position of the closest item for a coordinate. 22526 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 22527 * @protected 22528 * @param {Number} coordinate - The coordinate in pixel. 22529 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 22530 * @return {Number} - The absolute position of the closest item. 22531 */ 22532 Owl.prototype.closest = function(coordinate, direction) { 22533 var position = -1, 22534 pull = 30, 22535 width = this.width(), 22536 coordinates = this.coordinates(); 22537 22538 if (!this.settings.freeDrag) { 22539 // check closest item 22540 $.each(coordinates, $.proxy(function(index, value) { 22541 if (coordinate > value - pull && coordinate < value + pull) { 22542 position = index; 22543 } else if (this.op(coordinate, '<', value) 22544 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 22545 position = direction === 'left' ? index + 1 : index; 22546 } 22547 return position === -1; 22548 }, this)); 22549 } 22550 22551 if (!this.settings.loop) { 22552 // non loop boundries 22553 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 22554 position = coordinate = this.minimum(); 22555 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 22556 position = coordinate = this.maximum(); 22557 } 22558 } 22559 22560 return position; 22561 }; 22562 22563 /** 22564 * Animates the stage. 22565 * @todo #270 22566 * @public 22567 * @param {Number} coordinate - The coordinate in pixels. 22568 */ 22569 Owl.prototype.animate = function(coordinate) { 22570 var animate = this.speed() > 0; 22571 22572 this.is('animating') && this.onTransitionEnd(); 22573 22574 if (animate) { 22575 this.enter('animating'); 22576 this.trigger('translate'); 22577 } 22578 22579 if ($.support.transform3d && $.support.transition) { 22580 this.$stage.css({ 22581 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 22582 transition: (this.speed() / 1000) + 's' 22583 }); 22584 } else if (animate) { 22585 this.$stage.animate({ 22586 left: coordinate + 'px' 22587 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 22588 } else { 22589 this.$stage.css({ 22590 left: coordinate + 'px' 22591 }); 22592 } 22593 }; 22594 22595 /** 22596 * Checks whether the carousel is in a specific state or not. 22597 * @param {String} state - The state to check. 22598 * @returns {Boolean} - The flag which indicates if the carousel is busy. 22599 */ 22600 Owl.prototype.is = function(state) { 22601 return this._states.current[state] && this._states.current[state] > 0; 22602 }; 22603 22604 /** 22605 * Sets the absolute position of the current item. 22606 * @public 22607 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 22608 * @returns {Number} - The absolute position of the current item. 22609 */ 22610 Owl.prototype.current = function(position) { 22611 if (position === undefined) { 22612 return this._current; 22613 } 22614 22615 if (this._items.length === 0) { 22616 return undefined; 22617 } 22618 22619 position = this.normalize(position); 22620 22621 if (this._current !== position) { 22622 var event = this.trigger('change', { property: { name: 'position', value: position } }); 22623 22624 if (event.data !== undefined) { 22625 position = this.normalize(event.data); 22626 } 22627 22628 this._current = position; 22629 22630 this.invalidate('position'); 22631 22632 this.trigger('changed', { property: { name: 'position', value: this._current } }); 22633 } 22634 22635 return this._current; 22636 }; 22637 22638 /** 22639 * Invalidates the given part of the update routine. 22640 * @param {String} [part] - The part to invalidate. 22641 * @returns {Array.<String>} - The invalidated parts. 22642 */ 22643 Owl.prototype.invalidate = function(part) { 22644 if ($.type(part) === 'string') { 22645 this._invalidated[part] = true; 22646 this.is('valid') && this.leave('valid'); 22647 } 22648 return $.map(this._invalidated, function(v, i) { return i }); 22649 }; 22650 22651 /** 22652 * Resets the absolute position of the current item. 22653 * @public 22654 * @param {Number} position - The absolute position of the new item. 22655 */ 22656 Owl.prototype.reset = function(position) { 22657 position = this.normalize(position); 22658 22659 if (position === undefined) { 22660 return; 22661 } 22662 22663 this._speed = 0; 22664 this._current = position; 22665 22666 this.suppress([ 'translate', 'translated' ]); 22667 22668 this.animate(this.coordinates(position)); 22669 22670 this.release([ 'translate', 'translated' ]); 22671 }; 22672 22673 /** 22674 * Normalizes an absolute or a relative position of an item. 22675 * @public 22676 * @param {Number} position - The absolute or relative position to normalize. 22677 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 22678 * @returns {Number} - The normalized position. 22679 */ 22680 Owl.prototype.normalize = function(position, relative) { 22681 var n = this._items.length, 22682 m = relative ? 0 : this._clones.length; 22683 22684 if (!$.isNumeric(position) || n < 1) { 22685 position = undefined; 22686 } else if (position < 0 || position >= n + m) { 22687 position = ((position - m / 2) % n + n) % n + m / 2; 22688 } 22689 22690 return position; 22691 }; 22692 22693 /** 22694 * Converts an absolute position of an item into a relative one. 22695 * @public 22696 * @param {Number} position - The absolute position to convert. 22697 * @returns {Number} - The converted position. 22698 */ 22699 Owl.prototype.relative = function(position) { 22700 position -= this._clones.length / 2; 22701 return this.normalize(position, true); 22702 }; 22703 22704 /** 22705 * Gets the maximum position for the current item. 22706 * @public 22707 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 22708 * @returns {Number} 22709 */ 22710 Owl.prototype.maximum = function(relative) { 22711 var settings = this.settings, 22712 maximum = this._coordinates.length, 22713 boundary = Math.abs(this._coordinates[maximum - 1]) - this._width, 22714 i = -1, j; 22715 22716 if (settings.loop) { 22717 maximum = this._clones.length / 2 + this._items.length - 1; 22718 } else if (settings.autoWidth || settings.merge) { 22719 // binary search 22720 while (maximum - i > 1) { 22721 Math.abs(this._coordinates[j = maximum + i >> 1]) < boundary 22722 ? i = j : maximum = j; 22723 } 22724 } else if (settings.center) { 22725 maximum = this._items.length - 1; 22726 } else { 22727 maximum = this._items.length - settings.items; 22728 } 22729 22730 if (relative) { 22731 maximum -= this._clones.length / 2; 22732 } 22733 22734 return Math.max(maximum, 0); 22735 }; 22736 22737 /** 22738 * Gets the minimum position for the current item. 22739 * @public 22740 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 22741 * @returns {Number} 22742 */ 22743 Owl.prototype.minimum = function(relative) { 22744 return relative ? 0 : this._clones.length / 2; 22745 }; 22746 22747 /** 22748 * Gets an item at the specified relative position. 22749 * @public 22750 * @param {Number} [position] - The relative position of the item. 22751 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 22752 */ 22753 Owl.prototype.items = function(position) { 22754 if (position === undefined) { 22755 return this._items.slice(); 22756 } 22757 22758 position = this.normalize(position, true); 22759 return this._items[position]; 22760 }; 22761 22762 /** 22763 * Gets an item at the specified relative position. 22764 * @public 22765 * @param {Number} [position] - The relative position of the item. 22766 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 22767 */ 22768 Owl.prototype.mergers = function(position) { 22769 if (position === undefined) { 22770 return this._mergers.slice(); 22771 } 22772 22773 position = this.normalize(position, true); 22774 return this._mergers[position]; 22775 }; 22776 22777 /** 22778 * Gets the absolute positions of clones for an item. 22779 * @public 22780 * @param {Number} [position] - The relative position of the item. 22781 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 22782 */ 22783 Owl.prototype.clones = function(position) { 22784 var odd = this._clones.length / 2, 22785 even = odd + this._items.length, 22786 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 22787 22788 if (position === undefined) { 22789 return $.map(this._clones, function(v, i) { return map(i) }); 22790 } 22791 22792 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 22793 }; 22794 22795 /** 22796 * Sets the current animation speed. 22797 * @public 22798 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 22799 * @returns {Number} - The current animation speed in milliseconds. 22800 */ 22801 Owl.prototype.speed = function(speed) { 22802 if (speed !== undefined) { 22803 this._speed = speed; 22804 } 22805 22806 return this._speed; 22807 }; 22808 22809 /** 22810 * Gets the coordinate of an item. 22811 * @todo The name of this method is missleanding. 22812 * @public 22813 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 22814 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 22815 */ 22816 Owl.prototype.coordinates = function(position) { 22817 var coordinate = null; 22818 22819 if (position === undefined) { 22820 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 22821 return this.coordinates(index); 22822 }, this)); 22823 } 22824 22825 if (this.settings.center) { 22826 coordinate = this._coordinates[position]; 22827 coordinate += (this.width() - coordinate + (this._coordinates[position - 1] || 0)) / 2 * (this.settings.rtl ? -1 : 1); 22828 } else { 22829 coordinate = this._coordinates[position - 1] || 0; 22830 } 22831 22832 return coordinate; 22833 }; 22834 22835 /** 22836 * Calculates the speed for a translation. 22837 * @protected 22838 * @param {Number} from - The absolute position of the start item. 22839 * @param {Number} to - The absolute position of the target item. 22840 * @param {Number} [factor=undefined] - The time factor in milliseconds. 22841 * @returns {Number} - The time in milliseconds for the translation. 22842 */ 22843 Owl.prototype.duration = function(from, to, factor) { 22844 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 22845 }; 22846 22847 /** 22848 * Slides to the specified item. 22849 * @public 22850 * @param {Number} position - The position of the item. 22851 * @param {Number} [speed] - The time in milliseconds for the transition. 22852 */ 22853 Owl.prototype.to = function(position, speed) { 22854 var current = this.current(), 22855 revert = null, 22856 distance = position - this.relative(current), 22857 direction = (distance > 0) - (distance < 0), 22858 items = this._items.length, 22859 minimum = this.minimum(), 22860 maximum = this.maximum(); 22861 22862 if (this.settings.loop) { 22863 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 22864 distance += direction * -1 * items; 22865 } 22866 22867 position = current + distance; 22868 revert = ((position - minimum) % items + items) % items + minimum; 22869 22870 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 22871 current = revert - distance; 22872 position = revert; 22873 this.reset(current); 22874 } 22875 } else if (this.settings.rewind) { 22876 maximum += 1; 22877 position = (position % maximum + maximum) % maximum; 22878 } else { 22879 position = Math.max(minimum, Math.min(maximum, position)); 22880 } 22881 22882 this.speed(this.duration(current, position, speed)); 22883 this.current(position); 22884 22885 if (this.$element.is(':visible')) { 22886 this.update(); 22887 } 22888 }; 22889 22890 /** 22891 * Slides to the next item. 22892 * @public 22893 * @param {Number}
vendor: 4,086 bytes, lines 22893-23029
22893 [speed] - The time in milliseconds for the transition. 22894 */ 22895 Owl.prototype.next = function(speed) { 22896 speed = speed || false; 22897 this.to(this.relative(this.current()) + 1, speed); 22898 }; 22899 22900 /** 22901 * Slides to the previous item. 22902 * @public 22903 * @param {Number} [speed] - The time in milliseconds for the transition. 22904 */ 22905 Owl.prototype.prev = function(speed) { 22906 speed = speed || false; 22907 this.to(this.relative(this.current()) - 1, speed); 22908 }; 22909 22910 /** 22911 * Handles the end of an animation. 22912 * @protected 22913 * @param {Event} event - The event arguments. 22914 */ 22915 Owl.prototype.onTransitionEnd = function(event) { 22916 22917 // if css2 animation then event object is undefined 22918 if (event !== undefined) { 22919 event.stopPropagation(); 22920 22921 // Catch only owl-stage transitionEnd event 22922 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 22923 return false; 22924 } 22925 } 22926 22927 this.leave('animating'); 22928 this.trigger('translated'); 22929 }; 22930 22931 /** 22932 * Gets viewport width. 22933 * @protected 22934 * @return {Number} - The width in pixel. 22935 */ 22936 Owl.prototype.viewport = function() { 22937 var width; 22938 if (this.options.responsiveBaseElement !== window) { 22939 width = $(this.options.responsiveBaseElement).width(); 22940 } else if (window.innerWidth) { 22941 width = window.innerWidth; 22942 } else if (document.documentElement && document.documentElement.clientWidth) { 22943 width = document.documentElement.clientWidth; 22944 } else { 22945 throw 'Can not detect viewport width.'; 22946 } 22947 22948 return width; 22949 }; 22950 22951 /** 22952 * Replaces the current content. 22953 * @public 22954 * @param {HTMLElement|jQuery|String} content - The new content. 22955 */ 22956 Owl.prototype.replace = function(content) { 22957 this.$stage.empty(); 22958 this._items = []; 22959 22960 if (content) { 22961 content = (content instanceof jQuery) ? content : $(content); 22962 } 22963 22964 if (this.settings.nestedItemSelector) { 22965 content = content.find('.' + this.settings.nestedItemSelector); 22966 } 22967 22968 content.filter(function() { 22969 return this.nodeType === 1; 22970 }).each($.proxy(function(index, item) { 22971 item = this.prepare(item, index); 22972 this.$stage.append(item); 22973 this._items.push(item); 22974 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 22975 }, this)); 22976 22977 this.reset($.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 22978 22979 this.invalidate('items'); 22980 }; 22981 22982 /** 22983 * Adds an item. 22984 * @todo Use `item` instead of `content` for the event arguments. 22985 * @public 22986 * @param {HTMLElement|jQuery|String} content - The item content to add. 22987 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 22988 */ 22989 Owl.prototype.add = function(content, position) { 22990 var current = this.relative(this._current); 22991 22992 position = position === undefined ? this._items.length : this.normalize(position, true); 22993 content = content instanceof jQuery ? content : $(content); 22994 22995 this.trigger('add', { content: content, position: position }); 22996 22997 content = this.prepare(content, this._items[current].index()); 22998 22999 if (this._items.length === 0 || position === this._items.length) { 23000 this._items.length === 0 && this.$stage.append(content); 23001 this._items.length !== 0 && this._items[position - 1].after(content); 23002 this._items.push(content); 23003 this._mergers.push(content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 23004 } else { 23005 this._items[position].before(content); 23006 this._items.splice(position, 0, content); 23007 this._mergers.splice(position, 0, content.find('[data-merge]').andSelf('[data-merge]').attr('data-merge') * 1 || 1); 23008 } 23009 23010 this._items[current] && this.reset(this._items[current].index()); 23011 23012 this.invalidate('items'); 23013 23014 this.trigger('added', { content: content, position: position }); 23015 }; 23016 23017 /** 23018 * Removes an item by its position. 23019 * @todo Use `item` instead of `content` for the event arguments. 23020 * @public 23021 * @param {Number} position - The relative position of the item to remove. 23022 */ 23023 Owl.prototype.remove = function(position) { 23024 position = this.normalize(position, true); 23025 23026 if (position === undefined) { 23027 return; 23028 } 23029
vendor: 40,414 bytes, lines 23030-24596
23030 this.trigger('remove', { content: this._items[position], position: position }); 23031 23032 this._items[position].remove(); 23033 this._items.splice(position, 1); 23034 this._mergers.splice(position, 1); 23035 23036 this.invalidate('items'); 23037 23038 this.trigger('removed', { content: null, position: position }); 23039 }; 23040 23041 /** 23042 * Preloads images with auto width. 23043 * @todo Replace by a more generic approach 23044 * @protected 23045 */ 23046 Owl.prototype.preloadAutoWidthImages = function(images) { 23047 images.each($.proxy(function(i, element) { 23048 this.enter('pre-loading'); 23049 element = $(element); 23050 $(new Image()).one('load', $.proxy(function(e) { 23051 element.attr('src', e.target.src); 23052 element.css('opacity', 1); 23053 this.leave('pre-loading'); 23054 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 23055 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 23056 }, this)); 23057 }; 23058 23059 /** 23060 * Destroys the carousel. 23061 * @public 23062 */ 23063 Owl.prototype.destroy = function() { 23064 23065 this.$element.off('.owl.core'); 23066 this.$stage.off('.owl.core'); 23067 $(document).off('.owl.core'); 23068 23069 if (this.settings.responsive !== false) { 23070 window.clearTimeout(this.resizeTimer); 23071 this.off(window, 'resize', this._handlers.onThrottledResize); 23072 } 23073 23074 for (var i in this._plugins) { 23075 this._plugins[i].destroy(); 23076 } 23077 23078 this.$stage.children('.cloned').remove(); 23079 23080 this.$stage.unwrap(); 23081 this.$stage.children().contents().unwrap(); 23082 this.$stage.children().unwrap(); 23083 23084 this.$element 23085 .removeClass(this.options.refreshClass) 23086 .removeClass(this.options.loadingClass) 23087 .removeClass(this.options.loadedClass) 23088 .removeClass(this.options.rtlClass) 23089 .removeClass(this.options.dragClass) 23090 .removeClass(this.options.grabClass) 23091 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 23092 .removeData('owl.carousel'); 23093 }; 23094 23095 /** 23096 * Operators to calculate right-to-left and left-to-right. 23097 * @protected 23098 * @param {Number} [a] - The left side operand. 23099 * @param {String} [o] - The operator. 23100 * @param {Number} [b] - The right side operand. 23101 */ 23102 Owl.prototype.op = function(a, o, b) { 23103 var rtl = this.settings.rtl; 23104 switch (o) { 23105 case '<': 23106 return rtl ? a > b : a < b; 23107 case '>': 23108 return rtl ? a < b : a > b; 23109 case '>=': 23110 return rtl ? a <= b : a >= b; 23111 case '<=': 23112 return rtl ? a >= b : a <= b; 23113 default: 23114 break; 23115 } 23116 }; 23117 23118 /** 23119 * Attaches to an internal event. 23120 * @protected 23121 * @param {HTMLElement} element - The event source. 23122 * @param {String} event - The event name. 23123 * @param {Function} listener - The event handler to attach. 23124 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 23125 */ 23126 Owl.prototype.on = function(element, event, listener, capture) { 23127 if (element.addEventListener) { 23128 element.addEventListener(event, listener, capture); 23129 } else if (element.attachEvent) { 23130 element.attachEvent('on' + event, listener); 23131 } 23132 }; 23133 23134 /** 23135 * Detaches from an internal event. 23136 * @protected 23137 * @param {HTMLElement} element - The event source. 23138 * @param {String} event - The event name. 23139 * @param {Function} listener - The attached event handler to detach. 23140 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 23141 */ 23142 Owl.prototype.off = function(element, event, listener, capture) { 23143 if (element.removeEventListener) { 23144 element.removeEventListener(event, listener, capture); 23145 } else if (element.detachEvent) { 23146 element.detachEvent('on' + event, listener); 23147 } 23148 }; 23149 23150 /** 23151 * Triggers a public event. 23152 * @todo Remove `status`, `relatedTarget` should be used instead. 23153 * @protected 23154 * @param {String} name - The event name. 23155 * @param {*} [data=null] - The event data. 23156 * @param {String} [namespace=carousel] - The event namespace. 23157 * @param {String} [state] - The state which is associated with the event. 23158 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 23159 * @returns {Event} - The event arguments. 23160 */ 23161 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 23162 var status = { 23163 item: { count: this._items.length, index: this.current() } 23164 }, handler = $.camelCase( 23165 $.grep([ 'on', name, namespace ], function(v) { return v }) 23166 .join('-').toLowerCase() 23167 ), event = $.Event( 23168 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 23169 $.extend({ relatedTarget: this }, status, data) 23170 ); 23171 23172 if (!this._supress[name]) { 23173 $.each(this._plugins, function(name, plugin) { 23174 if (plugin.onTrigger) { 23175 plugin.onTrigger(event); 23176 } 23177 }); 23178 23179 this.register({ type: Owl.Type.Event, name: name }); 23180 this.$element.trigger(event); 23181 23182 if (this.settings && typeof this.settings[handler] === 'function') { 23183 this.settings[handler].call(this, event); 23184 } 23185 } 23186 23187 return event; 23188 }; 23189 23190 /** 23191 * Enters a state. 23192 * @param name - The state name. 23193 */ 23194 Owl.prototype.enter = function(name) { 23195 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 23196 if (this._states.current[name] === undefined) { 23197 this._states.current[name] = 0; 23198 } 23199 23200 this._states.current[name]++; 23201 }, this)); 23202 }; 23203 23204 /** 23205 * Leaves a state. 23206 * @param name - The state name. 23207 */ 23208 Owl.prototype.leave = function(name) { 23209 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 23210 this._states.current[name]--; 23211 }, this)); 23212 }; 23213 23214 /** 23215 * Registers an event or state. 23216 * @public 23217 * @param {Object} object - The event or state to register. 23218 */ 23219 Owl.prototype.register = function(object) { 23220 if (object.type === Owl.Type.Event) { 23221 if (!$.event.special[object.name]) { 23222 $.event.special[object.name] = {}; 23223 } 23224 23225 if (!$.event.special[object.name].owl) { 23226 var _default = $.event.special[object.name]._default; 23227 $.event.special[object.name]._default = function(e) { 23228 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 23229 return _default.apply(this, arguments); 23230 } 23231 return e.namespace && e.namespace.indexOf('owl') > -1; 23232 }; 23233 $.event.special[object.name].owl = true; 23234 } 23235 } else if (object.type === Owl.Type.State) { 23236 if (!this._states.tags[object.name]) { 23237 this._states.tags[object.name] = object.tags; 23238 } else { 23239 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 23240 } 23241 23242 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 23243 return $.inArray(tag, this._states.tags[object.name]) === i; 23244 }, this)); 23245 } 23246 }; 23247 23248 /** 23249 * Suppresses events. 23250 * @protected 23251 * @param {Array.<String>} events - The events to suppress. 23252 */ 23253 Owl.prototype.suppress = function(events) { 23254 $.each(events, $.proxy(function(index, event) { 23255 this._supress[event] = true; 23256 }, this)); 23257 }; 23258 23259 /** 23260 * Releases suppressed events. 23261 * @protected 23262 * @param {Array.<String>} events - The events to release. 23263 */ 23264 Owl.prototype.release = function(events) { 23265 $.each(events, $.proxy(function(index, event) { 23266 delete this._supress[event]; 23267 }, this)); 23268 }; 23269 23270 /** 23271 * Gets unified pointer coordinates from event. 23272 * @todo #261 23273 * @protected 23274 * @param {Event} - The `mousedown` or `touchstart` event. 23275 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 23276 */ 23277 Owl.prototype.pointer = function(event) { 23278 var result = { x: null, y: null }; 23279 23280 event = event.originalEvent || event || window.event; 23281 23282 event = event.touches && event.touches.length ? 23283 event.touches[0] : event.changedTouches && event.changedTouches.length ? 23284 event.changedTouches[0] : event; 23285 23286 if (event.pageX) { 23287 result.x = event.pageX; 23288 result.y = event.pageY; 23289 } else { 23290 result.x = event.clientX; 23291 result.y = event.clientY; 23292 } 23293 23294 return result; 23295 }; 23296 23297 /** 23298 * Gets the difference of two vectors. 23299 * @todo #261 23300 * @protected 23301 * @param {Object} - The first vector. 23302 * @param {Object} - The second vector. 23303 * @returns {Object} - The difference. 23304 */ 23305 Owl.prototype.difference = function(first, second) { 23306 return { 23307 x: first.x - second.x, 23308 y: first.y - second.y 23309 }; 23310 }; 23311 23312 /** 23313 * The jQuery Plugin for the Owl Carousel 23314 * @todo Navigation plugin `next` and `prev` 23315 * @public 23316 */ 23317 $.fn.owlCarousel = function(option) { 23318 var args = Array.prototype.slice.call(arguments, 1); 23319 23320 return this.each(function() { 23321 var $this = $(this), 23322 data = $this.data('owl.carousel'); 23323 23324 if (!data) { 23325 data = new Owl(this, typeof option == 'object' && option); 23326 $this.data('owl.carousel', data); 23327 23328 $.each([ 23329 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 23330 ], function(i, event) { 23331 data.register({ type: Owl.Type.Event, name: event }); 23332 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 23333 if (e.namespace && e.relatedTarget !== this) { 23334 this.suppress([ event ]); 23335 data[event].apply(this, [].slice.call(arguments, 1)); 23336 this.release([ event ]); 23337 } 23338 }, data)); 23339 }); 23340 } 23341 23342 if (typeof option == 'string' && option.charAt(0) !== '_') { 23343 data[option].apply(data, args); 23344 } 23345 }); 23346 }; 23347 23348 /** 23349 * The constructor for the jQuery Plugin 23350 * @public 23351 */ 23352 $.fn.owlCarousel.Constructor = Owl; 23353 23354})(window.Zepto || window.jQuery, window, document); 23355 23356/** 23357 * AutoRefresh Plugin 23358 * @version 2.0.0-beta.3 23359 * @author Artus Kolanowski 23360 * @license The MIT License (MIT) 23361 */ 23362;(function($, window, document, undefined) { 23363 23364 /** 23365 * Creates the auto refresh plugin. 23366 * @class The Auto Refresh Plugin 23367 * @param {Owl} carousel - The Owl Carousel 23368 */ 23369 var AutoRefresh = function(carousel) { 23370 /** 23371 * Reference to the core. 23372 * @protected 23373 * @type {Owl} 23374 */ 23375 this._core = carousel; 23376 23377 /** 23378 * Refresh interval. 23379 * @protected 23380 * @type {number} 23381 */ 23382 this._interval = null; 23383 23384 /** 23385 * Whether the element is currently visible or not. 23386 * @protected 23387 * @type {Boolean} 23388 */ 23389 this._visible = null; 23390 23391 /** 23392 * All event handlers. 23393 * @protected 23394 * @type {Object} 23395 */ 23396 this._handlers = { 23397 'initialized.owl.carousel': $.proxy(function(e) { 23398 if (e.namespace && this._core.settings.autoRefresh) { 23399 this.watch(); 23400 } 23401 }, this) 23402 }; 23403 23404 // set default options 23405 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 23406 23407 // register event handlers 23408 this._core.$element.on(this._handlers); 23409 }; 23410 23411 /** 23412 * Default options. 23413 * @public 23414 */ 23415 AutoRefresh.Defaults = { 23416 autoRefresh: true, 23417 autoRefreshInterval: 500 23418 }; 23419 23420 /** 23421 * Watches the element. 23422 */ 23423 AutoRefresh.prototype.watch = function() { 23424 if (this._interval) { 23425 return; 23426 } 23427 23428 this._visible = this._core.$element.is(':visible'); 23429 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 23430 }; 23431 23432 /** 23433 * Refreshes the element. 23434 */ 23435 AutoRefresh.prototype.refresh = function() { 23436 if (this._core.$element.is(':visible') === this._visible) { 23437 return; 23438 } 23439 23440 this._visible = !this._visible; 23441 23442 this._core.$element.toggleClass('owl-hidden', !this._visible); 23443 23444 this._visible && (this._core.invalidate('width') && this._core.refresh()); 23445 }; 23446 23447 /** 23448 * Destroys the plugin. 23449 */ 23450 AutoRefresh.prototype.destroy = function() { 23451 var handler, property; 23452 23453 window.clearInterval(this._interval); 23454 23455 for (handler in this._handlers) { 23456 this._core.$element.off(handler, this._handlers[handler]); 23457 } 23458 for (property in Object.getOwnPropertyNames(this)) { 23459 typeof this[property] != 'function' && (this[property] = null); 23460 } 23461 }; 23462 23463 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 23464 23465})(window.Zepto || window.jQuery, window, document); 23466 23467/** 23468 * Lazy Plugin 23469 * @version 2.0.0-beta.3 23470 * @author Bartosz Wojciechowski 23471 * @license The MIT License (MIT) 23472 */ 23473;(function($, window, document, undefined) { 23474 23475 /** 23476 * Creates the lazy plugin. 23477 * @class The Lazy Plugin 23478 * @param {Owl} carousel - The Owl Carousel 23479 */ 23480 var Lazy = function(carousel) { 23481 23482 /** 23483 * Reference to the core. 23484 * @protected 23485 * @type {Owl} 23486 */ 23487 this._core = carousel; 23488 23489 /** 23490 * Already loaded items. 23491 * @protected 23492 * @type {Array.<jQuery>} 23493 */ 23494 this._loaded = []; 23495 23496 /** 23497 * Event handlers. 23498 * @protected 23499 * @type {Object} 23500 */ 23501 this._handlers = { 23502 'initialized.owl.carousel change.owl.carousel': $.proxy(function(e) { 23503 if (!e.namespace) { 23504 return; 23505 } 23506 23507 if (!this._core.settings || !this._core.settings.lazyLoad) { 23508 return; 23509 } 23510 23511 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 23512 var settings = this._core.settings, 23513 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 23514 i = ((settings.center && n * -1) || 0), 23515 position = ((e.property && e.property.value) || this._core.current()) + i, 23516 clones = this._core.clones().length, 23517 load = $.proxy(function(i, v) { this.load(v) }, this); 23518 23519 while (i++ < n) { 23520 this.load(clones / 2 + this._core.relative(position)); 23521 clones && $.each(this._core.clones(this._core.relative(position)), load); 23522 position++; 23523 } 23524 } 23525 }, this) 23526 }; 23527 23528 // set the default options 23529 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 23530 23531 // register event handler 23532 this._core.$element.on(this._handlers); 23533 } 23534 23535 /** 23536 * Default options. 23537 * @public 23538 */ 23539 Lazy.Defaults = { 23540 lazyLoad: false 23541 } 23542 23543 /** 23544 * Loads all resources of an item at the specified position. 23545 * @param {Number} position - The absolute position of the item. 23546 * @protected 23547 */ 23548 Lazy.prototype.load = function(position) { 23549 var $item = this._core.$stage.children().eq(position), 23550 $elements = $item && $item.find('.owl-lazy'); 23551 23552 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 23553 return; 23554 } 23555 23556 $elements.each($.proxy(function(index, element) { 23557 var $element = $(element), image, 23558 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 23559 23560 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 23561 23562 if ($element.is('img')) { 23563 $element.one('load.owl.lazy', $.proxy(function() { 23564 $element.css('opacity', 1); 23565 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 23566 }, this)).attr('src', url); 23567 } else { 23568 image = new Image(); 23569 image.onload = $.proxy(function() { 23570 $element.css({ 23571 'background-image': 'url(' + url + ')', 23572 'opacity': '1' 23573 }); 23574 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 23575 }, this); 23576 image.src = url; 23577 } 23578 }, this)); 23579 23580 this._loaded.push($item.get(0)); 23581 } 23582 23583 /** 23584 * Destroys the plugin. 23585 * @public 23586 */ 23587 Lazy.prototype.destroy = function() { 23588 var handler, property; 23589 23590 for (handler in this.handlers) { 23591 this._core.$element.off(handler, this.handlers[handler]); 23592 } 23593 for (property in Object.getOwnPropertyNames(this)) { 23594 typeof this[property] != 'function' && (this[property] = null); 23595 } 23596 }; 23597 23598 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 23599 23600})(window.Zepto || window.jQuery, window, document); 23601 23602/** 23603 * AutoHeight Plugin 23604 * @version 2.0.0-beta.3 23605 * @author Bartosz Wojciechowski 23606 * @license The MIT License (MIT) 23607 */ 23608;(function($, window, document, undefined) { 23609 23610 /** 23611 * Creates the auto height plugin. 23612 * @class The Auto Height Plugin 23613 * @param {Owl} carousel - The Owl Carousel 23614 */ 23615 var AutoHeight = function(carousel) { 23616 /** 23617 * Reference to the core. 23618 * @protected 23619 * @type {Owl} 23620 */ 23621 this._core = carousel; 23622 23623 /** 23624 * All event handlers. 23625 * @protected 23626 * @type {Object} 23627 */ 23628 this._handlers = { 23629 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 23630 if (e.namespace && this._core.settings.autoHeight) { 23631 this.update(); 23632 } 23633 }, this), 23634 'changed.owl.carousel': $.proxy(function(e) { 23635 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 23636 this.update(); 23637 } 23638 }, this), 23639 'loaded.owl.lazy': $.proxy(function(e) { 23640 if (e.namespace && this._core.settings.autoHeight 23641 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 23642 this.update(); 23643 } 23644 }, this) 23645 }; 23646 23647 // set default options 23648 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 23649 23650 // register event handlers 23651 this._core.$element.on(this._handlers); 23652 }; 23653 23654 /** 23655 * Default options. 23656 * @public 23657 */ 23658 AutoHeight.Defaults = { 23659 autoHeight: false, 23660 autoHeightClass: 'owl-height' 23661 }; 23662 23663 /** 23664 * Updates the view. 23665 */ 23666 AutoHeight.prototype.update = function() { 23667 var start = this._core._current, 23668 end = start + this._core.settings.items, 23669 visible = this._core.$stage.children().toArray().slice(start, end); 23670 heights = [], 23671 maxheight = 0; 23672 23673 $.each(visible, function(index, item) { 23674 heights.push($(item).height()); 23675 }); 23676 23677 maxheight = Math.max.apply(null, heights); 23678 23679 this._core.$stage.parent() 23680 .height(maxheight) 23681 .addClass(this._core.settings.autoHeightClass); 23682 }; 23683 23684 AutoHeight.prototype.destroy = function() { 23685 var handler, property; 23686 23687 for (handler in this._handlers) { 23688 this._core.$element.off(handler, this._handlers[handler]); 23689 } 23690 for (property in Object.getOwnPropertyNames(this)) { 23691 typeof this[property] != 'function' && (this[property] = null); 23692 } 23693 }; 23694 23695 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 23696 23697})(window.Zepto || window.jQuery, window, document); 23698 23699/** 23700 * Video Plugin 23701 * @version 2.0.0-beta.3 23702 * @author Bartosz Wojciechowski 23703 * @license The MIT License (MIT) 23704 */ 23705;(function($, window, document, undefined) { 23706 23707 /** 23708 * Creates the video plugin. 23709 * @class The Video Plugin 23710 * @param {Owl} carousel - The Owl Carousel 23711 */ 23712 var Video = function(carousel) { 23713 /** 23714 * Reference to the core. 23715 * @protected 23716 * @type {Owl} 23717 */ 23718 this._core = carousel; 23719 23720 /** 23721 * Cache all video URLs. 23722 * @protected 23723 * @type {Object} 23724 */ 23725 this._videos = {}; 23726 23727 /** 23728 * Current playing item. 23729 * @protected 23730 * @type {jQuery} 23731 */ 23732 this._playing = null; 23733 23734 /** 23735 * All event handlers. 23736 * @todo The cloned content removale is too late 23737 * @protected 23738 * @type {Object} 23739 */ 23740 this._handlers = { 23741 'initialized.owl.carousel': $.proxy(function(e) { 23742 if (e.namespace) { 23743 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 23744 } 23745 }, this), 23746 'resize.owl.carousel': $.proxy(function(e) { 23747 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 23748 e.preventDefault(); 23749 } 23750 }, this), 23751 'refreshed.owl.carousel': $.proxy(function(e) { 23752 if (e.namespace && this._core.is('resizing')) { 23753 this._core.$stage.find('.cloned .owl-video-frame').remove(); 23754 } 23755 }, this), 23756 'changed.owl.carousel': $.proxy(function(e) { 23757 if (e.namespace && e.property.name === 'position' && this._playing) { 23758 this.stop(); 23759 } 23760 }, this), 23761 'prepared.owl.carousel': $.proxy(function(e) { 23762 if (!e.namespace) { 23763 return; 23764 } 23765 23766 var $element = $(e.content).find('.owl-video'); 23767 23768 if ($element.length) { 23769 $element.css('display', 'none'); 23770 this.fetch($element, $(e.content)); 23771 } 23772 }, this) 23773 }; 23774 23775 // set default options 23776 this._core.options = $.extend({}, Video.Defaults, this._core.options); 23777 23778 // register event handlers 23779 this._core.$element.on(this._handlers); 23780 23781 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 23782 this.play(e); 23783 }, this)); 23784 }; 23785 23786 /** 23787 * Default options. 23788 * @public 23789 */ 23790 Video.Defaults = { 23791 video: false, 23792 videoHeight: false, 23793 videoWidth: false 23794 }; 23795 23796 /** 23797 * Gets the video ID and the type (YouTube/Vimeo only). 23798 * @protected 23799 * @param {jQuery} target - The target containing the video data. 23800 * @param {jQuery} item - The item containing the video. 23801 */ 23802 Video.prototype.fetch = function(target, item) { 23803 var type = target.attr('data-vimeo-id') ? 'vimeo' : 'youtube', 23804 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id'), 23805 width = target.attr('data-width') || this._core.settings.videoWidth, 23806 height = target.attr('data-height') || this._core.settings.videoHeight, 23807 url = target.attr('href'); 23808 23809 if (url) { 23810 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+)?/); 23811 23812 if (id[3].indexOf('youtu') > -1) { 23813 type = 'youtube'; 23814 } else if (id[3].indexOf('vimeo') > -1) { 23815 type = 'vimeo'; 23816 } else { 23817 throw new Error('Video URL not supported.'); 23818 } 23819 id = id[6]; 23820 } else { 23821 throw new Error('Missing video URL.'); 23822 } 23823 23824 this._videos[url] = { 23825 type: type, 23826 id: id, 23827 width: width, 23828 height: height 23829 }; 23830 23831 item.attr('data-video', url); 23832 23833 this.thumbnail(target, this._videos[url]); 23834 }; 23835 23836 /** 23837 * Creates video thumbnail. 23838 * @protected 23839 * @param {jQuery} target - The target containing the video data. 23840 * @param {Object} info - The video info object. 23841 * @see `fetch` 23842 */ 23843 Video.prototype.thumbnail = function(target, video) { 23844 var tnLink, 23845 icon, 23846 path, 23847 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 23848 customTn = target.find('img'), 23849 srcType = 'src', 23850 lazyClass = '', 23851 settings = this._core.settings, 23852 create = function(path) { 23853 icon = '<div class="owl-video-play-icon"></div>'; 23854 23855 if (settings.lazyLoad) { 23856 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 23857 } else { 23858 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 23859 } 23860 target.after(tnLink); 23861 target.after(icon); 23862 }; 23863 23864 // wrap video content into owl-video-wrapper div 23865 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 23866 23867 if (this._core.settings.lazyLoad) { 23868 srcType = 'data-src'; 23869 lazyClass = 'owl-lazy'; 23870 } 23871 23872 // custom thumbnail 23873 if (customTn.length) { 23874 create(customTn.attr(srcType)); 23875 customTn.remove(); 23876 return false; 23877 } 23878 23879 if (video.type === 'youtube') { 23880 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 23881 create(path); 23882 } else if (video.type === 'vimeo') { 23883 $.ajax({ 23884 type: 'GET', 23885 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 23886 jsonp: 'callback', 23887 dataType: 'jsonp', 23888 success: function(data) { 23889 path = data[0].thumbnail_large; 23890 create(path); 23891 } 23892 }); 23893 } 23894 }; 23895 23896 /** 23897 * Stops the current video. 23898 * @public 23899 */ 23900 Video.prototype.stop = function() { 23901 this._core.trigger('stop', null, 'video'); 23902 this._playing.find('.owl-video-frame').remove(); 23903 this._playing.removeClass('owl-video-playing'); 23904 this._playing = null; 23905 this._core.leave('playing'); 23906 this._core.trigger('stopped', null, 'video'); 23907 }; 23908 23909 /** 23910 * Starts the current video. 23911 * @public 23912 * @param {Event} event - The event arguments. 23913 */ 23914 Video.prototype.play = function(event) { 23915 var target = $(event.target), 23916 item = target.closest('.' + this._core.settings.itemClass), 23917 video = this._videos[item.attr('data-video')], 23918 width = video.width || '100%', 23919 height = video.height || this._core.$stage.height(), 23920 html; 23921 23922 if (this._playing) { 23923 return; 23924 } 23925 23926 this._core.enter('playing'); 23927 this._core.trigger('play', null, 'video'); 23928 23929 item = this._core.items(this._core.relative(item.index())); 23930 23931 this._core.reset(item.index()); 23932 23933 if (video.type === 'youtube') { 23934 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 23935 video.id + '?autoplay=1&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 23936 } else if (video.type === 'vimeo') { 23937 html = '<iframe src="//player.vimeo.com/video/' + video.id + 23938 '?autoplay=1" width="' + width + '" height="' + height + 23939 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 23940 } 23941 23942 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 23943 23944 this._playing = item.addClass('owl-video-playing'); 23945 }; 23946 23947 /** 23948 * Checks whether an video is currently in full screen mode or not. 23949 * @todo Bad style because looks like a readonly method but changes members. 23950 * @protected 23951 * @returns {Boolean} 23952 */ 23953 Video.prototype.isInFullScreen = function() { 23954 var element = document.fullscreenElement || document.mozFullScreenElement || 23955 document.webkitFullscreenElement; 23956 23957 return element && $(element).parent().hasClass('owl-video-frame'); 23958 }; 23959 23960 /** 23961 * Destroys the plugin. 23962 */ 23963 Video.prototype.destroy = function() { 23964 var handler, property; 23965 23966 this._core.$element.off('click.owl.video'); 23967 23968 for (handler in this._handlers) { 23969 this._core.$element.off(handler, this._handlers[handler]); 23970 } 23971 for (property in Object.getOwnPropertyNames(this)) { 23972 typeof this[property] != 'function' && (this[property] = null); 23973 } 23974 }; 23975 23976 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 23977 23978})(window.Zepto || window.jQuery, window, document); 23979 23980/** 23981 * Animate Plugin 23982 * @version 2.0.0-beta.3 23983 * @author Bartosz Wojciechowski 23984 * @license The MIT License (MIT) 23985 */ 23986;(function($, window, document, undefined) { 23987 23988 /** 23989 * Creates the animate plugin. 23990 * @class The Navigation Plugin 23991 * @param {Owl} scope - The Owl Carousel 23992 */ 23993 var Animate = function(scope) { 23994 this.core = scope; 23995 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 23996 this.swapping = true; 23997 this.previous = undefined; 23998 this.next = undefined; 23999 24000 this.handlers = { 24001 'change.owl.carousel': $.proxy(function(e) { 24002 if (e.namespace && e.property.name == 'position') { 24003 this.previous = this.core.current(); 24004 this.next = e.property.value; 24005 } 24006 }, this), 24007 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 24008 if (e.namespace) { 24009 this.swapping = e.type == 'translated'; 24010 } 24011 }, this), 24012 'translate.owl.carousel': $.proxy(function(e) { 24013 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 24014 this.swap(); 24015 } 24016 }, this) 24017 }; 24018 24019 this.core.$element.on(this.handlers); 24020 }; 24021 24022 /** 24023 * Default options. 24024 * @public 24025 */ 24026 Animate.Defaults = { 24027 animateOut: false, 24028 animateIn: false 24029 }; 24030 24031 /** 24032 * Toggles the animation classes whenever an translations starts. 24033 * @protected 24034 * @returns {Boolean|undefined} 24035 */ 24036 Animate.prototype.swap = function() { 24037 24038 if (this.core.settings.items !== 1) { 24039 return; 24040 } 24041 24042 if (!$.support.animation || !$.support.transition) { 24043 return; 24044 } 24045 24046 this.core.speed(0); 24047 24048 var left, 24049 clear = $.proxy(this.clear, this), 24050 previous = this.core.$stage.children().eq(this.previous), 24051 next = this.core.$stage.children().eq(this.next), 24052 incoming = this.core.settings.animateIn, 24053 outgoing = this.core.settings.animateOut; 24054 24055 if (this.core.current() === this.previous) { 24056 return; 24057 } 24058 24059 if (outgoing) { 24060 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 24061 previous.css( { 'left': left + 'px' } ) 24062 .addClass('animated owl-animated-out') 24063 .addClass(outgoing) 24064 .on($.support.animation.end, clear); 24065 } 24066 24067 if (incoming) { 24068 next.addClass('animated owl-animated-in') 24069 .addClass(incoming) 24070 .on($.support.animation.end, clear); 24071 } 24072 }; 24073 24074 Animate.prototype.clear = function(e) { 24075 if ($(e.target).hasClass('animated')) { 24076 $(e.target).css( { 'left': '' } ) 24077 .removeClass('animated owl-animated-out owl-animated-in') 24078 .removeClass(this.core.settings.animateIn) 24079 .removeClass(this.core.settings.animateOut); 24080 this.core.onTransitionEnd(); 24081 } 24082 }; 24083 24084 /** 24085 * Destroys the plugin. 24086 * @public 24087 */ 24088 Animate.prototype.destroy = function() { 24089 var handler, property; 24090 24091 for (handler in this.handlers) { 24092 this.core.$element.off(handler, this.handlers[handler]); 24093 } 24094 for (property in Object.getOwnPropertyNames(this)) { 24095 typeof this[property] != 'function' && (this[property] = null); 24096 } 24097 }; 24098 24099 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 24100 24101})(window.Zepto || window.jQuery, window, document); 24102 24103/** 24104 * Autoplay Plugin 24105 * @version 2.0.0-beta.3 24106 * @author Bartosz Wojciechowski 24107 * @author Artus Kolanowski 24108 * @license The MIT License (MIT) 24109 */ 24110;(function($, window, document, undefined) { 24111 24112 /** 24113 * Creates the autoplay plugin. 24114 * @class The Autoplay Plugin 24115 * @param {Owl} scope - The Owl Carousel 24116 */ 24117 var Autoplay = function(carousel) { 24118 /** 24119 * Reference to the core. 24120 * @protected 24121 * @type {Owl} 24122 */ 24123 this._core = carousel; 24124 24125 /** 24126 * The autoplay interval. 24127 * @type {Number} 24128 */ 24129 this._interval = null; 24130 24131 /** 24132 * Indicates whenever the autoplay is paused. 24133 * @type {Boolean} 24134 */ 24135 this._paused = false; 24136 24137 /** 24138 * All event handlers. 24139 * @protected 24140 * @type {Object} 24141 */ 24142 this._handlers = { 24143 'changed.owl.carousel': $.proxy(function(e) { 24144 if (e.namespace && e.property.name === 'settings') { 24145 if (this._core.settings.autoplay) { 24146 this.play(); 24147 } else { 24148 this.stop(); 24149 } 24150 } 24151 }, this), 24152 'initialized.owl.carousel': $.proxy(function(e) { 24153 if (e.namespace && this._core.settings.autoplay) { 24154 this.play(); 24155 } 24156 }, this), 24157 'play.owl.autoplay': $.proxy(function(e, t, s) { 24158 if (e.namespace) { 24159 this.play(t, s); 24160 } 24161 }, this), 24162 'stop.owl.autoplay': $.proxy(function(e) { 24163 if (e.namespace) { 24164 this.stop(); 24165 } 24166 }, this), 24167 'mouseover.owl.autoplay': $.proxy(function() { 24168 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 24169 this.pause(); 24170 } 24171 }, this), 24172 'mouseleave.owl.autoplay': $.proxy(function() { 24173 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 24174 this.play(); 24175 } 24176 }, this) 24177 }; 24178 24179 // register event handlers 24180 this._core.$element.on(this._handlers); 24181 24182 // set default options 24183 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 24184 }; 24185 24186 /** 24187 * Default options. 24188 * @public 24189 */ 24190 Autoplay.Defaults = { 24191 autoplay: false, 24192 autoplayTimeout: 5000, 24193 autoplayHoverPause: false, 24194 autoplaySpeed: false 24195 }; 24196 24197 /** 24198 * Starts the autoplay. 24199 * @public 24200 * @param {Number} [timeout] - The interval before the next animation starts. 24201 * @param {Number} [speed] - The animation speed for the animations. 24202 */ 24203 Autoplay.prototype.play = function(timeout, speed) { 24204 this._paused = false; 24205 24206 if (this._core.is('rotating')) { 24207 return; 24208 } 24209 24210 this._core.enter('rotating'); 24211 24212 this._interval = window.setInterval($.proxy(function() { 24213 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 24214 return; 24215 } 24216 this._core.next(speed || this._core.settings.autoplaySpeed); 24217 }, this), timeout || this._core.settings.autoplayTimeout); 24218 }; 24219 24220 /** 24221 * Stops the autoplay. 24222 * @public 24223 */ 24224 Autoplay.prototype.stop = function() { 24225 if (!this._core.is('rotating')) { 24226 return; 24227 } 24228 24229 window.clearInterval(this._interval); 24230 this._core.leave('rotating'); 24231 }; 24232 24233 /** 24234 * Stops the autoplay. 24235 * @public 24236 */ 24237 Autoplay.prototype.pause = function() { 24238 if (!this._core.is('rotating')) { 24239 return; 24240 } 24241 24242 this._paused = true; 24243 }; 24244 24245 /** 24246 * Destroys the plugin. 24247 */ 24248 Autoplay.prototype.destroy = function() { 24249 var handler, property; 24250 24251 this.stop(); 24252 24253 for (handler in this._handlers) { 24254 this._core.$element.off(handler, this._handlers[handler]); 24255 } 24256 for (property in Object.getOwnPropertyNames(this)) { 24257 typeof this[property] != 'function' && (this[property] = null); 24258 } 24259 }; 24260 24261 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 24262 24263})(window.Zepto || window.jQuery, window, document); 24264 24265/** 24266 * Navigation 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 'use strict'; 24273 24274 /** 24275 * Creates the navigation plugin. 24276 * @class The Navigation Plugin 24277 * @param {Owl} carousel - The Owl Carousel. 24278 */ 24279 var Navigation = function(carousel) { 24280 /** 24281 * Reference to the core. 24282 * @protected 24283 * @type {Owl} 24284 */ 24285 this._core = carousel; 24286 24287 /** 24288 * Indicates whether the plugin is initialized or not. 24289 * @protected 24290 * @type {Boolean} 24291 */ 24292 this._initialized = false; 24293 24294 /** 24295 * The current paging indexes. 24296 * @protected 24297 * @type {Array} 24298 */ 24299 this._pages = []; 24300 24301 /** 24302 * All DOM elements of the user interface. 24303 * @protected 24304 * @type {Object} 24305 */ 24306 this._controls = {}; 24307 24308 /** 24309 * Markup for an indicator. 24310 * @protected 24311 * @type {Array.<String>} 24312 */ 24313 this._templates = []; 24314 24315 /** 24316 * The carousel element. 24317 * @type {jQuery} 24318 */ 24319 this.$element = this._core.$element; 24320 24321 /** 24322 * Overridden methods of the carousel. 24323 * @protected 24324 * @type {Object} 24325 */ 24326 this._overrides = { 24327 next: this._core.next, 24328 prev: this._core.prev, 24329 to: this._core.to 24330 }; 24331 24332 /** 24333 * All event handlers. 24334 * @protected 24335 * @type {Object} 24336 */ 24337 this._handlers = { 24338 'prepared.owl.carousel': $.proxy(function(e) { 24339 if (e.namespace && this._core.settings.dotsData) { 24340 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 24341 $(e.content).find('[data-dot]').andSelf('[data-dot]').attr('data-dot') + '</div>'); 24342 } 24343 }, this), 24344 'added.owl.carousel': $.proxy(function(e) { 24345 if (e.namespace && this._core.settings.dotsData) { 24346 this._templates.splice(e.position, 0, this._templates.pop()); 24347 } 24348 }, this), 24349 'remove.owl.carousel': $.proxy(function(e) { 24350 if (e.namespace && this._core.settings.dotsData) { 24351 this._templates.splice(e.position, 1); 24352 } 24353 }, this), 24354 'changed.owl.carousel': $.proxy(function(e) { 24355 if (e.namespace && e.property.name == 'position') { 24356 this.draw(); 24357 } 24358 }, this), 24359 'initialized.owl.carousel': $.proxy(function(e) { 24360 if (e.namespace && !this._initialized) { 24361 this._core.trigger('initialize', null, 'navigation'); 24362 this.initialize(); 24363 this.update(); 24364 this.draw(); 24365 this._initialized = true; 24366 this._core.trigger('initialized', null, 'navigation'); 24367 } 24368 }, this), 24369 'refreshed.owl.carousel': $.proxy(function(e) { 24370 if (e.namespace && this._initialized) { 24371 this._core.trigger('refresh', null, 'navigation'); 24372 this.update(); 24373 this.draw(); 24374 this._core.trigger('refreshed', null, 'navigation'); 24375 } 24376 }, this) 24377 }; 24378 24379 // set default options 24380 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 24381 24382 // register event handlers 24383 this.$element.on(this._handlers); 24384 }; 24385 24386 /** 24387 * Default options. 24388 * @public 24389 * @todo Rename `slideBy` to `navBy` 24390 */ 24391 Navigation.Defaults = { 24392 nav: false, 24393 navText: [ 'prev', 'next' ], 24394 navSpeed: false, 24395 navElement: 'div', 24396 navContainer: false, 24397 navContainerClass: 'owl-nav', 24398 navClass: [ 'owl-prev', 'owl-next' ], 24399 slideBy: 1, 24400 dotClass: 'owl-dot', 24401 dotsClass: 'owl-dots', 24402 dots: true, 24403 dotsEach: false, 24404 dotsData: false, 24405 dotsSpeed: false, 24406 dotsContainer: false 24407 }; 24408 24409 /** 24410 * Initializes the layout of the plugin and extends the carousel. 24411 * @protected 24412 */ 24413 Navigation.prototype.initialize = function() { 24414 var override, 24415 settings = this._core.settings; 24416 24417 // create DOM structure for relative navigation 24418 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 24419 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 24420 24421 this._controls.$previous = $('<' + settings.navElement + '>') 24422 .addClass(settings.navClass[0]) 24423 .html(settings.navText[0]) 24424 .prependTo(this._controls.$relative) 24425 .on('click', $.proxy(function(e) { 24426 this.prev(settings.navSpeed); 24427 }, this)); 24428 this._controls.$next = $('<' + settings.navElement + '>') 24429 .addClass(settings.navClass[1]) 24430 .html(settings.navText[1]) 24431 .appendTo(this._controls.$relative) 24432 .on('click', $.proxy(function(e) { 24433 this.next(settings.navSpeed); 24434 }, this)); 24435 24436 // create DOM structure for absolute navigation 24437 if (!settings.dotsData) { 24438 this._templates = [ $('<div>') 24439 .addClass(settings.dotClass) 24440 .append($('<span>')) 24441 .prop('outerHTML') ]; 24442 } 24443 24444 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 24445 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 24446 24447 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 24448 var index = $(e.target).parent().is(this._controls.$absolute) 24449 ? $(e.target).index() : $(e.target).parent().index(); 24450 24451 e.preventDefault(); 24452 24453 this.to(index, settings.dotsSpeed); 24454 }, this)); 24455 24456 // override public methods of the carousel 24457 for (override in this._overrides) { 24458 this._core[override] = $.proxy(this[override], this); 24459 } 24460 }; 24461 24462 /** 24463 * Destroys the plugin. 24464 * @protected 24465 */ 24466 Navigation.prototype.destroy = function() { 24467 var handler, control, property, override; 24468 24469 for (handler in this._handlers) { 24470 this.$element.off(handler, this._handlers[handler]); 24471 } 24472 for (control in this._controls) { 24473 this._controls[control].remove(); 24474 } 24475 for (override in this.overides) { 24476 this._core[override] = this._overrides[override]; 24477 } 24478 for (property in Object.getOwnPropertyNames(this)) { 24479 typeof this[property] != 'function' && (this[property] = null); 24480 } 24481 }; 24482 24483 /** 24484 * Updates the internal state. 24485 * @protected 24486 */ 24487 Navigation.prototype.update = function() { 24488 var i, j, k, 24489 lower = this._core.clones().length / 2, 24490 upper = lower + this._core.items().length, 24491 maximum = this._core.maximum(true), 24492 settings = this._core.settings, 24493 size = settings.center || settings.autoWidth || settings.dotsData 24494 ? 1 : settings.dotsEach || settings.items; 24495 24496 if (settings.slideBy !== 'page') { 24497 settings.slideBy = Math.min(settings.slideBy, settings.items); 24498 } 24499 24500 if (settings.dots || settings.slideBy == 'page') { 24501 this._pages = []; 24502 24503 for (i = lower, j = 0, k = 0; i < upper; i++) { 24504 if (j >= size || j === 0) { 24505 this._pages.push({ 24506 start: Math.min(maximum, i - lower), 24507 end: i - lower + size - 1 24508 }); 24509 if (Math.min(maximum, i - lower) === maximum) { 24510 break; 24511 } 24512 j = 0, ++k; 24513 } 24514 j += this._core.mergers(this._core.relative(i)); 24515 } 24516 } 24517 }; 24518 24519 /** 24520 * Draws the user interface. 24521 * @todo The option `dotsData` wont work. 24522 * @protected 24523 */ 24524 Navigation.prototype.draw = function() { 24525 var difference, 24526 settings = this._core.settings, 24527 disabled = this._core.items().length <= settings.items, 24528 index = this._core.relative(this._core.current()), 24529 loop = settings.loop || settings.rewind; 24530 24531 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 24532 24533 if (settings.nav) { 24534 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 24535 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 24536 } 24537 24538 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 24539 24540 if (settings.dots) { 24541 difference = this._pages.length - this._controls.$absolute.children().length; 24542 24543 if (settings.dotsData && difference !== 0) { 24544 this._controls.$absolute.html(this._templates.join('')); 24545 } else if (difference > 0) { 24546 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 24547 } else if (difference < 0) { 24548 this._controls.$absolute.children().slice(difference).remove(); 24549 } 24550 24551 this._controls.$absolute.find('.active').removeClass('active'); 24552 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 24553 } 24554 }; 24555 24556 /** 24557 * Extends event data. 24558 * @protected 24559 * @param {Event} event - The event object which gets thrown. 24560 */ 24561 Navigation.prototype.onTrigger = function(event) { 24562 var settings = this._core.settings; 24563 24564 event.page = { 24565 index: $.inArray(this.current(), this._pages), 24566 count: this._pages.length, 24567 size: settings && (settings.center || settings.autoWidth || settings.dotsData 24568 ? 1 : settings.dotsEach || settings.items) 24569 }; 24570 }; 24571 24572 /** 24573 * Gets the current page position of the carousel. 24574 * @protected 24575 * @returns {Number} 24576 */ 24577 Navigation.prototype.current = function() { 24578 var current = this._core.relative(this._core.current()); 24579 return $.grep(this._pages, $.proxy(function(page, index) { 24580 return page.start <= current && page.end >= current; 24581 }, this)).pop(); 24582 }; 24583 24584 /** 24585 * Gets the current succesor/predecessor position. 24586 * @protected 24587 * @returns {Number} 24588 */ 24589 Navigation.prototype.getPosition = function(successor) { 24590 var position, length, 24591 settings = this._core.settings; 24592 24593 if (settings.slideBy == 'page') { 24594 position = $.inArray(this.current(), this._pages); 24595 length = this._pages.length; 24596 successor ? ++position : --position;
vendor: 5,678 bytes, lines 24597-24821
24597 position = this._pages[((position % length) + length) % length].start; 24598 } else { 24599 position = this._core.relative(this._core.current()); 24600 length = this._core.items().length; 24601 successor ? position += settings.slideBy : position -= settings.slideBy; 24602 } 24603 24604 return position; 24605 }; 24606 24607 /** 24608 * Slides to the next item or page. 24609 * @public 24610 * @param {Number} [speed=false] - The time in milliseconds for the transition. 24611 */ 24612 Navigation.prototype.next = function(speed) { 24613 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 24614 }; 24615 24616 /** 24617 * Slides to the previous item or page. 24618 * @public 24619 * @param {Number} [speed=false] - The time in milliseconds for the transition. 24620 */ 24621 Navigation.prototype.prev = function(speed) { 24622 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 24623 }; 24624 24625 /** 24626 * Slides to the specified item or page. 24627 * @public 24628 * @param {Number} position - The position of the item or page. 24629 * @param {Number} [speed] - The time in milliseconds for the transition. 24630 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 24631 */ 24632 Navigation.prototype.to = function(position, speed, standard) { 24633 var length; 24634 24635 if (!standard) { 24636 length = this._pages.length; 24637 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 24638 } else { 24639 $.proxy(this._overrides.to, this._core)(position, speed); 24640 } 24641 }; 24642 24643 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 24644 24645})(window.Zepto || window.jQuery, window, document); 24646 24647/** 24648 * Hash Plugin 24649 * @version 2.0.0-beta.3 24650 * @author Artus Kolanowski 24651 * @license The MIT License (MIT) 24652 */ 24653;(function($, window, document, undefined) { 24654 'use strict'; 24655 24656 /** 24657 * Creates the hash plugin. 24658 * @class The Hash Plugin 24659 * @param {Owl} carousel - The Owl Carousel 24660 */ 24661 var Hash = function(carousel) { 24662 /** 24663 * Reference to the core. 24664 * @protected 24665 * @type {Owl} 24666 */ 24667 this._core = carousel; 24668 24669 /** 24670 * Hash index for the items. 24671 * @protected 24672 * @type {Object} 24673 */ 24674 this._hashes = {}; 24675 24676 /** 24677 * The carousel element. 24678 * @type {jQuery} 24679 */ 24680 this.$element = this._core.$element; 24681 24682 /** 24683 * All event handlers. 24684 * @protected 24685 * @type {Object} 24686 */ 24687 this._handlers = { 24688 /*'initialized.owl.carousel': $.proxy(function(e) { 24689 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 24690 $(window).trigger('hashchange.owl.navigation'); 24691 } 24692 }, this),*/ 24693 'prepared.owl.carousel': $.proxy(function(e) { 24694 if (e.namespace) { 24695 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 24696 24697 if (!hash) { 24698 return; 24699 } 24700 24701 this._hashes[hash] = e.content; 24702 } 24703 }, this), 24704 'changed.owl.carousel': $.proxy(function(e) { 24705 if (e.namespace && e.property.name === 'position') { 24706 var current = this._core.items(this._core.relative(this._core.current())), 24707 hash = $.map(this._hashes, function(item, hash) { 24708 return item === current ? hash : null; 24709 }).join(); 24710 24711 if (!hash || window.location.hash.slice(1) === hash) { 24712 return; 24713 } 24714 24715 window.location.hash = hash; 24716 } 24717 }, this) 24718 }; 24719 24720 // set default options 24721 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 24722 24723 // register the event handlers 24724 this.$element.on(this._handlers); 24725 24726 // register event listener for hash navigation 24727 /*$(window).on('hashchange.owl.navigation', $.proxy(function(e) { 24728 var hash = window.location.hash.substring(1), 24729 items = this._core.$stage.children(), 24730 position = this._hashes[hash] && items.index(this._hashes[hash]); 24731 24732 if (position === undefined || position === this._core.current()) { 24733 return; 24734 } 24735 24736 this._core.to(this._core.relative(position), false, true); 24737 }, this));*/ 24738 }; 24739 24740 /** 24741 * Default options. 24742 * @public 24743 */ 24744 Hash.Defaults = { 24745 URLhashListener: false 24746 }; 24747 24748 /** 24749 * Destroys the plugin. 24750 * @public 24751 */ 24752 Hash.prototype.destroy = function() { 24753 var handler, property; 24754 24755 $(window).off('hashchange.owl.navigation'); 24756 24757 for (handler in this._handlers) { 24758 this._core.$element.off(handler, this._handlers[handler]); 24759 } 24760 for (property in Object.getOwnPropertyNames(this)) { 24761 typeof this[property] != 'function' && (this[property] = null); 24762 } 24763 }; 24764 24765 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 24766 24767})(window.Zepto || window.jQuery, window, document); 24768 24769/** 24770 * Support Plugin 24771 * 24772 * @version 2.0.0-beta.3 24773 * @author Vivid Planet Software GmbH 24774 * @author Artus Kolanowski 24775 * @license The MIT License (MIT) 24776 */ 24777;(function($, window, document, undefined) { 24778 24779 var style = $('<support>').get(0).style, 24780 prefixes = 'Webkit Moz O ms'.split(' '), 24781 events = { 24782 transition: { 24783 end: { 24784 WebkitTransition: 'webkitTransitionEnd', 24785 MozTransition: 'transitionend', 24786 OTransition: 'oTransitionEnd', 24787 transition: 'transitionend' 24788 } 24789 }, 24790 animation: { 24791 end: { 24792 WebkitAnimation: 'webkitAnimationEnd', 24793 MozAnimation: 'animationend', 24794 OAnimation: 'oAnimationEnd', 24795 animation: 'animationend' 24796 } 24797 } 24798 }, 24799 tests = { 24800 csstransforms: function() { 24801 return !!test('transform'); 24802 }, 24803 csstransforms3d: function() { 24804 return !!test('perspective'); 24805 }, 24806 csstransitions: function() { 24807 return !!test('transition'); 24808 }, 24809 cssanimations: function() { 24810 return !!test('animation'); 24811 } 24812 }; 24813 24814 function test(property, prefixed) { 24815 var result = false, 24816 upper = property.charAt(0).toUpperCase() + property.slice(1); 24817 24818 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 24819 if (style[property] !== undefined) { 24820 result = prefixed ? property : true; 24821 return false;
24822 } 24823 }); 24824 24825 return result; 24826 } 24827 24828 function prefixed(property) { 24829 return test(property, true); 24830 } 24831 24832 if (tests.csstransitions()) { 24833 /* jshint -W053 */ 24834 $.support.transition = new String(prefixed('transition')) 24835 $.support.transition.end = events.transition.end[ $.support.transition ]; 24836 } 24837 24838 if (tests.cssanimations()) { 24839 /* jshint -W053 */ 24840 $.support.animation = new String(prefixed('animation')) 24841 $.support.animation.end = events.animation.end[ $.support.animation ]; 24842 } 24843 24844 if (tests.csstransforms()) { 24845 /* jshint -W053 */ 24846 $.support.transform = new String(prefixed('transform')); 24847 $.support.transform3d = tests.csstransforms3d(); 24848 } 24849 24850})(window.Zepto || window.jQuery, window, document); 24851 24852(function(window, document, undefined) { 24853 24854 /** 24855 * Find the absolute position of an element 24856 */ 24857 var absPos = function(element) { 24858 var offsetLeft, offsetTop; 24859 offsetLeft = offsetTop = 0; 24860 if (element.offsetParent) { 24861 do { 24862 offsetLeft += element.offsetLeft; 24863 offsetTop += element.offsetTop; 24864 } while (element = element.offsetParent); 24865 } 24866 return [offsetLeft, offsetTop]; 24867 }; 24868 24869 /** 24870 * @constructor Progress Circle class 24871 * @param params.canvas Canvas on which the circles will be drawn. 24872 * @param params.minRadius Inner radius of the innermost circle, in px. 24873 * @param params.arcWidth Width of each circle(to be more accurate, ring). 24874 * @param params.gapWidth Space between each circle. 24875 * @param params.centerX X coordinate of the center of circles. 24876 * @param params.centerY Y coordinate of the center of circles. 24877 * @param params.infoLineBaseAngle Base angle of the info line. 24878 * @param params.infoLineAngleInterval Angles between the info lines. 24879 */ 24880 var ProgressCircle = function(params) { 24881 this.canvas = params.canvas; 24882 this.minRadius = params.minRadius || 15; 24883 this.arcWidth = params.arcWidth || 5; 24884 this.gapWidth = params.gapWidth || 3; 24885 this.centerX = params.centerX || this.canvas.width / 2; 24886 this.centerY = params.centerY || this.canvas.height / 2;
24887 this.infoLineLength = params.infoLineLength || 60; 24888 this.horizLineLength = params.horizLineLength || 10; 24889 this.infoLineAngleInterval = params.infoLineAngleInterval || Math.PI / 8; 24890 this.infoLineBaseAngle = params.infoLineBaseAngle || Math.PI / 6; 24891 24892 this.context = this.canvas.getContext('2d'); 24893 24894 this.width = this.canvas.width; 24895 this.height = this.canvas.height; 24896 24897 this.circles = []; 24898 this.runningCount = 0; 24899 }; 24900 24901 ProgressCircle.prototype = { 24902 constructor: ProgressCircle, 24903 24904 /** 24905 * @method Adds an progress monitor entry. 24906 * @param params.fillColor Color to fill in the circle. 24907 * @param params.outlineColor Color to outline the circle. 24908 * @param params.progressListener Callback function to fetch the progress. 24909 * @param params.infoListener Callback function to fetch the info. 24910 * @returns this 24911 */ 24912 addEntry: function(params) { 24913 this.circles.push(new Circle({ 24914 canvas: this.canvas, 24915 context: this.context, 24916 centerX: this.centerX, 24917 centerY: this.centerY, 24918 innerRadius: this.minRadius + this.circles.length * 24919 (this.gapWidth + this.arcWidth), 24920 arcWidth: this.arcWidth,
24921 infoLineLength: this.infoLineLength, 24922 horizLineLength: this.horizLineLength, 24923 24924 id: this.circles.length, 24925 fillColor: params.fillColor, 24926 outlineColor: params.outlineColor, 24927 progressListener: params.progressListener, 24928 infoListener: params.infoListener, 24929 infoLineAngle: this.infoLineBaseAngle + 24930 this.circles.length * this.infoLineAngleInterval, 24931 })); 24932 24933 return this; 24934 }, 24935 24936 /** 24937 * @method Starts the monitor and updates with the given interval. 24938 * @param interval Interval between updates, in millisecond. 24939 * @returns this 24940 */ 24941 start: function(interval) { 24942 var self = this; 24943 this.timer = setInterval(function() { 24944 self._update(); 24945 }, interval || 33); 24946 24947 return this; 24948 }, 24949 24950 /** 24951 * @method Stop the animation. 24952 */ 24953 stop: function() { 24954 clearTimeout(this.timer); 24955 }, 24956 24957 /** 24958 * @private 24959 * @method Call update on each circle and redraw them. 24960 * @returns this 24961 */ 24962 _update: function() { 24963 this._clear(); 24964 this.circles.forEach(function(circle, idx, array) { 24965 circle.update(); 24966 }); 24967 24968 return this; 24969 }, 24970 24971 /** 24972 * @private 24973 * @method Clear the canvas. 24974 * @returns this 24975 */ 24976 _clear: function() { 24977 this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); 24978 24979 return this; 24980 }, 24981 24982 }; 24983 24984 /** 24985 * @private 24986 * @class Individual progress circle. 24987 * @param params.canvas Canvas on which the circle will be drawn. 24988 * @param params.context Context of the canvas. 24989 * @param params.innerRadius Inner radius of the circle, in px. 24990 * @param params.arcWidth Width of each arc(circle). 24991 * @param params.gapWidth Distance between each arc. 24992 * @param params.centerX X coordinate of the center of circles. 24993 * @param params.centerY Y coordinate of the center of circles. 24994 * @param params.fillColor Color to fill in the circle. 24995 * @param params.outlineColor Color to outline the circle. 24996 * @param params.progressListener Callback function to fetch the progress. 24997 * @param params.infoListener Callback function to fetch the info. 24998 * @param params.infoLineAngle Angle of info line. 24999 */ 25000 var Circle = function(params) { 25001 this.id = params.id; 25002 this.canvas = params.canvas; 25003 this.context = params.context; 25004 this.centerX = params.centerX; 25005 this.centerY = params.centerY; 25006 this.arcWidth = params.arcWidth; 25007 this.innerRadius = params.innerRadius || 0; 25008 this.fillColor = params.fillColor || '#fff'; 25009 this.outlineColor = params.outlineColor || this.fillColor; 25010 this.progressListener = params.progressListener;
25011 this.infoLineLength = params.infoLineLength || 250; 25012 this.horizLineLength = params.horizLineLength || 50; 25013 this.infoListener = params.infoListener; 25014 this.infoLineAngle = params.infoLineAngle; 25015 25016 this.outerRadius = this.innerRadius + this.arcWidth; 25017 25018 // If the info listener is not registered, then don't calculate 25019 // the related coordinates 25020 if (!this.infoListener) return; 25021 25022 // calculate the info-line turning points 25023 var angle = this.infoLineAngle, 25024 arcDistance = (this.innerRadius + this.outerRadius) / 2, 25025 25026 sinA = Math.sin(angle), 25027 cosA = Math.cos(angle); 25028 25029 this.infoLineStartX = this.centerX + sinA * arcDistance; 25030 this.infoLineStartY = this.centerY - cosA * arcDistance; 25031 25032 this.infoLineMidX = this.centerX + sinA * this.infoLineLength; 25033 this.infoLineMidY = this.centerY - cosA * this.infoLineLength; 25034 25035 this.infoLineEndX = this.infoLineMidX + 25036 (sinA < 0 ? -this.horizLineLength : this.horizLineLength); 25037 this.infoLineEndY = this.infoLineMidY; 25038 25039 var infoText = document.createElement('div'), 25040 style = infoText.style; 25041 25042 style.color = this.fillColor; 25043 style.position = 'absolute'; 25044 style.left = this.infoLineEndX + absPos(this.canvas)[0] + 'px'; 25045 // style.top will be calculated in the `drawInfo` method. Since 25046 // user may want to change the size of the font, so the top offset 25047 // must be updated in each loop. 25048 infoText.className = 'ProgressCircleInfo'; // For css styling 25049 infoText.id = 'progress_circle_info_' + this.id; 25050 document.body.appendChild(infoText); 25051 this.infoText = infoText; 25052 }; 25053 25054 Circle.prototype = { 25055 constructor: Circle, 25056 25057 update: function() { 25058 this.progress = this.progressListener(); 25059 this._draw(); 25060 25061 if (this.infoListener) { 25062 this.info = this.infoListener(); 25063 this._drawInfo(); 25064 } 25065 }, 25066 25067 /** 25068 * @private 25069 * @method Draw the circle on the canvas. 25070 * @returns this 25071 */ 25072 _draw: function() { 25073 var ctx = this.context, 25074 25075 ANGLE_OFFSET = -Math.PI / 2, 25076 25077 startAngle = 0 + ANGLE_OFFSET, 25078 endAngle= startAngle + this.progress * Math.PI * 2, 25079 25080 x = this.centerX, 25081 y = this.centerY, 25082 25083 innerRadius = this.innerRadius - this.arcWidth - 1, 25084 outerRadius = this.outerRadius - this.arcWidth - 1; 25085 25086 if ( innerRadius < 0 ) 25087 return; 25088 25089 ctx.fillStyle = this.fillColor; 25090 ctx.strokeStyle = this.outlineColor; 25091 25092 ctx.beginPath(); 25093 ctx.arc(x, y, innerRadius, startAngle, endAngle, false); 25094 ctx.arc(x, y, outerRadius, endAngle, startAngle, true); 25095 ctx.closePath(); 25096 ctx.stroke(); 25097 ctx.fill(); 25098 25099 return this; 25100 }, 25101 25102 /** 25103 * @private 25104 * @method Draw the info lines and info text. 25105 * @returns this 25106 */ 25107 _drawInfo: function() { 25108 25109 var pointList, lineHeight; 25110 25111 pointList = [ 25112 [this.infoLineStartX, this.infoLineStartY], 25113 [this.infoLineMidX, this.infoLineMidY], 25114 [this.infoLineEndX, this.infoLineEndY], 25115 ]; 25116 this._drawSegments(pointList, false); 25117 25118 this.infoText.innerHTML = this.info; 25119 25120 lineHeight = this.infoText.offsetHeight; 25121 this.infoText.style.top = this.infoLineEndY + 25122 absPos(this.canvas)[1] - lineHeight / 2 + 'px'; 25123 25124 return this; 25125 }, 25126 25127 /** 25128 * @private 25129 * @method Helper function to draw the segments 25130 * @param pointList An array of points in the form of [x, y]. 25131 * @param close Whether to connect the first and last point. 25132 */ 25133 _drawSegments: function(pointList, close) { 25134 var ctx = this.context; 25135 25136 ctx.beginPath(); 25137 ctx.moveTo(pointList[0][0], pointList[0][1]); 25138 for (var i = 1; i < pointList.length; ++i) { 25139 ctx.lineTo(pointList[i][0], pointList[i][1]); 25140 } 25141 25142 if (close) { 25143 ctx.closePath(); 25144 } 25145 ctx.stroke(); 25146 }, 25147 }; 25148 25149 window.ProgressCircle = ProgressCircle; 25150 25151})(window, document); 25152 25153 25154 25155 25156/* ========================================================= 25157 * jquery.vc_chart.js v1.0 25158 * ========================================================= 25159 * Copyright 2013 Wpbakery 25160 * 25161 * Jquery chart plugin for the Visual Composer. 25162 * ========================================================= */ 25163(function($){ 25164 /** 25165 * Pie chart animated. 25166 * @param element - DOM element 25167 * @param options - settings object. 25168 * @constructor 25169 */ 25170 var VcChart = function(element, options) { 25171 this.el = element; 25172 this.$el = $(this.el); 25173 var $this = this; 25174 $this.options = $.extend({ 25175 color: 'wpb_button', 25176 units: '', 25177 width: '', 25178 label_selector: '.vc_pie_chart_value', 25179 back_selector: '.vc_pie_chart_back', 25180 responsive: true 25181 }, options); 25182 $this.init(); 25183 }; 25184 VcChart.prototype = { 25185 constructor: VcChart, 25186 _progress_v: 0, 25187 animated: false, 25188 colors: { 25189 'wpb_button': 'rgba(247, 247, 247, 1)', 25190 'btn-primary': 'rgba(0, 136, 204, 1)', 25191 'btn-info': 'rgba(88, 185, 218, 1)', 25192 'btn-success': 'rgba(106, 177, 101, 1)', 25193 'btn-warning': 'rgba(255, 153, 0, 1)', 25194 'btn-danger': 'rgba(255, 103, 91, 1)', 25195 'btn-inverse': 'rgba(85, 85, 85, 1)' 25196 }, 25197 init: function() { 25198 this.setupColor(); 25199 this.value = this.$el.data('pie-value')/100; 25200 this.label_value = this.$el.data('pie-label-value') || this.$el.data('pie-value'); 25201 this.$wrapper = $('.vc_pie_wrapper', this.$el); 25202 this.$label = $(this.options.label_selector, this.$el); 25203 this.$back = $(this.options.back_selector, this.$el); 25204 this.$canvas = this.$el.find('canvas'); 25205 this.arcWidth = this.$el.data('pie-width') * 2; 25206 this.draw(); 25207 this.setWayPoint(); 25208 if(this.options.responsive === true) this.setResponsive(); 25209 if (UNCODE.isMobile) this._progress_v = this.value; 25210 }, 25211 setupColor: function() { 25212 // if(typeof this.colors[this.options.color] !== 'undefined') { 25213 // this.color = this.colors[this.options.color]; 25214 // } else if(typeof this.options.color === 'string' && this.options.color.match(/^rgba?\([^\)]+\)/)) { 25215 // this.color = this.options.color; 25216 // } else { 25217 // this.color = 'rgba(247, 247, 247, 0.2)'; 25218 // } 25219 if(typeof this.options.color !== 'undefined') { 25220 this.color = this.options.color; 25221 } else this.color = 'rgba(247, 247, 247, 0.2)'; 25222 25223 }, 25224 setResponsive: function() { 25225 var that = this; 25226 if (!UNCODE.isMobile) { 25227 $(window).resize(function(){ 25228 if(that.animated === true) that.circle.stop(); 25229 that.draw(true); 25230 }); 25231 } 25232 }, 25233 draw: function(redraw) { 25234 var w = this.$el.addClass('vc_ready').width() * 2, 25235 border_w = this.arcWidth, 25236 radius; 25237 if(!w) w = this.$el.parents(':visible').first().width()-2; 25238 //w = Math.round(w/100*80); 25239 //if (w < 250) w = 250; 25240 radius = w/2; 25241 this.$wrapper.css({"width" : (w / 2) + "px"}); 25242 this.$label.css({"width" : (w / 2), "height" : (w / 2), "line-height" : (w / 2)+"px"}); 25243 this.$back.css({"width" : (w / 2), "height" : (w / 2)}); 25244 this.$canvas.attr({"width" : w + "px", "height" : w + "px"}); 25245 this.$el.addClass('vc_ready'); 25246 this.circle = new ProgressCircle({ 25247 canvas: this.$canvas.get(0), 25248 minRadius: radius, 25249 arcWidth: border_w 25250 }); 25251 if(redraw === true && this.animated === true) { 25252 this._progress_v = this.value; 25253 this.circle.addEntry({ 25254 fillColor: this.color, 25255 progressListener: $.proxy(this.setProgress, this) 25256 }).start(); 25257 } 25258 }, 25259 setProgress: function() { 25260 if (this._progress_v >= this.value) { 25261 this.circle.stop(); 25262 this.animated = true; 25263 this.$label.html(this.label_value + this.options.units); 25264 return this._progress_v; 25265 } 25266 this._progress_v += 0.01; 25267 if (!isNaN(this.label_value)) { 25268 var label_value = this._progress_v/this.value*this.label_value; 25269 var val = Math.round(label_value) + this.options.units; 25270 this.$label.html(val); 25271 } else this.$label.html(this.label_value + this.options.units); 25272 return this._progress_v; 25273 }, 25274 animate: function() { 25275 if(this.animated !== true) { 25276 this.circle.addEntry({ 25277 fillColor: this.color, 25278 progressListener: $.proxy(this.setProgress, this) 25279 }).start(10); 25280 } 25281 }, 25282 setWayPoint: function() { 25283 if (typeof $.fn.waypoint !== 'undefined' && !UNCODE.isMobile) { 25284 this.$el.waypoint($.proxy(this.animate, this), { offset: '85%' }); 25285 } else { 25286 this.animate(); 25287 } 25288 } 25289 }; 25290 /** 25291 * jQuery plugin 25292 * @param option - object with settings 25293 * @return {*} 25294 */ 25295 $.fn.vcChat = function(option, value) { 25296 return this.each(function () { 25297 var $this = $(this), 25298 data = $this.data('vc_chart'), 25299 options = typeof option === 'object' ? option : { 25300 color: $this.data('pie-color'), 25301 units: $this.data('pie-units') 25302 }; 25303 if (typeof option == 'undefined') $this.data('vc_chart', (data = new VcChart(this, options))); 25304 if (typeof option == 'string') data[option](value); 25305 }); 25306 }; 25307 /** 25308 * Allows users to rewrite function inside theme. 25309 */ 25310 if ( typeof window['vc_pieChart'] !== 'function' ) { 25311 window.vc_pieChart = function() { 25312 $('.vc_pie_chart:visible:not(.vc_ready)').vcChat(); 25313 } 25314 } 25315 $(document).ready(function(){ 25316 !window.vc_iframe && vc_pieChart(); 25317 25318 /** 25319 * Tab and collapse integration. 25320 */ 25321 $('.nav-tabs a').on('shown.bs.tab', function(e){ 25322 var $cont = $(e.target).closest('.tab-container'), 25323 $active = $('.tab-pane.active', $cont); 25324 $('.vc_pie_chart:not(.vc_ready)', $active).vcChat(); 25325 }); 25326 25327 $('.panel-collapse').on('shown.bs.collapse', function (e) { 25328 $('.vc_pie_chart:not(.vc_ready)', e.target).vcChat(); 25329 }) 25330 }); 25331 25332})(window.jQuery); 25333 25334/* Progress bar 25335 ---------------------------------------------------------- */ 25336function uncode_progress_bar() { 25337 jQuery.each(jQuery('.vc_progress_bar'), function(index, val) { 25338 if (UNCODE.isUnmodalOpen && !val.closest('#unmodal-content')) { 25339 return; 25340 } 25341 if (!UNCODE.isMobile) { 25342 new Waypoint({ 25343 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 25344 element: val, 25345 handler: function() { 25346 var element = jQuery(this.element); 25347 element.find('.vc_single_bar').each(function(index) { 25348 var $this = jQuery(this), 25349 bar = $this.find('.vc_bar'), 25350 val = bar.data('percentage-value'); 25351 setTimeout(function() { 25352 bar.css({ 25353 "width": val + '%' 25354 }); 25355 }, index * 200); 25356 }); 25357 }, 25358 offset: '80%' 25359 }); 25360 } else { 25361 var element = jQuery(val); 25362 element.find('.vc_single_bar').each(function(index) { 25363 var $this = jQuery(this), 25364 bar = $this.find('.vc_bar'), 25365 val = bar.data('percentage-value'); 25366 setTimeout(function() { 25367 bar.css({ 25368 "width": val + '%' 25369 }); 25370 }, index * 200); 25371 }); 25372 } 25373 }); 25374}; 25375uncode_progress_bar(); 25376 25377/*! 25378 * jquery.counterup.js 1.0 25379 * 25380 * Copyright 2013, Benjamin Intal http://gambit.ph @bfintal 25381 * Released under the GPL v2 License 25382 * 25383 * Date: Nov 26, 2013 25384 */ 25385(function($) { 25386 "use strict"; 25387 $.fn.counterUp = function(options) { 25388 // Defaults 25389 var settings = $.extend({ 25390 'time': 400, 25391 'delay': 10 25392 }, options); 25393 return this.each(function() { 25394 // Store the object 25395 var $this = $(this); 25396 var $settings = settings; 25397 var counterUpper = function() { 25398 var nums = []; 25399 var divisions = $settings.time / $settings.delay; 25400 var numReal = $this.attr('data-val'), 25401 num = numReal; 25402 var isComma = /[0-9]+,[0-9]+/.test(num); 25403 num = num.replace(/,/g, ''); 25404 var isInt = /^[0-9]+$/.test(num); 25405 var isFloat = /^[0-9]+\.[0-9]+$/.test(num); 25406 var decimalPlaces = isFloat ? (num.split('.')[1] || []).length : 0; 25407 // Generate list of incremental numbers to display 25408 for (var i = divisions; i >= 1; i--) { 25409 // Preserve as int if input was int 25410 var newNum = parseInt(num / divisions * i); 25411 // Preserve float if input was float 25412 if (isFloat) { 25413 newNum = parseFloat(num / divisions * i).toFixed(decimalPlaces); 25414 } 25415 // Preserve commas if input had commas 25416 if (isComma) { 25417 while (/(\d+)(\d{3})/.test(newNum.toString())) { 25418 newNum = newNum.toString().replace(/(\d+)(\d{3})/, '$1' + ',' + '$2'); 25419 } 25420 } 25421 nums.unshift(newNum); 25422 } 25423 nums.push(numReal); 25424 $this.data('counterup-nums', nums); 25425 $this.text('0'); 25426 // Updates the number until we're done 25427 var f = function() { 25428 if ($this.data('counterup-nums') != null) { 25429 $this.text($this.data('counterup-nums').shift()); 25430 if ($this.data('counterup-nums').length) { 25431 setTimeout($this.data('counterup-func'), $settings.delay); 25432 } else { 25433 delete $this.data('counterup-nums'); 25434 $this.data('counterup-nums', null); 25435 $this.data('counterup-func', null); 25436 } 25437 } 25438 }; 25439 $this.data('counterup-func', f); 25440 // Start the count up 25441 setTimeout($this.data('counterup-func'), $settings.delay); 25442 }; 25443 // Perform counts when the element gets into view 25444 new Waypoint({ 25445 context: UNCODE.isUnmodalOpen ? document.getElementById('unmodal-content') : window, 25446 element: this, 25447 handler: function() { 25448 counterUpper(); 25449 if (!UNCODE.isUnmodalOpen) { 25450 this.destroy(); 25451 } 25452 }, 25453 offset: '100%' 25454 }); 25455 }); 25456 }; 25457})(jQuery); 25458 25459/*! 25460 * The Final Countdown for jQuery v2.2.0 (http://hilios.github.io/jQuery.countdown/) 25461 * Copyright (c) 2016 Edson Hilios 25462 * 25463 * Permission is hereby granted, free of charge, to any person obtaining a copy of 25464 * this software and associated documentation files (the "Software"), to deal in 25465 * the Software without restriction, including without limitation the rights to 25466 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 25467 * the Software, and to permit persons to whom the Software is furnished to do so, 25468 * subject to the following conditions: 25469 * 25470 * The above copyright notice and this permission notice shall be included in all 25471 * copies or substantial portions of the Software. 25472 * 25473 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25474 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 25475 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 25476 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 25477 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 25478 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25479 */ 25480(function(factory) { 25481 "use strict"; 25482 if (typeof define === "function" && define.amd) { 25483 define([ "jquery" ], factory); 25484 } else { 25485 factory(jQuery); 25486 } 25487})(function($) { 25488 "use strict"; 25489 var instances = [], matchers = [], defaultOptions = { 25490 precision: 100, 25491 elapse: false, 25492 defer: false 25493 }; 25494 matchers.push(/^[0-9]*$/.source); 25495 matchers.push(/([0-9]{1,2}\/){2}[0-9]{4}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 25496 matchers.push(/[0-9]{4}([\/\-][0-9]{1,2}){2}( [0-9]{1,2}(:[0-9]{2}){2})?/.source); 25497 matchers = new RegExp(matchers.join("|")); 25498 function parseDateString(dateString) { 25499 if (dateString instanceof Date) { 25500 return dateString; 25501 } 25502 if (String(dateString).match(matchers)) { 25503 if (String(dateString).match(/^[0-9]*$/)) { 25504 dateString = Number(dateString); 25505 } 25506 if (String(dateString).match(/\-/)) { 25507 dateString = String(dateString).replace(/\-/g, "/"); 25508 } 25509 return new Date(dateString); 25510 } else { 25511 throw new Error("Couldn't cast `" + dateString + "` to a date object."); 25512 } 25513 } 25514 var DIRECTIVE_KEY_MAP = { 25515 Y: "years", 25516 m: "months", 25517 n: "daysToMonth", 25518 d: "daysToWeek", 25519 w: "weeks", 25520 W: "weeksToMonth", 25521 H: "hours", 25522 M: "minutes", 25523 S: "seconds", 25524 D: "totalDays", 25525 I: "totalHours", 25526 N: "totalMinutes", 25527 T: "totalSeconds" 25528 }; 25529 function escapedRegExp(str) { 25530 var sanitize = str.toString().replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); 25531 return new RegExp(sanitize); 25532 } 25533 function strftime(offsetObject) { 25534 return function(format) { 25535 var directives = format.match(/%(-|!)?[A-Z]{1}(:[^;]+;)?/gi); 25536 if (directives) { 25537 for (var i = 0, len = directives.length; i < len; ++i) { 25538 var directive = directives[i].match(/%(-|!)?([a-zA-Z]{1})(:[^;]+;)?/), regexp = escapedRegExp(directive[0]), modifier = directive[1] || "", plural = directive[3] || "", value = null; 25539 directive = directive[2]; 25540 if (DIRECTIVE_KEY_MAP.hasOwnProperty(directive)) { 25541 value = DIRECTIVE_KEY_MAP[directive]; 25542 value = Number(offsetObject[value]); 25543 } 25544 if (value !== null) { 25545 if (modifier === "!") { 25546 value = pluralize(plural, value); 25547 } 25548 if (modifier === "") { 25549 if (value < 10) { 25550 value = "0" + value.toString(); 25551 } 25552 } 25553 format = format.replace(regexp, value.toString()); 25554 } 25555 } 25556 } 25557 format = format.replace(/%%/, "%"); 25558 return format; 25559 }; 25560 } 25561 function pluralize(format, count) { 25562 var plural = "s", singular = ""; 25563 if (format) { 25564 format = format.rep
vendor: 8,618 bytes, lines 25564-25708
25564lace(/(:|;|\s)/gi, "").split(/\,/); 25565 if (format.length === 1) { 25566 plural = format[0]; 25567 } else { 25568 singular = format[0]; 25569 plural = format[1]; 25570 } 25571 } 25572 if (Math.abs(count) > 1) { 25573 return plural; 25574 } else { 25575 return singular; 25576 } 25577 } 25578 var Countdown = function(el, finalDate, options) { 25579 this.el = el; 25580 this.$el = $(el); 25581 this.interval = null; 25582 this.offset = {}; 25583 this.options = $.extend({}, defaultOptions); 25584 this.instanceNumber = instances.length; 25585 instances.push(this); 25586 this.$el.data("countdown-instance", this.instanceNumber); 25587 if (options) { 25588 if (typeof options === "function") { 25589 this.$el.on("update.countdown", options); 25590 this.$el.on("stoped.countdown", options); 25591 this.$el.on("finish.countdown", options); 25592 } else { 25593 this.options = $.extend({}, defaultOptions, options); 25594 } 25595 } 25596 this.setFinalDate(finalDate); 25597 if (this.options.defer === false) { 25598 this.start(); 25599 } 25600 }; 25601 $.extend(Countdown.prototype, { 25602 start: function() { 25603 if (this.interval !== null) { 25604 clearInterval(this.interval); 25605 } 25606 var self = this; 25607 this.update(); 25608 this.interval = setInterval(function() { 25609 self.update.call(self); 25610 }, this.options.precision); 25611 }, 25612 stop: function() { 25613 clearInterval(this.interval); 25614 this.interval = null; 25615 this.dispatchEvent("stoped"); 25616 }, 25617 toggle: function() { 25618 if (this.interval) { 25619 this.stop(); 25620 } else { 25621 this.start(); 25622 } 25623 }, 25624 pause: function() { 25625 this.stop(); 25626 }, 25627 resume: function() { 25628 this.start(); 25629 }, 25630 remove: function() { 25631 this.stop.call(this); 25632 instances[this.instanceNumber] = null; 25633 delete this.$el.data().countdownInstance; 25634 }, 25635 setFinalDate: function(value) { 25636 this.finalDate = parseDateString(value); 25637 }, 25638 update: function() { 25639 if (this.$el.closest("html").length === 0) { 25640 this.remove(); 25641 return; 25642 } 25643 var hasEventsAttached = $._data(this.el, "events") !== undefined, now = new Date(), newTotalSecsLeft; 25644 newTotalSecsLeft = this.finalDate.getTime() - now.getTime(); 25645 newTotalSecsLeft = Math.ceil(newTotalSecsLeft / 1e3); 25646 newTotalSecsLeft = !this.options.elapse && newTotalSecsLeft < 0 ? 0 : Math.abs(newTotalSecsLeft); 25647 if (this.totalSecsLeft === newTotalSecsLeft || !hasEventsAttached) { 25648 return; 25649 } else { 25650 this.totalSecsLeft = newTotalSecsLeft; 25651 } 25652 this.elapsed = now >= this.finalDate; 25653 this.offset = { 25654 seconds: this.totalSecsLeft % 60, 25655 minutes: Math.floor(this.totalSecsLeft / 60) % 60, 25656 hours: Math.floor(this.totalSecsLeft / 60 / 60) % 24, 25657 days: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 25658 daysToWeek: Math.floor(this.totalSecsLeft / 60 / 60 / 24) % 7, 25659 daysToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 % 30.4368), 25660 weeks: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7), 25661 weeksToMonth: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 7) % 4, 25662 months: Math.floor(this.totalSecsLeft / 60 / 60 / 24 / 30.4368), 25663 years: Math.abs(this.finalDate.getFullYear() - now.getFullYear()), 25664 totalDays: Math.floor(this.totalSecsLeft / 60 / 60 / 24), 25665 totalHours: Math.floor(this.totalSecsLeft / 60 / 60), 25666 totalMinutes: Math.floor(this.totalSecsLeft / 60), 25667 totalSeconds: this.totalSecsLeft 25668 }; 25669 if (!this.options.elapse && this.totalSecsLeft === 0) { 25670 this.stop(); 25671 this.dispatchEvent("finish"); 25672 } else { 25673 this.dispatchEvent("update"); 25674 } 25675 }, 25676 dispatchEvent: function(eventName) { 25677 var event = $.Event(eventName + ".countdown"); 25678 event.finalDate = this.finalDate; 25679 event.elapsed = this.elapsed; 25680 event.offset = $.extend({}, this.offset); 25681 event.strftime = strftime(this.offset); 25682 this.$el.trigger(event); 25683 } 25684 }); 25685 $.fn.countdown = function() { 25686 var argumentsArray = Array.prototype.slice.call(arguments, 0); 25687 return this.each(function() { 25688 var instanceNumber = $(this).data("countdown-instance"); 25689 if (instanceNumber !== undefined) { 25690 var instance = instances[instanceNumber], method = argumentsArray[0]; 25691 if (Countdown.prototype.hasOwnProperty(method)) { 25692 instance[method].apply(instance, argumentsArray.slice(1)); 25693 } else if (String(method).match(/^[$A-Z_][0-9A-Z_$]*$/i) === null) { 25694 instance.setFinalDate.call(instance, method); 25695 instance.start(); 25696 } else { 25697 $.error("Method %s does not exist on jQuery.countdown".replace(/\%s/gi, method)); 25698 } 25699 } else { 25700 new Countdown(this, argumentsArray[0], argumentsArray[1]); 25701 } 25702 }); 25703 }; 25704}); 25705 25706!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; 25707function getStyles(config){ 25708 // 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;
25708left: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+"}" 25709}; 25710 var ShareUtils; 25711 25712if ((!("classList" in document.documentElement)) && Object.defineProperty && typeof HTMLElement !== "undefined") { 25713 Object.defineProperty(HTMLElement.prototype, "classList", { 25714 get: function() { 25715 var ret, self, update; 25716 update = function(fn) { 25717 return function(value) { 25718 var classes, index; 25719 classes = self.className.split(/\s+/); 25720 index = classes.indexOf(value); 25721 fn(classes, index, value); 25722 self.className = classes.join(" "); 25723 }; 25724 }; 25725 self = this; 25726 ret = { 25727 add: update(function(classes, index, value) { 25728 ~index || classes.push(value); 25729 }), 25730 remove: update(function(classes, index) { 25731 ~index && classes.splice(index, 1); 25732 }), 25733 toggle: update(function(classes, index, value) { 25734 if (~index) { 25735 classes.splice(index, 1); 25736 } else { 25737 classes.push(value); 25738 } 25739 }), 25740 contains: function(value) { 25741 return !!~self.className.split(/\s+/).indexOf(value); 25742 }, 25743 item: function(i) { 25744 return self.className.split(/\s+/)[i] || null; 25745 } 25746 }; 25747 Object.defineProperty(ret, "length", { 25748 get: function() { 25749 return self.className.split(/\s+/).length; 25750 } 25751 }); 25752 return ret; 25753 } 25754 }); 25755} 25756 25757String.prototype.to_rfc3986 = function() { 25758 var tmp; 25759 tmp = encodeURIComponent(this); 25760 return tmp.replace(/[!'()*]/g, function(c) { 25761 return "%" + c.charCodeAt(0).toString(16); 25762 }); 25763}; 25764 25765ShareUtils = (function() { 25766 function ShareUtils() {} 25767 25768 ShareUtils.prototype.extend = function(to, from, overwrite) { 25769 var hasProp, prop; 25770 for (prop in from) { 25771 hasProp = to[prop] !== undefined; 25772 if (hasProp && typeof from[prop] === "object") { 25773 this.extend(to[prop], from[prop], overwrite); 25774 } else { 25775 if (overwrite || !hasProp) { 25776 to[prop] = from[prop]; 25777 } 25778 } 25779 } 25780 }; 25781 25782 ShareUtils.prototype.hide = function(el) { 25783 return el.style.display = "none"; 25784 }; 25785 25786 ShareUtils.prototype.show = function(el) { 25787 return el.style.display = "block"; 25788 }; 25789 25790 ShareUtils.prototype.has_class = function(el, class_name) { 25791 return el.classList.contains(class_name); 25792 }; 25793 25794 ShareUtils.prototype.add_class = function(el, class_name) { 25795 return el.classList.add(class_name); 25796 }; 25797 25798 ShareUtils.prototype.remove_class = function(el, class_name) { 25799 return el.classList.remove(class_name); 25800 }; 25801 25802 ShareUtils.prototype.is_encoded = function(str) { 25803 str = str.to_rfc3986(); 25804 return decodeURIComponent(str) !== str; 25805 }; 25806 25807 ShareUtils.prototype.encode = function(str) { 25808 if (typeof str === "undefined" || this.is_encoded(str)) { 25809 return str; 25810 } else { 25811 return str.to_rfc3986(); 25812 } 25813 }; 25814 25815 ShareUtils.prototype.popup = function(url, params) { 25816 var k, popup, qs, v; 25817 if (params == null) { 25818 params = {}; 25819 } 25820 popup = { 25821 width: 500, 25822 height: 350 25823 }; 25824 popup.top = (screen.height / 2) - (popup.height / 2); 25825 popup.left = (screen.width / 2) - (popup.width / 2); 25826 qs = ((function() { 25827 var _results; 25828 _results = []; 25829 for (k in params) { 25830 v = params[k]; 25831 _results.push("" + k + "=" + (this.encode(v))); 25832 } 25833 return _results; 25834 }).call(this)).join('&'); 25835 if (qs) { 25836 qs = "?" + qs; 25837 } 25838 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="
25838+ popup.width + ",height=" + popup.height); 25839 }; 25840 25841 return ShareUtils; 25842 25843})(); 25844var Share, 25845 __hasProp = {}.hasOwnProperty, 25846 __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; }; 25847 25848Share = (function(_super) { 25849 __extends(Share, _super); 25850 25851 function Share(element, options) { 25852 this.element = element; 25853 this.el = { 25854 head: document.getElementsByTagName('head')[0], 25855 body: document.getElementsByTagName('body')[0] 25856 }; 25857 this.config = { 25858 enabled_networks: 0, 25859 protocol: ['http', 'https'].indexOf(window.location.href.split(':')[0]) === -1 ? 'https://' : '//', 25860 url: window.location.href.replace("&", "%26"), 25861 caption: null, 25862 title: this.default_title(), 25863 image: this.default_image(), 25864 description: this.default_description(), 25865 ui: { 25866 flyout: 'top center', 25867 button_text: 'Share', 25868 button_font: true, 25869 icon_font: true 25870 }, 25871 networks: { 25872 twitter: { 25873 enabled: true, 25874 url: null, 25875 title: null, 25876 description: null 25877 }, 25878 facebook: { 25879 enabled: true, 25880 load_sdk: true, 25881 url: null, 25882 app_id: null, 25883 title: null, 25884 caption: null, 25885 description: null, 25886 image: null 25887 }, 25888 pinterest: { 25889 enabled: true, 25890 url: null, 25891 image: null, 25892 description: null 25893 }, 25894 reddit: { 25895 enabled: true, 25896 url: null, 25897 title: null 25898 }, 25899 linkedin: { 25900 enabled: true, 25901 url: null, 25902 title: null, 25903 description: null 25904 }, 25905 xing: { 25906 enabled: true, 25907 url: null, 25908 title: null, 25909 image: null, 25910 description: null 25911 }, 25912 whatsapp: { 25913 enabled: true, 25914 description: null, 25915 url: null 25916 }, 25917 email: { 25918 enabled: true, 25919 title: null, 25920 description: null, 25921 url: null 25922 } 25923 } 25924 }; 25925 this.setup(element, options); 25926 return this; 25927 } 25928 25929 Share.prototype.setup = function(element, opts) { 25930 var index, instance, instances, _i, _len; 25931 instances = document.querySelectorAll(element); 25932 this.extend(this.config, opts, true); 25933 this.set_global_configuration(); 25934 this.normalize_network_configuration(); 25935 if (this.config.ui.icon_font) { 25936 this.inject_icons(); 25937 } 25938 if (this.config.ui.button_font) { 25939 this.inject_fonts(); 25940 } 25941 if (this.config.networks.facebook.enabled && this.config.networks.facebook.load_sdk) { 25942 this.inject_facebook_sdk(); 25943 } 25944 for (index = _i = 0, _len = instances.length; _i < _len; index = ++_i) { 25945 instance = instances[index]; 25946 this.setup_instance(element, index); 25947 } 25948 }; 25949 25950 Share.prototype.setup_instance = function(element, index) { 25951 var button, instance, label, network, networks, _i, _len, _results, 25952 _this = this; 25953 instance = document.querySelectorAll(element)[index]; 25954 this.hide(instance); 25955 this.add_class(instance, "sharer-" + index); 25956 instance = document.querySelectorAll(element)[index]; 25957 this.inject_css(instance); 25958 this.inject_html(instance); 25959 this.show(instance); 25960 label = instance.getElementsByTagName("label")[0]; 25961 button = instance.getElementsByClassName("social")[0]; 25962 networks = instance.getElementsByTagName('li'); 25963 this.add_class(button, "networks-" + this.config.enabled_networks); 25964 label.addEventListener("click", function() { 25965 return _this.event_toggle(button); 25966 }); 25967 _this = this; 25968 _results = []; 25969 for (index = _i = 0, _len = networks.length; _i < _len; index = ++_i) { 25970 network = networks[index]; 25971 _results.push(network.addEventListener("click", function() { 25972 _this.event_network(instance, this); 25973 return _this.event_close(button); 25974 })); 25975 } 25976 return _results; 25977 }; 25978 25979 Share.prototype.event_toggle = function(button) { 25980 if (this.has_class(button, "active")) { 25981 return this.event_close(button); 25982 } else { 25983 return this.event_open(button); 25984 } 25985 }; 25986 25987 Share.prototype.event_open = function(button) { 25988 if (this.has_class(button, "load")) { 25989 this.remove_class(button, "load"); 25990 } 25991 return this.add_class(button, "active"); 25992 }; 25993 25994 Share.prototype.event_close = function(button) { 25995 return this.remove_class(button, "active"); 25996 }; 25997 25998 Share.prototype.event_network = function(instance, network) { 25999 var name; 26000 name = network.getAttribute("data-network"); 26001 this.hook("before", name, instance);
26002 this["network_" + name](); 26003 return this.hook("after", name, instance); 26004 }; 26005 26006 Share.prototype.open = function() { 26007 return this["public"]("open"); 26008 }; 26009 26010 Share.prototype.close = function() { 26011 return this["public"]("close"); 26012 }; 26013 26014 Share.prototype.toggle = function() { 26015 return this["public"]("toggle"); 26016 }; 26017 26018 Share.prototype["public"] = function(action) { 26019 var button, index, instance, _i, _len, _ref, _results; 26020 _ref = document.querySelectorAll(this.element); 26021 _results = []; 26022 for (index = _i = 0, _len = _ref.length; _i < _len; index = ++_i) { 26023 instance = _ref[index]; 26024 button = instance.getElementsByClassName("social")[0]; 26025 _results.push(this["event_" + action](button)); 26026 } 26027 return _results; 26028 }; 26029 26030 Share.prototype.network_facebook = function() { 26031 if (this.config.networks.facebook.load_sdk) { 26032 if (!window.FB) { 26033 return console.error("The Facebook JS SDK hasn't loaded yet."); 26034 } 26035 return FB.ui({ 26036 method: 'feed', 26037 name: this.config.networks.facebook.title, 26038 link: this.config.networks.facebook.url, 26039 picture: this.config.networks.facebook.image, 26040 caption: this.config.networks.facebook.caption, 26041 description: this.config.networks.facebook.description 26042 }); 26043 } else { 26044 return this.popup('https://www.facebook.com/sharer/sharer.php', { 26045 u: this.config.networks.facebook.url 26046 }); 26047 } 26048 }; 26049 26050 Share.prototype.network_twitter = function() { 26051 return this.popup('https://twitter.com/intent/tweet', { 26052 text: this.config.networks.twitter.title, 26053 url: this.config.networks.twitter.url 26054 }); 26055 }; 26056 26057 Share.prototype.network_pinterest = function() { 26058 return this.popup('https://www.pinterest.com/pin/create/button', { 26059 url: this.config.networks.pinterest.url, 26060 media: this.config.networks.pinterest.image, 26061 description: this.config.networks.pinterest.description 26062 }); 26063 }; 26064 26065 Share.prototype.network_linkedin = function() { 26066 return this.popup('https://www.linkedin.com/shareArticle', { 26067 url: this.config.networks.linkedin.url, 26068 title: this.config.networks.linkedin.title, 26069 summary: this.config.networks.linkedin.description 26070 }); 26071 } 26072 26073 Share.prototype.network_xing = function() { 26074 return this.popup('https://www.xing.com/spi/shares/new', { 26075 url: this.config.networks.xing.url, 26076 image: this.config.networks.xing.image, 26077 title: this.config.networks.xing.title, 26078 summary: this.config.networks.xing.description 26079 }); 26080 } 26081 26082 Share.prototype.network_email = function() { 26083 return this.popup('mailto:', { 26084 subject: this.config.networks.email.title, 26085 body: this.config.networks.email.url + '%0A%0A' + this.config.networks.email.description, 26086 }); 26087 }; 26088 26089 Share.prototype.inject_icons = function() { 26090 // return this.inject_stylesheet("https://www.sharebutton.co/fonts/v2/entypo.min.css"); 26091 }; 26092 26093 Share.prototype.inject_fonts = function() { 26094 // return this.inject_stylesheet("http://fonts.googleapis.com/css?family=Lato:900&text=" + this.config.ui.button_text); 26095 }; 26096 26097 Share.prototype.inject_stylesheet = function(url) { 26098 var link; 26099 if (!this.el.head.querySelector("link[href=\"" + url + "\"]")) { 26100 link = document.createElement("link"); 26101 link.setAttribute("rel", "stylesheet"); 26102 link.setAttribute("href", url); 26103 return this.el.head.appendChild(link); 26104 } 26105 }; 26106 26107 Share.prototype.inject_css = function(instance) { 26108 var css, meta, selector, style; 26109 selector = "." + (instance.getAttribute('class').split(" ").join(".")); 26110 if (!this.el.head.querySelector("meta[name='sharer" + selector + "']")) { 26111 this.config.selector = selector; 26112 css = getStyles(this.config); 26113 style = document.createElement("style"); 26114 style.type = "text/css"; 26115 if (style.styleSheet) { 26116 style.styleSheet.cssText = css; 26117 } else { 26118 style.appendChild(document.createTextNode(css)); 26119 } 26120 this.el.head.appendChild(style); 26121 delete this.config.selector; 26122 meta = document.createElement("meta"); 26123 meta.setAttribute("name", "sharer" + selector); 26124 return this.el.head.appendChild(meta); 26125 } 26126 }; 26127 26128 Share.prototype.inject_html = function(instance) { 26129 //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>"; 26130 return instance.innerHTML = "<label class='social-export'><span>" + this.config.ui.button_text + "</span></label><div class='social load " + this.config.ui.flyout + "'><ul><li class='social-facebook' data-network='facebook' tabindex='0'></li><li class='social-twitter' data-network='twitter' tabindex='0'></li><li class='social-pinterest' data-network='pinterest' tabindex='0'></li><li class='social-linkedin' data-network='linkedin' tabindex='0'></li><li class='social-xing' data-network='xing' tabindex='0'></li><li class='social-paper-plane' data-network='email' tabindex='0'></li></ul></div>"; 26131 }; 26132 26133 Share.prototype.inject_facebook_sdk = function() { 26134 var fb_root, script; 26135 if (!window.FB && this.config.networks.facebook.app_id && !this.el.body.querySelector('#fb-root')) { 26136 script = document.createElement("script"); 26137 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')"; 26138 fb_root = document.createElement("div"); 26139 fb_root.id = "fb-root"; 26140 this.el.body.appendChild(fb_root); 26141 return this.el.body.appendChild(script); 26142 } 26143 }; 26144 26145 Share.prototype.hook = function(type, network, instance) { 26146 var fn, opts; 26147 fn = this.config.networks[network][type]; 26148 if (typeof fn === "function") { 26149 opts = fn.call(this.config.networks[network], instance); 26150 if (opts !== void 0) { 26151 opts = this.normalize_filter_config_updates(opts); 26152 this.extend(this.config.networks[network], opts, true); 26153 this.normalize_network_configuration(); 26154 } 26155 } 26156 }; 26157 26158 Share.prototype.default_title = function() { 26159 var content; 26160 if (content = document.querySelector('meta[property="og:title"]') || document.querySelector('meta[name="twitter:title"]')) { 26161 return encodeURIComponent(content.getAttribute('content')); 26162 } else if (content = document.querySelector('title')) { 26163 return encodeURIComponent(content.innerText); 26164 } 26165 }; 26166 26167 Share.prototype.default_image = function() { 26168 var content; 26169 if (content = document.querySelector('meta[property="og:image"]') || document.querySelector('meta[name="twitter:image"]')) { 26170 return content.getAttribute('content'); 26171 } 26172 }; 26173 26174 Share.prototype.default_description = function() { 26175 var content; 26176 if (content = document.querySelector('meta[property="og:description"]') || document.querySelector('meta[name="twitter:description"]') || document.querySelector('meta[name="description"]')) { 26177 return encodeURIComponent(content.getAttribute('content')); 26178 } else { 26179 return ''; 26180 } 26181 }; 26182 26183 Share.prototype.set_global_configuration = function() { 26184 var display, network, option, options, _ref, _results; 26185 _ref = this.config.networks; 26186 _results = []; 26187 for (network in _ref) { 26188 options = _ref[network]; 26189 for (option in options) { 26190 if (this.config.networks[network][option] == null) { 26191 this.config.networks[network][option] = this.config[option]; 26192 } 26193 } 26194 if (this.config.networks[network].enabled) { 26195 display = 'block'; 26196 this.config.enabled_networks += 1; 26197 } else { 26198 display = 'none'; 26199 } 26200 _results.push(this.config.networks[network].display = display); 26201 } 26202 return _results; 26203 }; 26204 26205 Share.prototype.normalize_network_configuration = function() { 26206 if (!this.config.networks.facebook.app_id) { 26207 this.config.networks.facebook.load_sdk = false;
26208 } 26209 if (!this.is_encoded(this.config.networks.twitter.description)) { 26210 this.config.networks.twitter.description = encodeURIComponent(this.config.networks.twitter.description); 26211 } 26212 if (typeof this.config.networks.facebook.app_id === 'number') { 26213 return this.config.networks.facebook.app_id = this.config.networks.facebook.app_id.toString(); 26214 } 26215 }; 26216 26217 Share.prototype.normalize_filter_config_updates = function(opts) { 26218 if (this.config.networks.facebook.app_id !== opts.app_id) { 26219 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."); 26220 delete opts.app_id; 26221 } 26222 if (this.config.networks.facebook.load_sdk !== opts.load_sdk) { 26223 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."); 26224 delete opts.app_id; 26225 } 26226 return opts; 26227 }; 26228 26229 return Share; 26230 26231})(ShareUtils); 26232 return Share; 26233}); 26234 26235// Generated by CoffeeScript 1.9.2 26236 26237// @license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 26238 26239(function() { 26240 var $, win; 26241 26242 $ = this.jQuery || window.jQuery; 26243 26244 win = $(window); 26245 26246 $.fn.stick_in_parent = function(opts) { 26247 var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class; 26248 if (opts == null) { 26249 opts = {}; 26250 } 26251 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; 26252 if (offset_top == null) { 26253 offset_top = 0; 26254 } 26255 if (parent_selector == null) { 26256 parent_selector = void 0; 26257 } 26258 if (inner_scrolling == null) { 26259 inner_scrolling = true; 26260 } 26261 if (sticky_class == null) { 26262 sticky_class = "is_stuck"; 26263 } 26264 doc = $(document); 26265 if (enable_bottoming == null) { 26266 enable_bottoming = true; 26267 } 26268 outer_width = function(el) { 26269 var _el, computed, w; 26270 if (window.getComputedStyle) { 26271 _el = el[0]; 26272 computed = window.getComputedStyle(el[0]); 26273 w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right")); 26274 if (computed.getPropertyValue("box-sizing") !== "border-box") { 26275 w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right")); 26276 } 26277 return w; 26278 } else { 26279 return el.outerWidth(true); 26280 } 26281 }; 26282 fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) { 26283 var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick; 26284 if (elm.data("sticky_kit")) { 26285 return; 26286 } 26287 elm.data("sticky_kit", true); 26288 last_scroll_height = doc.height(); 26289 parent = elm.parent(); 26290 if (parent_selector != null) { 26291 parent = parent.closest(parent_selector); 26292 } 26293 if (!parent.length) { 26294 throw "failed to find stick parent"; 26295 } 26296 fixed = false; 26297 bottomed = false; 26298 spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />"); 26299 if (spacer) { 26300 spacer.css('position', elm.css('position')); 26301 } 26302 recalc = function() { 26303 var border_top, padding_top, restore; 26304 if (detached) { 26305 return; 26306 } 26307 last_scroll_height = doc.height(); 26308 border_top = parseInt(parent.css("border-top-width"), 10); 26309 padding_top = parseInt(parent.css("padding-top"), 10); 26310 padding_bottom = parseInt(parent.css("padding-bottom"), 10); 26311 parent_top = parent.offset().top + border_top + padding_top; 26312 parent_height = parent.height(); 26313 if (fixed) { 26314 fixed = false;
vendor: 6,068 bytes, lines 26315-26509
26315 bottomed = false; 26316 if (manual_spacer == null) { 26317 elm.insertAfter(spacer); 26318 spacer.detach(); 26319 } 26320 elm.css({ 26321 position: "", 26322 top: "", 26323 width: "", 26324 bottom: "" 26325 }).removeClass(sticky_class); 26326 restore = true; 26327 } 26328 top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top; 26329 height = elm.outerHeight(true); 26330 el_float = elm.css("float"); 26331 if (spacer) { 26332 spacer.css({ 26333 width: outer_width(elm), 26334 height: height, 26335 display: elm.css("display"), 26336 "vertical-align": elm.css("vertical-align"), 26337 "float": el_float 26338 }); 26339 } 26340 if (restore) { 26341 return tick(); 26342 } 26343 }; 26344 recalc(); 26345 if (height === parent_height) { 26346 return; 26347 } 26348 last_pos = void 0; 26349 offset = offset_top; 26350 recalc_counter = recalc_every; 26351 tick = function() { 26352 var css, delta, recalced, scroll, will_bottom, win_height; 26353 if (detached) { 26354 return; 26355 } 26356 recalced = false; 26357 if (recalc_counter != null) { 26358 recalc_counter -= 1; 26359 if (recalc_counter <= 0) { 26360 recalc_counter = recalc_every; 26361 recalc(); 26362 recalced = true; 26363 } 26364 } 26365 if (!recalced && doc.height() !== last_scroll_height) { 26366 recalc(); 26367 recalced = true; 26368 } 26369 scroll = win.scrollTop(); 26370 if (last_pos != null) { 26371 delta = scroll - last_pos; 26372 } 26373 last_pos = scroll; 26374 if (fixed) { 26375 if (enable_bottoming) { 26376 will_bottom = scroll + height + offset > parent_height + parent_top; 26377 if (bottomed && !will_bottom) { 26378 bottomed = false; 26379 elm.css({ 26380 position: "fixed", 26381 bottom: "", 26382 top: offset 26383 }).trigger("sticky_kit:unbottom"); 26384 } 26385 } 26386 if (scroll < top) { 26387 fixed = false; 26388 offset = offset_top; 26389 if (manual_spacer == null) { 26390 if (el_float === "left" || el_float === "right") { 26391 elm.insertAfter(spacer); 26392 } 26393 spacer.detach(); 26394 } 26395 css = { 26396 position: "", 26397 width: "", 26398 top: "" 26399 }; 26400 elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick"); 26401 } 26402 if (inner_scrolling) { 26403 win_height = win.height(); 26404 if (height + offset_top > win_height) { 26405 if (!bottomed) { 26406 offset -= delta; 26407 offset = Math.max(win_height - height, offset); 26408 offset = Math.min(offset_top, offset); 26409 if (fixed) { 26410 elm.css({ 26411 top: offset + "px" 26412 }); 26413 } 26414 } 26415 } 26416 } 26417 } else { 26418 if (scroll > top) { 26419 fixed = true; 26420 css = { 26421 position: "fixed", 26422 top: offset 26423 }; 26424 css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px"; 26425 elm.css(css).addClass(sticky_class); 26426 if (manual_spacer == null) { 26427 elm.after(spacer); 26428 if (el_float === "left" || el_float === "right") { 26429 spacer.append(elm); 26430 } 26431 } 26432 elm.trigger("sticky_kit:stick"); 26433 } 26434 } 26435 if (fixed && enable_bottoming) { 26436 if (will_bottom == null) { 26437 will_bottom = scroll + height + offset > parent_height + parent_top; 26438 } 26439 if (!bottomed && will_bottom) { 26440 bottomed = true; 26441 if (parent.css("position") === "static") { 26442 parent.css({ 26443 position: "relative" 26444 }); 26445 } 26446 return elm.css({ 26447 position: "absolute", 26448 bottom: padding_bottom, 26449 top: "auto" 26450 }).trigger("sticky_kit:bottom"); 26451 } 26452 } 26453 }; 26454 recalc_and_tick = function() { 26455 recalc(); 26456 return tick(); 26457 }; 26458 detach = function() { 26459 detached = true; 26460 win.off("touchmove", tick); 26461 win.off("scroll", tick); 26462 win.off("resize", recalc_and_tick); 26463 $(document.body).off("sticky_kit:recalc", recalc_and_tick); 26464 elm.off("sticky_kit:detach", detach); 26465 elm.removeData("sticky_kit"); 26466 elm.css({ 26467 position: "", 26468 bottom: "", 26469 top: "", 26470 width: "" 26471 }); 26472 parent.position("position", ""); 26473 if (fixed) { 26474 if (manual_spacer == null) { 26475 if (el_float === "left" || el_float === "right") { 26476 elm.insertAfter(spacer); 26477 } 26478 spacer.remove(); 26479 } 26480 return elm.removeClass(sticky_class); 26481 } 26482 }; 26483 win.on("touchmove", tick); 26484 win.on("scroll", tick); 26485 win.on("resize", recalc_and_tick); 26486 $(document.body).on("sticky_kit:recalc", recalc_and_tick); 26487 elm.on("sticky_kit:detach", detach); 26488 return setTimeout(tick, 0); 26489 }; 26490 for (i = 0, len = this.length; i < len; i++) { 26491 elm = this[i]; 26492 fn($(elm)); 26493 } 26494 return this; 26495 }; 26496 26497}).call(this); 26498/* ========================================================================== 26499 * bootstrap-tab-history.js 26500 * Author: Michael Narayan <[email protected]> 26501 * Repository: https://github.com/mnarayan01/bootstrap-tab-history/ 26502 * ========================================================================== 26503 * Licensed under the Apache License, Version 2.0 (the "License"); you may 26504 * not use this file except in compliance with the License. You may obtain a 26505 * copy of the License at 26506 * 26507 * http://www.apache.org/licenses/LICENSE-2.0 26508 * 26509 * Unless required by applicable law or agreed to in writing, softw
26509are 26510 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 26511 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 26512 * License for the specific language governing permissions and limitations 26513 * under the License. 26514 * ========================================================================== */ 26515 26516/* ========================================================================== */ 26517/* JSHint directives */ 26518/* */ 26519/* global BootstrapTabHistory: true */ 26520/* */ 26521/* global document */ 26522/* global jQuery */ 26523/* global history */ 26524/* global window */ 26525/* ========================================================================== */ 26526 26527/** 26528 * Integrate [HTML5 history state tracking](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history) 26529 * with [`bootstrap/tab.js`](http://getbootstrap.com/javascript/#tabs). To enable tracking on a tab element, simply set 26530 * the `data-tab-history` attribute to true (or a string denoting a tab grouping). 26531 * 26532 * See the README for additional information. 26533 * 26534 * Functionality based upon bootstrap/tab.js v3.1.0; reference it when making any changes. 26535 */ 26536 26537BootstrapTabHistory = { 26538 options: { 26539 /** 26540 * When the anchor portion of the URI is used to activate a tab, scroll down to the given offset, rather than the 26541 * element with the given `id` attribute. Set to null to disable. Only relevant if showTabsBasedOnAnchor is true. 26542 * 26543 * May be overriden on a per-element basis by the attribute `data-tab-history-anchor-y-offset`. 26544 * 26545 * @public 26546 * @type {?number} 26547 */ 26548 defaultAnchorYOffset: 0, 26549 /** 26550 * Either 'push' or 'replace', for whether to use `history.pushState` or `history.replaceState`, resp. 26551 * 26552 * May be overriden on a per-element basis by the attribute `data-tab-history-changer`. 26553 * 26554 * @public 26555 * @type {string} 26556 */ 26557 defaultChanger: 'replace', 26558 /** 26559 * If true, update the URL in onShownTab in the calls to `history.pushState` and `history.replaceState`. Otherwise, 26560 * `null` is passed as the third parameter to these calls. 26561 * 26562 * May be overriden on a per-element basis by the attribute `data-tab-history-update-url`. 26563 * 26564 * @public 26565 * @type {boolean} 26566 */ 26567 defaultUpdateURL: false, 26568 /** 26569 * Should the anchor portion of the loaded URI be used to activate a single tab if no history was present on page 26570 * load. 26571 * 26572 * @public 26573 * @type {boolean} 26574 */ 26575 showTabsBasedOnAnchor: true 26576 } 26577}; 26578 26579(function () { 26580 'use strict'; 26581 26582 jQuery(function () { 26583 if(history && history.pushState && history.replaceState) { 26584 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 26585 26586 if(bootstrapTabHistory) { 26587 showTabsBasedOnState(bootstrapTabHistory); 26588 } else { 26589 showTabsBasedOnAnchor(); 26590 } 26591 26592 backfillHistoryState(); 26593 26594 jQuery(document).on('shown.bs.tab show.bs.collapse', onShownTab); 26595 jQuery(window).on('popstate', onPopState); 26596 } else { 26597 showTabsBasedOnAnchor(); 26598 } 26599 }); 26600 26601 /** 26602 * Used to prevent onShownTab from registering shown events that we triggered via showTabsBasedOnState. 26603 * 26604 * @type {boolean} 26605 */ 26606 var showingTabsBasedOnState = false; 26607 26608 /** 26609 * Used to update `history.state` to reflect the default active tabs on initial page load. This supports proper 26610 * `history.back` handling when `data-tab-history-update-url` is true. 26611 */ 26612 function backfillHistoryState() { 26613 var newState = null; 26614 26615 jQuery('li.active > [data-tab-history], .panel-title.active [data-tab-history]').each(function () {//edited by Uncode 26616 var $activeTabElement = jQuery(this); 26617 var selector = getTabSelector($activeTabElement); 26618 26619 if(selector) { 26620 var tabGroup = getTabGroup($activeTabElement); 26621 26622 if(tabGroup) { 26623 newState = createNewHistoryState(newState || history.state, tabGroup, selector); 26624 } 26625 } 26626 }); 26627 26628 if(newState) { 26629 history.replaceState(newState, '', null); 26630 } 26631 } 26632 26633 /** 26634 * Clone the existing state, ensure its bootstrapTabHistory attribute is an Object, and add the provided tabGroup to 26635 * said bootstrapTabHistory attribute. 26636 * 26637 * @param {?object} existingState 26638 * @param {!string} tabGroup 26639 * @param {!string} selector 26640 * @returns {!object} 26641 */ 26642 function createNewHistoryState(existingState, tabGroup, selector) { 26643 // Clone history.state and ensure it has a bootstrapTabHistory entry. 26644 var newState = jQuery.extend(true, {}, existingState, { 26645 bootstrapTabHistory: {} 26646 }); 26647 26648 newState.bootstrapTabHistory[tabGroup] = selector; 26649 26650 return newState; 26651 } 26652 26653 /** 26654 * @param {jQuery} $tab
26655 * @returns {?string} 26656 */ 26657 function getTabGroup($tab) { 26658 return parseTruthyAttributeValue($tab.data('tab-history')); 26659 } 26660 26661 /** 26662 * @param {jQuery} $tab 26663 * @returns {?string} 26664 */ 26665 function getTabSelector($tab) { 26666 return $tab.data('target') || $tab.attr('href'); 26667 } 26668 26669 /** 26670 * Receives the `shown.bs.tab` event. Updates `history.state` as appropriate. 26671 * 26672 * @param {jQuery.Event} shownEvt 26673 */ 26674 function onShownTab(shownEvt) { 26675 if(!showingTabsBasedOnState) { 26676 var $activatedTab = jQuery(shownEvt.target); 26677 if ( $activatedTab.hasClass('panel-collapse') ) 26678 $activatedTab = $activatedTab.closest('.panel').find('a'); 26679 var selector = getTabSelector($activatedTab); 26680 26681 if(selector) { 26682 var tabGroup = getTabGroup($activatedTab); 26683 26684 if(tabGroup) { 26685 var historyChanger = $activatedTab.data('tab-history-changer') || BootstrapTabHistory.options.defaultChanger; 26686 var newState = createNewHistoryState(history.state, tabGroup, selector); 26687 var updateURL = (function ($activatedTab) { 26688 if(selector[0] === '#') { 26689 var elementUpdateURLOption = parseTruthyAttributeValue($activatedTab.data('tab-history-update-url')); 26690 26691 if(elementUpdateURLOption === undefined) { 26692 return BootstrapTabHistory.options.defaultUpdateURL; 26693 } else { 26694 return elementUpdateURLOption; 26695 } 26696 } else { 26697 return false; 26698 } 26699 })($activatedTab); 26700 26701 switch(historyChanger) { 26702 case 'push': 26703 history.pushState(newState, '', updateURL ? selector : null); 26704 break; 26705 case 'replace': 26706 history.replaceState(newState, '', updateURL ? selector : null); 26707 break; 26708 default: 26709 throw new Error('Unknown tab-history-changer: ' + historyChanger); 26710 } 26711 } 26712 } 26713 } 26714 } 26715 26716 /** 26717 * Receives the `popstate` event. Shows tabs based on the value of `history.state` as appropriate. 26718 */ 26719 function onPopState() { 26720 var bootstrapTabHistory = history.state && history.state.bootstrapTabHistory; 26721 26722 if(bootstrapTabHistory) { 26723 showTabsBasedOnState(bootstrapTabHistory); 26724 } 26725 } 26726 26727 /** 26728 * Returns the given value, _unless_ that value is an empty string, in which case `true` is returned. 26729 * 26730 * Rationale: HAML data attributes which are set to `true` are rendered as a blank string. 26731 * 26732 * @param {*} value 26733 * @returns {*} 26734 */ 26735 function parseTruthyAttributeValue(value) { 26736 if(value) { 26737 return value; 26738 } else if(value === '') { 26739 return true; 26740 } else { 26741 return value; 26742 } 26743 } 26744 26745 /** 26746 * Show tabs based upon the anchor component of `window.location`. 26747 */ 26748 function showTabsBasedOnAnchor() { 26749 if(BootstrapTabHistory.options.showTabsBasedOnAnchor) { 26750 var anchor = window.location && window.location.hash; 26751 26752 if(anchor) { 26753 var $tabElement = showTabForSelector(anchor); 26754 26755 if($tabElement && window.addEventListener && window.removeEventListener) { 26756 var anchorYOffset = (function ($tabElement) { 26757 var elementSetting = $tabElement.data('tab-history-anchor-y-offset'); 26758 26759 if(elementSetting === undefined) { 26760 return BootstrapTabHistory.options.defaultAnchorYOffset; 26761 } else { 26762 return elementSetting; 26763 } 26764 })($tabElement); 26765 26766 // HACK: This prevents scrolling to the tab on page load. This relies on the fact that we should never get 26767 // here on `history.forward`, `history.back`, or `location.reload`, since in all those situations the 26768 // `history.state` object should have been used (unless the browser did not support the modern History API). 26769 if(anchorYOffset || anchorYOffset === 0) { 26770 var scrollListener = function resetAnchorScroll () { 26771 window.removeEventListener('scroll', scrollListener); 26772 window.scrollTo(0, anchorYOffset); 26773 }; 26774 26775 window.addEventListener('scroll', scrollListener); 26776 } 26777 } 26778 } 26779 } 26780 } 26781 26782 /** 26783 * Show a tab which corresponds to the provided selector. 26784 * 26785 * @param {string} selector - A CSS selector. 26786 * @returns {?jQuery} - The tab which was found to show (even if said tab was already active). 26787 */ 26788 function showTabForSelector(selector) { 26789 var $tabElement = (function (selector) { 26790 var $ret = null; 26791 26792 jQuery('[data-toggle="tab"], [data-toggle="pill"], [data-toggle="collapse"]').each(function () { 26793 var $potentialTab = jQuery(this); 26794 26795 if(($potentialTab.attr('href') === selector || $potentialTab.data('target') === selector ) && getTabGroup($potentialTab)) { 26796 $ret = $potentialTab; 26797 return false;
vendor: 43,417 bytes, lines 26798-28012
26798 } else { 26799 return null; 26800 } 26801 }); 26802 26803 return $ret; 26804 })(selector); 26805 26806 if($tabElement) { 26807 $tabElement.trigger('click'); 26808 //$tabElement.tab('show'); 26809 } 26810 26811 return $tabElement; 26812 } 26813 26814 /** 26815 * Iterate through the provided set of tab tab groups, showing the tabs based on the stored selectors. 26816 * 26817 * @param {object} bootstrapTabHistory - Each of the values is passed to showTabForSelector; the keys are actually irrelevant. 26818 */ 26819 function showTabsBasedOnState(bootstrapTabHistory) { 26820 showingTabsBasedOnState = true; 26821 26822 try { 26823 for(var k in bootstrapTabHistory) { 26824 if(bootstrapTabHistory.hasOwnProperty(k)) { 26825 showTabForSelector(bootstrapTabHistory[k]); 26826 } 26827 } 26828 } finally { 26829 showingTabsBasedOnState = false; 26830 } 26831 } 26832})(); 26833 26834/*! 26835 * justifiedGallery - v3.8.1 26836 * http://miromannino.github.io/Justified-Gallery/ 26837 * Copyright (c) 2020 Miro Mannino 26838 * Licensed under the MIT license. 26839 */ 26840(function (factory) { 26841 if (typeof define === 'function' && define.amd) { 26842 // AMD. Register as an anonymous module. 26843 define(['jquery'], factory); 26844 } else if (typeof module === 'object' && module.exports) { 26845 // Node/CommonJS 26846 module.exports = function (root, jQuery) { 26847 if (jQuery === undefined) { 26848 // require('jQuery') returns a factory that requires window to 26849 // build a jQuery instance, we normalize how we use modules 26850 // that require this pattern but the window provided is a noop 26851 // if it's defined (how jquery works) 26852 if (typeof window !== 'undefined') { 26853 jQuery = require('jquery'); 26854 } 26855 else { 26856 jQuery = require('jquery')(root); 26857 } 26858 } 26859 factory(jQuery); 26860 return jQuery; 26861 }; 26862 } else { 26863 // Browser globals 26864 factory(jQuery); 26865 } 26866}(function ($) { 26867 26868 /** 26869 * Justified Gallery controller constructor 26870 * 26871 * @param $gallery the gallery to build 26872 * @param settings the settings (the defaults are in JustifiedGallery.defaults) 26873 * @constructor 26874 */ 26875 var JustifiedGallery = function ($gallery, settings) { 26876 26877 this.settings = settings; 26878 this.checkSettings(); 26879 26880 this.imgAnalyzerTimeout = null; 26881 this.entries = null; 26882 this.buildingRow = { 26883 entriesBuff: [], 26884 width: 0, 26885 height: 0, 26886 aspectRatio: 0 26887 }; 26888 this.lastFetchedEntry = null; 26889 this.lastAnalyzedIndex = -1; 26890 this.yield = { 26891 every: 2, // do a flush every n flushes (must be greater than 1) 26892 flushed: 0 // flushed rows without a yield 26893 }; 26894 this.border = settings.border >= 0 ? settings.border : settings.margins; 26895 this.maxRowHeight = this.retrieveMaxRowHeight(); 26896 this.suffixRanges = this.retrieveSuffixRanges(); 26897 this.offY = this.border; 26898 this.rows = 0; 26899 this.spinner = { 26900 phase: 0, 26901 timeSlot: 150, 26902 $el: $('<div class="jg-spinner"><span></span><span></span><span></span></div>'), 26903 intervalId: null 26904 }; 26905 this.scrollBarOn = false; 26906 this.checkWidthIntervalId = null; 26907 this.galleryWidth = $gallery.width(); 26908 this.$gallery = $gallery; 26909 26910 }; 26911 26912 /** @returns {String} the best suffix given the width and the height */ 26913 JustifiedGallery.prototype.getSuffix = function (width, height) { 26914 var longestSide, i; 26915 longestSide = (width > height) ? width : height; 26916 for (i = 0; i < this.suffixRanges.length; i++) { 26917 if (longestSide <= this.suffixRanges[i]) { 26918 return this.settings.sizeRangeSuffixes[this.suffixRanges[i]]; 26919 } 26920 } 26921 return this.settings.sizeRangeSuffixes[this.suffixRanges[i - 1]]; 26922 }; 26923 26924 /** 26925 * Remove the suffix from the string 26926 * 26927 * @returns {string} a new string without the suffix 26928 */ 26929 JustifiedGallery.prototype.removeSuffix = function (str, suffix) { 26930 return str.substring(0, str.length - suffix.length); 26931 }; 26932 26933 /** 26934 * @returns {boolean} a boolean to say if the suffix is contained in the str or not 26935 */ 26936 JustifiedGallery.prototype.endsWith = function (str, suffix) { 26937 return str.indexOf(suffix, str.length - suffix.length) !== -1; 26938 }; 26939 26940 /** 26941 * Get the used suffix of a particular url 26942 * 26943 * @param str 26944 * @returns {String} return the used suffix 26945 */ 26946 JustifiedGallery.prototype.getUsedSuffix = function (str) { 26947 for (var si in this.settings.sizeRangeSuffixes) { 26948 if (this.settings.sizeRangeSuffixes.hasOwnProperty(si)) { 26949 if (this.settings.sizeRangeSuffixes[si].length === 0) continue; 26950 if (this.endsWith(str, this.settings.sizeRangeSuffixes[si])) return this.settings.sizeRangeSuffixes[si]; 26951 } 26952 } 26953 return ''; 26954 }; 26955 26956 /** 26957 * Given an image src, with the width and the height, returns the new image src with the 26958 * best suffix to show the best quality thumbnail. 26959 * 26960 * @returns {String} the suffix to use 26961 */ 26962 JustifiedGallery.prototype.newSrc = function (imageSrc, imgWidth, imgHeight, image) { 26963 var newImageSrc; 26964 26965 if (this.settings.thumbnailPath) { 26966 newImageSrc = this.settings.thumbnailPath(imageSrc, imgWidth, imgHeight, image); 26967 } else { 26968 var matchRes = imageSrc.match(this.settings.extension); 26969 var ext = (matchRes !== null) ? matchRes[0] : ''; 26970 newImageSrc = imageSrc.replace(this.settings.extension, ''); 26971 newImageSrc = this.removeSuffix(newImageSrc, this.getUsedSuffix(newImageSrc)); 26972 newImageSrc += this.getSuffix(imgWidth, imgHeight) + ext; 26973 } 26974 26975 return newImageSrc; 26976 }; 26977 26978 /** 26979 * Shows the images that is in the given entry 26980 * 26981 * @param $entry the entry 26982 * @param callback the callback that is called when the show animation is finished 26983 */ 26984 JustifiedGallery.prototype.showImg = function ($entry, callback) { 26985 if (this.settings.cssAnimation) { 26986 $entry.addClass('jg-entry-visible'); 26987 if (callback) callback(); 26988 } else { 26989 $entry.stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 26990 $entry.find(this.settings.imgSelector).stop().fadeTo(this.settings.imagesAnimationDuration, 1.0, callback); 26991 } 26992 }; 26993 26994 /** 26995 * Extract the image src form the image, looking from the 'safe-src', and if it can't be found, from the 26996 * 'src' attribute. It saves in the image data the 'jg.originalSrc' field, with the extracted src. 26997 * 26998 * @param $image the image to analyze 26999 * @returns {String} the extracted src 27000 */ 27001 JustifiedGallery.prototype.extractImgSrcFromImage = function ($image) { 27002 var imageSrc = $image.data('safe-src'); 27003 var imageSrcLoc = 'data-safe-src'; 27004 // Begin Uncode edit 27005 if (typeof imageSrc === 'undefined') { 27006 var imageCurrentSrc = $image[0].currentSrc; 27007 if (imageCurrentSrc) { 27008 imageSrc = imageCurrentSrc; 27009 } else { 27010 imageSrc = $image.attr('src'); 27011 } 27012 imageSrcLoc = 'src'; 27013 } 27014 // End Uncode edit 27015 $image.data('jg.originalSrc', imageSrc); // this is saved for the destroy method 27016 $image.data('jg.src', imageSrc); // this will change overtime 27017 $image.data('jg.originalSrcLoc', imageSrcLoc); // this is saved for the destroy method 27018 return imageSrc; 27019 }; 27020 27021 /** @returns {jQuery} the image in the given entry */ 27022 JustifiedGallery.prototype.imgFromEntry = function ($entry) { 27023 var $img = $entry.find(this.settings.imgSelector); 27024 if ($img.length === 0) $img = $entry.find('.t-entry-visual-cont img');//hacked by Uncode 27025 return $img.length === 0 ? null : $img; 27026 }; 27027 27028 /** @returns {jQuery} the caption in the given entry */ 27029 JustifiedGallery.prototype.captionFromEntry = function ($entry) { 27030 var $caption = $entry.find('> .jg-caption'); 27031 return $caption.length === 0 ? null : $caption; 27032 }; 27033 27034 /** 27035 * Display the entry 27036 * 27037 * @param {jQuery} $entry the entry to display 27038 * @param {int} x the x position where the entry must be positioned 27039 * @param y the y position where the entry must be positioned 27040 * @param imgWidth the image width 27041 * @param imgHeight the image height 27042 * @param rowHeight the row height of the row that owns the entry 27043 */ 27044 JustifiedGallery.prototype.displayEntry = function ($entry, x, y, imgWidth, imgHeight, rowHeight) { 27045 $entry.width(imgWidth); 27046 $entry.height(Math.floor(rowHeight));//hacked by Uncode 27047 $entry.css('top', Math.floor(y));//hacked by Uncode 27048 $entry.css('left', x); 27049 27050 var $image = this.imgFromEntry($entry); 27051 if ($image !== null) { 27052 $image.css('width', imgWidth); 27053 $image.css('height', imgHeight); 27054 $image.css('margin-left', - imgWidth / 2); 27055 $image.css('margin-top', - imgHeight / 2); 27056 27057 // Image reloading for an high quality of thumbnails 27058 var imageSrc = $image.data('jg.src'); 27059 if (imageSrc) { 27060 imageSrc = this.newSrc(imageSrc, imgWidth, imgHeight, $image[0]); 27061 27062 $image.one('error', function () { 27063 this.resetImgSrc($image); //revert to the original thumbnail 27064 }); 27065 27066 var loadNewImage = function () { 27067 // if (imageSrc !== newImageSrc) { 27068 $image.attr('src', imageSrc); 27069 // } 27070 }; 27071 27072 if ($entry.data('jg.loaded') === 'skipped' && imageSrc) { 27073 this.onImageEvent(imageSrc, (function() { 27074 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 27075 $entry.data('jg.loaded', true); 27076 }).bind(this)); 27077 } else { 27078 this.showImg($entry, loadNewImage); //load the new image after the fadeIn 27079 } 27080 27081 } 27082 27083 } else { 27084 this.showImg($entry); 27085 } 27086 27087 this.displayEntryCaption($entry); 27088 }; 27089 27090 /** 27091 * Display the entry caption. If the caption element doesn't exists, it creates the caption using the 'alt' 27092 * or the 'title' attributes. 27093 * 27094 * @param {jQuery} $entry the entry to process 27095 */ 27096 JustifiedGallery.prototype.displayEntryCaption = function ($entry) { 27097 var $image = this.imgFromEntry($entry); 27098 if ($image !== null && this.settings.captions) { 27099 var $imgCaption = this.captionFromEntry($entry); 27100 27101 // Create it if it doesn't exists 27102 if ($imgCaption === null) { 27103 var caption = $image.attr('alt'); 27104 if (!this.isValidCaption(caption)) caption = $entry.attr('title'); 27105 if (this.isValidCaption(caption)) { // Create only we found something 27106 $imgCaption = $('<div class="jg-caption">' + caption + '</div>'); 27107 $entry.append($imgCaption); 27108 $entry.data('jg.createdCaption', true); 27109 } 27110 } 27111 27112 // Create events (we check again the $imgCaption because it can be still inexistent) 27113 if ($imgCaption !== null) { 27114 if (!this.settings.cssAnimation) $imgCaption.stop().fadeTo(0, this.settings.captionSettings.nonVisibleOpacity); 27115 this.addCaptionEventsHandlers($entry); 27116 } 27117 } else { 27118 this.removeCaptionEventsHandlers($entry); 27119 } 27120 }; 27121 27122 /** 27123 * Validates the caption 27124 * 27125 * @param caption The caption that should be validated 27126 * @return {boolean} Validation result 27127 */ 27128 JustifiedGallery.prototype.isValidCaption = function (caption) { 27129 return (typeof caption !== 'undefined' && caption.length > 0); 27130 }; 27131 27132 /** 27133 * The callback for the event 'mouseenter'. It assumes that the event currentTarget is an entry. 27134 * It shows the caption using jQuery (or using CSS if it is configured so) 27135 * 27136 * @param {Event} eventObject the event object 27137 */ 27138 JustifiedGallery.prototype.onEntryMouseEnterForCaption = function (eventObject) { 27139 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 27140 if (this.settings.cssAnimation) { 27141 $caption.addClass('jg-caption-visible').removeClass('jg-caption-hidden'); 27142 } else { 27143 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 27144 this.settings.captionSettings.visibleOpacity); 27145 } 27146 }; 27147 27148 /** 27149 * The callback for the event 'mouseleave'. It assumes that the event currentTarget is an entry. 27150 * It hides the caption using jQuery (or using CSS if it is configured so) 27151 * 27152 * @param {Event} eventObject the event object 27153 */ 27154 JustifiedGallery.prototype.onEntryMouseLeaveForCaption = function (eventObject) { 27155 var $caption = this.captionFromEntry($(eventObject.currentTarget)); 27156 if (this.settings.cssAnimation) { 27157 $caption.removeClass('jg-caption-visible').removeClass('jg-caption-hidden'); 27158 } else { 27159 $caption.stop().fadeTo(this.settings.captionSettings.animationDuration, 27160 this.settings.captionSettings.nonVisibleOpacity); 27161 } 27162 }; 27163 27164 /** 27165 * Add the handlers of the entry for the caption 27166 * 27167 * @param $entry the entry to modify 27168 */ 27169 JustifiedGallery.prototype.addCaptionEventsHandlers = function ($entry) { 27170 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 27171 if (typeof captionMouseEvents === 'undefined') { 27172 captionMouseEvents = { 27173 mouseenter: $.proxy(this.onEntryMouseEnterForCaption, this), 27174 mouseleave: $.proxy(this.onEntryMouseLeaveForCaption, this) 27175 }; 27176 $entry.on('mouseenter', undefined, undefined, captionMouseEvents.mouseenter); 27177 $entry.on('mouseleave', undefined, undefined, captionMouseEvents.mouseleave); 27178 $entry.data('jg.captionMouseEvents', captionMouseEvents); 27179 } 27180 }; 27181 27182 /** 27183 * Remove the handlers of the entry for the caption 27184 * 27185 * @param $entry the entry to modify 27186 */ 27187 JustifiedGallery.prototype.removeCaptionEventsHandlers = function ($entry) { 27188 var captionMouseEvents = $entry.data('jg.captionMouseEvents'); 27189 if (typeof captionMouseEvents !== 'undefined') { 27190 $entry.off('mouseenter', undefined, captionMouseEvents.mouseenter); 27191 $entry.off('mouseleave', undefined, captionMouseEvents.mouseleave); 27192 $entry.removeData('jg.captionMouseEvents'); 27193 } 27194 }; 27195 27196 /** 27197 * Clear the building row data to be used for a new row 27198 */ 27199 JustifiedGallery.prototype.clearBuildingRow = function () { 27200 this.buildingRow.entriesBuff = []; 27201 this.buildingRow.aspectRatio = 0; 27202 this.buildingRow.width = 0; 27203 }; 27204 27205 /** 27206 * Justify the building row, preparing it to 27207 * 27208 * @param isLastRow 27209 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 27210 * @returns a boolean to know if the row has been justified or not 27211 */ 27212 JustifiedGallery.prototype.prepareBuildingRow = function (isLastRow, hiddenRow) { 27213 var i, $entry, imgAspectRatio, newImgW, newImgH, justify = true; 27214 var minHeight = 0; 27215 var availableWidth = this.galleryWidth - 2 * this.border - ( 27216 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 27217 var rowHeight = Math.floor( availableWidth / this.buildingRow.aspectRatio );//hacked by Uncode 27218 var defaultRowHeight = this.settings.rowHeight; 27219 var justifiable = this.buildingRow.width / availableWidth > this.settings.justifyThreshold; 27220 27221 //Skip the last row if we can't justify it and the lastRow == 'hide' 27222 if (hiddenRow || (isLastRow && this.settings.lastRow === 'hide' && !justifiable)) { 27223 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 27224 $entry = this.buildingRow.entriesBuff[i]; 27225 if (this.settings.cssAnimation) 27226 $entry.removeClass('jg-entry-visible'); 27227 else { 27228 $entry.stop().fadeTo(0, 0.1); 27229 $entry.find('> img, > a > img').fadeTo(0, 0); 27230 } 27231 } 27232 return -1; 27233 } 27234 27235 // With lastRow = nojustify, justify if is justificable (the images will not become too big) 27236 if (isLastRow && !justifiable && this.settings.lastRow !== 'justify' && this.settings.lastRow !== 'hide') { 27237 justify = false; 27238 27239 if (this.rows > 0) { 27240 defaultRowHeight = (this.offY - this.border - this.settings.margins * this.rows) / this.rows; 27241 justify = defaultRowHeight * this.buildingRow.aspectRatio / availableWidth > this.settings.justifyThreshold; 27242 } 27243 } 27244 27245 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 27246 $entry = this.buildingRow.entriesBuff[i]; 27247 imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 27248 27249 if (justify) { 27250 newImgW = (i === this.buildingRow.entriesBuff.length - 1) ? availableWidth : rowHeight * imgAspectRatio; 27251 newImgH = rowHeight; 27252 } else { 27253 newImgW = defaultRowHeight * imgAspectRatio; 27254 newImgH = defaultRowHeight; 27255 } 27256 27257 availableWidth -= Math.round(newImgW); 27258 $entry.data('jg.jwidth', Math.round(newImgW)); 27259 $entry.data('jg.jheight', Math.ceil(newImgH)); 27260 if (i === 0 || minHeight > newImgH) minHeight = newImgH; 27261 } 27262 27263 this.buildingRow.height = minHeight; 27264 return justify; 27265 }; 27266 27267 /** 27268 * Flush a row: justify it, modify the gallery height accordingly to the row height 27269 * 27270 * @param isLastRow 27271 * @param hiddenRow undefined or false for normal behavior. hiddenRow = true to hide the row. 27272 */ 27273 JustifiedGallery.prototype.flushRow = function (isLastRow, hiddenRow) { 27274 var settings = this.settings; 27275 var $entry, buildingRowRes, offX = this.border, i; 27276 27277 buildingRowRes = this.prepareBuildingRow(isLastRow, hiddenRow); 27278 if (hiddenRow || (isLastRow && settings.lastRow === 'hide' && buildingRowRes === -1)) { 27279 this.clearBuildingRow(); 27280 return; 27281 } 27282 27283 if (this.maxRowHeight) { 27284 if (this.maxRowHeight < this.buildingRow.height) this.buildingRow.height = this.maxRowHeight; 27285 } 27286 27287 //Align last (unjustified) row 27288 if (isLastRow && (settings.lastRow === 'center' || settings.lastRow === 'right')) { 27289 var availableWidth = this.galleryWidth - 2 * this.border - (this.buildingRow.entriesBuff.length - 1) * settings.margins; 27290 27291 for (i = 0; i < this.buildingRow.entriesBuff.length; i++) { 27292 $entry = this.buildingRow.entriesBuff[i]; 27293 availableWidth -= $entry.data('jg.jwidth'); 27294 } 27295 27296 if (settings.lastRow === 'center') 27297 offX += Math.round(availableWidth / 2); 27298 else if (settings.lastRow === 'right') 27299 offX += availableWidth; 27300 } 27301 27302 var lastEntryIdx = this.buildingRow.entriesBuff.length - 1; 27303 for (i = 0; i <= lastEntryIdx; i++) { 27304 $entry = this.buildingRow.entriesBuff[this.settings.rtl ? lastEntryIdx - i : i]; 27305 this.displayEntry($entry, offX, this.offY, $entry.data('jg.jwidth'), $entry.data('jg.jheight'), this.buildingRow.height); 27306 offX += $entry.data('jg.jwidth') + settings.margins; 27307 } 27308 27309 //Gallery Height 27310 this.galleryHeightToSet = this.offY + this.buildingRow.height + this.border; 27311 this.setGalleryTempHeight(this.galleryHeightToSet + this.getSpinnerHeight()); 27312 27313 if (!isLastRow || (this.buildingRow.height <= settings.rowHeight && buildingRowRes)) { 27314 //Ready for a new row 27315 this.offY += this.buildingRow.height + settings.margins; 27316 this.rows += 1; 27317 this.clearBuildingRow(); 27318 this.settings.triggerEvent.call(this, 'jg.rowflush'); 27319 } 27320 }; 27321 27322 27323 // Scroll position not restoring: https://github.com/miromannino/Justified-Gallery/issues/221 27324 var galleryPrevStaticHeight = 0; 27325 27326 JustifiedGallery.prototype.rememberGalleryHeight = function () { 27327 galleryPrevStaticHeight = this.$gallery.height(); 27328 this.$gallery.height(galleryPrevStaticHeight); 27329 }; 27330 27331 // grow only 27332 JustifiedGallery.prototype.setGalleryTempHeight = function (height) { 27333 galleryPrevStaticHeight = Math.max(height, galleryPrevStaticHeight); 27334 this.$gallery.height(galleryPrevStaticHeight); 27335 }; 27336 27337 JustifiedGallery.prototype.setGalleryFinalHeight = function (height) { 27338 galleryPrevStaticHeight = height; 27339 this.$gallery.height(height); 27340 }; 27341 27342 /** 27343 * Checks the width of the gallery container, to know if a new justification is needed 27344 */ 27345 JustifiedGallery.prototype.checkWidth = function () { 27346 this.checkWidthIntervalId = setInterval($.proxy(function () { 27347 27348 // if the gallery is not currently visible, abort. 27349 if (!this.$gallery.is(":visible")) return; 27350 27351 var galleryWidth = parseFloat(this.$gallery.width()); 27352 if (Math.abs(galleryWidth - this.galleryWidth) > this.settings.refreshSensitivity) { 27353 this.galleryWidth = galleryWidth; 27354 this.rewind(); 27355 27356 this.rememberGalleryHeight(); 27357 27358 // Restart to analyze 27359 this.startImgAnalyzer(true); 27360 } 27361 }, this), this.settings.refreshTime); 27362 }; 27363 27364 /** 27365 * @returns {boolean} a boolean saying if the spinner is active or not 27366 */ 27367 JustifiedGallery.prototype.isSpinnerActive = function () { 27368 return this.spinner.intervalId !== null; 27369 }; 27370 27371 /** 27372 * @returns {int} the spinner height 27373 */ 27374 JustifiedGallery.prototype.getSpinnerHeight = function () { 27375 return this.spinner.$el.innerHeight(); 27376 }; 27377 27378 /** 27379 * Stops the spinner animation and modify the gallery height to exclude the spinner 27380 */ 27381 JustifiedGallery.prototype.stopLoadingSpinnerAnimation = function () { 27382 clearInterval(this.spinner.intervalId); 27383 this.spinner.intervalId = null; 27384 this.setGalleryTempHeight(this.$gallery.height() - this.getSpinnerHeight()); 27385 this.spinner.$el.detach(); 27386 }; 27387 27388 /** 27389 * Starts the spinner animation 27390 */ 27391 JustifiedGallery.prototype.startLoadingSpinnerAnimation = function () { 27392 var spinnerContext = this.spinner; 27393 var $spinnerPoints = spinnerContext.$el.find('span'); 27394 clearInterval(spinnerContext.intervalId); 27395 this.$gallery.append(spinnerContext.$el); 27396 this.setGalleryTempHeight(this.offY + this.buildingRow.height + this.getSpinnerHeight()); 27397 spinnerContext.intervalId = setInterval(function () { 27398 if (spinnerContext.phase < $spinnerPoints.length) { 27399 $spinnerPoints.eq(spinnerContext.phase).fadeTo(spinnerContext.timeSlot, 1); 27400 } else { 27401 $spinnerPoints.eq(spinnerContext.phase - $spinnerPoints.length).fadeTo(spinnerContext.timeSlot, 0); 27402 } 27403 spinnerContext.phase = (spinnerContext.phase + 1) % ($spinnerPoints.length * 2); 27404 }, spinnerContext.timeSlot); 27405 }; 27406 27407 /** 27408 * Rewind the image analysis to start from the first entry. 27409 */ 27410 JustifiedGallery.prototype.rewind = function () { 27411 this.lastFetchedEntry = null; 27412 this.lastAnalyzedIndex = -1; 27413 this.offY = this.border; 27414 this.rows = 0; 27415 this.clearBuildingRow(); 27416 }; 27417 27418 /** 27419 * @returns {String} `settings.selector` rejecting spinner element 27420 */ 27421 JustifiedGallery.prototype.getSelectorWithoutSpinner = function () { 27422 return this.settings.selector + ', div:not(.jg-spinner)'; 27423 }; 27424 27425 /** 27426 * @returns {Array} all entries matched by `settings.selector` 27427 */ 27428 JustifiedGallery.prototype.getAllEntries = function () { 27429 var selector = this.getSelectorWithoutSpinner(); 27430 return this.$gallery.children(selector).toArray(); 27431 }; 27432 27433 /** 27434 * Update the entries searching it from the justified gallery HTML element 27435 * 27436 * @param norewind if norewind only the new entries will be changed (i.e. randomized, sorted or filtered) 27437 * @returns {boolean} true if some entries has been founded 27438 */ 27439 JustifiedGallery.prototype.updateEntries = function (norewind) { 27440 var newEntries; 27441 27442 if (norewind && this.lastFetchedEntry != null) { 27443 var selector = this.getSelectorWithoutSpinner(); 27444 newEntries = $(this.lastFetchedEntry).nextAll(selector).toArray(); 27445 } else { 27446 this.entries = []; 27447 newEntries = this.getAllEntries(); 27448 } 27449 27450 if (newEntries.length > 0) { 27451 27452 // Sort or randomize 27453 if ($.isFunction(this.settings.sort)) { 27454 newEntries = this.sortArray(newEntries); 27455 } else if (this.settings.randomize) { 27456 newEntries = this.shuffleArray(newEntries); 27457 } 27458 this.lastFetchedEntry = newEntries[newEntries.length - 1]; 27459 27460 // Filter 27461 if (this.settings.filter) { 27462 newEntries = this.filterArray(newEntries); 27463 } else { 27464 this.resetFilters(newEntries); 27465 } 27466 27467 } 27468 27469 this.entries = this.entries.concat(newEntries); 27470 return true; 27471 }; 27472 27473 /** 27474 * Apply the entries order to the DOM, iterating the entries and appending the images 27475 * 27476 * @param entries the entries that has been modified and that must be re-ordered in the DOM 27477 */ 27478 JustifiedGallery.prototype.insertToGallery = function (entries) { 27479 var that = this; 27480 $.each(entries, function () { 27481 $(this).appendTo(that.$gallery); 27482 }); 27483 }; 27484 27485 /** 27486 * Shuffle the array using the Fisher-Yates shuffle algorithm 27487 * 27488 * @param a the array to shuffle 27489 * @return the shuffled array 27490 */ 27491 JustifiedGallery.prototype.shuffleArray = function (a) { 27492 var i, j, temp; 27493 for (i = a.length - 1; i > 0; i--) { 27494 j = Math.floor(Math.random() * (i + 1)); 27495 temp = a[i]; 27496 a[i] = a[j]; 27497 a[j] = temp; 27498 } 27499 this.insertToGallery(a); 27500 return a; 27501 }; 27502 27503 /** 27504 * Sort the array using settings.comparator as comparator 27505 * 27506 * @param a the array to sort (it is sorted) 27507 * @return the sorted array 27508 */ 27509 JustifiedGallery.prototype.sortArray = function (a) { 27510 a.sort(this.settings.sort); 27511 this.insertToGallery(a); 27512 return a; 27513 }; 27514 27515 /** 27516 * Reset the filters removing the 'jg-filtered' class from all the entries 27517 * 27518 * @param a the array to reset 27519 */ 27520 JustifiedGallery.prototype.resetFilters = function (a) { 27521 for (var i = 0; i < a.length; i++) $(a[i]).removeClass('jg-filtered'); 27522 }; 27523 27524 /** 27525 * Filter the entries considering theirs classes (if a string has been passed) or using a function for filtering. 27526 * 27527 * @param a the array to filter 27528 * @return the filtered array 27529 */ 27530 JustifiedGallery.prototype.filterArray = function (a) { 27531 var settings = this.settings; 27532 if ($.type(settings.filter) === 'string') { 27533 // Filter only keeping the entries passed in the string 27534 return a.filter(function (el) { 27535 var $el = $(el); 27536 if ($el.is(settings.filter)) { 27537 $el.removeClass('jg-filtered'); 27538 return true; 27539 } else { 27540 $el.addClass('jg-filtered').removeClass('jg-visible'); 27541 return false; 27542 } 27543 }); 27544 } else if ($.isFunction(settings.filter)) { 27545 // Filter using the passed function 27546 var filteredArr = a.filter(settings.filter); 27547 for (var i = 0; i < a.length; i++) { 27548 if (filteredArr.indexOf(a[i]) === -1) { 27549 $(a[i]).addClass('jg-filtered').removeClass('jg-visible'); 27550 } else { 27551 $(a[i]).removeClass('jg-filtered'); 27552 } 27553 } 27554 return filteredArr; 27555 } 27556 }; 27557 27558 /** 27559 * Revert the image src to the default value. 27560 */ 27561 JustifiedGallery.prototype.resetImgSrc = function ($img) { 27562 if ($img.data('jg.originalSrcLoc') === 'src') { 27563 $img.attr('src', $img.data('jg.originalSrc')); 27564 } else { 27565 $img.attr('src', ''); 27566 } 27567 }; 27568 27569 /** 27570 * Destroy the Justified Gallery instance. 27571 * 27572 * It clears all the css properties added in the style attributes. We doesn't backup the original 27573 * values for those css attributes, because it costs (performance) and because in general one 27574 * shouldn't use the style attribute for an uniform set of images (where we suppose the use of 27575 * classes). Creating a backup is also difficult because JG could be called multiple times and 27576 * with different style attributes. 27577 */ 27578 JustifiedGallery.prototype.destroy = function () { 27579 clearInterval(this.checkWidthIntervalId); 27580 this.stopImgAnalyzerStarter(); 27581 27582 // Get fresh entries list since filtered entries are absent in `this.entries` 27583 $.each(this.getAllEntries(), $.proxy(function (_, entry) { 27584 var $entry = $(entry); 27585 27586 // Reset entry style 27587 $entry.css('width', ''); 27588 $entry.css('height', ''); 27589 $entry.css('top', ''); 27590 $entry.css('left', ''); 27591 $entry.data('jg.loaded', undefined); 27592 $entry.removeClass('jg-entry jg-filtered jg-entry-visible'); 27593 27594 // Reset image style 27595 var $img = this.imgFromEntry($entry); 27596 if ($img) { 27597 $img.css('width', ''); 27598 $img.css('height', ''); 27599 $img.css('margin-left', ''); 27600 $img.css('margin-top', ''); 27601 this.resetImgSrc($img); 27602 $img.data('jg.originalSrc', undefined); 27603 $img.data('jg.originalSrcLoc', undefined); 27604 $img.data('jg.src', undefined); 27605 } 27606 27607 // Remove caption 27608 this.removeCaptionEventsHandlers($entry); 27609 var $caption = this.captionFromEntry($entry); 27610 if ($entry.data('jg.createdCaption')) { 27611 // remove also the caption element (if created by jg) 27612 $entry.data('jg.createdCaption', undefined); 27613 if ($caption !== null) $caption.remove(); 27614 } else { 27615 if ($caption !== null) $caption.fadeTo(0, 1); 27616 } 27617 27618 }, this)); 27619 27620 this.$gallery.css('height', ''); 27621 this.$gallery.removeClass('justified-gallery'); 27622 this.$gallery.data('jg.controller', undefined); 27623 this.settings.triggerEvent.call(this, 'jg.destroy'); 27624 }; 27625 27626 /** 27627 * Analyze the images and builds the rows. It returns if it found an image that is not loaded. 27628 * 27629 * @param isForResize if the image analyzer is called for resizing or not, to call a different callback at the end 27630 */ 27631 JustifiedGallery.prototype.analyzeImages = function (isForResize) { 27632 for (var i = this.lastAnalyzedIndex + 1; i < this.entries.length; i++) { 27633 var $entry = $(this.entries[i]); 27634 if ($entry.data('jg.loaded') === true || $entry.data('jg.loaded') === 'skipped') { 27635 var availableWidth = this.galleryWidth - 2 * this.border - ( 27636 (this.buildingRow.entriesBuff.length - 1) * this.settings.margins); 27637 var imgAspectRatio = $entry.data('jg.width') / $entry.data('jg.height'); 27638 27639 this.buildingRow.entriesBuff.push($entry); 27640 this.buildingRow.aspectRatio += imgAspectRatio; 27641 this.buildingRow.width += imgAspectRatio * this.settings.rowHeight; 27642 this.lastAnalyzedIndex = i; 27643 27644 if (availableWidth / (this.buildingRow.aspectRatio + imgAspectRatio) < this.settings.rowHeight) { 27645 this.flushRow(false, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 27646 27647 if (++this.yield.flushed >= this.yield.every) { 27648 this.startImgAnalyzer(isForResize); 27649 return; 27650 } 27651 } 27652 } else if ($entry.data('jg.loaded') !== 'error') { 27653 return; 27654 } 27655 } 27656 27657 // Last row flush (the row is not full) 27658 if (this.buildingRow.entriesBuff.length > 0) { 27659 this.flushRow(true, this.settings.maxRowsCount > 0 && this.rows === this.settings.maxRowsCount); 27660 } 27661 27662 if (this.isSpinnerActive()) { 27663 this.stopLoadingSpinnerAnimation(); 27664 } 27665 27666 /* Stop, if there is, the timeout to start the analyzeImages. 27667 This is because an image can be set loaded, and the timeout can be set, 27668 but this image can be analyzed yet. 27669 */ 27670 this.stopImgAnalyzerStarter(); 27671 27672 this.setGalleryFinalHeight(this.galleryHeightToSet); 27673 27674 //On complete callback 27675 this.settings.triggerEvent.call(this, isForResize ? 'jg.resize' : 'jg.complete'); 27676 }; 27677 27678 /** 27679 * Stops any ImgAnalyzer starter (that has an assigned timeout) 27680 */ 27681 JustifiedGallery.prototype.stopImgAnalyzerStarter = function () { 27682 this.yield.flushed = 0; 27683 if (this.imgAnalyzerTimeout !== null) { 27684 clearTimeout(this.imgAnalyzerTimeout); 27685 this.imgAnalyzerTimeout = null; 27686 } 27687 }; 27688 27689 /** 27690 * Starts the image analyzer. It is not immediately called to let the browser to update the view 27691 * 27692 * @param isForResize specifies if the image analyzer must be called for resizing or not 27693 */ 27694 JustifiedGallery.prototype.startImgAnalyzer = function (isForResize) { 27695 var that = this; 27696 this.stopImgAnalyzerStarter(); 27697 this.imgAnalyzerTimeout = setTimeout(function () { 27698 that.analyzeImages(isForResize); 27699 }, 0.001); // we can't start it immediately due to a IE different behaviour 27700 }; 27701 27702 /** 27703 * Checks if the image is loaded or not using another image object. We cannot use the 'complete' image property, 27704 * because some browsers, with a 404 set complete = true. 27705 * 27706 * @param imageSrc the image src to load 27707 * @param onLoad callback that is called when the image has been loaded 27708 * @param onError callback that is called in case of an error 27709 */ 27710 JustifiedGallery.prototype.onImageEvent = function (imageSrc, onLoad, onError) { 27711 if (!onLoad && !onError) return; 27712 27713 var memImage = new Image(); 27714 var $memImage = $(memImage); 27715 if (onLoad) { 27716 $memImage.one('load', function () { 27717 $memImage.off('load error'); 27718 onLoad(memImage); 27719 }); 27720 } 27721 if (onError) { 27722 $memImage.one('error', function () { 27723 $memImage.off('load error'); 27724 onError(memImage); 27725 }); 27726 } 27727 memImage.src = imageSrc; 27728 }; 27729 27730 /** 27731 * Init of Justified Gallery controlled 27732 * It analyzes all the entries starting theirs loading and calling the image analyzer (that works with loaded images) 27733 */ 27734 JustifiedGallery.prototype.init = function () { 27735 var imagesToLoad = false, skippedImages = false, that = this; 27736 $.each(this.entries, function (index, entry) { 27737 var $entry = $(entry); 27738 var $image = that.imgFromEntry($entry); 27739 27740 $entry.addClass('jg-entry'); 27741 27742 if ($entry.data('jg.loaded') !== true && $entry.data('jg.loaded') !== 'skipped') { 27743 27744 // Link Rel global overwrite 27745 if (that.settings.rel !== null) $entry.attr('rel', that.settings.rel); 27746 27747 // Link Target global overwrite 27748 if (that.settings.target !== null) $entry.attr('target', that.settings.target); 27749 27750 if ($image !== null) { 27751 27752 // Image src 27753 var imageSrc = that.extractImgSrcFromImage($image); 27754 27755 /* If we have the height and the width, we don't wait that the image is loaded, 27756 but we start directly with the justification */ 27757 if (that.settings.waitThumbnailsLoad === false || !imageSrc) { 27758 var width = parseFloat($image.attr('width')); 27759 var height = parseFloat($image.attr('height')); 27760 if ($image.prop('tagName') === 'svg') { 27761 width = parseFloat($image[0].getBBox().width); 27762 height = parseFloat($image[0].getBBox().height); 27763 } 27764 if (!isNaN(width) && !isNaN(height)) { 27765 $entry.data('jg.width', width); 27766 $entry.data('jg.height', height); 27767 $entry.data('jg.loaded', 'skipped'); 27768 skippedImages = true; 27769 that.startImgAnalyzer(false); 27770 return true; // continue 27771 } 27772 } 27773 27774 $entry.data('jg.loaded', false); 27775 imagesToLoad = true; 27776 27777 // Spinner start 27778 if (!that.isSpinnerActive()) that.startLoadingSpinnerAnimation(); 27779 27780 that.onImageEvent(imageSrc, function (loadImg) { // image loaded 27781 $entry.data('jg.width', loadImg.width); 27782 $entry.data('jg.height', loadImg.height); 27783 $entry.data('jg.loaded', true); 27784 that.startImgAnalyzer(false); 27785 }, function () { // image load error 27786 $entry.data('jg.loaded', 'error'); 27787 that.startImgAnalyzer(false); 27788 }); 27789 27790 } else { 27791 $entry.data('jg.loaded', true); 27792 $entry.data('jg.width', $entry.width() | parseFloat($entry.css('width')) | 1); 27793 $entry.data('jg.height', $entry.height() | parseFloat($entry.css('height')) | 1); 27794 } 27795 27796 } 27797 27798 }); 27799 27800 if (!imagesToLoad && !skippedImages) this.startImgAnalyzer(false); 27801 this.checkWidth(); 27802 }; 27803 27804 /** 27805 * Checks that it is a valid number. If a string is passed it is converted to a number 27806 * 27807 * @param settingContainer the object that contains the setting (to allow the conversion) 27808 * @param settingName the setting name 27809 */ 27810 JustifiedGallery.prototype.checkOrConvertNumber = function (settingContainer, settingName) { 27811 if ($.type(settingContainer[settingName]) === 'string') { 27812 settingContainer[settingName] = parseFloat(settingContainer[settingName]); 27813 } 27814 27815 if ($.type(settingContainer[settingName]) === 'number') { 27816 if (isNaN(settingContainer[settingName])) throw 'invalid number for ' + settingName; 27817 } else { 27818 throw settingName + ' must be a number'; 27819 } 27820 }; 27821 27822 /** 27823 * Checks the sizeRangeSuffixes and, if necessary, converts 27824 * its keys from string (e.g. old settings with 'lt100') to int. 27825 */ 27826 JustifiedGallery.prototype.checkSizeRangesSuffixes = function () { 27827 if ($.type(this.settings.sizeRangeSuffixes) !== 'object') { 27828 throw 'sizeRangeSuffixes must be defined and must be an object'; 27829 } 27830 27831 var suffixRanges = []; 27832 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 27833 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(rangeIdx); 27834 } 27835 27836 var newSizeRngSuffixes = { 0: '' }; 27837 for (var i = 0; i < suffixRanges.length; i++) { 27838 if ($.type(suffixRanges[i]) === 'string') { 27839 try { 27840 var numIdx = parseInt(suffixRanges[i].replace(/^[a-z]+/, ''), 10); 27841 newSizeRngSuffixes[numIdx] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 27842 } catch (e) { 27843 throw 'sizeRangeSuffixes keys must contains correct numbers (' + e + ')'; 27844 } 27845 } else { 27846 newSizeRngSuffixes[suffixRanges[i]] = this.settings.sizeRangeSuffixes[suffixRanges[i]]; 27847 } 27848 } 27849 27850 this.settings.sizeRangeSuffixes = newSizeRngSuffixes; 27851 }; 27852 27853 /** 27854 * check and convert the maxRowHeight setting 27855 * requires rowHeight to be already set 27856 * TODO: should be always called when only rowHeight is changed 27857 * @return number or null 27858 */ 27859 JustifiedGallery.prototype.retrieveMaxRowHeight = function () { 27860 var newMaxRowHeight = null; 27861 var rowHeight = this.settings.rowHeight; 27862 27863 if ($.type(this.settings.maxRowHeight) === 'string') { 27864 if (this.settings.maxRowHeight.match(/^[0-9]+%$/)) { 27865 newMaxRowHeight = rowHeight * parseFloat(this.settings.maxRowHeight.match(/^([0-9]+)%$/)[1]) / 100; 27866 } else { 27867 newMaxRowHeight = parseFloat(this.settings.maxRowHeight); 27868 } 27869 } else if ($.type(this.settings.maxRowHeight) === 'number') { 27870 newMaxRowHeight = this.settings.maxRowHeight; 27871 } else if (this.settings.maxRowHeight === false || this.settings.maxRowHeight == null) { 27872 return null; 27873 } else { 27874 throw 'maxRowHeight must be a number or a percentage'; 27875 } 27876 27877 // check if the converted value is not a number 27878 if (isNaN(newMaxRowHeight)) throw 'invalid number for maxRowHeight'; 27879 27880 // check values, maxRowHeight must be >= rowHeight 27881 if (newMaxRowHeight < rowHeight) newMaxRowHeight = rowHeight; 27882 27883 return newMaxRowHeight; 27884 }; 27885 27886 /** 27887 * Checks the settings 27888 */ 27889 JustifiedGallery.prototype.checkSettings = function () { 27890 this.checkSizeRangesSuffixes(); 27891 27892 this.checkOrConvertNumber(this.settings, 'rowHeight'); 27893 this.checkOrConvertNumber(this.settings, 'margins'); 27894 this.checkOrConvertNumber(this.settings, 'border'); 27895 this.checkOrConvertNumber(this.settings, 'maxRowsCount'); 27896 27897 var lastRowModes = [ 27898 'justify', 27899 'nojustify', 27900 'left', 27901 'center', 27902 'right', 27903 'hide' 27904 ]; 27905 if (lastRowModes.indexOf(this.settings.lastRow) === -1) { 27906 throw 'lastRow must be one of: ' + lastRowModes.join(', '); 27907 } 27908 27909 this.checkOrConvertNumber(this.settings, 'justifyThreshold'); 27910 if (this.settings.justifyThreshold < 0 || this.settings.justifyThreshold > 1) { 27911 throw 'justifyThreshold must be in the interval [0,1]'; 27912 } 27913 if ($.type(this.settings.cssAnimation) !== 'boolean') { 27914 throw 'cssAnimation must be a boolean'; 27915 } 27916 27917 if ($.type(this.settings.captions) !== 'boolean') throw 'captions must be a boolean'; 27918 this.checkOrConvertNumber(this.settings.captionSettings, 'animationDuration'); 27919 27920 this.checkOrConvertNumber(this.settings.captionSettings, 'visibleOpacity'); 27921 if (this.settings.captionSettings.visibleOpacity < 0 || 27922 this.settings.captionSettings.visibleOpacity > 1) { 27923 throw 'captionSettings.visibleOpacity must be in the interval [0, 1]'; 27924 } 27925 27926 this.checkOrConvertNumber(this.settings.captionSettings, 'nonVisibleOpacity'); 27927 if (this.settings.captionSettings.nonVisibleOpacity < 0 || 27928 this.settings.captionSettings.nonVisibleOpacity > 1) { 27929 throw 'captionSettings.nonVisibleOpacity must be in the interval [0, 1]'; 27930 } 27931 27932 this.checkOrConvertNumber(this.settings, 'imagesAnimationDuration'); 27933 this.checkOrConvertNumber(this.settings, 'refreshTime'); 27934 this.checkOrConvertNumber(this.settings, 'refreshSensitivity'); 27935 if ($.type(this.settings.randomize) !== 'boolean') throw 'randomize must be a boolean'; 27936 if ($.type(this.settings.selector) !== 'string') throw 'selector must be a string'; 27937 27938 if (this.settings.sort !== false && !$.isFunction(this.settings.sort)) { 27939 throw 'sort must be false or a comparison function'; 27940 } 27941 27942 if (this.settings.filter !== false && !$.isFunction(this.settings.filter) && 27943 $.type(this.settings.filter) !== 'string') { 27944 throw 'filter must be false, a string or a filter function'; 27945 } 27946 }; 27947 27948 /** 27949 * It brings all the indexes from the sizeRangeSuffixes and it orders them. They are then sorted and returned. 27950 * @returns {Array} sorted suffix ranges 27951 */ 27952 JustifiedGallery.prototype.retrieveSuffixRanges = function () { 27953 var suffixRanges = []; 27954 for (var rangeIdx in this.settings.sizeRangeSuffixes) { 27955 if (this.settings.sizeRangeSuffixes.hasOwnProperty(rangeIdx)) suffixRanges.push(parseInt(rangeIdx, 10)); 27956 } 27957 suffixRanges.sort(function (a, b) { return a > b ? 1 : a < b ? -1 : 0; }); 27958 return suffixRanges; 27959 }; 27960 27961 /** 27962 * Update the existing settings only changing some of them 27963 * 27964 * @param newSettings the new settings (or a subgroup of them) 27965 */ 27966 JustifiedGallery.prototype.updateSettings = function (newSettings) { 27967 // In this case Justified Gallery has been called again changing only some options 27968 this.settings = $.extend({}, this.settings, newSettings); 27969 this.checkSettings(); 27970 27971 // As reported in the settings: negative value = same as margins, 0 = disabled 27972 this.border = this.settings.border >= 0 ? this.settings.border : this.settings.margins; 27973 27974 this.maxRowHeight = this.retrieveMaxRowHeight(); 27975 this.suffixRanges = this.retrieveSuffixRanges(); 27976 }; 27977 27978 JustifiedGallery.prototype.defaults = { 27979 sizeRangeSuffixes: {}, /* e.g. Flickr configuration 27980 { 27981 100: '_t', // used when longest is less than 100px 27982 240: '_m', // used when longest is between 101px and 240px 27983 320: '_n', // ... 27984 500: '', 27985 640: '_z', 27986 1024: '_b' // used as else case because it is the last 27987 } 27988 */ 27989 thumbnailPath: undefined, /* If defined, sizeRangeSuffixes is not used, and this function is used to determine the 27990 path relative to a specific thumbnail size. The function should accept respectively three arguments: 27991 current path, width and height */ 27992 rowHeight: 120, // required? required to be > 0? 27993 maxRowHeight: false, // false or negative value to deactivate. Positive number to express the value in pixels, 27994 // A string '[0-9]+%' to express in percentage (e.g. 300% means that the row height 27995 // can't exceed 3 * rowHeight) 27996 maxRowsCount: 0, // maximum number of rows to be displayed (0 = disabled) 27997 margins: 1, 27998 border: -1, // negative value = same as margins, 0 = disabled, any other value to set the border 27999 28000 lastRow: 'nojustify', // ⦠which is the same as 'left', or can be 'justify', 'center', 'right' or 'hide' 28001 28002 justifyThreshold: 0.90, /* if row width / available space > 0.90 it will be always justified 28003 * (i.e. lastRow setting is not considered) */ 28004 waitThumbnailsLoad: true, 28005 captions: true, 28006 cssAnimation: true, 28007 imagesAnimationDuration: 500, // ignored with css animations 28008 captionSettings: { // ignored with css animations 28009 animationDuration: 500, 28010 visibleOpacity: 0.7, 28011 nonVisibleOpacity: 0.0 28012 },
28013 rel: null, // rewrite the rel of each analyzed links 28014 target: null, // rewrite the target of all links 28015 extension: /\.[^.\\/]+$/, // regexp to capture the extension of an image 28016 refreshTime: 200, // time interval (in ms) to check if the page changes its width 28017 refreshSensitivity: 0, // change in width allowed (in px) without re-building the gallery 28018 randomize: false, 28019 rtl: false, // right-to-left mode 28020 sort: false, /* 28021 - false: to do not sort 28022 - function: to sort them using the function as comparator (see Array.prototype.sort()) 28023 */ 28024 filter: false, /* 28025 - false, null or undefined: for a disabled filter 28026 - a string: an entry is kept if entry.is(filter string) returns true 28027 see jQuery's .is() function for further information 28028 - a function: invoked with arguments (entry, index, array). Return true to keep the entry, false otherwise. 28029 It follows the specifications of the Array.prototype.filter() function of JavaScript. 28030 */ 28031 selector: 'a', // The selector that is used to know what are the entries of the gallery 28032 imgSelector: '> img, > a > img, > svg, > a > svg', // The selector that is used to know what are the images of each entry 28033 triggerEvent: function (event) { // This is called to trigger events, the default behavior is to call $.trigger 28034 this.$gallery.trigger(event); // Consider that 'this' is this set to the JustifiedGallery object, so it can 28035 } // access to fields such as $gallery, useful to trigger events with jQuery. 28036 }; 28037 28038 28039 /** 28040 * Justified Gallery plugin for jQuery 28041 * 28042 * Events 28043 * - jg.complete : called when all the gallery has been created 28044 * - jg.resize : called when the gallery has been resized 28045 * - jg.rowflush : when a new row appears 28046 * 28047 * @param arg the action (or the settings) passed when the plugin is called 28048 * @returns {*} the object itself 28049 */ 28050 $.fn.justifiedGallery = function (arg) { 28051 return this.each(function (index, gallery) { 28052 28053 var $gallery = $(gallery); 28054 $gallery.addClass('justified-gallery'); 28055 28056 var controller = $gallery.data('jg.controller'); 28057 if (typeof controller === 'undefined') { 28058 // Create controller and assign it to the object data 28059 if (typeof arg !== 'undefined' && arg !== null && $.type(arg) !== 'object') { 28060 if (arg === 'destroy') return; // Just a call to an unexisting object 28061 throw 'The argument must be an object'; 28062 } 28063 controller = new JustifiedGallery($gallery, $.extend({}, JustifiedGallery.prototype.defaults, arg)); 28064 $gallery.data('jg.controller', controller); 28065 } else if (arg === 'norewind') { 28066 // In this case we don't rewind: we analyze only the latest images (e.g. to complete the last unfinished row 28067 // ... left to be more readable 28068 } else if (arg === 'destroy') { 28069 controller.destroy(); 28070 return; 28071 } else { 28072 // In this case Justified Gallery has been called again changing only some options 28073 controller.updateSettings(arg); 28074 controller.rewind(); 28075 } 28076 28077 // Update the entries list 28078 if (!controller.updateEntries(arg === 'norewind')) return; 28079 28080 // Init justified gallery 28081 controller.init(); 28082 28083 }); 28084 }; 28085 28086})); 28087 28088/*! 28089* Customized version of iScroll.js 0.0.1 28090* It fixes bugs affecting its integration with fullpage.js 28091*/ 28092/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ 28093(function (window, document, Math) { 28094var rAF = window.requestAnimationFrame || 28095 window.webkitRequestAnimationFrame || 28096 window.mozRequestAnimationFrame || 28097 window.oRequestAnimationFrame || 28098 window.msRequestAnimationFrame || 28099 function (callback) { window.setTimeout(callback, 1000 / 60); }; 28100 28101var utils = (function () { 28102 var me = {}; 28103 28104 var _elementStyle = document.createElement('div').style; 28105 var _vendor = (function () { 28106 var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], 28107 transform, 28108 i = 0, 28109 l = vendors.length; 28110 28111 for ( ; i < l; i++ ) { 28112 transform = vendors[i] + 'ransform'; 28113 if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); 28114 } 28115 28116 return false;
28117 })(); 28118 28119 function _prefixStyle (style) { 28120 if ( _vendor === false ) return false; 28121 if ( _vendor === '' ) return style; 28122 return _vendor + style.charAt(0).toUpperCase() + style.substr(1); 28123 } 28124 28125 me.getTime = Date.now || function getTime () { return new Date().getTime(); }; 28126 28127 me.extend = function (target, obj) { 28128 for ( var i in obj ) { 28129 target[i] = obj[i]; 28130 } 28131 }; 28132 28133 me.addEvent = function (el, type, fn, capture) { 28134 el.addEventListener(type, fn, !!capture); 28135 }; 28136 28137 me.removeEvent = function (el, type, fn, capture) { 28138 el.removeEventListener(type, fn, !!capture); 28139 }; 28140 28141 me.prefixPointerEvent = function (pointerEvent) { 28142 return window.MSPointerEvent ? 28143 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): 28144 pointerEvent; 28145 }; 28146 28147 me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { 28148 var distance = current - start, 28149 speed = Math.abs(distance) / time, 28150 destination, 28151 duration; 28152 28153 deceleration = deceleration === undefined ? 0.0006 : deceleration; 28154 28155 destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); 28156 duration = speed / deceleration; 28157 28158 if ( destination < lowerMargin ) { 28159 destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; 28160 distance = Math.abs(destination - current); 28161 duration = distance / speed; 28162 } else if ( destination > 0 ) { 28163 destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; 28164 distance = Math.abs(current) + destination; 28165 duration = distance / speed; 28166 } 28167 28168 return { 28169 destination: Math.round(destination), 28170 duration: duration 28171 }; 28172 }; 28173 28174 var _transform = _prefixStyle('transform'); 28175 28176 me.extend(me, { 28177 hasTransform: _transform !== false, 28178 hasPerspective: _prefixStyle('perspective') in _elementStyle, 28179 hasTouch: 'ontouchstart' in window, 28180 hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed 28181 hasTransition: _prefixStyle('transition') in _elementStyle 28182 }); 28183 28184 /* 28185 This should find all Android browsers lower than build 535.19 (both stock browser and webview) 28186 - galaxy S2 is ok 28187 - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` 28188 - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 28189 - galaxy S3 is badAndroid (stock brower, webview) 28190 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 28191 - galaxy S4 is badAndroid (stock brower, webview) 28192 `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` 28193 - galaxy S5 is OK 28194 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 28195 - galaxy S6 is OK 28196 `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` 28197 */ 28198 me.isBadAndroid = (function() { 28199 var appVersion = window.navigator.appVersion; 28200 // Android browser is not a chrome browser. 28201 if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { 28202 var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); 28203 if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { 28204 return parseFloat(safariVersion[1]) < 535.19; 28205 } else { 28206 return true; 28207 } 28208 } else { 28209 return false; 28210 } 28211 })(); 28212 28213 me.extend(me.style = {}, { 28214 transform: _transform, 28215 transitionTimingFunction: _prefixStyle('transitionTimingFunction'), 28216 transitionDuration: _prefixStyle('transitionDuration'), 28217 transitionDelay: _prefixStyle('transitionDelay'), 28218 transformOrigin: _prefixStyle('transformOrigin') 28219 }); 28220 28221 me.hasClass = function (e, c) { 28222 var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); 28223 return re.test(e.className); 28224 }; 28225 28226 me.addClass = function (e, c) { 28227 if ( me.hasClass(e, c) ) { 28228 return; 28229 } 28230 28231 var newclass = e.className.split(' '); 28232 newclass.push(c); 28233 e.className = newclass.join(' '); 28234 }; 28235 28236 me.removeClass = function (e, c) { 28237 if ( !me.hasClass(e, c) ) { 28238 return; 28239 } 28240 28241 var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); 28242 e.className = e.className.replace(re, ' '); 28243 }; 28244 28245 me.offset = function (el) { 28246 var left = -el.offsetLeft, 28247 top = -el.offsetTop; 28248 28249 // jshint -W084 28250 while (el = el.offsetParent) { 28251 left -= el.offsetLeft; 28252 top -= el.offsetTop; 28253 } 28254 // jshint +W084 28255 28256 return { 28257 left: left, 28258 top: top 28259 }; 28260 }; 28261 28262 me.preventDefaultException = function (el, exceptions) { 28263 for ( var i in exceptions ) { 28264 if ( exceptions[i].test(el[i]) ) { 28265 return true; 28266 } 28267 } 28268 28269 return false;
28270 }; 28271 28272 me.extend(me.eventType = {}, { 28273 touchstart: 1, 28274 touchmove: 1, 28275 touchend: 1, 28276 28277 mousedown: 2, 28278 mousemove: 2, 28279 mouseup: 2, 28280 28281 pointerdown: 3, 28282 pointermove: 3, 28283 pointerup: 3, 28284 28285 MSPointerDown: 3, 28286 MSPointerMove: 3, 28287 MSPointerUp: 3 28288 }); 28289 28290 me.extend(me.ease = {}, { 28291 quadratic: { 28292 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', 28293 fn: function (k) { 28294 return k * ( 2 - k ); 28295 } 28296 }, 28297 circular: { 28298 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) 28299 fn: function (k) { 28300 return Math.sqrt( 1 - ( --k * k ) ); 28301 } 28302 }, 28303 back: { 28304 style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', 28305 fn: function (k) { 28306 var b = 4; 28307 return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; 28308 } 28309 }, 28310 bounce: { 28311 style: '', 28312 fn: function (k) { 28313 if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { 28314 return 7.5625 * k * k; 28315 } else if ( k < ( 2 / 2.75 ) ) { 28316 return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; 28317 } else if ( k < ( 2.5 / 2.75 ) ) { 28318 return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; 28319 } else { 28320 return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; 28321 } 28322 } 28323 }, 28324 elastic: { 28325 style: '', 28326 fn: function (k) { 28327 var f = 0.22, 28328 e = 0.4; 28329 28330 if ( k === 0 ) { return 0; } 28331 if ( k == 1 ) { return 1; } 28332 28333 return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); 28334 } 28335 } 28336 }); 28337 28338 me.tap = function (e, eventName) { 28339 var ev = document.createEvent('Event'); 28340 ev.initEvent(eventName, true, true); 28341 ev.pageX = e.pageX; 28342 ev.pageY = e.pageY; 28343 e.target.dispatchEvent(ev); 28344 }; 28345 28346 me.click = function (e) { 28347 var target = e.target, 28348 ev; 28349 28350 if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { 28351 // https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 28352 // initMouseEvent is deprecated. 28353 ev = document.createEvent(window.MouseEvent ? 'MouseEvents' : 'Event'); 28354 ev.initEvent('click', true, true); 28355 ev.view = e.view || window; 28356 ev.detail = 1; 28357 ev.screenX = target.screenX || 0; 28358 ev.screenY = target.screenY || 0; 28359 ev.clientX = target.clientX || 0; 28360 ev.clientY = target.clientY || 0; 28361 ev.ctrlKey = !!e.ctrlKey; 28362 ev.altKey = !!e.altKey; 28363 ev.shiftKey = !!e.shiftKey; 28364 ev.metaKey = !!e.metaKey; 28365 ev.button = 0; 28366 ev.relatedTarget = null; 28367 ev._constructed = true; 28368 target.dispatchEvent(ev); 28369 } 28370 }; 28371 28372 return me; 28373})(); 28374function IScroll (el, options) { 28375 this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; 28376 this.scroller = this.wrapper.children[0]; 28377 this.scrollerStyle = this.scroller.style; // cache style for better performance 28378 28379 this.options = { 28380 28381 resizeScrollbars: true, 28382 28383 mouseWheelSpeed: 20, 28384 28385 snapThreshold: 0.334, 28386 28387// INSERT POINT: OPTIONS 28388 disablePointer : !utils.hasPointer, 28389 disableTouch : utils.hasPointer || !utils.hasTouch, 28390 disableMouse : utils.hasPointer || utils.hasTouch, 28391 startX: 0, 28392 startY: 0, 28393 scrollY: true, 28394 directionLockThreshold: 5, 28395 momentum: true, 28396 28397 bounce: true, 28398 bounceTime: 600, 28399 bounceEasing: '', 28400 28401 preventDefault: true, 28402 preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|LABEL)$/ }, 28403 28404 HWCompositing: true, 28405 useTransition: true, 28406 useTransform: true, 28407 bindToWrapper: typeof window.onmousedown === "undefined" 28408 }; 28409 28410 for ( var i in options ) { 28411 this.options[i] = options[i]; 28412 } 28413 28414 // Normalize options 28415 this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; 28416 28417 this.options.useTransition = utils.hasTransition && this.options.useTransition; 28418 this.options.useTransform = utils.hasTransform && this.options.useTransform; 28419 28420 this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; 28421 this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; 28422 28423 // If you want eventPassthrough I have to lock one of the axes 28424 this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; 28425 this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; 28426 28427 // With eventPassthrough we also need lockDirection mechanism 28428 this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; 28429 this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; 28430 28431 this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; 28432 28433 this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; 28434 28435 if ( this.options.tap === true ) {
28436 this.options.tap = 'tap'; 28437 } 28438 28439 // https://github.com/cubiq/iscroll/issues/1029 28440 if (!this.options.useTransition && !this.options.useTransform) { 28441 if(!(/relative|absolute/i).test(this.scrollerStyle.position)) { 28442 this.scrollerStyle.position = "relative"; 28443 } 28444 } 28445 28446 if ( this.options.shrinkScrollbars == 'scale' ) { 28447 this.options.useTransition = false; 28448 } 28449 28450 this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; 28451 28452// INSERT POINT: NORMALIZATION 28453 28454 // Some defaults 28455 this.x = 0; 28456 this.y = 0; 28457 this.directionX = 0; 28458 this.directionY = 0; 28459 this._events = {}; 28460 28461// INSERT POINT: DEFAULTS 28462 28463 this._init(); 28464 this.refresh(); 28465 28466 this.scrollTo(this.options.startX, this.options.startY); 28467 this.enable(); 28468} 28469 28470IScroll.prototype = { 28471 version: '5.2.0', 28472 28473 _init: function () { 28474 this._initEvents(); 28475 28476 if ( this.options.scrollbars || this.options.indicators ) { 28477 this._initIndicators(); 28478 } 28479 28480 if ( this.options.mouseWheel ) { 28481 this._initWheel(); 28482 } 28483 28484 if ( this.options.snap ) { 28485 this._initSnap(); 28486 } 28487 28488 if ( this.options.keyBindings ) { 28489 this._initKeys(); 28490 } 28491 28492// INSERT POINT: _init 28493 28494 }, 28495 28496 destroy: function () { 28497 this._initEvents(true); 28498 clearTimeout(this.resizeTimeout); 28499 this.resizeTimeout = null; 28500 this._execEvent('destroy'); 28501 }, 28502 28503 _transitionEnd: function (e) { 28504 if ( e.target != this.scroller || !this.isInTransition ) { 28505 return; 28506 } 28507 28508 this._transitionTime(); 28509 if ( !this.resetPosition(this.options.bounceTime) ) { 28510 this.isInTransition = false; 28511 this._execEvent('scrollEnd'); 28512 } 28513 }, 28514 28515 _start: function (e) { 28516 // React to left mouse button only 28517 if ( utils.eventType[e.type] != 1 ) { 28518 // for button property 28519 // http://unixpapa.com/js/mouse.html 28520 var button; 28521 if (!e.which) { 28522 /* IE case */ 28523 button = (e.button < 2) ? 0 : 28524 ((e.button == 4) ? 1 : 2); 28525 } else { 28526 /* All others */ 28527 button = e.button; 28528 } 28529 if ( button !== 0 ) { 28530 return; 28531 } 28532 } 28533 28534 if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { 28535 return; 28536 } 28537 28538 if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 28539 e.preventDefault(); 28540 } 28541 28542 var point = e.touches ? e.touches[0] : e, 28543 pos; 28544 28545 this.initiated = utils.eventType[e.type]; 28546 this.moved = false; 28547 this.distX = 0; 28548 this.distY = 0; 28549 this.directionX = 0; 28550 this.directionY = 0; 28551 this.directionLocked = 0; 28552 28553 this.startTime = utils.getTime(); 28554 28555 if ( this.options.useTransition && this.isInTransition ) { 28556 this._transitionTime(); 28557 this.isInTransition = false; 28558 pos = this.getComputedPosition(); 28559 this._translate(Math.round(pos.x), Math.round(pos.y)); 28560 this._execEvent('scrollEnd'); 28561 } else if ( !this.options.useTransition && this.isAnimating ) { 28562 this.isAnimating = false; 28563 this._execEvent('scrollEnd'); 28564 } 28565 28566 this.startX = this.x; 28567 this.startY = this.y; 28568 this.absStartX = this.x; 28569 this.absStartY = this.y; 28570 this.pointX = point.pageX; 28571 this.pointY = point.pageY; 28572 28573 this._execEvent('beforeScrollStart'); 28574 }, 28575 28576 _move: function (e) { 28577 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 28578 return; 28579 } 28580 28581 if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! 28582 e.preventDefault(); 28583 } 28584 28585 var point = e.touches ? e.touches[0] : e, 28586 deltaX = point.pageX - this.pointX, 28587 deltaY = point.pageY - this.pointY, 28588 timestamp = utils.getTime(), 28589 newX, newY, 28590 absDistX, absDistY; 28591 28592 this.pointX = point.pageX; 28593 this.pointY = point.pageY; 28594 28595 this.distX += deltaX; 28596 this.distY += deltaY; 28597 absDistX = Math.abs(this.distX); 28598 absDistY = Math.abs(this.distY); 28599 28600 // We need to move at least 10 pixels for the scrolling to initiate 28601 if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { 28602 return; 28603 } 28604 28605 // If you are scrolling in one direction lock the other 28606 if ( !this.directionLocked && !this.options.freeScroll ) { 28607 if ( absDistX > absDistY + this.options.directionLockThreshold ) {
28608 this.directionLocked = 'h'; // lock horizontally 28609 } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { 28610 this.directionLocked = 'v'; // lock vertically 28611 } else { 28612 this.directionLocked = 'n'; // no lock 28613 } 28614 } 28615 28616 if ( this.directionLocked == 'h' ) { 28617 if ( this.options.eventPassthrough == 'vertical' ) { 28618 e.preventDefault(); 28619 } else if ( this.options.eventPassthrough == 'horizontal' ) { 28620 this.initiated = false; 28621 return; 28622 } 28623 28624 deltaY = 0; 28625 } else if ( this.directionLocked == 'v' ) { 28626 if ( this.options.eventPassthrough == 'horizontal' ) { 28627 e.preventDefault(); 28628 } else if ( this.options.eventPassthrough == 'vertical' ) { 28629 this.initiated = false; 28630 return; 28631 } 28632 28633 deltaX = 0; 28634 } 28635 28636 deltaX = this.hasHorizontalScroll ? deltaX : 0; 28637 deltaY = this.hasVerticalScroll ? deltaY : 0; 28638 28639 newX = this.x + deltaX; 28640 newY = this.y + deltaY; 28641 28642 // Slow down if outside of the boundaries 28643 if ( newX > 0 || newX < this.maxScrollX ) { 28644 newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; 28645 } 28646 if ( newY > 0 || newY < this.maxScrollY ) { 28647 newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; 28648 } 28649 28650 this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; 28651 this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; 28652 28653 if ( !this.moved ) { 28654 this._execEvent('scrollStart'); 28655 } 28656 28657 this.moved = true; 28658 28659 this._translate(newX, newY); 28660 28661/* REPLACE START: _move */ 28662 28663 if ( timestamp - this.startTime > 300 ) { 28664 this.startTime = timestamp; 28665 this.startX = this.x; 28666 this.startY = this.y; 28667 } 28668 28669/* REPLACE END: _move */ 28670 28671 }, 28672 28673 _end: function (e) { 28674 if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { 28675 return; 28676 } 28677 28678 if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { 28679 e.preventDefault(); 28680 } 28681 28682 var point = e.changedTouches ? e.changedTouches[0] : e, 28683 momentumX, 28684 momentumY, 28685 duration = utils.getTime() - this.startTime, 28686 newX = Math.round(this.x), 28687 newY = Math.round(this.y), 28688 distanceX = Math.abs(newX - this.startX), 28689 distanceY = Math.abs(newY - this.startY), 28690 time = 0, 28691 easing = ''; 28692 28693 this.isInTransition = 0; 28694 this.initiated = 0; 28695 this.endTime = utils.getTime(); 28696 28697 // reset if we are outside of the boundaries 28698 if ( this.resetPosition(this.options.bounceTime) ) { 28699 return; 28700 } 28701 28702 this.scrollTo(newX, newY); // ensures that the last position is rounded 28703 28704 // we scrolled less than 10 pixels 28705 if ( !this.moved ) { 28706 if ( this.options.tap ) { 28707 utils.tap(e, this.options.tap); 28708 } 28709 28710 if ( this.options.click ) { 28711 utils.click(e); 28712 } 28713 28714 this._execEvent('scrollCancel'); 28715 return; 28716 } 28717 28718 if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { 28719 this._execEvent('flick'); 28720 return; 28721 } 28722 28723 // start momentum animation if needed 28724 if ( this.options.momentum && duration < 300 ) { 28725 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 }; 28726 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 }; 28727 newX = momentumX.destination; 28728 newY = momentumY.destination; 28729 time = Math.max(momentumX.duration, momentumY.duration); 28730 this.isInTransition = 1; 28731 } 28732 28733 28734 if ( this.options.snap ) { 28735 var snap = this._nearestSnap(newX, newY); 28736 this.currentPage = snap; 28737 time = this.options.snapSpeed || Math.max( 28738 Math.max( 28739 Math.min(Math.abs(newX - snap.x), 1000), 28740 Math.min(Math.abs(newY - snap.y), 1000) 28741 ), 300); 28742 newX = snap.x; 28743 newY = snap.y; 28744 28745 this.directionX = 0; 28746 this.directionY = 0; 28747 easing = this.options.bounceEasing; 28748 } 28749 28750// INSERT POINT: _end 28751 28752 if ( newX != this.x || newY != this.y ) { 28753 // change easing function when scroller goes out of the boundaries 28754 if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { 28755 easing = utils.ease.quadratic; 28756 } 28757 28758 this.scrollTo(newX, newY, time, easing); 28759 return; 28760 } 28761 28762 this._execEvent('scrollEnd'); 28763 }, 28764 28765 _resize: function () { 28766 var that = this; 28767 28768 clearTimeout(this.resizeTimeout); 28769 28770 this.resizeTimeout = setTimeout(function () { 28771 that.refresh(); 28772 }, this.options.resizePolling); 28773 }, 28774 28775 resetPosition: function (time) { 28776 var x = this.x, 28777 y = this.y; 28778 28779 time = time || 0; 28780 28781 if ( !this.hasHorizontalScroll || this.x > 0 ) { 28782 x = 0; 28783 } else if ( this.x < this.maxScrollX ) { 28784 x = this.maxScrollX; 28785 } 28786 28787 if ( !this.hasVerticalScroll || this.y > 0 ) { 28788 y = 0; 28789 } else if ( this.y < this.maxScrollY ) { 28790 y = this.maxScrollY; 28791 } 28792 28793 if ( x == this.x && y == this.y ) { 28794 return false;
28795 } 28796 28797 this.scrollTo(x, y, time, this.options.bounceEasing); 28798 28799 return true; 28800 }, 28801 28802 disable: function () { 28803 this.enabled = false; 28804 }, 28805 28806 enable: function () { 28807 this.enabled = true; 28808 }, 28809 28810 refresh: function () { 28811 var rf = this.wrapper.offsetHeight; // Force reflow 28812 28813 this.wrapperWidth = this.wrapper.clientWidth; 28814 this.wrapperHeight = this.wrapper.clientHeight; 28815 28816/* REPLACE START: refresh */ 28817 28818 this.scrollerWidth = this.scroller.offsetWidth; 28819 this.scrollerHeight = this.scroller.offsetHeight; 28820 28821 this.maxScrollX = this.wrapperWidth - this.scrollerWidth; 28822 this.maxScrollY = this.wrapperHeight - this.scrollerHeight; 28823 28824/* REPLACE END: refresh */ 28825 28826 this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; 28827 this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; 28828 28829 if ( !this.hasHorizontalScroll ) { 28830 this.maxScrollX = 0; 28831 this.scrollerWidth = this.wrapperWidth; 28832 } 28833 28834 if ( !this.hasVerticalScroll ) { 28835 this.maxScrollY = 0; 28836 this.scrollerHeight = this.wrapperHeight; 28837 } 28838 28839 this.endTime = 0; 28840 this.directionX = 0; 28841 this.directionY = 0; 28842 28843 this.wrapperOffset = utils.offset(this.wrapper); 28844 28845 this._execEvent('refresh'); 28846 28847 this.resetPosition(); 28848 28849// INSERT POINT: _refresh 28850 28851 }, 28852 28853 28854 on: function (type, fn) { 28855 if ( !this._events[type] ) { 28856 this._events[type] = []; 28857 } 28858 28859 this._events[type].push(fn); 28860 }, 28861 28862 off: function (type, fn) { 28863 if ( !this._events[type] ) { 28864 return; 28865 } 28866 28867 var index = this._events[type].indexOf(fn); 28868 28869 if ( index > -1 ) { 28870 this._events[type].splice(index, 1); 28871 } 28872 }, 28873 28874 _execEvent: function (type) { 28875 if ( !this._events[type] ) { 28876 return; 28877 } 28878 28879 var i = 0, 28880 l = this._events[type].length; 28881 28882 if ( !l ) { 28883 return; 28884 } 28885 28886 for ( ; i < l; i++ ) { 28887 this._events[type][i].apply(this, [].slice.call(arguments, 1)); 28888 } 28889 }, 28890 28891 scrollBy: function (x, y, time, easing) { 28892 x = this.x + x; 28893 y = this.y + y; 28894 time = time || 0; 28895 28896 this.scrollTo(x, y, time, easing); 28897 }, 28898 28899 scrollTo: function (x, y, time, easing) { 28900 easing = easing || utils.ease.circular; 28901 28902 this.isInTransition = this.options.useTransition && time > 0; 28903 var transitionType = this.options.useTransition && easing.style; 28904 if ( !time || transitionType ) { 28905 if(transitionType) { 28906 this._transitionTimingFunction(easing.style); 28907 this._transitionTime(time); 28908 } 28909 this._translate(x, y); 28910 } else { 28911 this._animate(x, y, time, easing.fn); 28912 } 28913 }, 28914 28915 scrollToElement: function (el, time, offsetX, offsetY, easing) { 28916 el = el.nodeType ? el : this.scroller.querySelector(el); 28917 28918 if ( !el ) { 28919 return; 28920 } 28921 28922 var pos = utils.offset(el); 28923 28924 pos.left -= this.wrapperOffset.left; 28925 pos.top -= this.wrapperOffset.top; 28926 28927 // if offsetX/Y are true we center the element to the screen 28928 if ( offsetX === true ) { 28929 offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); 28930 } 28931 if ( offsetY === true ) { 28932 offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); 28933 } 28934 28935 pos.left -= offsetX || 0; 28936 pos.top -= offsetY || 0; 28937 28938 pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; 28939 pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; 28940 28941 time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; 28942 28943 this.scrollTo(pos.left, pos.top, time, easing); 28944 }, 28945 28946 _transitionTime: function (time) { 28947 if (!this.options.useTransition) { 28948 return; 28949 } 28950 time = time || 0; 28951 var durationProp = utils.style.transitionDuration; 28952 if(!durationProp) { 28953 return; 28954 } 28955 28956 this.scrollerStyle[durationProp] = time + 'ms'; 28957 28958 if ( !time && utils.isBadAndroid ) { 28959 this.scrollerStyle[durationProp] = '0.0001ms'; 28960 // remove 0.0001ms 28961 var self = this; 28962 rAF(function() { 28963 if(self.scrollerStyle[durationProp] === '0.0001ms') { 28964 self.scrollerStyle[durationProp] = '0s'; 28965 } 28966 }); 28967 } 28968 28969 28970 if ( this.indicators ) { 28971 for ( var i = this.indicators.length; i--; ) { 28972 this.indicators[i].transitionTime(time); 28973 } 28974 } 28975 28976 28977// INSERT POINT: _transitionTime 28978 28979 }, 28980 28981 _transitionTimingFunction: function (easing) { 28982 this.scrollerStyle[utils.style.transitionTimingFunction] = easing; 28983 28984 28985 if ( this.indicators ) { 28986 for ( var i = this.indicators.length; i--; ) { 28987 this.indicators[i].transitionTimingFunction(easing); 28988 } 28989 } 28990 28991 28992// INSERT POINT: _transitionTimingFunction 28993 28994 }, 28995 28996 _translate: function (x, y) { 28997 //Uncode addition 28998 if ( (" " + this.wrapper.className + " ").replace(/[\n\t]/g, " ").indexOf(" no-scrolloverflow ") > -1 ) 28999 return false;
29000 29001 if ( this.options.useTransform ) { 29002 29003/* REPLACE START: _translate */ 29004 29005 this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; 29006 29007/* REPLACE END: _translate */ 29008 29009 } else { 29010 x = Math.round(x); 29011 y = Math.round(y); 29012 this.scrollerStyle.left = x + 'px'; 29013 this.scrollerStyle.top = y + 'px'; 29014 } 29015 29016 this.x = x; 29017 this.y = y; 29018 29019 29020 if ( this.indicators ) { 29021 for ( var i = this.indicators.length; i--; ) { 29022 this.indicators[i].updatePosition(); 29023 } 29024 } 29025 29026 //Uncode addition 29027 var uncodevent = new CustomEvent('fp-slide-scroll'); 29028 window.dispatchEvent(uncodevent); 29029 29030// INSERT POINT: _translate 29031 29032 }, 29033 29034 _initEvents: function (remove) { 29035 var eventType = remove ? utils.removeEvent : utils.addEvent, 29036 target = this.options.bindToWrapper ? this.wrapper : window; 29037 29038 eventType(window, 'orientationchange', this); 29039 eventType(window, 'resize', this); 29040 29041 if ( this.options.click ) { 29042 eventType(this.wrapper, 'click', this, true); 29043 } 29044 29045 if ( !this.options.disableMouse ) { 29046 eventType(this.wrapper, 'mousedown', this); 29047 eventType(target, 'mousemove', this); 29048 eventType(target, 'mousecancel', this); 29049 eventType(target, 'mouseup', this); 29050 } 29051 29052 if ( utils.hasPointer && !this.options.disablePointer ) { 29053 eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); 29054 eventType(target, utils.prefixPointerEvent('pointermove'), this); 29055 eventType(target, utils.prefixPointerEvent('pointercancel'), this); 29056 eventType(target, utils.prefixPointerEvent('pointerup'), this); 29057 } 29058 29059 if ( utils.hasTouch && !this.options.disableTouch ) { 29060 eventType(this.wrapper, 'touchstart', this); 29061 eventType(target, 'touchmove', this); 29062 eventType(target, 'touchcancel', this); 29063 eventType(target, 'touchend', this); 29064 } 29065 29066 eventType(this.scroller, 'transitionend', this); 29067 eventType(this.scroller, 'webkitTransitionEnd', this); 29068 eventType(this.scroller, 'oTransitionEnd', this); 29069 eventType(this.scroller, 'MSTransitionEnd', this); 29070 }, 29071 29072 getComputedPosition: function () { 29073 var matrix = window.getComputedStyle(this.scroller, null), 29074 x, y; 29075 29076 if ( this.options.useTransform ) { 29077 matrix = matrix[utils.style.transform].split(')')[0].split(', '); 29078 x = +(matrix[12] || matrix[4]); 29079 y = +(matrix[13] || matrix[5]); 29080 } else { 29081 x = +matrix.left.replace(/[^-\d.]/g, ''); 29082 y = +matrix.top.replace(/[^-\d.]/g, ''); 29083 } 29084 29085 return { x: x, y: y }; 29086 }, 29087 _initIndicators: function () { 29088 var interactive = this.options.interactiveScrollbars, 29089 customStyle = typeof this.options.scrollbars != 'string', 29090 indicators = [], 29091 indicator; 29092 29093 var that = this; 29094 29095 this.indicators = []; 29096 29097 if ( this.options.scrollbars ) { 29098 // Vertical scrollbar 29099 if ( this.options.scrollY ) { 29100 indicator = { 29101 el: createDefaultScrollbar('v', interactive, this.options.scrollbars), 29102 interactive: interactive, 29103 defaultScrollbars: true, 29104 customStyle: customStyle, 29105 resize: this.options.resizeScrollbars, 29106 shrink: this.options.shrinkScrollbars, 29107 fade: this.options.fadeScrollbars, 29108 listenX: false 29109 }; 29110 29111 this.wrapper.appendChild(indicator.el); 29112 indicators.push(indicator); 29113 } 29114 29115 // Horizontal scrollbar 29116 if ( this.options.scrollX ) { 29117 indicator = { 29118 el: createDefaultScrollbar('h', interactive, this.options.scrollbars), 29119 interactive: interactive, 29120 defaultScrollbars: true, 29121 customStyle: customStyle, 29122 resize: this.options.resizeScrollbars, 29123 shrink: this.options.shrinkScrollbars, 29124 fade: this.options.fadeScrollbars, 29125 listenY: false 29126 }; 29127 29128 this.wrapper.appendChild(indicator.el); 29129 indicators.push(indicator); 29130 } 29131 } 29132 29133 if ( this.options.indicators ) { 29134 // TODO: check concat compatibility 29135 indicators = indicators.concat(this.options.indicators); 29136 } 29137 29138 for ( var i = indicators.length; i--; ) { 29139 this.indicators.push( new Indicator(this, indicators[i]) ); 29140 } 29141 29142 // TODO: check if we can use array.map (wide compatibility and performance issues) 29143 function _indicatorsMap (fn) { 29144 if (that.indicators) { 29145 for ( var i = that.indicators.length; i--; ) { 29146 fn.call(that.indicators[i]); 29147 } 29148 } 29149 } 29150 29151 if ( this.options.fadeScrollbars ) { 29152 this.on('scrollEnd', function () { 29153 _indicatorsMap(function () { 29154 this.fade(); 29155 }); 29156 }); 29157 29158 this.on('scrollCancel', function () { 29159 _indicatorsMap(function () { 29160 this.fade(); 29161 }); 29162 }); 29163 29164 this.on('scrollStart', function () { 29165 _indicatorsMap(function () { 29166 this.fade(1); 29167 }); 29168 }); 29169 29170 this.on('beforeScrollStart', function () { 29171 _indicatorsMap(function () { 29172 this.fade(1, true); 29173 }); 29174 }); 29175 } 29176 29177 29178 this.on('refresh', function () { 29179 _indicatorsMap(function () { 29180 this.refresh(); 29181 }); 29182 }); 29183 29184 this.on('destroy', function () { 29185 _indicatorsMap(function () { 29186 this.destroy(); 29187 }); 29188 29189 delete this.indicators; 29190 }); 29191 }, 29192 29193 _initWheel: function () { 29194 utils.addEvent(this.wrapper, 'wheel', this); 29195 utils.addEvent(this.wrapper, 'mousewheel', this); 29196 utils.addEvent(this.wrapper, 'DOMMouseScroll', this); 29197 29198 this.on('destroy', function () { 29199 clearTimeout(this.wheelTimeout); 29200 this.wheelTimeout = null; 29201 utils.removeEvent(this.wrapper, 'wheel', this); 29202 utils.removeEvent(this.wrapper, 'mousewheel', this); 29203 utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); 29204 }); 29205 }, 29206 29207 _wheel: function (e) { 29208 if ( !this.enabled ) { 29209 return; 29210 } 29211 29212 var wheelDeltaX, wheelDeltaY, 29213 newX, newY, 29214 that = this; 29215 29216 if ( this.wheelTimeout === undefined ) { 29217 that._execEvent('scrollStart'); 29218 } 29219 29220 // Execute the scrollEnd event after 400ms the wheel stopped scrolling 29221 clearTimeout(this.wheelTimeout); 29222 this.wheelTimeout = setTimeout(function () { 29223 if(!that.options.snap) { 29224 that._execEvent('scrollEnd'); 29225 } 29226 that.wheelTimeout = undefined; 29227 }, 400); 29228 29229 if ( 'deltaX' in e ) { 29230 if (e.deltaMode === 1) { 29231 wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; 29232 wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; 29233 } else { 29234 wheelDeltaX = -e.deltaX; 29235 wheelDeltaY = -e.deltaY; 29236 } 29237 } else if ( 'wheelDeltaX' in e ) { 29238 wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; 29239 wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; 29240 } else if ( 'wheelDelta' in e ) { 29241 wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; 29242 } else if ( 'detail' in e ) { 29243 wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; 29244 } else { 29245 return; 29246 } 29247 29248 wheelDeltaX *= this.options.invertWheelDirection; 29249 wheelDeltaY *= this.options.invertWheelDirection; 29250 29251 if ( !this.hasVerticalScroll ) { 29252 wheelDeltaX = wheelDeltaY; 29253 wheelDeltaY = 0; 29254 } 29255 29256 if ( this.options.snap ) { 29257 newX = this.currentPage.pageX; 29258 newY = this.currentPage.pageY; 29259 29260 if ( wheelDeltaX > 0 ) { 29261 newX--; 29262 } else if ( wheelDeltaX < 0 ) { 29263 newX++; 29264 } 29265 29266 if ( wheelDeltaY > 0 ) { 29267 newY--; 29268 } else if ( wheelDeltaY < 0 ) { 29269 newY++; 29270 } 29271 29272 this.goToPage(newX, newY); 29273 29274 return; 29275 } 29276 29277 newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); 29278 newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); 29279 29280 this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; 29281 this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; 29282 29283 if ( newX > 0 ) { 29284 newX = 0; 29285 } else if ( newX < this.maxScrollX ) { 29286 newX = this.maxScrollX; 29287 } 29288 29289 if ( newY > 0 ) { 29290 newY = 0; 29291 } else if ( newY < this.maxScrollY ) { 29292 newY = this.maxScrollY; 29293 } 29294 29295 this.scrollTo(newX, newY, 0); 29296 29297// INSERT POINT: _wheel 29298 }, 29299 29300 _initSnap: function () { 29301 this.currentPage = {}; 29302 29303 if ( typeof this.options.snap == 'string' ) { 29304 this.options.snap = this.scroller.querySelectorAll(this.options.snap); 29305 } 29306 29307 this.on('refresh', function () { 29308 var i = 0, l, 29309 m = 0, n, 29310 cx, cy, 29311 x = 0, y,
29312 stepX = this.options.snapStepX || this.wrapperWidth, 29313 stepY = this.options.snapStepY || this.wrapperHeight, 29314 el; 29315 29316 this.pages = []; 29317 29318 if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { 29319 return; 29320 } 29321 29322 if ( this.options.snap === true ) { 29323 cx = Math.round( stepX / 2 ); 29324 cy = Math.round( stepY / 2 ); 29325 29326 while ( x > -this.scrollerWidth ) { 29327 this.pages[i] = []; 29328 l = 0; 29329 y = 0; 29330 29331 while ( y > -this.scrollerHeight ) { 29332 this.pages[i][l] = { 29333 x: Math.max(x, this.maxScrollX), 29334 y: Math.max(y, this.maxScrollY), 29335 width: stepX, 29336 height: stepY, 29337 cx: x - cx, 29338 cy: y - cy 29339 }; 29340 29341 y -= stepY; 29342 l++; 29343 } 29344 29345 x -= stepX; 29346 i++; 29347 } 29348 } else { 29349 el = this.options.snap; 29350 l = el.length; 29351 n = -1; 29352 29353 for ( ; i < l; i++ ) { 29354 if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { 29355 m = 0; 29356 n++; 29357 } 29358 29359 if ( !this.pages[m] ) { 29360 this.pages[m] = []; 29361 } 29362 29363 x = Math.max(-el[i].offsetLeft, this.maxScrollX); 29364 y = Math.max(-el[i].offsetTop, this.maxScrollY); 29365 cx = x - Math.round(el[i].offsetWidth / 2); 29366 cy = y - Math.round(el[i].offsetHeight / 2); 29367 29368 this.pages[m][n] = { 29369 x: x, 29370 y: y, 29371 width: el[i].offsetWidth, 29372 height: el[i].offsetHeight, 29373 cx: cx, 29374 cy: cy 29375 }; 29376 29377 if ( x > this.maxScrollX ) { 29378 m++; 29379 } 29380 } 29381 } 29382 29383 this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); 29384 29385 // Update snap threshold if needed 29386 if ( this.options.snapThreshold % 1 === 0 ) { 29387 this.snapThresholdX = this.options.snapThreshold; 29388 this.snapThresholdY = this.options.snapThreshold; 29389 } else { 29390 this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); 29391 this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); 29392 } 29393 }); 29394 29395 this.on('flick', function () { 29396 var time = this.options.snapSpeed || Math.max( 29397 Math.max( 29398 Math.min(Math.abs(this.x - this.startX), 1000), 29399 Math.min(Math.abs(this.y - this.startY), 1000) 29400 ), 300); 29401 29402 this.goToPage( 29403 this.currentPage.pageX + this.directionX, 29404 this.currentPage.pageY + this.directionY, 29405 time 29406 ); 29407 }); 29408 }, 29409 29410 _nearestSnap: function (x, y) { 29411 if ( !this.pages.length ) { 29412 return { x: 0, y: 0, pageX: 0, pageY: 0 }; 29413 } 29414 29415 var i = 0, 29416 l = this.pages.length, 29417 m = 0; 29418 29419 // Check if we exceeded the snap threshold 29420 if ( Math.abs(x - this.absStartX) < this.snapThresholdX && 29421 Math.abs(y - this.absStartY) < this.snapThresholdY ) { 29422 return this.currentPage; 29423 } 29424 29425 if ( x > 0 ) { 29426 x = 0; 29427 } else if ( x < this.maxScrollX ) { 29428 x = this.maxScrollX; 29429 } 29430 29431 if ( y > 0 ) { 29432 y = 0; 29433 } else if ( y < this.maxScrollY ) { 29434 y = this.maxScrollY; 29435 } 29436 29437 for ( ; i < l; i++ ) { 29438 if ( x >= this.pages[i][0].cx ) { 29439 x = this.pages[i][0].x; 29440 break; 29441 } 29442 } 29443 29444 l = this.pages[i].length; 29445 29446 for ( ; m < l; m++ ) { 29447 if ( y >= this.pages[0][m].cy ) { 29448 y = this.pages[0][m].y; 29449 break; 29450 } 29451 } 29452 29453 if ( i == this.currentPage.pageX ) { 29454 i += this.directionX; 29455 29456 if ( i < 0 ) { 29457 i = 0; 29458 } else if ( i >= this.pages.length ) { 29459 i = this.pages.length - 1; 29460 } 29461 29462 x = this.pages[i][0].x; 29463 } 29464 29465 if ( m == this.currentPage.pageY ) { 29466 m += this.directionY; 29467 29468 if ( m < 0 ) { 29469 m = 0; 29470 } else if ( m >= this.pages[0].length ) { 29471 m = this.pages[0].length - 1; 29472 } 29473 29474 y = this.pages[0][m].y; 29475 } 29476 29477 return { 29478 x: x, 29479 y: y, 29480 pageX: i, 29481 pageY: m 29482 }; 29483 }, 29484 29485 goToPage: function (x, y, time, easing) { 29486 easing = easing || this.options.bounceEasing; 29487 29488 if ( x >= this.pages.length ) { 29489 x = this.pages.length - 1; 29490 } else if ( x < 0 ) { 29491 x = 0; 29492 } 29493 29494 if ( y >= this.pages[x].length ) { 29495 y = this.pages[x].length - 1; 29496 } else if ( y < 0 ) { 29497 y = 0; 29498 } 29499 29500 var posX = this.pages[x][y].x, 29501 posY = this.pages[x][y].y; 29502 29503 time = time === undefined ? this.options.snapSpeed || Math.max( 29504 Math.max( 29505 Math.min(Math.abs(posX - this.x), 1000), 29506 Math.min(Math.abs(posY - this.y), 1000) 29507 ), 300) : time; 29508 29509 this.currentPage = { 29510 x: posX, 29511 y: posY, 29512 pageX: x, 29513 pageY: y 29514 }; 29515 29516 this.scrollTo(posX, posY, time, easing); 29517 }, 29518 29519 next: function (time, easing) { 29520 var x = this.currentPage.pageX, 29521 y = this.currentPage.pageY; 29522 29523 x++; 29524 29525 if ( x >= this.pages.length && this.hasVerticalScroll ) { 29526 x = 0; 29527 y++; 29528 } 29529 29530 this.goToPage(x, y, time, easing); 29531 }, 29532 29533 prev: function (time, easing) { 29534 var x = this.currentPage.pageX, 29535 y = this.currentPage.pageY; 29536 29537 x--; 29538 29539 if ( x < 0 && this.hasVerticalScroll ) { 29540 x = 0; 29541 y--; 29542 } 29543 29544 this.goToPage(x, y, time, easing); 29545 }, 29546 29547 _initKeys: function (e) { 29548 // default key bindings 29549 var keys = { 29550 pageUp: 33, 29551 pageDown: 34, 29552 end: 35, 29553 home: 36, 29554 left: 37, 29555 up: 38, 29556 right: 39, 29557 down: 40 29558 }; 29559 var i; 29560 29561 // if you give me characters I give you keycode 29562 if ( typeof this.options.keyBindings == 'object' ) { 29563 for ( i in this.options.keyBindings ) { 29564 if ( typeof this.options.keyBindings[i] == 'string' ) { 29565 this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCo
29565deAt(0); 29566 } 29567 } 29568 } else { 29569 this.options.keyBindings = {}; 29570 } 29571 29572 for ( i in keys ) { 29573 this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; 29574 } 29575 29576 utils.addEvent(window, 'keydown', this); 29577 29578 this.on('destroy', function () { 29579 utils.removeEvent(window, 'keydown', this); 29580 }); 29581 }, 29582 29583 _key: function (e) { 29584 if ( !this.enabled ) { 29585 return; 29586 } 29587 29588 var snap = this.options.snap, // we are using this alot, better to cache it 29589 newX = snap ? this.currentPage.pageX : this.x, 29590 newY = snap ? this.currentPage.pageY : this.y, 29591 now = utils.getTime(), 29592 prevTime = this.keyTime || 0, 29593 acceleration = 0.250, 29594 pos; 29595 29596 if ( this.options.useTransition && this.isInTransition ) { 29597 pos = this.getComputedPosition(); 29598 29599 this._translate(Math.round(pos.x), Math.round(pos.y)); 29600 this.isInTransition = false; 29601 } 29602 29603 this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; 29604 29605 switch ( e.keyCode ) { 29606 case this.options.keyBindings.pageUp: 29607 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 29608 newX += snap ? 1 : this.wrapperWidth; 29609 } else { 29610 newY += snap ? 1 : this.wrapperHeight; 29611 } 29612 break; 29613 case this.options.keyBindings.pageDown: 29614 if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { 29615 newX -= snap ? 1 : this.wrapperWidth; 29616 } else { 29617 newY -= snap ? 1 : this.wrapperHeight; 29618 } 29619 break; 29620 case this.options.keyBindings.end: 29621 newX = snap ? this.pages.length-1 : this.maxScrollX; 29622 newY = snap ? this.pages[0].length-1 : this.maxScrollY; 29623 break; 29624 case this.options.keyBindings.home: 29625 newX = 0; 29626 newY = 0; 29627 break; 29628 case this.options.keyBindings.left: 29629 newX += snap ? -1 : 5 + this.keyAcceleration>>0; 29630 break; 29631 case this.options.keyBindings.up: 29632 newY += snap ? 1 : 5 + this.keyAcceleration>>0; 29633 break; 29634 case this.options.keyBindings.right: 29635 newX -= snap ? -1 : 5 + this.keyAcceleration>>0; 29636 break; 29637 case this.options.keyBindings.down: 29638 newY -= snap ? 1 : 5 + this.keyAcceleration>>0; 29639 break; 29640 default: 29641 return; 29642 } 29643 29644 if ( snap ) { 29645 this.goToPage(newX, newY); 29646 return; 29647 } 29648 29649 if ( newX > 0 ) { 29650 newX = 0; 29651 this.keyAcceleration = 0; 29652 } else if ( newX < this.maxScrollX ) { 29653 newX = this.maxScrollX; 29654 this.keyAcceleration = 0; 29655 } 29656 29657 if ( newY > 0 ) { 29658 newY = 0; 29659 this.keyAcceleration = 0; 29660 } else if ( newY < this.maxScrollY ) { 29661 newY = this.maxScrollY; 29662 this.keyAcceleration = 0; 29663 } 29664 29665 this.scrollTo(newX, newY, 0); 29666 29667 this.keyTime = now; 29668 }, 29669 29670 _animate: function (destX, destY, duration, easingFn) { 29671 var that = this, 29672 startX = this.x, 29673 startY = this.y, 29674 startTime = utils.getTime(), 29675 destTime = startTime + duration; 29676 29677 function step () { 29678 var now = utils.getTime(), 29679 newX, newY, 29680 easing; 29681 29682 if ( now >= destTime ) { 29683 that.isAnimating = false; 29684 that._translate(destX, destY); 29685 29686 if ( !that.resetPosition(that.options.bounceTime) ) { 29687 that._execEvent('scrollEnd'); 29688 } 29689 29690 return; 29691 } 29692 29693 now = ( now - startTime ) / duration; 29694 easing = easingFn(now); 29695 newX = ( destX - startX ) * easing + startX; 29696 newY = ( destY - startY ) * easing + startY; 29697 that._translate(newX, newY); 29698 29699 if ( that.isAnimating ) { 29700 rAF(step); 29701 } 29702 } 29703 29704 this.isAnimating = true; 29705 step(); 29706 }, 29707 handleEvent: function (e) { 29708 switch ( e.type ) { 29709 case 'touchstart': 29710 case 'pointerdown': 29711 case 'MSPointerDown': 29712 case 'mousedown': 29713 this._start(e); 29714 break; 29715 case 'touchmove': 29716 case 'pointermove': 29717 case 'MSPointerMove': 29718 case 'mousemove': 29719 this._move(e); 29720 break; 29721 case 'touchend': 29722 case 'pointerup': 29723 case 'MSPointerUp': 29724 case 'mouseup': 29725 case 'touchcancel': 29726 case 'pointercancel': 29727 case 'MSPointerCancel': 29728 case 'mousecancel': 29729 this._end(e); 29730 break; 29731 case 'orientationchange': 29732 case 'resize': 29733 this._resize(); 29734 break; 29735 case 'transitionend': 29736 case 'webkitTransitionEnd': 29737 case 'oTransitionEnd': 29738 case 'MSTransitionEnd': 29739 this._transitionEnd(e); 29740 break; 29741 case 'wheel': 29742 case 'DOMMouseScroll': 29743 case 'mousewheel': 29744 this._wheel(e); 29745 break; 29746 case 'keydown': 29747 this._key(e); 29748 break; 29749 case 'click': 29750 if ( this.enabled && !e._constructed ) { 29751 e.preventDefault(); 29752 e.stopPropagation(); 29753 } 29754 break; 29755 } 29756 } 29757}; 29758function createDefaultScrollbar (direction, interactive, type) { 29759 var scrollbar = document.createElement('div'), 29760 indicator = document.createElement('div'); 29761 29762 if ( type === true ) { 29763 scrollbar.style.cssText = 'position:absolute;z-index:9999'; 29764 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'; 29765 } 29766 29767 indicator.className = 'iScrollIndicator'; 29768 29769 if ( direction == 'h' ) { 29770 if ( type === true ) { 29771 scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; 29772 indicator.style.height = '100%'; 29773 } 29774 scrollbar.className = 'iScrollHorizontalScrollbar'; 29775 } else { 29776 if ( type === true ) { 29777 scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; 29778 indicator.style.width = '100%'; 29779 } 29780 scrollbar.className = 'iScrollVerticalScrollbar'; 29781 } 29782 29783 scrollbar.style.cssText += ';overflow:hidden'; 29784 29785 if ( !interactive ) { 29786 scrollbar.style.pointerEvents = 'none'; 29787 } 29788 29789 scrollbar.appendChild(indicator); 29790 29791 return scrollbar; 29792} 29793 29794function Indicator (scroller, options) { 29795 this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; 29796 this.wrapperStyle = this.wrapper.style; 29797 this.indicator = this.wrapper.children[0]; 29798 this.indicatorStyle = this.indicator.style; 29799 this.scroller = scroller; 29800 29801 this.options = { 29802 listenX: true, 29803 listenY: true, 29804 interactive: false, 29805 resize: true, 29806 defaultScrollbars: false, 29807 shrink: false, 29808 fade: false, 29809 speedRatioX: 0, 29810 speedRatioY: 0 29811 }; 29812 29813 for ( var i in options ) { 29814 this.options[i] = options[i]; 29815 } 29816 29817 this.sizeRatioX = 1; 29818 this.sizeRatioY = 1; 29819 this.maxPosX = 0; 29820 this.maxPosY = 0; 29821 29822 if ( this.options.interactive ) { 29823 if ( !this.options.disableTouch ) { 29824 utils.addEvent(this.indicator, 'touchstart', this); 29825 utils.addEvent(window, 'touchend', this); 29826 } 29827 if ( !this.options.disablePointer ) { 29828 utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 29829 utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); 29830 } 29831 if ( !this.options.disableMouse ) { 29832 utils.addEvent(this.indicator, 'mousedown', this); 29833 utils.addEvent(window, 'mouseup', this); 29834 } 29835 } 29836 29837 if ( this.options.fade ) { 29838 this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; 29839 var durationProp = utils.style.transitionDuration; 29840 if(!durationProp) { 29841 return; 29842 } 29843 this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; 29844 // remove 0.0001ms 29845 var self = this; 29846 if(utils.isBadAndroid) { 29847 rAF(function() { 29848 if(self.wrapperStyle[durationProp] === '0.0001ms') { 29849 self.wrapperStyle[durationProp] = '0s'; 29850 } 29851 }); 29852 } 29853 this.wrapperStyle.opacity = '0'; 29854 } 29855} 29856 29857Indicator.prototype = { 29858 handleEvent: function (e) { 29859 switch ( e.type ) { 29860 case 'touchstart': 29861 case 'pointerdown': 29862 case 'MSPointerDown': 29863 case 'mousedown': 29864 this._start(e); 29865 break; 29866 case 'touchmove': 29867 case 'pointermove': 29868 case 'MSPointerMove': 29869 case 'mousemove': 29870 this._move(e); 29871 break; 29872 case 'touchend': 29873 case 'pointerup': 29874 case 'MSPointerUp': 29875 case 'mouseup': 29876 case 'touchcancel': 29877 case 'pointercancel': 29878 case 'MSPointerCancel': 29879 case 'mousecancel': 29880 this._end(e); 29881 break; 29882 } 29883 }, 29884 29885 destroy: function () { 29886 if ( this.options.fadeScrollbars ) { 29887 clearTimeout(this.fadeTimeout); 29888 this.fadeTimeout = null; 29889 } 29890 if ( this.options.interactive ) { 29891 utils.removeEvent(this.indicator, 'touchstart', this); 29892 utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); 29893 utils.removeEvent(this.indicator, 'mousedown', this); 29894 29895 utils.removeEvent(window, 'touchmove', this); 29896 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 29897 utils.removeEvent(window, 'mousemove', this); 29898 29899 utils.removeEvent(window, 'touchend', this); 29900 utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); 29901 utils.removeEvent(window, 'mouseup', this); 29902 } 29903 29904 if ( this.options.defaultScrollbars ) { 29905 this.wrapper.parentNode.removeChild(this.wrapper); 29906 } 29907 }, 29908 29909 _start: function (e) { 29910 var point = e.touches ? e.touches[0] : e; 29911 29912 e.preventDefault(); 29913 e.stopPropagation(); 29914 29915 this.transitionTime(); 29916 29917 this.initiated = true; 29918 this.moved = false;
29919 this.lastPointX = point.pageX; 29920 this.lastPointY = point.pageY; 29921 29922 this.startTime = utils.getTime(); 29923 29924 if ( !this.options.disableTouch ) { 29925 utils.addEvent(window, 'touchmove', this); 29926 } 29927 if ( !this.options.disablePointer ) { 29928 utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); 29929 } 29930 if ( !this.options.disableMouse ) { 29931 utils.addEvent(window, 'mousemove', this); 29932 } 29933 29934 this.scroller._execEvent('beforeScrollStart'); 29935 }, 29936 29937 _move: function (e) { 29938 var point = e.touches ? e.touches[0] : e, 29939 deltaX, deltaY, 29940 newX, newY, 29941 timestamp = utils.getTime(); 29942 29943 if ( !this.moved ) { 29944 this.scroller._execEvent('scrollStart'); 29945 } 29946 29947 this.moved = true; 29948 29949 deltaX = point.pageX - this.lastPointX; 29950 this.lastPointX = point.pageX; 29951 29952 deltaY = point.pageY - this.lastPointY; 29953 this.lastPointY = point.pageY; 29954 29955 newX = this.x + deltaX; 29956 newY = this.y + deltaY; 29957 29958 this._pos(newX, newY); 29959 29960// INSERT POINT: indicator._move 29961 29962 e.preventDefault(); 29963 e.stopPropagation(); 29964 }, 29965 29966 _end: function (e) { 29967 if ( !this.initiated ) { 29968 return; 29969 } 29970 29971 this.initiated = false; 29972 29973 e.preventDefault(); 29974 e.stopPropagation(); 29975 29976 utils.removeEvent(window, 'touchmove', this); 29977 utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); 29978 utils.removeEvent(window, 'mousemove', this); 29979 29980 if ( this.scroller.options.snap ) { 29981 var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); 29982 29983 var time = this.options.snapSpeed || Math.max( 29984 Math.max( 29985 Math.min(Math.abs(this.scroller.x - snap.x), 1000), 29986 Math.min(Math.abs(this.scroller.y - snap.y), 1000) 29987 ), 300); 29988 29989 if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { 29990 this.scroller.directionX = 0; 29991 this.scroller.directionY = 0; 29992 this.scroller.currentPage = snap; 29993 this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); 29994 } 29995 } 29996 29997 if ( this.moved ) { 29998 this.scroller._execEvent('scrollEnd'); 29999 } 30000 }, 30001 30002 transitionTime: function (time) { 30003 time = time || 0; 30004 var durationProp = utils.style.transitionDuration; 30005 if(!durationProp) { 30006 return; 30007 } 30008 30009 this.indicatorStyle[durationProp] = time + 'ms'; 30010 30011 if ( !time && utils.isBadAndroid ) { 30012 this.indicatorStyle[durationProp] = '0.0001ms'; 30013 // remove 0.0001ms 30014 var self = this; 30015 rAF(function() { 30016 if(self.indicatorStyle[durationProp] === '0.0001ms') { 30017 self.indicatorStyle[durationProp] = '0s'; 30018 } 30019 }); 30020 } 30021 }, 30022 30023 transitionTimingFunction: function (easing) { 30024 this.indicatorStyle[utils.style.transitionTimingFunction] = easing; 30025 }, 30026 30027 refresh: function () { 30028 this.transitionTime(); 30029 30030 if ( this.options.listenX && !this.options.listenY ) { 30031 this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; 30032 } else if ( this.options.listenY && !this.options.listenX ) { 30033 this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; 30034 } else { 30035 this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; 30036 } 30037 30038 if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { 30039 utils.addClass(this.wrapper, 'iScrollBothScrollbars'); 30040 utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); 30041 30042 if ( this.options.defaultScrollbars && this.options.customStyle ) { 30043 if ( this.options.listenX ) { 30044 this.wrapper.style.right = '8px'; 30045 } else { 30046 this.wrapper.style.bottom = '8px'; 30047 } 30048 } 30049 } else { 30050 utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); 30051 utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); 30052 30053 if ( this.options.defaultScrollbars && this.options.customStyle ) { 30054 if ( this.options.listenX ) { 30055 this.wrapper.style.right = '2px'; 30056 } else { 30057 this.wrapper.style.bottom = '2px'; 30058 } 30059 } 30060 } 30061 30062 var r = this.wrapper.offsetHeight; // force refresh 30063 30064 if ( this.options.listenX ) {
30065 this.wrapperWidth = this.wrapper.clientWidth; 30066 if ( this.options.resize ) { 30067 this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); 30068 this.indicatorStyle.width = this.indicatorWidth + 'px'; 30069 } else { 30070 this.indicatorWidth = this.indicator.clientWidth; 30071 } 30072 30073 this.maxPosX = this.wrapperWidth - this.indicatorWidth; 30074 30075 if ( this.options.shrink == 'clip' ) { 30076 this.minBoundaryX = -this.indicatorWidth + 8; 30077 this.maxBoundaryX = this.wrapperWidth - 8; 30078 } else { 30079 this.minBoundaryX = 0; 30080 this.maxBoundaryX = this.maxPosX; 30081 } 30082 30083 this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); 30084 } 30085 30086 if ( this.options.listenY ) { 30087 this.wrapperHeight = this.wrapper.clientHeight; 30088 if ( this.options.resize ) { 30089 this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); 30090 this.indicatorStyle.height = this.indicatorHeight + 'px'; 30091 } else { 30092 this.indicatorHeight = this.indicator.clientHeight; 30093 } 30094 30095 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 30096 30097 if ( this.options.shrink == 'clip' ) { 30098 this.minBoundaryY = -this.indicatorHeight + 8; 30099 this.maxBoundaryY = this.wrapperHeight - 8; 30100 } else { 30101 this.minBoundaryY = 0; 30102 this.maxBoundaryY = this.maxPosY; 30103 } 30104 30105 this.maxPosY = this.wrapperHeight - this.indicatorHeight; 30106 this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); 30107 } 30108 30109 this.updatePosition(); 30110 }, 30111 30112 updatePosition: function () { 30113 var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, 30114 y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; 30115 30116 if ( !this.options.ignoreBoundaries ) { 30117 if ( x < this.minBoundaryX ) { 30118 if ( this.options.shrink == 'scale' ) { 30119 this.width = Math.max(this.indicatorWidth + x, 8); 30120 this.indicatorStyle.width = this.width + 'px'; 30121 } 30122 x = this.minBoundaryX; 30123 } else if ( x > this.maxBoundaryX ) { 30124 if ( this.options.shrink == 'scale' ) { 30125 this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); 30126 this.indicatorStyle.width = this.width + 'px'; 30127 x = this.maxPosX + this.indicatorWidth - this.width; 30128 } else { 30129 x = this.maxBoundaryX; 30130 } 30131 } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { 30132 this.width = this.indicatorWidth; 30133 this.indicatorStyle.width = this.width + 'px'; 30134 } 30135 30136 if ( y < this.minBoundaryY ) { 30137 if ( this.options.shrink == 'scale' ) { 30138 this.height = Math.max(this.indicatorHeight + y * 3, 8); 30139 this.indicatorStyle.height = this.height + 'px'; 30140 } 30141 y = this.minBoundaryY; 30142 } else if ( y > this.maxBoundaryY ) { 30143 if ( this.options.shrink == 'scale' ) { 30144 this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); 30145 this.indicatorStyle.height = this.height + 'px'; 30146 y = this.maxPosY + this.indicatorHeight - this.height; 30147 } else { 30148 y = this.maxBoundaryY; 30149 } 30150 } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { 30151 this.height = this.indicatorHeight; 30152 this.indicatorStyle.height = this.height + 'px'; 30153 } 30154 } 30155 30156 this.x = x; 30157 this.y = y; 30158 30159 if ( this.scroller.options.useTransform ) { 30160 this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; 30161 } else { 30162 this.indicatorStyle.left = x + 'px'; 30163 this.indicatorStyle.top = y + 'px'; 30164 } 30165 }, 30166 30167 _pos: function (x, y) { 30168 if ( x < 0 ) { 30169 x = 0; 30170 } else if ( x > this.maxPosX ) { 30171 x = this.maxPosX; 30172 } 30173 30174 if ( y < 0 ) { 30175 y = 0; 30176 } else if ( y > this.maxPosY ) { 30177 y = this.maxPosY;
30178 } 30179 30180 x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; 30181 y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; 30182 30183 this.scroller.scrollTo(x, y); 30184 }, 30185 30186 fade: function (val, hold) { 30187 if ( hold && !this.visible ) { 30188 return; 30189 } 30190 30191 clearTimeout(this.fadeTimeout); 30192 this.fadeTimeout = null; 30193 30194 var time = val ? 250 : 500, 30195 delay = val ? 0 : 300; 30196 30197 val = val ? '1' : '0'; 30198 30199 this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; 30200 30201 this.fadeTimeout = setTimeout((function (val) { 30202 this.wrapperStyle.opacity = val; 30203 this.visible = +val; 30204 }).bind(this, val), delay); 30205 } 30206}; 30207 30208IScroll.utils = utils; 30209 30210if ( typeof module != 'undefined' && module.exports ) { 30211 module.exports = IScroll; 30212} else if ( typeof define == 'function' && define.amd ) { 30213 define( function () { return IScroll; } ); 30214} else { 30215 window.IScroll = IScroll; 30216} 30217 30218})(window, document, Math); 30219/*! 30220 * fullPage 2.9.4 30221 * https://github.com/alvarotrigo/fullPage.js 30222 * @license MIT licensed 30223 * 30224 * Copyright (C) 2015 alvarotrigo.com - A project by Alvaro Trigo 30225 */ 30226(function(global, factory) { 30227 'use strict'; 30228 if (typeof define === 'function' && define.amd) { 30229 define(['jquery'], function($) { 30230 return factory($, global, global.document, global.Math); 30231 }); 30232 } else if (typeof exports === "object" && exports) { 30233 module.exports = factory(require('jquery'), global, global.document, global.Math); 30234 } else { 30235 factory(jQuery, global, global.document, global.Math); 30236 } 30237})(typeof window !== 'undefined' ? window : this, function($, window, document, Math, undefined) { 30238 'use strict'; 30239 30240 // keeping central set of classnames and selectors 30241 var WRAPPER = 'fullpage-wrapper'; 30242 var WRAPPER_SEL = '.' + WRAPPER; 30243 30244 // slimscroll 30245 var SCROLLABLE = 'fp-scrollable'; 30246 var SCROLLABLE_SEL = '.' + SCROLLABLE; 30247 30248 // util 30249 var RESPONSIVE = 'fp-responsive'; 30250 var NO_TRANSITION = 'fp-notransition'; 30251 var DESTROYED = 'fp-destroyed'; 30252 var ENABLED = 'fp-enabled'; 30253 var VIEWING_PREFIX = 'fp-viewing'; 30254 var ACTIVE = 'active'; 30255 var ACTIVE_SEL = '.' + ACTIVE; 30256 var COMPLETELY = 'fp-completely'; 30257 var COMPLETELY_SEL = '.' + COMPLETELY; 30258 30259 // section 30260 var SECTION_DEFAULT_SEL = '.section'; 30261 var SECTION = 'fp-section'; 30262 var SECTION_SEL = '.' + SECTION; 30263 var SECTION_ACTIVE_SEL = SECTION_SEL + ACTIVE_SEL; 30264 var SECTION_FIRST_SEL = SECTION_SEL + ':first'; 30265 var SECTION_LAST_SEL = SECTION_SEL + ':last'; 30266 var TABLE_CELL = 'fp-tableCell'; 30267 var TABLE_CELL_SEL = '.' + TABLE_CELL; 30268 var AUTO_HEIGHT = 'fp-auto-height'; 30269 var AUTO_HEIGHT_SEL = '.fp-auto-height'; 30270 var NORMAL_SCROLL = 'fp-normal-scroll'; 30271 var NORMAL_SCROLL_SEL = '.fp-normal-scroll'; 30272 30273 // section nav 30274 var SECTION_NAV = 'fp-nav'; 30275 var SECTION_NAV_SEL = '#' + SECTION_NAV; 30276 var SECTION_NAV_TOOLTIP = 'fp-tooltip'; 30277 var SECTION_NAV_TOOLTIP_SEL='.'+SECTION_NAV_TOOLTIP; 30278 var SHOW_ACTIVE_TOOLTIP = 'fp-show-active'; 30279 30280 // slide 30281 var SLIDE_DEFAULT_SEL = '.slide'; 30282 var SLIDE = 'fp-slide'; 30283 var SLIDE_SEL = '.' + SLIDE; 30284 var SLIDE_ACTIVE_SEL = SLIDE_SEL + ACTIVE_SEL; 30285 var SLIDES_WRAPPER = 'fp-slides'; 30286 var SLIDES_WRAPPER_SEL = '.' + SLIDES_WRAPPER; 30287 var SLIDES_CONTAINER = 'fp-slidesContainer'; 30288 var SLIDES_CONTAINER_SEL = '.' + SLIDES_CONTAINER; 30289 var TABLE = 'fp-table'; 30290 30291 // slide nav 30292 var SLIDES_NAV = 'fp-slidesNav'; 30293 var SLIDES_NAV_SEL = '.' + SLIDES_NAV; 30294 var SLIDES_NAV_LINK_SEL = SLIDES_NAV_SEL + ' a'; 30295 var SLIDES_ARROW = 'fp-controlArrow'; 30296 var SLIDES_ARROW_SEL = '.' + SLIDES_ARROW; 30297 var SLIDES_PREV = 'fp-prev'; 30298 var SLIDES_PREV_SEL = '.' + SLIDES_PREV; 30299 var SLIDES_ARROW_PREV = SLIDES_ARROW + ' ' + SLIDES_PREV; 30300 var SLIDES_ARROW_PREV_SEL = SLIDES_ARROW_SEL + SLIDES_PREV_SEL; 30301 var SLIDES_NEXT = 'fp-next';
30302 var SLIDES_NEXT_SEL = '.' + SLIDES_NEXT; 30303 var SLIDES_ARROW_NEXT = SLIDES_ARROW + ' ' + SLIDES_NEXT; 30304 var SLIDES_ARROW_NEXT_SEL = SLIDES_ARROW_SEL + SLIDES_NEXT_SEL; 30305 30306 var $window = $(window); 30307 var $document = $(document); 30308 30309 // Default options for iScroll.js used when using scrollOverflow 30310 var iscrollOptions = { 30311 scrollbars: true, 30312 mouseWheel: true, 30313 hideScrollbars: false, 30314 fadeScrollbars: false, 30315 disableMouse: true, 30316 interactiveScrollbars: true, 30317 bounce: false, 30318 }; 30319 30320 $.fn.fullpage = function(options) { 30321 //only once my friend! 30322 if($('html').hasClass(ENABLED)){ displayWarnings(); return; } 30323 30324 // common jQuery objects 30325 var $htmlBody = $('html, body'); 30326 var $body = $('body'); 30327 30328 var FP = $.fn.fullpage; 30329 30330 // Creating some defaults, extending them with any options that were provided 30331 options = $.extend({ 30332 //navigation 30333 menu: false, 30334 anchors:[], 30335 lockAnchors: false, 30336 navigation: false, 30337 navigationPosition: 'right', 30338 navigationTooltips: [], 30339 showActiveTooltip: false, 30340 slidesNavigation: false, 30341 slidesNavPosition: 'bottom', 30342 scrollBar: false, 30343 hybrid: false, 30344 30345 //scrolling 30346 css3: true, 30347 scrollingSpeed: 700, 30348 autoScrolling: true, 30349 fitToSection: true, 30350 fitToSectionDelay: 1000, 30351 easing: 'easeInOutCubic', 30352 easingcss3: 'ease', 30353 loopBottom: false, 30354 loopTop: false, 30355 loopHorizontal: true, 30356 continuousVertical: false, 30357 continuousHorizontal: false, 30358 scrollHorizontally: false, 30359 interlockedSlides: false, 30360 dragAndMove: false, 30361 offsetSections: false, 30362 resetSliders: false, 30363 fadingEffect: false, 30364 normalScrollElements: null, 30365 scrollOverflow: false, 30366 scrollOverflowReset: false, 30367 scrollOverflowHandler: iscrollHandler, 30368 scrollOverflowOptions: null, 30369 touchSensitivity: 5, 30370 normalScrollElementTouchThreshold: 5, 30371 bigSectionsDestination: null, 30372 30373 //Accessibility 30374 keyboardScrolling: true, 30375 animateAnchor: true, 30376 recordHistory: true, 30377 30378 //design 30379 controlArrows: true, 30380 controlArrowColor: '#fff', 30381 verticalCentered: true, 30382 sectionsColor : [], 30383 paddingTop: 0, 30384 paddingBottom: 0, 30385 fixedElements: null, 30386 responsive: 0, //backwards compabitility with responsiveWiddth 30387 responsiveWidth: 0, 30388 responsiveHeight: 0, 30389 responsiveSlides: false, 30390 parallax: false, 30391 parallaxOptions: { 30392 type: 'reveal', 30393 percentage: 62, 30394 property: 'translate' 30395 }, 30396 30397 //Custom selectors 30398 sectionSelector: SECTION_DEFAULT_SEL, 30399 slideSelector: SLIDE_DEFAULT_SEL, 30400 30401 //events 30402 afterLoad: null, 30403 onLeave: null, 30404 afterRender: null, 30405 afterResize: null, 30406 afterReBuild: null, 30407 afterSlideLoad: null, 30408 onSlideLeave: null, 30409 afterResponsive: null, 30410 30411 lazyLoading: true 30412 }, options); 30413 30414 //flag to avoid very fast sliding for landscape sliders 30415 var slideMoving = false; 30416 30417 var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|playbook|silk|BlackBerry|BB10|Windows Phone|Tizen|Bada|webOS|IEMobile|Opera Mini)/); 30418 var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints)); 30419 var container = $(this); 30420 var windowsHeight = $window.height(); 30421 var isResizing = false; 30422 var isWindowFocused = true; 30423 var lastScrolledDestiny; 30424 var lastScrolledSlide; 30425 var canScroll = true; 30426 var scrollings = []; 30427 var controlPressed; 30428 var startingSection; 30429 var isScrollAllowed = {}; 30430 isScrollAllowed.m = { 'up':true, 'down':true, 'left':true, 'right':true }; 30431 isScrollAllowed.k = $.extend(true,{}, isScrollAllowed.m); 30432 var MSPointer = getMSPointer(); 30433 var events = { 30434 touchmove: 'ontouchmove' in window ? 'touchmove' : MSPointer.move, 30435 touchstart: 'ontouchstart' in window ? 'touchstart' : MSPointer.down 30436 }; 30437 30438 //cheks for passive event support 30439 //added by Uncode from new fullPage updates 30440 var g_supportsPassive = false;
30441 try { 30442 var opts = Object.defineProperty({}, 'passive', { 30443 get: function() { 30444 g_supportsPassive = true; 30445 } 30446 }); 30447 window.addEventListener("testPassive", null, opts); 30448 window.removeEventListener("testPassive", null, opts); 30449 } catch (e) {} 30450 30451 //timeouts 30452 var resizeId; 30453 var afterSectionLoadsId; 30454 var afterSlideLoadsId; 30455 var scrollId; 30456 var scrollId2; 30457 var keydownId; 30458 var originals = $.extend(true, {}, options); //deep copy 30459 30460 //Uncode addition 30461 var $masthead = $('#masthead'); 30462 var hideMenu = !$('body').hasClass('vmenu') && $('body').hasClass('uncode-fp-menu-hide') ? true : false; 30463 var menuHeight = $masthead.hasClass('menu-transparent') || hideMenu ? 0 : UNCODE.menuHeight; 30464 var bodyBorder = UNCODE.bodyBorder; 30465 var adminBarHeight = UNCODE.adminBarHeight; 30466 30467 displayWarnings(); 30468 30469 //fixing bug in iScroll with links: https://github.com/cubiq/iscroll/issues/783 30470 iscrollOptions.click = isTouch; // see #2035 30471 30472 //extending iScroll options with the user custom ones 30473 iscrollOptions = $.extend(iscrollOptions, options.scrollOverflowOptions); 30474 30475 //easeInOutCubic animation included in the plugin 30476 $.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;}}); 30477 30478 /** 30479 * Sets the autoScroll option. 30480 * It changes the scroll bar visibility and the history of the site as a result. 30481 */ 30482 function setAutoScrolling(value, type){ 30483 //removing the transformation 30484 if(!value){ 30485 silentScroll(0); 30486 } 30487 30488 setVariableState('autoScrolling', value, type); 30489 30490 var element = $(SECTION_ACTIVE_SEL); 30491 30492 if(options.autoScrolling && !options.scrollBar){ 30493 $htmlBody.css({ 30494 'overflow' : 'hidden !important', 30495 'height' : '100%' 30496 }); 30497 30498 //Uncode addition 30499 //setRecordHistory(originals.recordHistory, 'internal'); 30500 30501 //for IE touch devices 30502 container.css({ 30503 '-ms-touch-action': 'none', 30504 'touch-action': 'none' 30505 }); 30506 30507 if(element.length){ 30508 //moving the container up 30509 silentScroll(element.position().top); 30510 } 30511 30512 }else{ 30513 $htmlBody.css({ 30514 'overflow' : 'visible !important', 30515 'height' : 'initial' 30516 }); 30517 30518 //Uncode addition 30519 //setRecordHistory(false, 'internal'); 30520 30521 //for IE touch devices 30522 container.css({ 30523 '-ms-touch-action': '', 30524 'touch-action': '' 30525 }); 30526 30527 //scrolling the page to the section with no animation 30528 if (element.length) { 30529 $htmlBody.scrollTop(element.position().top); 30530 } 30531 } 30532 } 30533 30534 /** 30535 * Defines wheter to record the history for each hash change in the URL. 30536 */ 30537 function setRecordHistory(value, type){ 30538 setVariableState('recordHistory', value, type); 30539 } 30540 30541 /** 30542 * Defines the scrolling speed 30543 */ 30544 function setScrollingSpeed(value, type){ 30545 setVariableState('scrollingSpeed', value, type); 30546 } 30547 30548 /** 30549 * Sets fitToSection 30550 */ 30551 function setFitToSection(value, type){ 30552 setVariableState('fitToSection', value, type); 30553 } 30554 30555 /** 30556 * Sets lockAnchors 30557 */ 30558 function setLockAnchors(value){ 30559 options.lockAnchors = value; 30560 } 30561 30562 /** 30563 * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad. 30564 */ 30565 function setMouseWheelScrolling(value){ 30566 if(value){ 30567 addMouseWheelHandler(); 30568 addMiddleWheelHandler(); 30569 }else{ 30570 removeMouseWheelHandler(); 30571 removeMiddleWheelHandler(); 30572 } 30573 } 30574 30575 /** 30576 * Adds or remove the possibility of scrolling through sections by using the mouse wheel/trackpad or touch gestures. 30577 * Optionally a second parameter can be used to specify the direction for which the action will be applied. 30578 * 30579 * @param directions string containing the direction or directions separated by comma. 30580 */ 30581 function setAllowScrolling(value, directions){ 30582 if(typeof directions !== 'undefined'){ 30583 directions = directions.replace(/ /g,'').split(','); 30584 30585 $.each(directions, function (index, direction){ 30586 setIsScrollAllowed(value, direction, 'm'); 30587 }); 30588 } 30589 else if(value){ 30590 setMouseWheelScrolling(true); 30591 addTouchHandler(); 30592 }else{ 30593 setMouseWheelScrolling(false); 30594 removeTouchHandler(); 30595 } 30596 } 30597 30598 /** 30599 * Adds or remove the possibility of scrolling through sections by using the keyboard arrow keys 30600 */ 30601 function setKeyboardScrolling(value, directions){ 30602 if(typeof directions !== 'undefined'){ 30603 directions = directions.replace(/ /g,'').split(','); 30604 30605 $.each(directions, function (index, direction){ 30606 setIsScrollAllowed(value, direction, 'k'); 30607 }); 30608 }else{ 30609 options.keyboardScrolling = value; 30610 } 30611 } 30612 30613 /** 30614 * Moves the page up one section. 30615 */ 30616 function moveSectionUp(){ 30617 var prev = $(SECTION_ACTIVE_SEL).prev(SECTION_SEL); 30618 30619 //looping to the bottom if there's no more sections above 30620 if (!prev.length && (options.loopTop || options.continuousVertical)) {
30621 prev = $(SECTION_SEL).last(); 30622 } 30623 30624 if (prev.length) { 30625 scrollPage(prev, null, true); 30626 } 30627 } 30628 30629 /** 30630 * Moves the page down one section. 30631 */ 30632 function moveSectionDown(){ 30633 var next = $(SECTION_ACTIVE_SEL).next(SECTION_SEL); 30634 30635 //looping to the top if there's no more sections below 30636 if(!next.length && 30637 (options.loopBottom || options.continuousVertical)){ 30638 next = $(SECTION_SEL).first(); 30639 } 30640 30641 if(next.length){ 30642 scrollPage(next, null, false); 30643 } 30644 } 30645 30646 /** 30647 * Moves the page to the given section and slide with no animation. 30648 * Anchors or index positions can be used as params. 30649 */ 30650 function silentMoveTo(sectionAnchor, slideAnchor){ 30651 setScrollingSpeed (0, 'internal'); 30652 moveTo(sectionAnchor, slideAnchor); 30653 setScrollingSpeed (originals.scrollingSpeed, 'internal'); 30654 } 30655 30656 /** 30657 * Moves the page to the given section and slide. 30658 * Anchors or index positions can be used as params. 30659 */ 30660 function moveTo(sectionAnchor, slideAnchor){ 30661 var destiny = getSectionByAnchor(sectionAnchor); 30662 30663 if (typeof slideAnchor !== 'undefined'){ 30664 scrollPageAndSlide(sectionAnchor, slideAnchor); 30665 }else if(destiny.length > 0){ 30666 scrollPage(destiny); 30667 } 30668 } 30669 30670 /** 30671 * Slides right the slider of the active section. 30672 * Optional `section` param. 30673 */ 30674 function moveSlideRight(section){ 30675 moveSlide('right', section); 30676 } 30677 30678 /** 30679 * Slides left the slider of the active section. 30680 * Optional `section` param. 30681 */ 30682 function moveSlideLeft(section){ 30683 moveSlide('left', section); 30684 } 30685 30686 /** 30687 * When resizing is finished, we adjust the slides sizes and positions 30688 */ 30689 function reBuild(resizing){ 30690 if(container.hasClass(DESTROYED)){ return; } //nothing to do if the plugin was destroyed 30691 30692 isResizing = true; 30693 30694 windowsHeight = $window.height(); //updating global var 30695 30696 $(SECTION_SEL).each(function(){ 30697 var slidesWrap = $(this).find(SLIDES_WRAPPER_SEL); 30698 var slides = $(this).find(SLIDE_SEL); 30699 30700 //adjusting the height of the table-cell for IE and Firefox 30701 if(options.verticalCentered){ 30702 $(this).find(TABLE_CELL_SEL).css('height', getTableHeight($(this)) + 'px'); 30703 } 30704 30705 $(this).css('height', windowsHeight + 'px'); 30706 30707 //resizing the scrolling divs 30708 if(options.scrollOverflow){ 30709 if(slides.length){ 30710 slides.each(function(){ 30711 createScrollBar($(this)); 30712 }); 30713 }else{ 30714 createScrollBar($(this)); 30715 } 30716 } 30717 30718 //adjusting the position fo the FULL WIDTH slides... 30719 if (slides.length > 1) { 30720 landscapeScroll(slidesWrap, slidesWrap.find(SLIDE_ACTIVE_SEL)); 30721 } 30722 }); 30723 30724 var activeSection = $(SECTION_ACTIVE_SEL); 30725 var sectionIndex = activeSection.index(SECTION_SEL); 30726 30727 //isn't it the first section? 30728 if(sectionIndex){ 30729 //adjusting the position for the current section 30730 silentMoveTo(sectionIndex + 1); 30731 } 30732 30733 isResizing = false; 30734 // Uncode change 30735 // $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container); 30736 $.isFunction( options.afterResize ) && resizing && options.afterResize.call(container, getTableHeight()); 30737 $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call(container); 30738 } 30739 30740 /** 30741 * Turns fullPage.js to normal scrolling mode when the viewport `width` or `height` 30742 * are smaller than the set limit values. 30743 */ 30744 function setResponsive(active){ 30745 var isResponsive = $body.hasClass(RESPONSIVE); 30746 30747 if(active){ 30748 if(!isResponsive){ 30749 setAutoScrolling(false, 'internal'); 30750 setFitToSection(false, 'internal'); 30751 $(SECTION_NAV_SEL).hide(); 30752 $body.addClass(RESPONSIVE); 30753 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 30754 } 30755 } 30756 else if(isResponsive){ 30757 setAutoScrolling(originals.autoScrolling, 'internal'); 30758 setFitToSection(originals.autoScrolling, 'internal'); 30759 $(SECTION_NAV_SEL).show(); 30760 $body.removeClass(RESPONSIVE); 30761 $.isFunction( options.afterResponsive ) && options.afterResponsive.call( container, active); 30762 } 30763 } 30764 30765 if($(this).length){ 30766 //public functions 30767 FP.setAutoScrolling = setAutoScrolling; 30768 FP.setRecordHistory = setRecordHistory; 30769 FP.setScrollingSpeed = setScrollingSpeed; 30770 FP.setFitToSection = setFitToSection; 30771 FP.setLockAnchors = setLockAnchors; 30772 FP.setMouseWheelScrolling = setMouseWheelScrolling; 30773 FP.setAllowScrolling = setAllowScrolling; 30774 FP.setKeyboardScrolling = setKeyboardScrolling; 30775 FP.moveSectionUp = moveSectionUp; 30776 FP.moveSectionDown = moveSectionDown; 30777 FP.silentMoveTo = silentMoveTo; 30778 FP.moveTo = moveTo; 30779 FP.moveSlideRight = moveSlideRight; 30780 FP.moveSlideLeft = moveSlideLeft; 30781 FP.fitToSection = fitToSection; 30782 FP.reBuild = reBuild; 30783 FP.setResponsive = setResponsive; 30784 FP.destroy = destroy; 30785 30786 init(); 30787 30788 bindEvents(); 30789 } 30790
30791 function init(){ 30792 //if css3 is not supported, it will use jQuery animations 30793 if(options.css3){ 30794 options.css3 = support3d(); 30795 } 30796 30797 options.scrollBar = options.scrollBar || options.hybrid; 30798 30799 setOptionsFromDOM(); 30800 prepareDom(); 30801 setAllowScrolling(true); 30802 setAutoScrolling(options.autoScrolling, 'internal'); 30803 responsive(); 30804 30805 //setting the class for the body element 30806 setBodyClass(); 30807 30808 //Uncode addition 30809 // if(document.readyState === 'complete'){ 30810 // scrollToAnchor(); 30811 // } 30812 // $window.on('load', scrollToAnchor); 30813 } 30814 30815 function bindEvents(){ 30816 $window 30817 //when scrolling... 30818 //.on('scroll', scrollHandler) 30819 30820 //detecting any change on the URL to scroll to the given anchor link 30821 //(a way to detect back history button as we play with the hashes on the URL) 30822 .on('hashchange', hashChangeHandler) 30823 30824 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 30825 .blur(blurHandler) 30826 30827 //when resizing the site, we adjust the heights of the sections, slimScroll... 30828 .resize(resizeHandler); 30829 30830 $document 30831 //Sliding with arrow keys, both, vertical and horizontal 30832 .keydown(keydownHandler) 30833 30834 //to prevent scrolling while zooming 30835 .keyup(keyUpHandler) 30836 30837 //Scrolls to the section when clicking the navigation bullet 30838 .on('click touchstart', SECTION_NAV_SEL + ' a', sectionBulletHandler) 30839 30840 //Scrolls the slider to the given slide destination for the given section 30841 .on('click touchstart', SLIDES_NAV_LINK_SEL, slideBulletHandler) 30842 30843 .on('click', SECTION_NAV_TOOLTIP_SEL, tooltipTextHandler); 30844 30845 //Scrolling horizontally when clicking on the slider controls. 30846 $(SECTION_SEL).on('click touchstart', SLIDES_ARROW_SEL, slideArrowHandler); 30847 30848 /** 30849 * Applying normalScroll elements. 30850 * Ignoring the scrolls over the specified selectors. 30851 */ 30852 if(options.normalScrollElements){ 30853 $document.on('mouseenter', options.normalScrollElements, function () { 30854 setMouseWheelScrolling(false); 30855 }); 30856 30857 $document.on('mouseleave', options.normalScrollElements, function(){ 30858 setMouseWheelScrolling(true); 30859 }); 30860 } 30861 } 30862 30863 /** 30864 * Setting options from DOM elements if they are not provided. 30865 */ 30866 function setOptionsFromDOM(){ 30867 var sections = container.find(options.sectionSelector); 30868 30869 //no anchors option? Checking for them in the DOM attributes 30870 if(!options.anchors.length){ 30871 options.anchors = sections.filter('[data-anchor]').map(function(){ 30872 return $(this).data('anchor').toString(); 30873 }).get(); 30874 } 30875 30876 //no tooltips option? Checking for them in the DOM attributes 30877 if(!options.navigationTooltips.length){ 30878 options.navigationTooltips = sections.filter('[data-tooltip]').map(function(){ 30879 return $(this).data('tooltip').toString(); 30880 }).get(); 30881 } 30882 } 30883 30884 /** 30885 * Works over the DOM structure to set it up for the current fullpage options. 30886 */ 30887 function prepareDom(){ 30888 container.css({ 30889 'height': '100%', 30890 'position': 'relative' 30891 }); 30892 30893 //adding a class to recognize the container internally in the code 30894 container.addClass(WRAPPER); 30895 $('html').addClass(ENABLED); 30896 30897 windowsHeight = $window.height(); 30898 30899 container.removeClass(DESTROYED); //in case it was destroyed before initializing it again 30900 30901 addInternalSelectors(); 30902 30903 //styling the sections / slides / menu 30904 $(SECTION_SEL).each(function(index){ 30905 var section = $(this); 30906 var slides = section.find(SLIDE_SEL); 30907 var numSlides = slides.length; 30908 30909 styleSection(section, index); 30910 styleMenu(section, index); 30911 30912 // if there's any slide 30913 if (numSlides > 0) { 30914 styleSlides(section, slides, numSlides); 30915 }else{ 30916 if(options.verticalCentered){ 30917 addTableClass(section); 30918 } 30919 } 30920 }); 30921 30922 //fixed elements need to be moved out of the plugin container due to problems with CSS3. 30923 if(options.fixedElements && options.css3){ 30924 $(options.fixedElements).appendTo($body); 30925 } 30926 30927 //vertical centered of the navigation + active bullet 30928 if(options.navigation){ 30929 addVerticalNavigation(); 30930 } 30931 30932 enableYoutubeAPI(); 30933 30934 if(options.scrollOverflow){ 30935 if(document.readyState === 'complete'){ 30936 createScrollBarHandler(); 30937 } 30938 //after DOM and images are loaded 30939 $window.on('load', createScrollBarHandler); 30940 }else{ 30941 afterRenderActions(); 30942 } 30943 } 30944 30945 /** 30946 * Styles the horizontal slides for a section. 30947 */ 30948 function styleSlides(section, slides, numSlides){ 30949 var sliderWidth = numSlides * 100; 30950 var slideWidth = 100 / numSlides; 30951 30952 slides.wrapAll('<div class="' + SLIDES_CONTAINER + '" />'); 30953 slides.parent().wrap('<div class="' + SLIDES_WRAPPER + '" />'); 30954 30955 section.find(SLIDES_CONTAINER_SEL).css('width', sliderWidth + '%'); 30956 30957 if(numSlides > 1){ 30958 if(options.controlArrows){ 30959 createSlideArrows(section); 30960 } 30961 30962 if(options.slidesNavigation){ 30963 addSlidesNavigation(section, numSlides); 30964 } 30965 } 30966 30967 slides.each(function(index) { 30968 $(this).css('width', slideWidth + '%'); 30969 30970 if(options.verticalCentered){ 30971 addTableClass($(this)); 30972 } 30973 }); 30974 30975 var startingSlide = section.find(SLIDE_ACTIVE_SEL); 30976 30977 //if the slide won't be an starting point, the default will be the first one 30978 //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/sl
30978ide by default. 30979 if( startingSlide.length && ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) !== 0 || ($(SECTION_ACTIVE_SEL).index(SECTION_SEL) === 0 && startingSlide.index() !== 0))){ 30980 silentLandscapeScroll(startingSlide, 'internal'); 30981 }else{ 30982 slides.eq(0).addClass(ACTIVE); 30983 } 30984 } 30985 30986 /** 30987 * Styling vertical sections 30988 */ 30989 function styleSection(section, index){ 30990 //if no active section is defined, the 1st one will be the default one 30991 if(!index && $(SECTION_ACTIVE_SEL).length === 0) { 30992 section.addClass(ACTIVE); 30993 } 30994 startingSection = $(SECTION_ACTIVE_SEL); 30995 30996 section.css('height', windowsHeight + 'px'); 30997 30998 if(options.paddingTop){ 30999 section.css('padding-top', options.paddingTop); 31000 } 31001 31002 if(options.paddingBottom){ 31003 section.css('padding-bottom', options.paddingBottom); 31004 } 31005 31006 if (typeof options.sectionsColor[index] !== 'undefined') { 31007 section.css('background-color', options.sectionsColor[index]); 31008 } 31009 31010 if (typeof options.anchors[index] !== 'undefined') { 31011 section.attr('data-anchor', options.anchors[index]); 31012 } 31013 } 31014 31015 /** 31016 * Sets the data-anchor attributes to the menu elements and activates the current one. 31017 */ 31018 function styleMenu(section, index){ 31019 if (typeof options.anchors[index] !== 'undefined') { 31020 //activating the menu / nav element on load 31021 if(section.hasClass(ACTIVE)){ 31022 activateMenuAndNav(options.anchors[index], index); 31023 } 31024 } 31025 31026 //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms) 31027 if(options.menu && options.css3 && $(options.menu).closest(WRAPPER_SEL).length){ 31028 $(options.menu).appendTo($body); 31029 } 31030 } 31031 31032 /** 31033 * Adds internal classes to be able to provide customizable selectors 31034 * keeping the link with the style sheet. 31035 */ 31036 function addInternalSelectors(){ 31037 container.find(options.sectionSelector).addClass(SECTION); 31038 container.find(options.slideSelector).addClass(SLIDE); 31039 } 31040 31041 /** 31042 * Creates the control arrows for the given section 31043 */ 31044 function createSlideArrows(section){ 31045 section.find(SLIDES_WRAPPER_SEL).after('<div class="' + SLIDES_ARROW_PREV + '"></div><div class="' + SLIDES_ARROW_NEXT + '"></div>'); 31046 31047 if(options.controlArrowColor!='#fff'){ 31048 section.find(SLIDES_ARROW_NEXT_SEL).css('border-color', 'transparent transparent transparent '+options.controlArrowColor); 31049 section.find(SLIDES_ARROW_PREV_SEL).css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent'); 31050 } 31051 31052 if(!options.loopHorizontal){ 31053 section.find(SLIDES_ARROW_PREV_SEL).hide(); 31054 } 31055 } 31056 31057 /** 31058 * Creates a vertical navigation bar. 31059 */ 31060 function addVerticalNavigation(){ 31061 $body.append('<div id="' + SECTION_NAV + '"><ul></ul></div>'); 31062 var nav = $(SECTION_NAV_SEL); 31063 31064 nav.addClass(function() { 31065 return options.showActiveTooltip ? SHOW_ACTIVE_TOOLTIP + ' ' + options.navigationPosition : options.navigationPosition; 31066 }); 31067 31068 for (var i = 0; i < $(SECTION_SEL).length; i++) { 31069 var link = ''; 31070 if (options.anchors.length) { 31071 link = options.anchors[i]; 31072 } 31073 31074 var li = '<li><a href="#' + link + '"><span></span></a>'; 31075 31076 // Only add tooltip if needed (defined by user) 31077 var tooltip = options.navigationTooltips[i]; 31078 31079 if (typeof tooltip !== 'undefined' && tooltip !== '') { 31080 li += '<div class="' + SECTION_NAV_TOOLTIP + ' ' + options.navigationPosition + '">' + tooltip + '</div>'; 31081 } 31082 31083 li += '</li>'; 31084 31085 nav.find('ul').append(li); 31086 } 31087 31088 //centering it vertically 31089 $(SECTION_NAV_SEL).css('margin-top', '-' + ($(SECTION_NAV_SEL).height()/2) + 'px'); 31090 31091 //activating the current active section 31092 $(SECTION_NAV_SEL).find('li').eq($(SECTION_ACTIVE_SEL).index(SECTION_SEL)).find('a').addClass(ACTIVE); 31093 } 31094 31095 /** 31096 * Creates the slim scroll scrollbar for the sections and slides inside them. 31097 */ 31098 function createScrollBarHandler(){ 31099 $(SECTION_SEL).each(function(){ 31100 var slides = $(this).find(SLIDE_SEL); 31101 31102 if(slides.length){ 31103 slides.each(function(){ 31104 createScrollBar($(this)); 31105 }); 31106 }else{ 31107 createScrollBar($(this)); 31108 } 31109 31110 }); 31111 afterRenderActions(); 31112 } 31113 31114 /*
31115 * Enables the Youtube videos API so we can control their flow if necessary. 31116 */ 31117 function enableYoutubeAPI(){ 31118 container.find('iframe[src*="youtube.com/embed/"]').each(function(){ 31119 addURLParam($(this), 'enablejsapi=1'); 31120 }); 31121 } 31122 31123 /** 31124 * Adds a new parameter and its value to the `src` of a given element 31125 */ 31126 function addURLParam(element, newParam){ 31127 var originalSrc = element.attr('src'); 31128 element.attr('src', originalSrc + getUrlParamSign(originalSrc) + newParam); 31129 } 31130 31131 /* 31132 * Returns the prefix sign to use for a new parameter in an existen URL. 31133 * 31134 * @return {String} ? | & 31135 */ 31136 function getUrlParamSign(url){ 31137 return ( !/\?/.test( url ) ) ? '?' : '&'; 31138 } 31139 31140 /** 31141 * Actions and callbacks to fire afterRender 31142 */ 31143 function afterRenderActions(){ 31144 var section = $(SECTION_ACTIVE_SEL); 31145 31146 section.addClass(COMPLETELY); 31147 31148 if(options.scrollOverflowHandler.afterRender){ 31149 options.scrollOverflowHandler.afterRender(section); 31150 } 31151 lazyLoad(section); 31152 playMedia(section); 31153 options.scrollOverflowHandler.afterLoad(); 31154 31155 if(isDestinyTheStartingSection()){ 31156 $.isFunction( options.afterLoad ) && options.afterLoad.call(section, section.data('anchor'), (section.index(SECTION_SEL) + 1)); 31157 } 31158 31159 // Uncode change 31160 // $.isFunction( options.afterRender ) && options.afterRender.call(container); 31161 $.isFunction( options.afterRender ) && options.afterRender.call(container, getTableHeight()); 31162 } 31163 31164 /** 31165 * Determines if the URL anchor destiny is the starting section (the one using 'active' class before initialization) 31166 */ 31167 function isDestinyTheStartingSection(){ 31168 var anchors = window.location.hash.replace('#', '').split('/'); 31169 var destinationSection = getSectionByAnchor(decodeURIComponent(anchors[0])); 31170 31171 return !destinationSection.length || destinationSection.length && destinationSection.index() === startingSection.index(); 31172 } 31173 31174 31175 var isScrolling = false; 31176 var lastScroll = 0; 31177 31178 //when scrolling... 31179 function scrollHandler(){ 31180 var currentSection; 31181 31182 if(!options.autoScrolling || options.scrollBar){ 31183 var currentScroll = $window.scrollTop(); 31184 var scrollDirection = getScrollDirection(currentScroll); 31185 var visibleSectionIndex = 0; 31186 var screen_mid = currentScroll + ($window.height() / 2.0); 31187 var isAtBottom = $body.height() - $window.height() === currentScroll; 31188 var sections = document.querySelectorAll(SECTION_SEL); 31189 31190 //when using `auto-height` for a small last section it won't be centered in the viewport 31191 if(isAtBottom){ 31192 visibleSectionIndex = sections.length - 1; 31193 } 31194 //is at top? when using `auto-height` for a small first section it won't be centered in the viewport 31195 else if(!currentScroll){ 31196 visibleSectionIndex = 0; 31197 } 31198 31199 //taking the section which is showing more content in the viewport 31200 else{ 31201 for (var i = 0; i < sections.length; ++i) { 31202 var section = sections[i]; 31203 31204 // Pick the the last section which passes the middle line of the screen. 31205 if (section.offsetTop <= screen_mid) 31206 { 31207 visibleSectionIndex = i; 31208 } 31209 } 31210 } 31211 31212 if(isCompletelyInViewPort(scrollDirection)){ 31213 if(!$(SECTION_ACTIVE_SEL).hasClass(COMPLETELY)){ 31214 $(SECTION_ACTIVE_SEL).addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 31215 } 31216 } 31217 31218 //geting the last one, the current one on the screen 31219 currentSection = $(sections).eq(visibleSectionIndex); 31220 31221 //setting the visible section as active when manually scrolling 31222 //executing only once the first time we reach the section 31223 if(!currentSection.hasClass(ACTIVE)){ 31224 isScrolling = true; 31225 var leavingSection = $(SECTION_ACTIVE_SEL); 31226 var leavingSectionIndex = leavingSection.index(SECTION_SEL) + 1; 31227 var yMovement = getYmovement(currentSection); 31228 var anchorLink = currentSection.data('anchor'); 31229 var sectionIndex = currentSection.index(SECTION_SEL) + 1; 31230 var activeSlide = currentSection.find(SLIDE_ACTIVE_SEL); 31231 var slideIndex; 31232 var slideAnchorLink; 31233 31234 if(activeSlide.length){ 31235 slideAnchorLink = activeSlide.data('anchor'); 31236 slideIndex = activeSlide.index(); 31237 } 31238 31239 if(canScroll){ 31240 currentSection.addClass(ACTIVE).siblings().removeClass(ACTIVE); 31241 31242 $.isFunction( options.onLeave ) && options.onLeave.call( leavingSection, leavingSectionIndex, sectionIndex, yMovement); 31243 $.isFunction( options.afterLoad ) && options.afterLoad.call( currentSection, anchorLink, sectionIndex); 31244 31245 stopMedia(leavingSection); 31246 lazyLoad(currentSection); 31247 playMedia(currentSection); 31248 31249 activateMenuAndNav(anchorLink, sectionIndex - 1); 31250 31251 if(options.anchors.length){ 31252 //needed to enter in hashChange event when using the menu with anchor links 31253 lastScrolledDestiny = anchorLink; 31254 } 31255 setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex); 31256 } 31257 31258 //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet 31259 clearTimeout(scrollId); 31260 scrollId = setTimeout(function(){ 31261 isScrolling = false;
31262 }, 100); 31263 } 31264 31265 if(options.fitToSection){ 31266 //for the auto adjust of the viewport to fit a whole section 31267 clearTimeout(scrollId2); 31268 31269 scrollId2 = setTimeout(function(){ 31270 //checking it again in case it changed during the delay 31271 if(options.fitToSection){ 31272 fitToSection(); 31273 } 31274 }, options.fitToSectionDelay); 31275 } 31276 } 31277 } 31278 31279 /** 31280 * Fits the site to the nearest active section 31281 */ 31282 function fitToSection(){ 31283 //checking fitToSection again in case it was set to false before the timeout delay 31284 if(canScroll){ 31285 //allows to scroll to an active section and 31286 //if the section is already active, we prevent firing callbacks 31287 isResizing = true; 31288 31289 scrollPage($(SECTION_ACTIVE_SEL)); 31290 isResizing = false; 31291 } 31292 } 31293 31294 /** 31295 * Determines whether the active section has seen in its whole or not. 31296 */ 31297 function isCompletelyInViewPort(movement){ 31298 var top = $(SECTION_ACTIVE_SEL).position().top; 31299 var bottom = top + $window.height(); 31300 31301 if(movement == 'up'){ 31302 return bottom >= ($window.scrollTop() + $window.height()); 31303 } 31304 return top <= $window.scrollTop(); 31305 } 31306 31307 /** 31308 * Gets the directon of the the scrolling fired by the scroll event. 31309 */ 31310 function getScrollDirection(currentScroll){ 31311 var direction = currentScroll > lastScroll ? 'down' : 'up'; 31312 31313 lastScroll = currentScroll; 31314 31315 //needed for auto-height sections to determine if we want to scroll to the top or bottom of the destination 31316 previousDestTop = currentScroll; 31317 31318 return direction; 31319 } 31320 31321 /** 31322 * Determines the way of scrolling up or down: 31323 * by 'automatically' scrolling a section or by using the default and normal scrolling. 31324 */ 31325 function scrolling(type, scrollable){ 31326 if (!isScrollAllowed.m[type]){ 31327 return; 31328 } 31329 var check = (type === 'down') ? 'bottom' : 'top'; 31330 var scrollSection = (type === 'down') ? moveSectionDown : moveSectionUp; 31331 31332 if(scrollable.length > 0 ){ 31333 //is the scrollbar at the start/end of the scroll? 31334 if(options.scrollOverflowHandler.isScrolled(check, scrollable)){ 31335 scrollSection(); 31336 }else{ 31337 return true; 31338 } 31339 }else{ 31340 // moved up/down 31341 scrollSection(); 31342 } 31343 } 31344 31345 /* 31346 * Preventing bouncing in iOS #2285 31347 */ 31348 function preventBouncing(event){ 31349 var e = event.originalEvent; 31350 if(!checkParentForNormalScrollElement(event.target) && options.autoScrolling && isReallyTouch(e) && isScrollAllowed.m.up){ 31351 //preventing the easing on iOS devices 31352 event.preventDefault(); 31353 } 31354 } 31355 31356 var touchStartY = 0; 31357 var touchStartX = 0; 31358 var touchEndY = 0; 31359 var touchEndX = 0; 31360 31361 /* Detecting touch events 31362 31363 * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it. 31364 * This way, the touchstart and the touch moves shows an small difference between them which is the 31365 * used one to determine the direction. 31366 */ 31367 function touchMoveHandler(event){ 31368 var e = event.originalEvent; 31369 var activeSection = $(e.target).closest(SECTION_SEL); 31370 31371 // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain 31372 if (!checkParentForNormalScrollElement(event.target) && isReallyTouch(e) ) { 31373 31374 if(options.autoScrolling){ 31375 //preventing the easing on iOS devices 31376 event.preventDefault(); 31377 } 31378 31379 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 31380 var touchEvents = getEventsPage(e); 31381 31382 touchEndY = touchEvents.y; 31383 touchEndX = touchEvents.x; 31384 31385 //if movement in the X axys is greater than in the Y and the currect section has slides... 31386 if (activeSection.find(SLIDES_WRAPPER_SEL).length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) { 31387 31388 //is the movement greater than the minimum resistance to scroll? 31389 if (!slideMoving && Math.abs(touchStartX - touchEndX) > ($window.outerWidth() / 100 * options.touchSensitivity)) { 31390 if (touchStartX > touchEndX) { 31391 if(isScrollAllowed.m.right){ 31392 moveSlideRight(activeSection); //next 31393 } 31394 } else { 31395 if(isScrollAllowed.m.left){ 31396 moveSlideLeft(activeSection); //prev 31397 } 31398 } 31399 } 31400 } 31401 31402 //vertical scrolling (only when autoScrolling is enabled) 31403 else if(options.autoScrolling && canScroll){ 31404 31405 //is the movement greater than the minimum resistance to scroll? 31406 if (Math.abs(touchStartY - touchEndY) > ($window.height() / 100 * options.touchSensitivity)) { 31407 if (touchStartY > touchEndY) { 31408 scrolling('down', scrollable); 31409 } else if (touchEndY > touchStartY) { 31410 scrolling('up', scrollable); 31411 } 31412 } 31413 } 31414 } 31415 } 31416 31417 /** 31418 * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements 31419 * Currently works well for iOS - Android might need some testing 31420 * @param {Element} el target element / jquery selector (in subsequent nodes) 31421 * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold 31422 * @return {boolean} true if there is a match to options.normalScrollElements 31423 */ 31424 function checkParentForNormalScrollElement (el, hop) { 31425 hop = hop || 0; 31426 var parent = $(el).parent(); 31427 31428 if (hop < options.normalScrollElementTouchThreshold && 31429 parent.is(options.normalScrollElements) ) { 31430 return true; 31431 } else if (hop == options.normalScrollElementTouchThreshold) { 31432 return false;
31433 } else { 31434 return checkParentForNormalScrollElement(parent, ++hop); 31435 } 31436 } 31437 31438 /** 31439 * As IE >= 10 fires both touch and mouse events when using a mouse in a touchscreen 31440 * this way we make sure that is really a touch event what IE is detecting. 31441 */ 31442 function isReallyTouch(e){ 31443 //if is not IE || IE is detecting `touch` or `pen` 31444 return typeof e.pointerType === 'undefined' || e.pointerType != 'mouse'; 31445 } 31446 31447 /** 31448 * Handler for the touch start event. 31449 */ 31450 function touchStartHandler(event){ 31451 var e = event.originalEvent; 31452 31453 //stopping the auto scroll to adjust to a section 31454 if(options.fitToSection){ 31455 $htmlBody.stop(); 31456 } 31457 31458 if(isReallyTouch(e)){ 31459 var touchEvents = getEventsPage(e); 31460 touchStartY = touchEvents.y; 31461 touchStartX = touchEvents.x; 31462 } 31463 } 31464 31465 /** 31466 * Gets the average of the last `number` elements of the given array. 31467 */ 31468 function getAverage(elements, number){ 31469 var sum = 0; 31470 31471 //taking `number` elements from the end to make the average, if there are not enought, 1 31472 var lastElements = elements.slice(Math.max(elements.length - number, 1)); 31473 31474 for(var i = 0; i < lastElements.length; i++){ 31475 sum = sum + lastElements[i]; 31476 } 31477 31478 return Math.ceil(sum/number); 31479 } 31480 31481 /** 31482 * Detecting mousewheel scrolling 31483 * 31484 * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html 31485 * http://www.sitepoint.com/html5-javascript-mouse-wheel/ 31486 */ 31487 var prevTime = new Date().getTime(); 31488 31489 function MouseWheelHandler(e) { 31490 var curTime = new Date().getTime(); 31491 var isNormalScroll = $(COMPLETELY_SEL).hasClass(NORMAL_SCROLL); 31492 31493 //autoscrolling and not zooming? 31494 if(options.autoScrolling && !controlPressed && !isNormalScroll){ 31495 // cross-browser wheel delta 31496 e = e || window.event; 31497 var value = e.wheelDelta || -e.deltaY || -e.detail; 31498 var delta = Math.max(-1, Math.min(1, value)); 31499 31500 var horizontalDetection = typeof e.wheelDeltaX !== 'undefined' || typeof e.deltaX !== 'undefined'; 31501 var isScrollingVertically = (Math.abs(e.wheelDeltaX) < Math.abs(e.wheelDelta)) || (Math.abs(e.deltaX ) < Math.abs(e.deltaY) || !horizontalDetection); 31502 31503 //Limiting the array to 150 (lets not waste memory!) 31504 if(scrollings.length > 149){ 31505 scrollings.shift(); 31506 } 31507 31508 //keeping record of the previous scrollings 31509 scrollings.push(Math.abs(value)); 31510 31511 //preventing to scroll the site on mouse wheel when scrollbar is present 31512 if(options.scrollBar){ 31513 e.preventDefault ? e.preventDefault() : e.returnValue = false; 31514 } 31515 31516 var activeSection = $(SECTION_ACTIVE_SEL); 31517 var scrollable = options.scrollOverflowHandler.scrollable(activeSection); 31518 31519 //time difference between the last scroll and the current one 31520 var timeDiff = curTime-prevTime; 31521 prevTime = curTime; 31522 31523 //haven't they scrolled in a while? 31524 //(enough to be consider a different scrolling action to scroll another section) 31525 if(timeDiff > 200){ 31526 //emptying the array, we dont care about old scrollings for our averages 31527 scrollings = []; 31528 } 31529 31530 if(canScroll){ 31531 var averageEnd = getAverage(scrollings, 10); 31532 var averageMiddle = getAverage(scrollings, 70); 31533 var isAccelerating = averageEnd >= averageMiddle; 31534 31535 //to avoid double swipes... 31536 if(isAccelerating && isScrollingVertically){ 31537 //scrolling down? 31538 if (delta < 0) { 31539 scrolling('down', scrollable); 31540 31541 //scrolling up? 31542 }else { 31543 scrolling('up', scrollable); 31544 } 31545 } 31546 } 31547 31548 return false;
31549 } 31550 31551 if(options.fitToSection){ 31552 //stopping the auto scroll to adjust to a section 31553 $htmlBody.stop(); 31554 } 31555 } 31556 31557 /** 31558 * Slides a slider to the given direction. 31559 * Optional `section` param. 31560 */ 31561 function moveSlide(direction, section){ 31562 var activeSection = typeof section === 'undefined' ? $(SECTION_ACTIVE_SEL) : section; 31563 var slides = activeSection.find(SLIDES_WRAPPER_SEL); 31564 var numSlides = slides.find(SLIDE_SEL).length; 31565 31566 // more than one slide needed and nothing should be sliding 31567 if (!slides.length || slideMoving || numSlides < 2) { 31568 return; 31569 } 31570 31571 var currentSlide = slides.find(SLIDE_ACTIVE_SEL); 31572 var destiny = null; 31573 31574 if(direction === 'left'){ 31575 destiny = currentSlide.prev(SLIDE_SEL); 31576 }else{ 31577 destiny = currentSlide.next(SLIDE_SEL); 31578 } 31579 31580 //isn't there a next slide in the secuence? 31581 if(!destiny.length){ 31582 //respect loopHorizontal settin 31583 if (!options.loopHorizontal) return; 31584 31585 if(direction === 'left'){ 31586 destiny = currentSlide.siblings(':last'); 31587 }else{ 31588 destiny = currentSlide.siblings(':first'); 31589 } 31590 } 31591 31592 slideMoving = true; 31593 31594 landscapeScroll(slides, destiny, direction); 31595 } 31596 31597 /** 31598 * Maintains the active slides in the viewport 31599 * (Because the `scroll` animation might get lost with some actions, such as when using continuousVertical) 31600 */ 31601 function keepSlidesPosition(){ 31602 $(SLIDE_ACTIVE_SEL).each(function(){ 31603 silentLandscapeScroll($(this), 'internal'); 31604 }); 31605 } 31606 31607 var previousDestTop = 0; 31608 /** 31609 * Returns the destination Y position based on the scrolling direction and 31610 * the height of the section. 31611 */ 31612 function getDestinationPosition(element){ 31613 var elemPosition = element.position(); 31614 31615 //top of the desination will be at the top of the viewport 31616 var position = elemPosition.top; 31617 var isScrollingDown = elemPosition.top > previousDestTop; 31618 var sectionBottom = position - windowsHeight + element.outerHeight(); 31619 var bigSectionsDestination = options.bigSectionsDestination; 31620 31621 //Uncode addition 31622 var containerH = container.outerHeight(); 31623 var containerPosition = container.offset(); 31624 31625 //########### Commented by Uncode - START ########### 31626 //is the destination element bigger than the viewport? 31627 // if(element.outerHeight() > windowsHeight){ 31628 // //scrolling up? 31629 // if(!isScrollingDown && !bigSectionsDestination || bigSectionsDestination === 'bottom' ){ 31630 // position = sectionBottom; 31631 // } 31632 // } 31633 31634 // //sections equal or smaller than the viewport height && scrolling down? || is resizing and its in the last section 31635 // else if(isScrollingDown || (isResizing && element.is(':last-child')) ){ 31636 // //The bottom of the destination will be at the bottom of the viewport 31637 // position = sectionBottom; 31638 // } 31639 //########### Commented by Uncode - END ########### 31640 31641 //Uncode addition 31642 if ( !$masthead.hasClass('menu-transparent') && $('body').hasClass('uncode-fp-menu-shrink') && !element.is(':first-child') ) 31643 position += 18; 31644 if ( ( containerH + menuHeight + bodyBorder + adminBarHeight - windowsHeight ) < position || ( isResizing && element.is(':last-child') ) ) { 31645 position = sectionBottom + menuHeight + bodyBorder*2 + adminBarHeight; 31646 } 31647 31648 /* 31649 Keeping record of the last scrolled position to determine the scrolling direction. 31650 No conventional methods can be used as the scroll bar might not be present 31651 AND the section might not be active if it is auto-height and didnt reach the middle 31652 of the viewport. 31653 */ 31654 previousDestTop = position; 31655 return position; 31656 } 31657 31658 /** 31659 * Scrolls the site to the given element and scrolls to the slide if a callback is given. 31660 */ 31661 function scrollPage(element, callback, isMovementUp){ 31662 if(typeof element === 'undefined'){ return; } //there's no element to scroll, leaving the function 31663 31664 var dtop = getDestinationPosition(element); 31665 var slideAnchorLink; 31666 var slideIndex; 31667 31668 //local variables 31669 var v = { 31670 element: element, 31671 callback: callback, 31672 isMovementUp: isMovementUp, 31673 dtop: dtop, 31674 yMovement: getYmovement(element), 31675 anchorLink: element.data('anchor'), 31676 sectionIndex: element.index(SECTION_SEL), 31677 activeSlide: element.find(SLIDE_ACTIVE_SEL), 31678 activeSection: $(SECTION_ACTIVE_SEL), 31679 leavingSection: $(SECTION_ACTIVE_SEL).index(SECTION_SEL) + 1, 31680 31681 //caching the value of isResizing at the momment the function is called 31682 //because it will be checked later inside a setTimeout and the value might change 31683 localIsResizing: isResizing 31684 }; 31685 31686 //quiting when destination scroll is the same as the current one 31687 if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $window.scrollTop() === v.dtop && !element.hasClass(AUTO_HEIGHT) )){ return; } 31688 31689 if(v.activeSlide.length){ 31690 slideAnchorLink = v.activeSlide.data('anchor'); 31691 slideIndex = v.activeSlide.index(); 31692 } 31693 31694 // If continuousVertical && we need to wrap around 31695 if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" && 31696 ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or 31697 (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down 31698 31699 v = createInfiniteSections(v); 31700 } 31701 31702 //callback (onLeave) if the site is not just resizing and readjusting the slides 31703 if($.isFunction(options.onLeave) && !v.localIsResizing){ 31704 if(options.onLeave.call(v.activeSection, v.leavingSection, (v.sectionIndex + 1), v.yMovement) === false){ 31705 return; 31706 } 31707 } 31708 31709 //pausing media of the leaving section (if we are not just resizing, as destinatino will be the same one) 31710 if(!v.localIsResizing){ 31711 stopMedia(v.activeSection); 31712 } 31713 31714 options.scrollOverflowHandler.beforeLeave(); 31715 element.addClass(ACTIVE).siblings().removeClass(ACTIVE); 31716 lazyLoad(element); 31717 options.scrollOverflowHandler.onLeave(); 31718 31719 31720 //preventing from activating the MouseWheelHandler event 31721 //more than once if the page is scrolling 31722 canScroll = false;
31723 31724 setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex); 31725 31726 performMovement(v); 31727 31728 //flag to avoid callingn `scrollPage()` twice in case of using anchor links 31729 lastScrolledDestiny = v.anchorLink; 31730 31731 //avoid firing it twice (as it does also on scroll) 31732 activateMenuAndNav(v.anchorLink, v.sectionIndex); 31733 } 31734 31735 /** 31736 * Performs the vertical movement (by CSS3 or by jQuery) 31737 */ 31738 function performMovement(v){ 31739 // using CSS3 translate functionality 31740 if (options.css3 && options.autoScrolling && !options.scrollBar) { 31741 31742 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 31743 // that's why we round it to 0. 31744 var translate3d = 'translate3d(0px, -' + Math.round(v.dtop) + 'px, 0px)'; 31745 transformContainer(translate3d, true); 31746 31747 //even when the scrollingSpeed is 0 there's a little delay, which might cause the 31748 //scrollingSpeed to change in case of using silentMoveTo(); 31749 if(options.scrollingSpeed){ 31750 clearTimeout(afterSectionLoadsId); 31751 afterSectionLoadsId = setTimeout(function () { 31752 afterSectionLoads(v); 31753 }, options.scrollingSpeed); 31754 }else{ 31755 afterSectionLoads(v); 31756 } 31757 } 31758 31759 // using jQuery animate 31760 else{ 31761 var scrollSettings = getScrollSettings(v); 31762 31763 $(scrollSettings.element).animate( 31764 scrollSettings.options, 31765 options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body` 31766 if(options.scrollBar){ 31767 31768 /* Hack! 31769 The timeout prevents setting the most dominant section in the viewport as "active" when the user 31770 scrolled to a smaller section by using the mousewheel (auto scrolling) rather than draging the scroll bar. 31771 31772 When using scrollBar:true It seems like the scroll events still getting propagated even after the scrolling animation has finished. 31773 */ 31774 setTimeout(function(){ 31775 afterSectionLoads(v); 31776 },30); 31777 }else{ 31778 afterSectionLoads(v); 31779 } 31780 }); 31781 } 31782 } 31783 31784 /** 31785 * Gets the scrolling settings depending on the plugin autoScrolling option 31786 */ 31787 function getScrollSettings(v){ 31788 var scroll = {}; 31789 31790 if(options.autoScrolling && !options.scrollBar){ 31791 scroll.options = { 'top': -v.dtop}; 31792 scroll.element = WRAPPER_SEL; 31793 }else{ 31794 scroll.options = { 'scrollTop': v.dtop}; 31795 scroll.element = 'html, body'; 31796 } 31797 31798 return scroll; 31799 } 31800 31801 /** 31802 * Adds sections before or after the current one to create the infinite effect. 31803 */ 31804 function createInfiniteSections(v){ 31805 // Scrolling down 31806 if (!v.isMovementUp) { 31807 // Move all previous sections to after the active section 31808 $(SECTION_ACTIVE_SEL).after(v.activeSection.prevAll(SECTION_SEL).get().reverse()); 31809 } 31810 else { // Scrolling up 31811 // Move all next sections to before the active section 31812 $(SECTION_ACTIVE_SEL).before(v.activeSection.nextAll(SECTION_SEL)); 31813 } 31814 31815 // Maintain the displayed position (now that we changed the element order) 31816 silentScroll($(SECTION_ACTIVE_SEL).position().top); 31817 31818 // Maintain the active slides visible in the viewport 31819 keepSlidesPosition(); 31820 31821 // save for later the elements that still need to be reordered 31822 v.wrapAroundElements = v.activeSection; 31823 31824 // Recalculate animation variables 31825 v.dtop = v.element.position().top; 31826 v.yMovement = getYmovement(v.element); 31827 31828 return v; 31829 } 31830 31831 /** 31832 * Fix section order after continuousVertical changes have been animated 31833 */ 31834 function continuousVerticalFixSectionOrder (v) {
31835 // If continuousVertical is in effect (and autoScrolling would also be in effect then), 31836 // finish moving the elements around so the direct navigation will function more simply 31837 if (!v.wrapAroundElements || !v.wrapAroundElements.length) { 31838 return; 31839 } 31840 31841 if (v.isMovementUp) { 31842 $(SECTION_FIRST_SEL).before(v.wrapAroundElements); 31843 } 31844 else { 31845 $(SECTION_LAST_SEL).after(v.wrapAroundElements); 31846 } 31847 31848 silentScroll($(SECTION_ACTIVE_SEL).position().top); 31849 31850 // Maintain the active slides visible in the viewport 31851 keepSlidesPosition(); 31852 } 31853 31854 31855 /** 31856 * Actions to do once the section is loaded. 31857 */ 31858 function afterSectionLoads (v){ 31859 continuousVerticalFixSectionOrder(v); 31860 31861 //callback (afterLoad) if the site is not just resizing and readjusting the slides 31862 $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(v.element, v.anchorLink, (v.sectionIndex + 1)); 31863 options.scrollOverflowHandler.afterLoad(); 31864 31865 if(!v.localIsResizing){ 31866 playMedia(v.element); 31867 } 31868 31869 v.element.addClass(COMPLETELY).siblings().removeClass(COMPLETELY); 31870 31871 canScroll = true; 31872 31873 $.isFunction(v.callback) && v.callback.call(this); 31874 } 31875 31876 /** 31877 * Sets the value for the given attribute from the `data-` attribute with the same suffix 31878 * ie: data-srcset ==> srcset | data-src ==> src 31879 */ 31880 function setSrc(element, attribute){ 31881 element 31882 .attr(attribute, element.data(attribute)) 31883 .removeAttr('data-' + attribute); 31884 } 31885 31886 /** 31887 * Lazy loads image, video and audio elements. 31888 */ 31889 function lazyLoad(destiny){ 31890 if (!options.lazyLoading){ 31891 return; 31892 } 31893 31894 var panel = getSlideOrSection(destiny); 31895 var element; 31896 31897 panel.find('img[data-src], img[data-srcset], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 31898 element = $(this); 31899 31900 $.each(['src', 'srcset'], function(index, type){ 31901 var attribute = element.attr('data-' + type); 31902 if(typeof attribute !== 'undefined' && attribute){ 31903 setSrc(element, type); 31904 } 31905 }); 31906 31907 if(element.is('source')){ 31908 element.closest('video').get(0).load(); 31909 } 31910 }); 31911 } 31912 31913 /** 31914 * Plays video and audio elements. 31915 */ 31916 function playMedia(destiny){ 31917 var panel = getSlideOrSection(destiny); 31918 31919 //playing HTML5 media elements 31920 panel.find('video, audio').each(function(){ 31921 var element = $(this).get(0); 31922 31923 if( element.hasAttribute('data-autoplay') && typeof element.play === 'function' ) { 31924 element.play(); 31925 } 31926 }); 31927 31928 //youtube videos 31929 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 31930 var element = $(this).get(0); 31931 31932 if ( element.hasAttribute('data-autoplay') ){ 31933 playYoutube(element); 31934 } 31935 31936 //in case the URL was not loaded yet. On page load we need time for the new URL (with the API string) to load. 31937 element.onload = function() { 31938 if ( element.hasAttribute('data-autoplay') ){ 31939 playYoutube(element); 31940 } 31941 }; 31942 }); 31943 } 31944 31945 /** 31946 * Plays a youtube video 31947 */ 31948 function playYoutube(element){ 31949 element.contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*'); 31950 } 31951 31952 /** 31953 * Stops video and audio elements. 31954 */ 31955 function stopMedia(destiny){ 31956 var panel = getSlideOrSection(destiny); 31957 31958 //stopping HTML5 media elements 31959 panel.find('video, audio').each(function(){ 31960 var element = $(this).get(0); 31961 31962 if( !element.hasAttribute('data-keepplaying') && typeof element.pause === 'function' ) { 31963 element.pause(); 31964 } 31965 }); 31966 31967 //youtube videos 31968 panel.find('iframe[src*="youtube.com/embed/"]').each(function(){ 31969 var element = $(this).get(0); 31970 31971 if( /youtube\.com\/embed\//.test($(this).attr('src')) && !element.hasAttribute('data-keepplaying')){ 31972 $(this).get(0).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}','*'); 31973 } 31974 }); 31975 } 31976 31977 /** 31978 * Gets the active slide (or section) for the given section 31979 */ 31980 function getSlideOrSection(destiny){ 31981 var slide = destiny.find(SLIDE_ACTIVE_SEL); 31982 if( slide.length ) { 31983 destiny = $(slide); 31984 } 31985 31986 return destiny; 31987 } 31988 31989 /**
31990 * Scrolls to the anchor in the URL when loading the site 31991 */ 31992 function scrollToAnchor(){ 31993 //getting the anchor link in the URL and deleting the `#` 31994 var value = window.location.hash.replace('#', '').split('/'); 31995 var sectionAnchor = decodeURIComponent(value[0]); 31996 var slideAnchor = decodeURIComponent(value[1]); 31997 31998 if(sectionAnchor){ //if theres any # 31999 if(options.animateAnchor){ 32000 scrollPageAndSlide(sectionAnchor, slideAnchor); 32001 }else{ 32002 silentMoveTo(sectionAnchor, slideAnchor); 32003 } 32004 } 32005 } 32006 32007 /** 32008 * Detecting any change on the URL to scroll to the given anchor link 32009 * (a way to detect back history button as we play with the hashes on the URL) 32010 */ 32011 function hashChangeHandler(){ 32012 if(!isScrolling && !options.lockAnchors){ 32013 var value = window.location.hash.replace('#', '').split('/'); 32014 var sectionAnchor = decodeURIComponent(value[0]); 32015 var slideAnchor = decodeURIComponent(value[1]); 32016 32017 //when moving to a slide in the first section for the first time (first time to add an anchor to the URL) 32018 var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined'); 32019 var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slideAnchor === 'undefined' && !slideMoving); 32020 32021 32022 if(sectionAnchor.length){ 32023 /*in order to call scrollpage() only once for each destination at a time 32024 It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange` 32025 event is fired on every scroll too.*/ 32026 if ((sectionAnchor && sectionAnchor !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slideAnchor )) { 32027 scrollPageAndSlide(sectionAnchor, slideAnchor); 32028 } 32029 } 32030 } 32031 } 32032 32033 //Sliding with arrow keys, both, vertical and horizontal 32034 function keydownHandler(e) { 32035 32036 clearTimeout(keydownId); 32037 32038 var activeElement = $(':focus'); 32039 32040 if(!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select') && 32041 activeElement.attr('contentEditable') !== "true" && activeElement.attr('contentEditable') !== '' && 32042 options.keyboardScrolling && options.autoScrolling){ 32043 var keyCode = e.which; 32044 32045 //preventing the scroll with arrow keys & spacebar & Page Up & Down keys 32046 var keyControls = [40, 38, 32, 33, 34]; 32047 if($.inArray(keyCode, keyControls) > -1){ 32048 e.preventDefault(); 32049 } 32050 32051 controlPressed = e.ctrlKey; 32052 32053 keydownId = setTimeout(function(){ 32054 onkeydown(e); 32055 },150); 32056 } 32057 } 32058 32059 function tooltipTextHandler(){ 32060 $(this).prev().trigger('click'); 32061 } 32062 32063 //to prevent scrolling while zooming 32064 function keyUpHandler(e){ 32065 if(isWindowFocused){ //the keyup gets fired on new tab ctrl + t in Firefox 32066 controlPressed = e.ctrlKey; 32067 } 32068 } 32069 32070 //binding the mousemove when the mouse's middle button is released 32071 function mouseDownHandler(e){ 32072 //middle button 32073 if (e.which == 2){ 32074 oldPageY = e.pageY; 32075 container.on('mousemove', mouseMoveHandler); 32076 } 32077 } 32078 32079 //unbinding the mousemove when the mouse's middle button is released 32080 function mouseUpHandler(e){ 32081 //middle button 32082 if (e.which == 2){ 32083 container.off('mousemove'); 32084 } 32085 } 32086 32087 //Scrolling horizontally when clicking on the slider controls. 32088 function slideArrowHandler(){ 32089 var section = $(this).closest(SECTION_SEL); 32090 32091 if ($(this).hasClass(SLIDES_PREV)) { 32092 if(isScrollAllowed.m.left){ 32093 moveSlideLeft(section); 32094 } 32095 } else { 32096 if(isScrollAllowed.m.right){ 32097 moveSlideRight(section); 32098 } 32099 } 32100 } 32101 32102 //when opening a new tab (ctrl + t), `control` won't be pressed when coming back. 32103 function blurHandler(){ 32104 isWindowFocused = false;
32105 controlPressed = false; 32106 } 32107 32108 //Scrolls to the section when clicking the navigation bullet 32109 function sectionBulletHandler(e){ 32110 e.preventDefault(); 32111 var index = $(this).parent().index(); 32112 scrollPage($(SECTION_SEL).eq(index)); 32113 } 32114 32115 //Scrolls the slider to the given slide destination for the given section 32116 function slideBulletHandler(e){ 32117 e.preventDefault(); 32118 var slides = $(this).closest(SECTION_SEL).find(SLIDES_WRAPPER_SEL); 32119 var destiny = slides.find(SLIDE_SEL).eq($(this).closest('li').index()); 32120 32121 landscapeScroll(slides, destiny); 32122 } 32123 32124 /** 32125 * Keydown event 32126 */ 32127 function onkeydown(e){ 32128 var shiftPressed = e.shiftKey; 32129 32130 //do nothing if we can not scroll or we are not using horizotnal key arrows. 32131 if(!canScroll && [37,39].indexOf(e.which) < 0){ 32132 return; 32133 } 32134 32135 switch (e.which) { 32136 //up 32137 case 38: 32138 case 33: 32139 if(isScrollAllowed.k.up){ 32140 moveSectionUp(); 32141 } 32142 break; 32143 32144 //down 32145 case 32: //spacebar 32146 if(shiftPressed && isScrollAllowed.k.up){ 32147 moveSectionUp(); 32148 break; 32149 } 32150 /* falls through */ 32151 case 40: 32152 case 34: 32153 if(isScrollAllowed.k.down){ 32154 moveSectionDown(); 32155 } 32156 break; 32157 32158 //Home 32159 case 36: 32160 if(isScrollAllowed.k.up){ 32161 moveTo(1); 32162 } 32163 break; 32164 32165 //End 32166 case 35: 32167 if(isScrollAllowed.k.down){ 32168 moveTo( $(SECTION_SEL).length ); 32169 } 32170 break; 32171 32172 //left 32173 case 37: 32174 if(isScrollAllowed.k.left){ 32175 moveSlideLeft(); 32176 } 32177 break; 32178 32179 //right 32180 case 39: 32181 if(isScrollAllowed.k.right){ 32182 moveSlideRight(); 32183 } 32184 break; 32185 32186 default: 32187 return; // exit this handler for other keys 32188 } 32189 } 32190 32191 /** 32192 * Detecting the direction of the mouse movement. 32193 * Used only for the middle button of the mouse. 32194 */ 32195 var oldPageY = 0; 32196 function mouseMoveHandler(e){ 32197 if(canScroll){ 32198 // moving up 32199 if (e.pageY < oldPageY && isScrollAllowed.m.up){ 32200 moveSectionUp(); 32201 } 32202 32203 // moving down 32204 else if(e.pageY > oldPageY && isScrollAllowed.m.down){ 32205 moveSectionDown(); 32206 } 32207 } 32208 oldPageY = e.pageY; 32209 } 32210 32211 /** 32212 * Scrolls horizontal sliders. 32213 */ 32214 function landscapeScroll(slides, destiny, direction){ 32215 var section = slides.closest(SECTION_SEL); 32216 var v = { 32217 slides: slides, 32218 destiny: destiny, 32219 direction: direction, 32220 destinyPos: destiny.position(), 32221 slideIndex: destiny.index(), 32222 section: section, 32223 sectionIndex: section.index(SECTION_SEL), 32224 anchorLink: section.data('anchor'), 32225 slidesNav: section.find(SLIDES_NAV_SEL), 32226 slideAnchor: getAnchor(destiny), 32227 prevSlide: section.find(SLIDE_ACTIVE_SEL), 32228 prevSlideIndex: section.find(SLIDE_ACTIVE_SEL).index(), 32229 32230 //caching the value of isResizing at the momment the function is called 32231 //because it will be checked later inside a setTimeout and the value might change 32232 localIsResizing: isResizing 32233 }; 32234 v.xMovement = getXmovement(v.prevSlideIndex, v.slideIndex); 32235 v.direction = v.direction ? v.direction : v.xMovement; 32236 32237 //important!! Only do it when not resizing 32238 if(!v.localIsResizing){ 32239 //preventing from scrolling to the next/prev section when using scrollHorizontally 32240 canScroll = false;
32241 } 32242 32243 if(options.onSlideLeave){ 32244 32245 //if the site is not just resizing and readjusting the slides 32246 if(!v.localIsResizing && v.xMovement!=='none'){ 32247 if($.isFunction( options.onSlideLeave )){ 32248 if(options.onSlideLeave.call( v.prevSlide, v.anchorLink, (v.sectionIndex + 1), v.prevSlideIndex, v.xMovement, v.slideIndex ) === false){ 32249 slideMoving = false; 32250 return; 32251 } 32252 } 32253 } 32254 } 32255 32256 destiny.addClass(ACTIVE).siblings().removeClass(ACTIVE); 32257 32258 if(!v.localIsResizing){ 32259 stopMedia(v.prevSlide); 32260 lazyLoad(destiny); 32261 } 32262 32263 if(!options.loopHorizontal && options.controlArrows){ 32264 //hidding it for the fist slide, showing for the rest 32265 section.find(SLIDES_ARROW_PREV_SEL).toggle(v.slideIndex!==0); 32266 32267 //hidding it for the last slide, showing for the rest 32268 section.find(SLIDES_ARROW_NEXT_SEL).toggle(!destiny.is(':last-child')); 32269 } 32270 32271 //only changing the URL if the slides are in the current section (not for resize re-adjusting) 32272 if(section.hasClass(ACTIVE) && !v.localIsResizing){ 32273 setState(v.slideIndex, v.slideAnchor, v.anchorLink, v.sectionIndex); 32274 } 32275 32276 performHorizontalMove(slides, v, true); 32277 } 32278 32279 32280 function afterSlideLoads(v){ 32281 activeSlidesNavigation(v.slidesNav, v.slideIndex); 32282 32283 //if the site is not just resizing and readjusting the slides 32284 if(!v.localIsResizing){ 32285 $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( v.destiny, v.anchorLink, (v.sectionIndex + 1), v.slideAnchor, v.slideIndex); 32286 32287 //needs to be inside the condition to prevent problems with continuousVertical and scrollHorizontally 32288 //and to prevent double scroll right after a windows resize 32289 canScroll = true; 32290 32291 playMedia(v.destiny); 32292 } 32293 32294 //letting them slide again 32295 slideMoving = false; 32296 } 32297 32298 /** 32299 * Performs the horizontal movement. (CSS3 or jQuery) 32300 * 32301 * @param fireCallback {Bool} - determines whether or not to fire the callback 32302 */ 32303 function performHorizontalMove(slides, v, fireCallback){ 32304 var destinyPos = v.destinyPos; 32305 32306 if(options.css3){ 32307 var translate3d = 'translate3d(-' + Math.round(destinyPos.left) + 'px, 0px, 0px)'; 32308 32309 addAnimation(slides.find(SLIDES_CONTAINER_SEL)).css(getTransforms(translate3d), v); 32310 32311 afterSlideLoadsId = setTimeout(function(){ 32312 fireCallback && afterSlideLoads(v); 32313 }, options.scrollingSpeed, options.easing); 32314 }else{ 32315 slides.animate({ 32316 scrollLeft : Math.round(destinyPos.left) 32317 }, options.scrollingSpeed, options.easing, function() { 32318 32319 fireCallback && afterSlideLoads(v); 32320 }); 32321 } 32322 } 32323 32324 /** 32325 * Sets the state for the horizontal bullet navigations. 32326 */ 32327 function activeSlidesNavigation(slidesNav, slideIndex){ 32328 slidesNav.find(ACTIVE_SEL).removeClass(ACTIVE); 32329 slidesNav.find('li').eq(slideIndex).find('a').addClass(ACTIVE); 32330 } 32331 32332 var previousHeight = windowsHeight; 32333 32334 //when resizing the site, we adjust the heights of the sections, slimScroll... 32335 function resizeHandler(){ 32336 //checking if it needs to get responsive 32337 responsive(); 32338 32339 // rebuild immediately on touch devices 32340 if (isTouchDevice) { 32341 var activeElement = $(document.activeElement); 32342 32343 //if the keyboard is NOT visible 32344 if (!activeElement.is('textarea') && !activeElement.is('input') && !activeElement.is('select')) { 32345 var currentHeight = $window.height(); 32346 32347 //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) 32348 if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){ 32349 reBuild(true); 32350 previousHeight = currentHeight; 32351 } 32352 } 32353 }else{ 32354 //in order to call the functions only when the resize is finished 32355 //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing 32356 clearTimeout(resizeId); 32357 32358 resizeId = setTimeout(function(){ 32359 reBuild(true); 32360 }, 350); 32361 } 32362 } 32363 32364 /** 32365 * Checks if the site needs to get responsive and disables autoScrolling if so. 32366 * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS. 32367 */ 32368 function responsive(){ 32369 var widthLimit = options.responsive || options.responsiveWidth; //backwards compatiblity 32370 var heightLimit = options.responsiveHeight; 32371 32372 //only calculating what we need. Remember its called on the resize event. 32373 var isBreakingPointWidth = widthLimit && $window.outerWidth() < widthLimit; 32374 var isBreakingPointHeight = heightLimit && $window.height() < heightLimit; 32375 32376 if(widthLimit && heightLimit){ 32377 setResponsive(isBreakingPointWidth || isBreakingPointHeight); 32378 } 32379 else if(widthLimit){ 32380 setResponsive(isBreakingPointWidth); 32381 } 32382 else if(heightLimit){ 32383 setResponsive(isBreakingPointHeight); 32384 } 32385 } 32386 32387 /** 32388 * Adds transition animations for the given element 32389 */ 32390 function addAnimation(container, element){ 32391 var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3; 32392 32393 container.removeClass(NO_TRANSITION); 32394 return container.css({
32395 '-webkit-transition': transition, 32396 'transition': transition 32397 }); 32398 } 32399 32400 /** 32401 * Remove transition animations for the given element 32402 */ 32403 function removeAnimation(element){ 32404 return element.addClass(NO_TRANSITION); 32405 } 32406 32407 /** 32408 * Activating the vertical navigation bullets according to the given slide name. 32409 */ 32410 function activateNavDots(name, sectionIndex){ 32411 if(options.navigation){ 32412 $(SECTION_NAV_SEL).find(ACTIVE_SEL).removeClass(ACTIVE); 32413 if(name){ 32414 $(SECTION_NAV_SEL).find('a[href="#' + name + '"]').addClass(ACTIVE); 32415 }else{ 32416 $(SECTION_NAV_SEL).find('li').eq(sectionIndex).find('a').addClass(ACTIVE); 32417 } 32418 } 32419 } 32420 32421 /** 32422 * Activating the website main menu elements according to the given slide name. 32423 */ 32424 function activateMenuElement(name){ 32425 if(options.menu){ 32426 $(options.menu).find(ACTIVE_SEL).removeClass(ACTIVE); 32427 $(options.menu).find('[data-menuanchor="'+name+'"]').addClass(ACTIVE); 32428 } 32429 } 32430 32431 /** 32432 * Sets to active the current menu and vertical nav items. 32433 */ 32434 function activateMenuAndNav(anchor, index){ 32435 activateMenuElement(anchor); 32436 activateNavDots(anchor, index); 32437 } 32438 32439 /** 32440 * Retuns `up` or `down` depending on the scrolling movement to reach its destination 32441 * from the current section. 32442 */ 32443 function getYmovement(destiny){ 32444 var fromIndex = $(SECTION_ACTIVE_SEL).index(SECTION_SEL); 32445 var toIndex = destiny.index(SECTION_SEL); 32446 if( fromIndex == toIndex){ 32447 return 'none'; 32448 } 32449 if(fromIndex > toIndex){ 32450 return 'up'; 32451 } 32452 return 'down'; 32453 } 32454 32455 /** 32456 * Retuns `right` or `left` depending on the scrolling movement to reach its destination 32457 * from the current slide. 32458 */ 32459 function getXmovement(fromIndex, toIndex){ 32460 if( fromIndex == toIndex){ 32461 return 'none'; 32462 } 32463 if(fromIndex > toIndex){ 32464 return 'left'; 32465 } 32466 return 'right'; 32467 } 32468 32469 /** 32470 * Checks if the element needs scrollbar and if the user wants to apply it. 32471 * If so it creates it. 32472 * 32473 * @param {Object} element jQuery object of the section or slide 32474 */ 32475 function createScrollBar(element){ 32476 //User doesn't want scrollbar here? Sayonara baby! 32477 if(element.hasClass('fp-noscroll')) return; 32478 32479 //needed to make `scrollHeight` work under Opera 12 32480 element.css('overflow', 'hidden'); 32481 32482 var scrollOverflowHandler = options.scrollOverflowHandler; 32483 var wrap = scrollOverflowHandler.wrapContent(); 32484 //in case element is a slide 32485 var section = element.closest(SECTION_SEL); 32486 var scrollable = scrollOverflowHandler.scrollable(element); 32487 var contentHeight; 32488 32489 //if there was scroll, the contentHeight will be the one in the scrollable section 32490 if(scrollable.length){ 32491 contentHeight = scrollOverflowHandler.scrollHeight(element); 32492 }else{ 32493 contentHeight = element.get(0).scrollHeight; 32494 if(options.verticalCentered){ 32495 contentHeight = element.find(TABLE_CELL_SEL).get(0).scrollHeight; 32496 } 32497 } 32498 32499 var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top')); 32500 32501 //needs scroll? 32502 if ( contentHeight > scrollHeight) { 32503 //did we already have an scrollbar ? Updating it 32504 if(scrollable.length){ 32505 scrollOverflowHandler.update(element, scrollHeight); 32506 } 32507 //creating the scrolling 32508 else{ 32509 if(options.verticalCentered){ 32510 element.find(TABLE_CELL_SEL).wrapInner(wrap); 32511 }else{ 32512 element.wrapInner(wrap); 32513 } 32514 scrollOverflowHandler.create(element, scrollHeight); 32515 } 32516 } 32517 //removing the scrolling when it is not necessary anymore 32518 else{ 32519 scrollOverflowHandler.remove(element); 32520 } 32521 32522 //undo 32523 element.css('overflow', ''); 32524 } 32525 32526 function addTableClass(element){ 32527 //In case we are styling for the 2nd time as in with reponsiveSlides 32528 if(!element.hasClass(TABLE)){ 32529 element.addClass(TABLE).wrapInner('<div class="' + TABLE_CELL + '" style="height:' + getTableHeight(element) + 'px;" />'); 32530 } 32531 } 32532 32533 function getTableHeight(element){ 32534 var sectionHeight = windowsHeight; 32535 32536 if(options.paddingTop || options.paddingBottom){ 32537 var section = element; 32538 if(!section.hasClass(SECTION)){ 32539 section = element.closest(SECTION_SEL); 32540 } 32541 32542 var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom')); 32543 sectionHeight = (windowsHeight - paddings); 32544 } 32545 32546 return sectionHeight; 32547 } 32548 32549 /** 32550 * Adds a css3 transform property to the container class with or without animation depending on the animated param. 32551 */ 32552 function transformContainer(translate3d, animated){ 32553 if(animated){ 32554 addAnimation(container); 32555 }else{ 32556 removeAnimation(container); 32557 } 32558 32559 container.css(getTransforms(translate3d)); 32560 32561 //syncronously removing the class after the animation has been applied. 32562 setTimeout(function(){ 32563 container.removeClass(NO_TRANSITION); 32564 },10); 32565 } 32566 32567 /** 32568 * Gets a section by its anchor / index 32569 */ 32570 function getSectionByAnchor(sectionAnchor){ 32571 if(!sectionAnchor) return []; 32572 32573 var section = container.find(SECTION_SEL + '[data-anchor="'+sectionAnchor+'"]'); 32574 if(!section.length){ 32575 section = $(SECTION_SEL).eq( sectionAnchor -1); 32576 } 32577 32578 return section; 32579 } 32580 32581 /** 32582 * Gets a slide inside a given section by its anchor / index 32583 */ 32584 function getSlideByAnchor(slideAnchor, section){ 32585 var slides = section.find(SLIDES_WRAPPER_SEL); 32586 var slide = slides.find(SLIDE_SEL + '[data-anchor="'+slideAnchor+'"]'); 32587
32588 if(!slide.length){ 32589 slide = slides.find(SLIDE_SEL).eq(slideAnchor); 32590 } 32591 32592 return slide; 32593 } 32594 32595 /** 32596 * Scrolls to the given section and slide anchors 32597 */ 32598 function scrollPageAndSlide(destiny, slide){ 32599 var section = getSectionByAnchor(destiny); 32600 32601 //do nothing if there's no section with the given anchor name 32602 if(!section.length) return; 32603 32604 //default slide 32605 if (typeof slide === 'undefined') { 32606 slide = 0; 32607 } 32608 32609 //we need to scroll to the section and then to the slide 32610 if (destiny !== lastScrolledDestiny && !section.hasClass(ACTIVE)){ 32611 scrollPage(section, function(){ 32612 scrollSlider(section, slide); 32613 }); 32614 } 32615 //if we were already in the section 32616 else{ 32617 scrollSlider(section, slide); 32618 } 32619 } 32620 32621 /** 32622 * Scrolls the slider to the given slide destination for the given section 32623 */ 32624 function scrollSlider(section, slideAnchor){ 32625 if(typeof slideAnchor !== 'undefined'){ 32626 var slides = section.find(SLIDES_WRAPPER_SEL); 32627 var destiny = getSlideByAnchor(slideAnchor, section); 32628 32629 if(destiny.length){ 32630 landscapeScroll(slides, destiny); 32631 } 32632 } 32633 } 32634 32635 /** 32636 * Creates a landscape navigation bar with dots for horizontal sliders. 32637 */ 32638 function addSlidesNavigation(section, numSlides){ 32639 section.append('<div class="' + SLIDES_NAV + '"><ul></ul></div>'); 32640 var nav = section.find(SLIDES_NAV_SEL); 32641 32642 //top or bottom 32643 nav.addClass(options.slidesNavPosition); 32644 32645 for(var i=0; i< numSlides; i++){ 32646 nav.find('ul').append('<li><a href="#"><span></span></a></li>'); 32647 } 32648 32649 //centering it 32650 nav.css('margin-left', '-' + (nav.width()/2) + 'px'); 32651 32652 nav.find('li').first().find('a').addClass(ACTIVE); 32653 } 32654 32655 32656 /** 32657 * Sets the state of the website depending on the active section/slide. 32658 * It changes the URL hash when needed and updates the body class. 32659 */ 32660 function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){ 32661 var sectionHash = ''; 32662 32663 if(options.anchors.length && !options.lockAnchors){ 32664 32665 //isn't it the first slide? 32666 if(slideIndex){ 32667 if(typeof anchorLink !== 'undefined'){ 32668 sectionHash = anchorLink; 32669 } 32670 32671 //slide without anchor link? We take the index instead. 32672 if(typeof slideAnchor === 'undefined'){ 32673 slideAnchor = slideIndex; 32674 } 32675 32676 lastScrolledSlide = slideAnchor; 32677 setUrlHash(sectionHash + '/' + slideAnchor); 32678 32679 //first slide won't have slide anchor, just the section one 32680 }else if(typeof slideIndex !== 'undefined'){ 32681 lastScrolledSlide = slideAnchor; 32682 setUrlHash(anchorLink); 32683 } 32684 32685 //section without slides 32686 else{ 32687 setUrlHash(anchorLink); 32688 } 32689 } 32690 32691 setBodyClass(); 32692 } 32693 32694 /** 32695 * Sets the URL hash. 32696 */ 32697 function setUrlHash(url){ 32698 //Uncode addition 32699 if ( typeof SiteParameters.slide_footer != 'undefined' && url == SiteParameters.slide_footer ) 32700 return false; 32701 32702 if(options.recordHistory){ 32703 location.hash = url; 32704 }else{ 32705 //Uncode addition 32706 //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :) 32707 // if(isTouchDevice || isTouch){ 32708 // window.history.replaceState(undefined, undefined, '#' + url); 32709 // }else{ 32710 // var baseUrl = window.location.href.split('#')[0]; 32711 // window.location.replace( baseUrl + '#' + url ); 32712 // } 32713 return false;
32714 } 32715 } 32716 32717 /** 32718 * Gets the anchor for the given slide / section. Its index will be used if there's none. 32719 */ 32720 function getAnchor(element){ 32721 var anchor = element.data('anchor'); 32722 var index = element.index(); 32723 32724 //Slide without anchor link? We take the index instead. 32725 if(typeof anchor === 'undefined'){ 32726 anchor = index; 32727 } 32728 32729 return anchor; 32730 } 32731 32732 /** 32733 * Sets a class for the body of the page depending on the active section / slide 32734 */ 32735 function setBodyClass(){ 32736 var section = $(SECTION_ACTIVE_SEL); 32737 var slide = section.find(SLIDE_ACTIVE_SEL); 32738 32739 var sectionAnchor = getAnchor(section); 32740 var slideAnchor = getAnchor(slide); 32741 32742 var text = String(sectionAnchor); 32743 32744 if(slide.length){ 32745 text = text + '-' + slideAnchor; 32746 } 32747 32748 //changing slash for dash to make it a valid CSS style 32749 text = text.replace('/', '-').replace('#',''); 32750 32751 //removing previous anchor classes 32752 var classRe = new RegExp('\\b\\s?' + VIEWING_PREFIX + '-[^\\s]+\\b', "g"); 32753 $body[0].className = $body[0].className.replace(classRe, ''); 32754 32755 //adding the current anchor 32756 $body.addClass(VIEWING_PREFIX + '-' + text); 32757 } 32758 32759 /** 32760 * Checks for translate3d support 32761 * @return boolean 32762 * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support 32763 */ 32764 function support3d() { 32765 var el = document.createElement('p'), 32766 has3d, 32767 transforms = { 32768 'webkitTransform':'-webkit-transform', 32769 'OTransform':'-o-transform', 32770 'msTransform':'-ms-transform', 32771 'MozTransform':'-moz-transform', 32772 'transform':'transform' 32773 }; 32774 32775 // Add it to the body to get the computed style. 32776 document.body.insertBefore(el, null); 32777 32778 for (var t in transforms) { 32779 if (el.style[t] !== undefined) { 32780 el.style[t] = 'translate3d(1px,1px,1px)'; 32781 has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); 32782 } 32783 } 32784 32785 document.body.removeChild(el); 32786 32787 return (has3d !== undefined && has3d.length > 0 && has3d !== 'none'); 32788 } 32789 32790 /** 32791 * Removes the auto scrolling action fired by the mouse wheel and trackpad. 32792 * After this function is called, the mousewheel and trackpad movements won't scroll through sections. 32793 */ 32794 function removeMouseWheelHandler(){ 32795 if (document.addEventListener) { 32796 document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper 32797 document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox 32798 document.removeEventListener('MozMousePixelScroll', MouseWheelHandler, false); //old Firefox 32799 } else { 32800 document.detachEvent('onmousewheel', MouseWheelHandler); //IE 6/7/8 32801 } 32802 } 32803 32804 /** 32805 * Adds the auto scrolling action for the mouse wheel and trackpad. 32806 * After this function is called, the mousewheel and trackpad movements will scroll through sections 32807 * https://developer.mozilla.org/en-US/docs/Web/Events/wheel 32808 */ 32809 function addMouseWheelHandler(){ 32810 var prefix = ''; 32811 var _addEventListener; 32812 32813 if (window.addEventListener){ 32814 _addEventListener = "addEventListener"; 32815 }else{ 32816 _addEventListener = "attachEvent"; 32817 prefix = 'on'; 32818 } 32819 32820 // detect available wheel event 32821 var support = 'onwheel' in document.createElement('div') ? 'wheel' : // Modern browsers support "wheel" 32822 document.onmousewheel !== undefined ? 'mousewheel' : // Webkit and IE support at least "mousewheel" 32823 'DOMMouseScroll'; // let's assume that remaining browsers are older Firefox 32824 var passiveEvent = g_supportsPassive ? {passive: false }
32824: false; 32825 32826 32827 if(support == 'DOMMouseScroll'){ 32828 document[ _addEventListener ](prefix + 'MozMousePixelScroll', MouseWheelHandler, passiveEvent); 32829 } 32830 32831 //handle MozMousePixelScroll in older Firefox 32832 else{ 32833 document[ _addEventListener ](prefix + support, MouseWheelHandler, passiveEvent); 32834 } 32835 } 32836 32837 /** 32838 * Binding the mousemove when the mouse's middle button is pressed 32839 */ 32840 function addMiddleWheelHandler(){ 32841 container 32842 .on('mousedown', mouseDownHandler) 32843 .on('mouseup', mouseUpHandler); 32844 } 32845 32846 /** 32847 * Unbinding the mousemove when the mouse's middle button is released 32848 */ 32849 function removeMiddleWheelHandler(){ 32850 container 32851 .off('mousedown', mouseDownHandler) 32852 .off('mouseup', mouseUpHandler); 32853 } 32854 32855 /** 32856 * Adds the possibility to auto scroll through sections on touch devices. 32857 */ 32858 function addTouchHandler(){ 32859 if(isTouchDevice || isTouch){ 32860 if(options.autoScrolling){ 32861 $body.off(events.touchmove).on(events.touchmove, preventBouncing); 32862 } 32863 32864 $(WRAPPER_SEL) 32865 .off(events.touchstart).on(events.touchstart, touchStartHandler) 32866 .off(events.touchmove).on(events.touchmove, touchMoveHandler); 32867 } 32868 } 32869 32870 /** 32871 * Removes the auto scrolling for touch devices. 32872 */ 32873 function removeTouchHandler(){ 32874 if(isTouchDevice || isTouch){ 32875 $(WRAPPER_SEL) 32876 .off(events.touchstart) 32877 .off(events.touchmove); 32878 } 32879 } 32880 32881 /* 32882 * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11) 32883 * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx 32884 */ 32885 function getMSPointer(){ 32886 var pointer; 32887 32888 //IE >= 11 & rest of browsers 32889 if(window.PointerEvent){ 32890 pointer = { down: 'pointerdown', move: 'pointermove'}; 32891 } 32892 32893 //IE < 11 32894 else{ 32895 pointer = { down: 'MSPointerDown', move: 'MSPointerMove'}; 32896 } 32897 32898 return pointer; 32899 } 32900 32901 /** 32902 * Gets the pageX and pageY properties depending on the browser. 32903 * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854 32904 */ 32905 function getEventsPage(e){ 32906 var events = []; 32907 32908 events.y = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY); 32909 events.x = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX); 32910 32911 //in touch devices with scrollBar:true, e.pageY is detected, but we have to deal with touch events. #1008 32912 if(isTouch && isReallyTouch(e) && options.scrollBar){ 32913 events.y = e.touches[0].pageY; 32914 events.x = e.touches[0].pageX; 32915 } 32916 32917 return events; 32918 } 32919 32920 /** 32921 * Slides silently (with no animation) the active slider to the given slide. 32922 * @param noCallback {bool} true or defined -> no callbacks 32923 */ 32924 function silentLandscapeScroll(activeSlide, noCallbacks){ 32925 setScrollingSpeed (0, 'internal'); 32926 32927 if(typeof noCallbacks !== 'undefined'){ 32928 //preventing firing callbacks afterSlideLoad etc. 32929 isResizing = true; 32930 } 32931 32932 landscapeScroll(activeSlide.closest(SLIDES_WRAPPER_SEL), activeSlide); 32933 32934 if(typeof noCallbacks !== 'undefined'){ 32935 isResizing = false; 32936 } 32937 32938 setScrollingSpeed(originals.scrollingSpeed, 'internal'); 32939 } 32940 32941 /** 32942 * Scrolls silently (with no animation) the page to the given Y position. 32943 */ 32944 function silentScroll(top){ 32945 // The first section can have a negative value in iOS 10. Not quite sure why: -0.0142822265625 32946 // that's why we round it to 0. 32947 var roundedTop = Math.round(top); 32948 32949 if (options.css3 && options.autoScrolling && !options.scrollBar){ 32950 var translate3d = 'translate3d(0px, -' + roundedTop + 'px, 0px)'; 32951 transformContainer(translate3d, false); 32952 } 32953 else if(options.autoScrolling && !options.scrollBar){ 32954 container.css('top', -roundedTop); 32955 } 32956 else{ 32957 $htmlBody.scrollTop(roundedTop); 32958 } 32959 } 32960 32961 /** 32962 * Returns the cross-browser transform string. 32963 */ 32964 function getTransforms(translate3d){ 32965 return {
32966 '-webkit-transform': translate3d, 32967 '-moz-transform': translate3d, 32968 '-ms-transform':translate3d, 32969 'transform': translate3d 32970 }; 32971 } 32972 32973 /** 32974 * Allowing or disallowing the mouse/swipe scroll in a given direction. (not for keyboard) 32975 * @type m (mouse) or k (keyboard) 32976 */ 32977 function setIsScrollAllowed(value, direction, type){ 32978 switch (direction){ 32979 case 'up': isScrollAllowed[type].up = value; break; 32980 case 'down': isScrollAllowed[type].down = value; break; 32981 case 'left': isScrollAllowed[type].left = value; break; 32982 case 'right': isScrollAllowed[type].right = value; break; 32983 case 'all': 32984 if(type == 'm'){ 32985 setAllowScrolling(value); 32986 }else{ 32987 setKeyboardScrolling(value); 32988 } 32989 } 32990 } 32991 32992 /* 32993 * Destroys fullpage.js plugin events and optinally its html markup and styles 32994 */ 32995 function destroy(all){ 32996 setAutoScrolling(false, 'internal'); 32997 setAllowScrolling(false); 32998 setKeyboardScrolling(false); 32999 container.addClass(DESTROYED); 33000 33001 clearTimeout(afterSlideLoadsId); 33002 clearTimeout(afterSectionLoadsId); 33003 clearTimeout(resizeId); 33004 clearTimeout(scrollId); 33005 clearTimeout(scrollId2); 33006 33007 $window 33008 .off('scroll', scrollHandler) 33009 .off('hashchange', hashChangeHandler) 33010 .off('resize', resizeHandler); 33011 33012 $document 33013 .off('click touchstart', SECTION_NAV_SEL + ' a') 33014 .off('mouseenter', SECTION_NAV_SEL + ' li') 33015 .off('mouseleave', SECTION_NAV_SEL + ' li') 33016 .off('click touchstart', SLIDES_NAV_LINK_SEL) 33017 .off('mouseover', options.normalScrollElements) 33018 .off('mouseout', options.normalScrollElements); 33019 33020 $(SECTION_SEL) 33021 .off('click touchstart', SLIDES_ARROW_SEL); 33022 33023 clearTimeout(afterSlideLoadsId); 33024 clearTimeout(afterSectionLoadsId); 33025 33026 //lets make a mess! 33027 if(all){ 33028 destroyStructure(); 33029 } 33030 } 33031 33032 /* 33033 * Removes inline styles added by fullpage.js 33034 */ 33035 function destroyStructure(){ 33036 //reseting the `top` or `translate` properties to 0 33037 silentScroll(0); 33038 33039 //loading all the lazy load content 33040 container.find('img[data-src], source[data-src], audio[data-src], iframe[data-src]').each(function(){ 33041 setSrc($(this), 'src'); 33042 }); 33043 33044 container.find('img[data-srcset]').each(function(){ 33045 setSrc($(this), 'srcset'); 33046 }); 33047 33048 $(SECTION_NAV_SEL + ', ' + SLIDES_NAV_SEL + ', ' + SLIDES_ARROW_SEL).remove(); 33049 33050 //removing inline styles 33051 $(SECTION_SEL).css( { 33052 'height': '', 33053 'background-color' : '', 33054 'padding': '' 33055 }); 33056 33057 $(SLIDE_SEL).css( { 33058 'width': '' 33059 }); 33060 33061 container.css({ 33062 'height': '', 33063 'position': '', 33064 '-ms-touch-action': '', 33065 'touch-action': '' 33066 }); 33067 33068 $htmlBody.css({ 33069 'overflow': '', 33070 'height': '' 33071 }); 33072 33073 // remove .fp-enabled class 33074 $('html').removeClass(ENABLED); 33075 33076 // remove .fp-responsive class 33077 $body.removeClass(RESPONSIVE); 33078 33079 // remove all of the .fp-viewing- classes 33080 $.each($body.get(0).className.split(/\s+/), function (index, className) { 33081 if (className.indexOf(VIEWING_PREFIX) === 0) { 33082 $body.removeClass(className); 33083 } 33084 }); 33085 33086 //removing added classes 33087 $(SECTION_SEL + ', ' + SLIDE_SEL).each(function(){ 33088 options.scrollOverflowHandler.remove($(this)); 33089 $(this).removeClass(TABLE + ' ' + ACTIVE); 33090 }); 33091 33092 removeAnimation(container); 33093 33094 //Unwrapping content 33095 container.find(TABLE_CELL_SEL + ', ' + SLIDES_CONTAINER_SEL + ', ' + SLIDES_WRAPPER_SEL).each(function(){ 33096 //unwrap not being use in case there's no child element inside and its just text 33097 $(this).replaceWith(this.childNodes); 33098 }); 33099 33100 //removing the applied transition from the fullpage wrapper 33101 container.css({
33102 '-webkit-transition': 'none', 33103 'transition': 'none' 33104 }); 33105 33106 //scrolling the page to the top with no animation 33107 $htmlBody.scrollTop(0); 33108 33109 //removing selectors 33110 var usedSelectors = [SECTION, SLIDE, SLIDES_CONTAINER]; 33111 $.each(usedSelectors, function(index, value){ 33112 $('.' + value).removeClass(value); 33113 }); 33114 } 33115 33116 /* 33117 * Sets the state for a variable with multiple states (original, and temporal) 33118 * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`. 33119 * This function is used to keep track of both states, the original and the temporal one. 33120 * If type is not 'internal', then we assume the user is globally changing the variable. 33121 */ 33122 function setVariableState(variable, value, type){ 33123 options[variable] = value; 33124 if(type !== 'internal'){ 33125 originals[variable] = value; 33126 } 33127 } 33128 33129 /** 33130 * Displays warnings 33131 */ 33132 function displayWarnings(){ 33133 var extensions = ['fadingEffect', 'continuousHorizontal', 'scrollHorizontally', 'interlockedSlides', 'resetSliders', 'responsiveSlides', 'offsetSections', 'dragAndMove', 'scrollOverflowReset', 'parallax']; 33134 //UNCODE.addition 33135 // if($('html').hasClass(ENABLED)){ 33136 // showError('error', 'Fullpage.js can only be initialized once and you are doing it multiple times!'); 33137 // return; 33138 // } 33139 33140 // Disable mutually exclusive settings 33141 //UNCODE.addition 33142 // if (options.continuousVertical && 33143 // (options.loopTop || options.loopBottom)) { 33144 // options.continuousVertical = false;
33145 // showError('warn', 'Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 33146 // } 33147 33148 // if(options.scrollBar && options.scrollOverflow){ 33149 // showError('warn', 'Option `scrollBar` is mutually exclusive with `scrollOverflow`. Sections with scrollOverflow might not work well in Firefox'); 33150 // } 33151 33152 // if(options.continuousVertical && (options.scrollBar || !options.autoScrolling)){ 33153 // options.continuousVertical = false; 33154 // showError('warn', 'Scroll bars (`scrollBar:true` or `autoScrolling:false`) are mutually exclusive with `continuousVertical`; `continuousVertical` disabled'); 33155 // } 33156 33157 //using extensions? Wrong file! 33158 $.each(extensions, function(index, extension){ 33159 //is the option set to true? 33160 if(options[extension]){ 33161 showError('warn', 'fullpage.js extensions require jquery.fullpage.extensions.min.js file instead of the usual jquery.fullpage.js. Requested: '+ extension); 33162 } 33163 }); 33164 33165 //anchors can not have the same value as any element ID or NAME 33166 $.each(options.anchors, function(index, name){ 33167 33168 //case insensitive selectors (http://stackoverflow.com/a/19465187/1081396) 33169 var nameAttr = $document.find('[name]').filter(function() { 33170 return $(this).attr('name') && $(this).attr('name').toLowerCase() == name.toLowerCase(); 33171 }); 33172 33173 var idAttr = $document.find('[id]').filter(function() { 33174 return $(this).attr('id') && $(this).attr('id').toLowerCase() == name.toLowerCase(); 33175 }); 33176 33177 if(idAttr.length || nameAttr.length ){ 33178 showError('error', 'data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).'); 33179 idAttr.length && showError('error', '"' + name + '" is is being used by another element `id` property'); 33180 nameAttr.length && showError('error', '"' + name + '" is is being used by another element `name` property'); 33181 } 33182 }); 33183 } 33184 33185 /** 33186 * Shows a message in the console of the given type. 33187 */ 33188 function showError(type, text){ 33189 console && console[type] && console[type]('fullPage: ' + text); 33190 } 33191 33192 }; //end of $.fn.fullpage 33193 33194 if(typeof IScroll !== 'undefined'){ 33195 /* 33196 * Turns iScroll `mousewheel` option off dynamically 33197 * https://github.com/cubiq/iscroll/issues/1036 33198 */ 33199 IScroll.prototype.wheelOn = function () { 33200 this.wrapper.addEventListener('wheel', this); 33201 this.wrapper.addEventListener('mousewheel', this); 33202 this.wrapper.addEventListener('DOMMouseScroll', this); 33203 }; 33204 33205 /* 33206 * Turns iScroll `mousewheel` option on dynamically 33207 * https://github.com/cubiq/iscroll/issues/1036 33208 */ 33209 IScroll.prototype.wheelOff = function () { 33210 this.wrapper.removeEventListener('wheel', this); 33211 this.wrapper.removeEventListener('mousewheel', this); 33212 this.wrapper.removeEventListener('DOMMouseScroll', this); 33213 }; 33214 } 33215 33216 /** 33217 * An object to handle overflow scrolling. 33218 * This uses jquery.slimScroll to accomplish overflow scrolling. 33219 * It is possible to pass in an alternate scrollOverflowHandler 33220 * to the fullpage.js option that implements the same functions 33221 * as this handler. 33222 * 33223 * @type {Object} 33224 */ 33225 var iscrollHandler = { 33226 refreshId: null, 33227 iScrollInstances: [], 33228 33229 // Enables or disables the mouse wheel for the active section or all slides in it 33230 toggleWheel: function(value){ 33231 var scrollable = $(SECTION_ACTIVE_SEL).find(SCROLLABLE_SEL); 33232 scrollable.each(function(){ 33233 var iScrollInstance = $(this).data('iscrollInstance'); 33234 if(typeof iScrollInstance !== 'undefined' && iScrollInstance){ 33235 if(value){ 33236 iScrollInstance.wheelOn(); 33237 } 33238 else{ 33239 iScrollInstance.wheelOff(); 33240 } 33241 } 33242 }); 33243 }, 33244 33245 /** 33246 * Turns off iScroll for the destination section. 33247 * When scrolling very fast on some trackpads (and Apple laptops) the inertial scrolling would
33248 * scroll the destination section/slide before the sections animations ends. 33249 */ 33250 onLeave: function(){ 33251 iscrollHandler.toggleWheel(false); 33252 }, 33253 33254 // Turns off iScroll for the leaving section 33255 beforeLeave: function(){ 33256 iscrollHandler.onLeave() 33257 }, 33258 33259 // Turns on iScroll on section load 33260 afterLoad: function(){ 33261 iscrollHandler.toggleWheel(true); 33262 }, 33263 33264 /** 33265 * Called when overflow scrolling is needed for a section. 33266 * 33267 * @param {Object} element jQuery object containing current section 33268 * @param {Number} scrollHeight Current window height in pixels 33269 */ 33270 create: function(element, scrollHeight) { 33271 var scrollable = element.find(SCROLLABLE_SEL); 33272 33273 scrollable.height(scrollHeight); 33274 scrollable.each(function() { 33275 var $this = $(this); 33276 var iScrollInstance = $this.data('iscrollInstance'); 33277 if (iScrollInstance) { 33278 $.each(iscrollHandler.iScrollInstances, function(){ 33279 $(this).destroy(); 33280 }); 33281 } 33282 33283 iScrollInstance = new IScroll($this.get(0), iscrollOptions); 33284 iscrollHandler.iScrollInstances.push(iScrollInstance); 33285 33286 //off by default until the section gets active 33287 iScrollInstance.wheelOff(); 33288 33289 $this.data('iscrollInstance', iScrollInstance); 33290 }); 33291 }, 33292 33293 /** 33294 * Return a boolean depending on whether the scrollable element is a 33295 * the end or at the start of the scrolling depending on the given type. 33296 * 33297 * @param {String} type Either 'top' or 'bottom' 33298 * @param {Object} scrollable jQuery object for the scrollable element 33299 * @return {Boolean} 33300 */ 33301 isScrolled: function(type, scrollable) { 33302 var scroller = scrollable.data('iscrollInstance'); 33303 33304 //no scroller? 33305 if (!scroller) { 33306 return true; 33307 } 33308 33309 if (type === 'top') { 33310 return scroller.y >= 0 && !scrollable.scrollTop(); 33311 } else if (type === 'bottom') { 33312 return (0 - scroller.y) + scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight; 33313 } 33314 }, 33315 33316 /** 33317 * Returns the scrollable element for the given section. 33318 * If there are landscape slides, will only return a scrollable element 33319 * if it is in the active slide. 33320 * 33321 * @param {Object} activeSection jQuery object containing current section 33322 * @return {Boolean} 33323 */ 33324 scrollable: function(activeSection){ 33325 // if there are landscape slides, we check if the scrolling bar is in the current one or not 33326 if (activeSection.find(SLIDES_WRAPPER_SEL).length) { 33327 return activeSection.find(SLIDE_ACTIVE_SEL).find(SCROLLABLE_SEL); 33328 } 33329 return activeSection.find(SCROLLABLE_SEL); 33330 }, 33331 33332 /** 33333 * Returns the scroll height of the wrapped content. 33334 * If this is larger than the window height minus section padding, 33335 * overflow scrolling is needed. 33336 * 33337 * @param {Object} element jQuery object containing current section 33338 * @return {Number} 33339 */ 33340 scrollHeight: function(element) { 33341 return element.find(SCROLLABLE_SEL).children().first().get(0).scrollHeight; 33342 }, 33343 33344 /** 33345 * Called when overflow scrolling is no longer needed for a section. 33346 * 33347 * @param {Object} element jQuery object containing current section 33348 */ 33349 remove: function(element) { 33350 var scrollable = element.find(SCROLLABLE_SEL); 33351 if (scrollable.length) { 33352 var iScrollInstance = scrollable.data('iscrollInstance'); 33353 iScrollInstance.destroy(); 33354 33355 scrollable.data('iscrollInstance', null); 33356 } 33357 element.find(SCROLLABLE_SEL).children().first().children().first().unwrap().unwrap(); 33358 }, 33359 33360 /** 33361 * Called when overflow scrolling has already been setup but the 33362 * window height has potentially changed. 33363 * 33364 * @param {Object}
33364 element jQuery object containing current section 33365 * @param {Number} scrollHeight Current window height in pixels 33366 */ 33367 update: function(element, scrollHeight) { 33368 //using a timeout in order to execute the refresh function only once when `update` is called multiple times in a 33369 //short period of time. 33370 //it also comes on handy because iScroll requires the use of timeout when using `refresh`. 33371 clearTimeout(iscrollHandler.refreshId); 33372 iscrollHandler.refreshId = setTimeout(function(){ 33373 $.each(iscrollHandler.iScrollInstances, function(){ 33374 $(this).get(0).refresh(); 33375 }); 33376 }, 150); 33377 33378 //updating the wrappers height 33379 element.find(SCROLLABLE_SEL).css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px'); 33380 }, 33381 33382 /** 33383 * Called to get any additional elements needed to wrap the section 33384 * content in order to facilitate overflow scrolling. 33385 * 33386 * @return {String|Object} Can be a string containing HTML, 33387 * a DOM element, or jQuery object. 33388 */ 33389 wrapContent: function() { 33390 return '<div class="' + SCROLLABLE + '"><div class="fp-scroller"></div></div>'; 33391 } 33392 }; 33393}); 33394 33395(function (global, factory) { 33396 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : 33397 typeof define === 'function' && define.amd ? define(['exports'], factory) : 33398 (global = global || self, factory(global.window = global.window || {})); 33399}(this, (function (exports) { 'use strict'; 33400 33401 /*! 33402 * ScrollTrigger 3.8.0 33403 * https://greensock.com 33404 * 33405 * @license Copyright 2008-2021, GreenSock. All rights reserved. 33406 * Subject to the terms at https://greensock.com/standard-license or for 33407 * Club GreenSock members, the agreement issued with that membership. 33408 * @author: Jack Doyle, [email protected] 33409 */ 33410 var gsap, 33411 _coreInitted, 33412 _win, 33413 _doc, 33414 _docEl, 33415 _body, 33416 _root, 33417 _resizeDelay, 33418 _raf, 33419 _request, 33420 _toArray, 33421 _clamp, 33422 _time2, 33423 _syncInterval, 33424 _refreshing, 33425 _pointerIsDown, 33426 _transformProp, 33427 _i, 33428 _prevWidth, 33429 _prevHeight, 33430 _autoRefresh, 33431 _sort, 33432 _suppressOverwrites, 33433 _ignoreResize, 33434 _limitCallbacks, 33435 _startup = 1, 33436 _proxies = [], 33437 _scrollers = [], 33438 _getTime = Date.now, 33439 _time1 = _getTime(), 33440 _lastScrollTime = 0, 33441 _enabled = 1, 33442 _passThrough = function _passThrough(v) { 33443 return v; 33444 }, 33445 _getTarget = function _getTarget(t) { 33446 return _toArray(t)[0] || (_isString(t) ? console.warn("Element not found:", t) : null); 33447 }, 33448 _round = function _round(value) { 33449 return Math.round(value * 100000) / 100000 || 0; 33450 }, 33451 _windowExists = function _windowExists() { 33452 return typeof window !== "undefined"; 33453 }, 33454 _getGSAP = function _getGSAP() { 33455 return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap; 33456 }, 33457 _isViewport = function _isViewport(e) { 33458 return !!~_root.indexOf(e); 33459 }, 33460 _getProxyProp = function _getProxyProp(element, property) { 33461 return ~_proxies.indexOf(element) && _proxies[_proxies.indexOf(element) + 1][property]; 33462 }, 33463 _getScrollFunc = function _getScrollFunc(element, _ref) { 33464 var s = _ref.s, 33465 sc = _ref.sc; 33466 33467 var i = _scrollers.indexOf(element), 33468 offset = sc === _vertical.sc ? 1 : 2; 33469 33470 !~i && (i = _scrollers.push(element) - 1); 33471 return _scrollers[i + offset] || (_scrollers[i + offset] = _getProxyProp(element, s) || (_isViewport(element) ? sc : function (value) { 33472 return arguments.length ? element[s] = value : element[s]; 33473 })); 33474 }, 33475 _getBoundsFunc = function _getBoundsFunc(element) { 33476 return _getProxyProp(element, "getBoundingClientRect") || (_isViewport(element) ? function () { 33477 _winOffsets.width = _win.innerWidth; 33478 _winOffsets.height = _win.innerHeight; 33479 return _winOffsets; 33480 } : function () { 33481 return _getBounds(element); 33482 }); 33483 }, 33484 _getSizeFunc = function _getSizeFunc(scroller, isViewport, _ref2) { 33485 var d = _ref2.d, 33486 d2 = _ref2.d2, 33487 a = _ref2.a; 33488 return (a = _getProxyProp(scroller, "getBoundingClientRect")) ? function () { 33489 return a()[d]; 33490 } : function () { 33491 return (isViewport ? _win["inner" + d2] : scroller["client" + d2]) || 0; 33492 }; 33493 }, 33494 _getOffsetsFunc = function _getOffsetsFunc(element, isViewport) { 33495 return !isViewport || ~_proxies.indexOf(element) ? _getBoundsFunc(element) : function () { 33496 return _winOffsets; 33497 }; 33498 }, 33499 _maxScroll = function _maxScroll(element, _ref3) { 33500 var s = _ref3.s, 33501 d2 = _ref3.d2, 33502 d = _ref3.d, 33503 a = _ref3.a; 33504 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]; 33505 }, 33506 _iterateAutoRefresh = function _iterateAutoRefresh(func, events) { 33507 for (var i = 0; i < _autoRefresh.length; i += 3) {
33508 (!events || ~events.indexOf(_autoRefresh[i + 1])) && func(_autoRefresh[i], _autoRefresh[i + 1], _autoRefresh[i + 2]); 33509 } 33510 }, 33511 _isString = function _isString(value) { 33512 return typeof value === "string"; 33513 }, 33514 _isFunction = function _isFunction(value) { 33515 return typeof value === "function"; 33516 }, 33517 _isNumber = function _isNumber(value) { 33518 return typeof value === "number"; 33519 }, 33520 _isObject = function _isObject(value) { 33521 return typeof value === "object"; 33522 }, 33523 _callIfFunc = function _callIfFunc(value) { 33524 return _isFunction(value) && value(); 33525 }, 33526 _combineFunc = function _combineFunc(f1, f2) { 33527 return function () { 33528 var result1 = _callIfFunc(f1), 33529 result2 = _callIfFunc(f2); 33530 33531 return function () { 33532 _callIfFunc(result1); 33533 33534 _callIfFunc(result2); 33535 }; 33536 }; 33537 }, 33538 _endAnimation = function _endAnimation(animation, reversed, pause) { 33539 return animation && animation.progress(reversed ? 0 : 1) && pause && animation.pause(); 33540 }, 33541 _callback = function _callback(self, func) { 33542 var result = func(self); 33543 result && result.totalTime && (self.callbackAnimation = result); 33544 }, 33545 _abs = Math.abs, 33546 _scrollLeft = "scrollLeft", 33547 _scrollTop = "scrollTop", 33548 _left = "left", 33549 _top = "top", 33550 _right = "right", 33551 _bottom = "bottom", 33552 _width = "width", 33553 _height = "height", 33554 _Right = "Right", 33555 _Left = "Left", 33556 _Top = "Top", 33557 _Bottom = "Bottom", 33558 _padding = "padding", 33559 _margin = "margin", 33560 _Width = "Width", 33561 _Height = "Height", 33562 _px = "px", 33563 _horizontal = { 33564 s: _scrollLeft, 33565 p: _left, 33566 p2: _Left, 33567 os: _right, 33568 os2: _Right, 33569 d: _width, 33570 d2: _Width, 33571 a: "x", 33572 sc: function sc(value) { 33573 return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0; 33574 } 33575 }, 33576 _vertical = { 33577 s: _scrollTop, 33578 p: _top, 33579 p2: _Top, 33580 os: _bottom, 33581 os2: _Bottom, 33582 d: _height, 33583 d2: _Height, 33584 a: "y", 33585 op: _horizontal, 33586 sc: function sc(value) { 33587 return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0; 33588 } 33589 }, 33590 _getComputedStyle = function _getComputedStyle(element) { 33591 return _win.getComputedStyle(element); 33592 }, 33593 _makePositionable = function _makePositionable(element) { 33594 var position = _getComputedStyle(element).position; 33595 33596 element.style.position = position === "absolute" || position === "fixed" ? position : "relative"; 33597 }, 33598 _setDefaults = function _setDefaults(obj, defaults) { 33599 for (var p in defaults) { 33600 p in obj || (obj[p] = defaults[p]); 33601 } 33602 33603 return obj; 33604 }, 33605 _getBounds = function _getBounds(element, withoutTransforms) { 33606 var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, { 33607 x: 0, 33608 y: 0, 33609 xPercent: 0, 33610 yPercent: 0, 33611 rotation: 0, 33612 rotationX: 0, 33613 rotationY: 0, 33614 scale: 1, 33615 skewX: 0, 33616 skewY: 0 33617 }).progress(1), 33618 bounds = element.getBoundingClientRect(); 33619 tween && tween.progress(0).kill(); 33620 return bounds; 33621 }, 33622 _getSize = function _getSize(element, _ref4) { 33623 var d2 = _ref4.d2; 33624 return element["offset" + d2] || element["client" + d2] || 0; 33625 }, 33626 _getLabelRatioArray = function _getLabelRatioArray(timeline) { 33627 var a = [], 33628 labels = timeline.labels, 33629 duration = timeline.duration(), 33630 p; 33631 33632 for (p in labels) { 33633 a.push(labels[p] / duration); 33634 } 33635 33636 return a; 33637 }, 33638 _getClosestLabel = function _getClosestLabel(animation) { 33639 return function (value) { 33640 return gsap.utils.snap(_getLabelRatioArray(animation), value); 33641 }; 33642 }, 33643 _snapDirectional = function _snapDirectional(snapIncrementOrArray) { 33644 var snap = gsap.utils.snap(snapIncrementOrArray), 33645 a = Array.isArray(snapIncrementOrArray) && snapIncrementOrArray.slice(0).sort(function (a, b) { 33646 return a - b; 33647 }); 33648 return a ? function (value, direction) { 33649 var i; 33650 33651 if (!direction) { 33652 return snap(value); 33653 } 33654 33655 if (direction > 0) { 33656 value -= 1e-4; 33657 33658 for (i = 0; i < a.length; i++) { 33659 if (a[i] >= value) { 33660 return a[i]; 33661 } 33662 } 33663 33664 return a[i - 1]; 33665 } else { 33666 i = a.length; 33667 value += 1e-4; 33668 33669 while (i--) { 33670 if (a[i] <= value) { 33671 return a[i]; 33672 } 33673 } 33674 } 33675 33676 return a[0]; 33677 } : function (value, direction) { 33678 var snapped = snap(value); 33679 return !direction || Math.abs(snapped - value) < 0.001 || snapped - value < 0 === direction < 0 ? snapped : snap(direction < 0 ? value - snapIncrementOrArray : value + snapIncrementOrArray); 33680 }; 33681 }, 33682 _getLabelAtDirection = function _getLabelAtDirection(timeline) { 33683 return function (value, st) { 33684 return _snapDirectional(_getLabelRatioArray(timeline))(value, st.direction); 33685 }; 33686 }, 33687 _multiListener = function _multiListener(func, element, types, callback) { 33688 return types.split(",").forEach(function (type) { 33689 return func(element, type, callback); 33690 }); 33691 }, 33692 _addListener = function _addListener(element, type, func) { 33693 return element.addEventListener(type, func, { 33694 passive: true 33695 }); 33696 }, 33697 _removeListener = function _removeListener(element, type, func) { 33698 return element.removeEventListener(type, func); 33699 }, 33700 _markerDefaults = { 33701 startColor: "green", 33702 endColor: "red", 33703 indent: 0, 33704 fontSize: "16px", 33705 fontWeight: "normal" 33706 }, 33707 _defaults = { 33708 toggleActions: "play", 33709 anticipatePin: 0 33710 }, 33711 _keywords = { 33712 top: 0,
33713 left: 0, 33714 center: 0.5, 33715 bottom: 1, 33716 right: 1 33717 }, 33718 _offsetToPx = function _offsetToPx(value, size) { 33719 if (_isString(value)) { 33720 var eqIndex = value.indexOf("="), 33721 relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0; 33722 33723 if (~eqIndex) { 33724 value.indexOf("%") > eqIndex && (relative *= size / 100); 33725 value = value.substr(0, eqIndex - 1); 33726 } 33727 33728 value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0); 33729 } 33730 33731 return value; 33732 }, 33733 _createMarker = function _createMarker(type, name, container, direction, _ref5, offset, matchWidthEl, containerAnimation) { 33734 var startColor = _ref5.startColor, 33735 endColor = _ref5.endColor, 33736 fontSize = _ref5.fontSize, 33737 indent = _ref5.indent, 33738 fontWeight = _ref5.fontWeight; 33739 33740 var e = _doc.createElement("div"), 33741 useFixedPosition = _isViewport(container) || _getProxyProp(container, "pinType") === "fixed", 33742 isScroller = type.indexOf("scroller") !== -1, 33743 parent = useFixedPosition ? _body : container, 33744 isStart = type.indexOf("start") !== -1, 33745 color = isStart ? startColor : endColor, 33746 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;"; 33747 33748 css += "position:" + ((isScroller || containerAnimation) && useFixedPosition ? "fixed;" : "absolute;"); 33749 (isScroller || containerAnimation || !useFixedPosition) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;"); 33750 matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;"); 33751 e._isStart = isStart; 33752 e.setAttribute("class", "gsap-marker-" + type + (name ? " marker-" + name : "")); 33753 e.style.cssText = css; 33754 e.innerText = name || name === 0 ? type + "-" + name : type; 33755 parent.children[0] ? parent.insertBefore(e, parent.children[0]) : parent.appendChild(e); 33756 e._offset = e["offset" + direction.op.d2]; 33757 33758 _positionMarker(e, 0, direction, isStart); 33759 33760 return e; 33761 }, 33762 _positionMarker = function _positionMarker(marker, start, direction, flipped) { 33763 var vars = { 33764 display: "block" 33765 }, 33766 side = direction[flipped ? "os2" : "p2"], 33767 oppositeSide = direction[flipped ? "p2" : "os2"]; 33768 marker._isFlipped = flipped; 33769 vars[direction.a + "Percent"] = flipped ? -100 : 0; 33770 vars[direction.a] = flipped ? "1px" : 0; 33771 vars["border" + side + _Width] = 1; 33772 vars["border" + oppositeSide + _Width] = 0; 33773 vars[direction.p] = start + "px"; 33774 gsap.set(marker, vars); 33775 }, 33776 _triggers = [], 33777 _ids = {}, 33778 _sync = function _sync() { 33779 return _getTime() - _lastScrollTime > 20 && _updateAll(); 33780 }, 33781 _onScroll = function _onScroll() { 33782 var time = _getTime(); 33783 33784 if (_lastScrollTime !== time) { 33785 _updateAll(); 33786 33787 _lastScrollTime || _dispatch("scrollStart"); 33788 _lastScrollTime = time; 33789 } else if (!_request) { 33790 _request = _raf(_updateAll); 33791 } 33792 }, 33793 _onResize = function _onResize() { 33794 return !_refreshing && !_ignoreResize && !_doc.fullscreenElement && _resizeDelay.restart(true); 33795 }, 33796 _listeners = {}, 33797 _emptyArray = [], 33798 _media = [], 33799 _creatingMedia, 33800 _lastMediaTick, 33801 _onMediaChange = function _onMediaChange(e) { 33802 var tick = gsap.ticker.frame, 33803 matches = [], 33804 i = 0, 33805 index; 33806 33807 if (_lastMediaTick !== tick || _startup) { 33808 _revertAll(); 33809 33810 for (; i < _media.length; i += 4) { 33811 index = _win.matchMedia(_media[i]).matches; 33812 33813 if (index !== _media[i + 3]) { 33814 _media[i + 3] = index; 33815 index ? matches.push(i) : _revertAll(1, _media[i]) || _isFunction(_media[i + 2]) && _media[i + 2](); 33816 } 33817 } 33818 33819 _revertRecorded(); 33820 33821 for (i = 0; i < matches.length; i++) { 33822 index = matches[i]; 33823 _creatingMedia = _media[index]; 33824 _media[index + 2] = _media[index + 1](e); 33825 } 33826 33827 _creatingMedia = 0; 33828 _coreInitted && _refreshAll(0, 1); 33829 _lastMediaTick = tick; 33830 33831 _dispatch("matchMedia"); 33832 } 33833 }, 33834 _softRefresh = function _softRefresh() { 33835 return _removeListener(ScrollTrigger, "scrollEnd", _softRefresh) || _refreshAll(true); 33836 }, 33837 _dispatch = function _dispatch(type) { 33838 return _listeners[type] && _listeners[type].map(function (f) { 33839 return f(); 33840 }) || _emptyArray; 33841 }, 33842 _savedStyles = [], 33843 _revertRecorded = function _revertRecorded(media) { 33844 for (var i = 0; i < _savedStyles.length; i += 5) { 33845 if (!media || _savedStyles[i + 4] === media) { 33846 _savedStyles[i].style.cssText = _savedStyles[i + 1]; 33847 _savedStyles[i].getBBox && _savedStyles[i].setAttribute("transform", _savedStyles[i + 2] || ""); 33848 _savedStyles[i + 3].uncache = 1; 33849 } 33850 } 33851 }, 33852 _revertAll = function _revertAll(kill, media) { 33853 var trigger; 33854 33855 for (_i = 0; _i < _triggers.length; _i++) { 33856 trigger = _triggers[_i]; 33857 33858 if (!media || trigger.media === media) { 33859 if (kill) { 33860 trigger.kill(1); 33861 } else { 33862 trigger.revert(); 33863 } 33864 } 33865 } 33866 33867 media && _revertRecorded(media); 33868 media || _dispatch("revert"); 33869 }, 33870 _clearScrollMemory = function _clearScrollMemory() {
vendor: 10,266 bytes, lines 33871-34205
33871 return _scrollers.forEach(function (obj) { 33872 return typeof obj === "function" && (obj.rec = 0); 33873 }); 33874 }, 33875 _refreshingAll, 33876 _refreshAll = function _refreshAll(force, skipRevert) { 33877 if (_lastScrollTime && !force) { 33878 _addListener(ScrollTrigger, "scrollEnd", _softRefresh); 33879 33880 return; 33881 } 33882 33883 _refreshingAll = true; 33884 33885 var refreshInits = _dispatch("refreshInit"); 33886 33887 _sort && ScrollTrigger.sort(); 33888 skipRevert || _revertAll(); 33889 33890 _triggers.forEach(function (t) { 33891 return t.refresh(); 33892 }); 33893 33894 refreshInits.forEach(function (result) { 33895 return result && result.render && result.render(-1); 33896 }); 33897 33898 _clearScrollMemory(); 33899 33900 _resizeDelay.pause(); 33901 33902 _refreshingAll = false; 33903 33904 _dispatch("refresh"); 33905 }, 33906 _lastScroll = 0, 33907 _direction = 1, 33908 _updateAll = function _updateAll() { 33909 if (!_refreshingAll) { 33910 var l = _triggers.length, 33911 time = _getTime(), 33912 recordVelocity = time - _time1 >= 50, 33913 scroll = l && _triggers[0].scroll(); 33914 33915 _direction = _lastScroll > scroll ? -1 : 1; 33916 _lastScroll = scroll; 33917 33918 if (recordVelocity) { 33919 if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) { 33920 _lastScrollTime = 0; 33921 33922 _dispatch("scrollEnd"); 33923 } 33924 33925 _time2 = _time1; 33926 _time1 = time; 33927 } 33928 33929 if (_direction < 0) { 33930 _i = l; 33931 33932 while (_i-- > 0) { 33933 _triggers[_i] && _triggers[_i].update(0, recordVelocity); 33934 } 33935 33936 _direction = 1; 33937 } else { 33938 for (_i = 0; _i < l; _i++) { 33939 _triggers[_i] && _triggers[_i].update(0, recordVelocity); 33940 } 33941 } 33942 33943 _request = 0; 33944 } 33945 }, 33946 _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"], 33947 _stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]), 33948 _swapPinOut = function _swapPinOut(pin, spacer, state) { 33949 _setState(state); 33950 33951 var cache = pin._gsap; 33952 33953 if (cache.spacerIsNative) { 33954 _setState(cache.spacerState); 33955 } else if (pin.parentNode === spacer) { 33956 var parent = spacer.parentNode; 33957 33958 if (parent) { 33959 parent.insertBefore(pin, spacer); 33960 parent.removeChild(spacer); 33961 } 33962 } 33963 }, 33964 _swapPinIn = function _swapPinIn(pin, spacer, cs, spacerState) { 33965 if (pin.parentNode !== spacer) { 33966 var i = _propNamesToCopy.length, 33967 spacerStyle = spacer.style, 33968 pinStyle = pin.style, 33969 p; 33970 33971 while (i--) { 33972 p = _propNamesToCopy[i]; 33973 spacerStyle[p] = cs[p]; 33974 } 33975 33976 spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative"; 33977 cs.display === "inline" && (spacerStyle.display = "inline-block"); 33978 pinStyle[_bottom] = pinStyle[_right] = "auto"; 33979 spacerStyle.overflow = "visible"; 33980 spacerStyle.boxSizing = "border-box"; 33981 spacerStyle[_width] = _getSize(pin, _horizontal) + _px; 33982 spacerStyle[_height] = _getSize(pin, _vertical) + _px; 33983 spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0"; 33984 33985 _setState(spacerState); 33986 33987 pinStyle[_width] = pinStyle["max" + _Width] = cs[_width]; 33988 pinStyle[_height] = pinStyle["max" + _Height] = cs[_height]; 33989 pinStyle[_padding] = cs[_padding]; 33990 pin.parentNode.insertBefore(spacer, pin); 33991 spacer.appendChild(pin); 33992 } 33993 }, 33994 _capsExp = /([A-Z])/g, 33995 _setState = function _setState(state) { 33996 if (state) { 33997 var style = state.t.style, 33998 l = state.length, 33999 i = 0, 34000 p, 34001 value; 34002 (state.t._gsap || gsap.core.getCache(state.t)).uncache = 1; 34003 34004 for (; i < l; i += 2) { 34005 value = state[i + 1]; 34006 p = state[i]; 34007 34008 if (value) { 34009 style[p] = value; 34010 } else if (style[p]) { 34011 style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase()); 34012 } 34013 } 34014 } 34015 }, 34016 _getState = function _getState(element) { 34017 var l = _stateProps.length, 34018 style = element.style, 34019 state = [], 34020 i = 0; 34021 34022 for (; i < l; i++) { 34023 state.push(_stateProps[i], style[_stateProps[i]]); 34024 } 34025 34026 state.t = element; 34027 return state; 34028 }, 34029 _copyState = function _copyState(state, override, omitOffsets) { 34030 var result = [], 34031 l = state.length, 34032 i = omitOffsets ? 8 : 0, 34033 p; 34034 34035 for (; i < l; i += 2) { 34036 p = state[i]; 34037 result.push(p, p in override ? override[p] : state[i + 1]); 34038 } 34039 34040 result.t = state.t; 34041 return result; 34042 }, 34043 _winOffsets = { 34044 left: 0, 34045 top: 0 34046 }, 34047 _parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, useFixedPosition, scrollerMax, containerAnimation) { 34048 _isFunction(value) && (value = value(self)); 34049 34050 if (_isString(value) && value.substr(0, 3) === "max") { 34051 value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0); 34052 } 34053 34054 var time = containerAnimation ? containerAnimation.time() : 0, 34055 p1, 34056 p2, 34057 element; 34058 containerAnimation && containerAnimation.seek(0); 34059 34060 if (!_isNumber(value)) { 34061 _isFunction(trigger) && (trigger = trigger(self)); 34062 var offsets = value.split(" "), 34063 bounds, 34064 localOffset, 34065 globalOffset, 34066 display; 34067 element = _getTarget(trigger) || _body; 34068 bounds = _getBounds(element) || {}; 34069 34070 if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") { 34071 display = element.style.display; 34072 element.style.display = "block"; 34073 bounds = _getBounds(element); 34074 display ? element.style.display = display : element.style.removeProperty("display"); 34075 } 34076 34077 localOffset = _offsetToPx(offsets[0], bounds[direction.d]); 34078 globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize); 34079 value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset; 34080 markerScroller && _positionMarker(markerScroller, globalOffset, direction, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20); 34081 scrollerSize -= scrollerSize - globalOffset; 34082 } else if (markerScroller) { 34083 _positionMarker(markerScroller, scrollerSize, direction, true); 34084 } 34085 34086 if (marker) { 34087 var position = value + scrollerSize, 34088 isStart = marker._isStart; 34089 p1 = "scroll" + direction.d2; 34090 34091 _positionMarker(marker, position, direction, isStart && position > 20 || !isStart && (useFixedPosition ? Math.max(_body[p1], _docEl[p1]) : marker.parentNode[p1]) <= position + 1); 34092 34093 if (useFixedPosition) { 34094 scrollerBounds = _getBounds(markerScroller); 34095 useFixedPosition && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px); 34096 } 34097 } 34098 34099 if (containerAnimation && element) { 34100 p1 = _getBounds(element); 34101 containerAnimation.seek(scrollerMax); 34102 p2 = _getBounds(element); 34103 containerAnimation._caScrollDist = p1[direction.p] - p2[direction.p]; 34104 value = value / containerAnimation._caScrollDist * scrollerMax; 34105 } 34106 34107 containerAnimation && containerAnimation.seek(time); 34108 return containerAnimation ? value : Math.round(value); 34109 }, 34110 _prefixExp = /(?:webkit|moz|length|cssText|inset)/i, 34111 _reparent = function _reparent(element, parent, top, left) { 34112 if (element.parentNode !== parent) { 34113 var style = element.style, 34114 p, 34115 cs; 34116 34117 if (parent === _body) { 34118 element._stOrig = style.cssText; 34119 cs = _getComputedStyle(element); 34120 34121 for (p in cs) { 34122 if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") { 34123 style[p] = cs[p]; 34124 } 34125 } 34126 34127 style.top = top; 34128 style.left = left; 34129 } else { 34130 style.cssText = element._stOrig; 34131 } 34132 34133 gsap.core.getCache(element).uncache = 1; 34134 parent.appendChild(element); 34135 } 34136 }, 34137 _getTweenCreator = function _getTweenCreator(scroller, direction) { 34138 var getScroll = _getScrollFunc(scroller, direction), 34139 prop = "_scroll" + direction.p2, 34140 lastScroll1, 34141 lastScroll2, 34142 getTween = function getTween(scrollTo, vars, initialValue, change1, change2) { 34143 var tween = getTween.tween, 34144 onComplete = vars.onComplete, 34145 modifiers = {}; 34146 tween && tween.kill(); 34147 lastScroll1 = Math.round(initialValue); 34148 vars[prop] = scrollTo; 34149 vars.modifiers = modifiers; 34150 34151 modifiers[prop] = function (value) { 34152 value = _round(getScroll()); 34153 34154 if (value !== lastScroll1 && value !== lastScroll2 && Math.abs(value - lastScroll1) > 2) { 34155 tween.kill(); 34156 getTween.tween = 0; 34157 } else { 34158 value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio; 34159 } 34160 34161 lastScroll2 = lastScroll1; 34162 return lastScroll1 = _round(value); 34163 }; 34164 34165 vars.onComplete = function () { 34166 getTween.tween = 0; 34167 onComplete && onComplete.call(tween); 34168 }; 34169 34170 tween = getTween.tween = gsap.to(scroller, vars); 34171 return tween; 34172 }; 34173 34174 scroller[prop] = getScroll; 34175 scroller.addEventListener("wheel", function () { 34176 return getTween.tween && getTween.tween.kill() && (getTween.tween = 0); 34177 }, { 34178 passive: true 34179 }); 34180 return getTween; 34181 }; 34182 34183 _horizontal.op = _vertical; 34184 var ScrollTrigger = function () { 34185 function ScrollTrigger(vars, animation) { 34186 _coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)"); 34187 this.init(vars, animation); 34188 } 34189 34190 var _proto = ScrollTrigger.prototype; 34191 34192 _proto.init = function init(vars, animation) { 34193 this.progress = this.start = 0; 34194 this.vars && this.kill(1); 34195 34196 if (!_enabled) { 34197 this.update = this.refresh = this.kill = _passThrough; 34198 return; 34199 } 34200 34201 vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? { 34202 trigger: vars 34203 } : vars, _defaults); 34204 34205 var _vars = vars,
34206 onUpdate = _vars.onUpdate, 34207 toggleClass = _vars.toggleClass, 34208 id = _vars.id, 34209 onToggle = _vars.onToggle, 34210 onRefresh = _vars.onRefresh, 34211 scrub = _vars.scrub, 34212 trigger = _vars.trigger, 34213 pin = _vars.pin, 34214 pinSpacing = _vars.pinSpacing, 34215 invalidateOnRefresh = _vars.invalidateOnRefresh, 34216 anticipatePin = _vars.anticipatePin, 34217 onScrubComplete = _vars.onScrubComplete, 34218 onSnapComplete = _vars.onSnapComplete, 34219 once = _vars.once, 34220 snap = _vars.snap, 34221 pinReparent = _vars.pinReparent, 34222 pinSpacer = _vars.pinSpacer, 34223 containerAnimation = _vars.containerAnimation, 34224 fastScrollEnd = _vars.fastScrollEnd, 34225 preventOverlaps = _vars.preventOverlaps, 34226 direction = vars.horizontal || vars.containerAnimation && vars.horizontal !== false ? _horizontal : _vertical, 34227 isToggle = !scrub && scrub !== 0, 34228 scroller = _getTarget(vars.scroller || _win), 34229 scrollerCache = gsap.core.getCache(scroller), 34230 isViewport = _isViewport(scroller), 34231 useFixedPosition = ("pinType" in vars ? vars.pinType : _getProxyProp(scroller, "pinType") || isViewport && "fixed") === "fixed", 34232 callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack], 34233 toggleActions = isToggle && vars.toggleActions.split(" "), 34234 markers = "markers" in vars ? vars.markers : _defaults.markers, 34235 borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0, 34236 self = this, 34237 onRefreshInit = vars.onRefreshInit && function () { 34238 return vars.onRefreshInit(self); 34239 }, 34240 getScrollerSize = _getSizeFunc(scroller, isViewport, direction), 34241 getScrollerOffsets = _getOffsetsFunc(scroller, isViewport), 34242 lastSnap = 0, 34243 scrollFunc = _getScrollFunc(scroller, direction), 34244 tweenTo, 34245 pinCache, 34246 snapFunc, 34247 scroll1, 34248 scroll2, 34249 start, 34250 end, 34251 markerStart, 34252 markerEnd, 34253 markerStartTrigger, 34254 markerEndTrigger, 34255 markerVars, 34256 change, 34257 pinOriginalState, 34258 pinActiveState, 34259 pinState, 34260 spacer, 34261 offset, 34262 pinGetter, 34263 pinSetter, 34264 pinStart, 34265 pinChange, 34266 spacingStart, 34267 spacerState, 34268 markerStartSetter, 34269 markerEndSetter, 34270 cs, 34271 snap1, 34272 snap2, 34273 scrubTween, 34274 scrubSmooth, 34275 snapDurClamp, 34276 snapDelayedCall, 34277 prevProgress, 34278 prevScroll, 34279 prevAnimProgress, 34280 caMarkerSetter; 34281 34282 self.media = _creatingMedia; 34283 anticipatePin *= 45; 34284 self.scroller = scroller; 34285 self.scroll = containerAnimation ? containerAnimation.time.bind(containerAnimation) : scrollFunc; 34286 scroll1 = scrollFunc(); 34287 self.vars = vars; 34288 animation = animation || vars.animation; 34289 "refreshPriority" in vars && (_sort = 1); 34290 scrollerCache.tweenScroll = scrollerCache.tweenScroll || { 34291 top: _getTweenCreator(scroller, _vertical), 34292 left: _getTweenCreator(scroller, _horizontal) 34293 }; 34294 self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p]; 34295 34296 if (animation) { 34297 animation.vars.lazy = false; 34298 animation._initted || animation.vars.immediateRender !== false && vars.immediateRender !== false && animation.render(0, true, true); 34299 self.animation = animation.pause(); 34300 animation.scrollTrigger = self; 34301 scrubSmooth = _isNumber(scrub) && scrub; 34302 scrubSmooth && (scrubTween = gsap.to(animation, { 34303 ease: "power3", 34304 duration: scrubSmooth, 34305 onComplete: function onComplete() { 34306 return onScrubComplete && onScrubComplete(self); 34307 } 34308 })); 34309 snap1 = 0; 34310 id || (id = animation.vars.id); 34311 } 34312 34313 _triggers.push(self); 34314 34315 if (snap) { 34316 if (!_isObject(snap) || snap.push) { 34317 snap = { 34318 snapTo: snap 34319 }; 34320 } 34321 34322 "scrollBehavior" in _body.style && gsap.set(isViewport ? [_body, _docEl] : scroller, { 34323 scrollBehavior: "auto" 34324 }); 34325 snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getClosestLabel(animation) : snap.snapTo === "labelsDirectional" ? _getLabelAtDirection(animation) : snap.directional !== false ? function (value, st) { 34326 return _snapDirectional(snap.snapTo)(value, st.direction); 34327 } : gsap.utils.snap(snap.snapTo); 34328 snapDurClamp = snap.duration || { 34329 min: 0.1, 34330 max: 2 34331 }; 34332 snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp); 34333 snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () { 34334 if (Math.abs(self.getVelocity()) < 10 && !_pointerIsDown && lastSnap !== scrollFunc()) { 34335 var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress, 34336 velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0, 34337 change1 = gsap.utils.clamp(-self.progress, 1 - self.progress, _abs(velocity / 2) * velocity / 0.185), 34338 naturalEnd = self.progress + (snap.inertia === false ? 0 : change1), 34339 endValue = _clamp(0, 1, snapFunc(naturalEnd, self)), 34340 scroll = scrollFunc(), 34341 endScroll = Math.round(start + endValue * change), 34342 _snap = snap, 34343 onStart = _snap.onStart, 34344 _onInterrupt = _snap.onInterrupt, 34345 _onComplete = _snap.onComplete, 34346 tween = tweenTo.tween; 34347 34348 if (scroll <= end && scroll >= start && endScroll !== scroll) { 34349 if (tween && !tween._initted && tween.data <= _abs(endScroll - scroll)) { 34350 return; 34351 } 34352 34353 if (snap.inertia === false) { 34354 change1 = endValue - self.progress; 34355 } 34356 34357 tweenTo(endScroll, { 34358 duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)), 34359 ease: snap.ease || "power3", 34360 data: _abs(endScroll - scroll), 34361 onInterrupt: function onInterrupt() { 34362 return snapDelayedCall.restart(true) && _onInterrupt && _onInterrupt(self); 34363 }, 34364 onComplete: function onComplete() { 34365 lastSnap = scrollFunc(); 34366 snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress; 34367 onSnapComplete && onSnapComplete(self); 34368 _onComplete && _onComplete(self); 34369 } 34370 }, scroll, change1 * change, endScroll - scroll - change1 * change); 34371 onStart && onStart(self, tweenTo.tween); 34372 } 34373 } else if (self.isActive) { 34374 snapDelayedCall.restart(true); 34375 } 34376 }).pause(); 34377 } 34378 34379 id && (_ids[id] = self); 34380 trigger = self.trigger = _getTarget(trigger || pin); 34381 pin = pin === true ? trigger : _getTarget(pin); 34382 _isString(toggleClass) && (toggleClass = { 34383 targets: trigger, 34384 className: toggleClass 34385 }); 34386 34387 if (pin) { 34388 pinSpacing === false || pinSpacing === _margin || (pinSpacing = !pinSpacing && _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding); 34389 self.pin = pin; 34390 vars.force3D !== false && gsap.set(pin, {
34391 force3D: true 34392 }); 34393 pinCache = gsap.core.getCache(pin); 34394 34395 if (!pinCache.spacer) { 34396 if (pinSpacer) { 34397 pinSpacer = _getTarget(pinSpacer); 34398 pinSpacer && !pinSpacer.nodeType && (pinSpacer = pinSpacer.current || pinSpacer.nativeElement); 34399 pinCache.spacerIsNative = !!pinSpacer; 34400 pinSpacer && (pinCache.spacerState = _getState(pinSpacer)); 34401 } 34402 34403 pinCache.spacer = spacer = pinSpacer || _doc.createElement("div"); 34404 spacer.classList.add("pin-spacer"); 34405 id && spacer.classList.add("pin-spacer-" + id); 34406 pinCache.pinState = pinOriginalState = _getState(pin); 34407 } else { 34408 pinOriginalState = pinCache.pinState; 34409 } 34410 34411 self.spacer = spacer = pinCache.spacer; 34412 cs = _getComputedStyle(pin); 34413 spacingStart = cs[pinSpacing + direction.os2]; 34414 pinGetter = gsap.getProperty(pin); 34415 pinSetter = gsap.quickSetter(pin, direction.a, _px); 34416 34417 _swapPinIn(pin, spacer, cs); 34418 34419 pinState = _getState(pin); 34420 } 34421 34422 if (markers) { 34423 markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults; 34424 markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0); 34425 markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger); 34426 offset = markerStartTrigger["offset" + direction.op.d2]; 34427 markerStart = _createMarker("start", id, scroller, direction, markerVars, offset, 0, containerAnimation); 34428 markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset, 0, containerAnimation); 34429 containerAnimation && (caMarkerSetter = gsap.quickSetter([markerStart, markerEnd], direction.a, _px)); 34430 34431 if (!useFixedPosition && !(_proxies.length && _getProxyProp(scroller, "fixedMarkers") === true)) { 34432 _makePositionable(isViewport ? _body : scroller); 34433 34434 gsap.set([markerStartTrigger, markerEndTrigger], { 34435 force3D: true 34436 }); 34437 markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px); 34438 markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px); 34439 } 34440 } 34441 34442 if (containerAnimation) { 34443 var oldOnUpdate = containerAnimation.vars.onUpdate, 34444 oldParams = containerAnimation.vars.onUpdateParams; 34445 containerAnimation.eventCallback("onUpdate", function () { 34446 self.update(0, 0, 1); 34447 oldOnUpdate && oldOnUpdate.apply(oldParams || []); 34448 }); 34449 } 34450 34451 self.previous = function () { 34452 return _triggers[_triggers.indexOf(self) - 1]; 34453 }; 34454 34455 self.next = function () { 34456 return _triggers[_triggers.indexOf(self) + 1]; 34457 }; 34458 34459 self.revert = function (revert) { 34460 var r = revert !== false || !self.enabled, 34461 prevRefreshing = _refreshing; 34462 34463 if (r !== self.isReverted) { 34464 if (r) { 34465 self.scroll.rec || (self.scroll.rec = scrollFunc()); 34466 prevScroll = Math.max(scrollFunc(), self.scroll.rec || 0); 34467 prevProgress = self.progress; 34468 prevAnimProgress = animation && animation.progress(); 34469 } 34470 34471 markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) { 34472 return m.style.display = r ? "none" : "block"; 34473 }); 34474 r && (_refreshing = 1); 34475 self.update(r); 34476 _refreshing = prevRefreshing; 34477 pin && (r ? _swapPinOut(pin, spacer, pinOriginalState) : (!pinReparent || !self.isActive) && _swapPinIn(pin, spacer, _getComputedStyle(pin), spacerState)); 34478 self.isReverted = r; 34479 } 34480 }; 34481 34482 self.refresh = function (soft, force) { 34483 if ((_refreshing || !self.enabled) && !force) { 34484 return; 34485 } 34486 34487 if (pin && soft && _lastScrollTime) { 34488 _addListener(ScrollTrigger, "scrollEnd", _softRefresh); 34489 34490 return; 34491 } 34492 34493 _refreshing = 1; 34494 scrubTween && scrubTween.pause(); 34495 invalidateOnRefresh && animation && animation.progress(0).invalidate(); 34496 self.isReverted || self.revert(); 34497 34498 var size = getScrollerSize(), 34499 scrollerBounds = getScrollerOffsets(),
34500 max = containerAnimation ? containerAnimation.duration() : _maxScroll(scroller, direction), 34501 offset = 0, 34502 otherPinOffset = 0, 34503 parsedEnd = vars.end, 34504 parsedEndTrigger = vars.endTrigger || trigger, 34505 parsedStart = vars.start || (vars.start === 0 || !trigger ? 0 : pin ? "0 0" : "0 100%"), 34506 pinnedContainer = vars.pinnedContainer && _getTarget(vars.pinnedContainer), 34507 triggerIndex = trigger && Math.max(0, _triggers.indexOf(self)) || 0, 34508 i = triggerIndex, 34509 cs, 34510 bounds, 34511 scroll, 34512 isVertical, 34513 override, 34514 curTrigger, 34515 curPin, 34516 oppositeScroll, 34517 initted, 34518 revertedPins; 34519 34520 while (i--) { 34521 curTrigger = _triggers[i]; 34522 curTrigger.end || curTrigger.refresh(0, 1) || (_refreshing = 1); 34523 curPin = curTrigger.pin; 34524 34525 if (curPin && (curPin === trigger || curPin === pin) && !curTrigger.isReverted) { 34526 revertedPins || (revertedPins = []); 34527 revertedPins.unshift(curTrigger); 34528 curTrigger.revert(); 34529 } 34530 } 34531 34532 _isFunction(parsedStart) && (parsedStart = parsedStart(self)); 34533 start = _parsePosition(parsedStart, trigger, size, direction, scrollFunc(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, useFixedPosition, max, containerAnimation) || (pin ? -0.001 : 0); 34534 _isFunction(parsedEnd) && (parsedEnd = parsedEnd(self)); 34535 34536 if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) { 34537 if (~parsedEnd.indexOf(" ")) { 34538 parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd; 34539 } else { 34540 offset = _offsetToPx(parsedEnd.substr(2), size); 34541 parsedEnd = _isString(parsedStart) ? parsedStart : start + offset; 34542 parsedEndTrigger = trigger; 34543 } 34544 } 34545 34546 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; 34547 change = end - start || (start -= 0.01) && 0.001; 34548 offset = 0; 34549 i = triggerIndex; 34550 34551 while (i--) { 34552 curTrigger = _triggers[i]; 34553 curPin = curTrigger.pin; 34554 34555 if (curPin && curTrigger.start - curTrigger._pinPush < start && !containerAnimation) { 34556 cs = curTrigger.end - curTrigger.start; 34557 (curPin === trigger || curPin === pinnedContainer) && !_isNumber(parsedStart) && (offset += cs); 34558 curPin === pin && (otherPinOffset += cs); 34559 } 34560 } 34561 34562 start += offset; 34563 end += offset; 34564 self._pinPush = otherPinOffset; 34565 34566 if (markerStart && offset) { 34567 cs = {}; 34568 cs[direction.a] = "+=" + offset; 34569 pinnedContainer && (cs[direction.p] = "-=" + scrollFunc()); 34570 gsap.set([markerStart, markerEnd], cs); 34571 } 34572 34573 if (pin) { 34574 cs = _getComputedStyle(pin); 34575 isVertical = direction === _vertical; 34576 scroll = scrollFunc(); 34577 pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset; 34578 !max && end > 1 && ((isViewport ? _body : scroller).style["overflow-" + direction.a] = "scroll"); 34579 34580 _swapPinIn(pin, spacer, cs); 34581 34582 pinState = _getState(pin); 34583 bounds = _getBounds(pin, true); 34584 oppositeScroll = useFixedPosition && _getScrollFunc(scroller, isVertical ? _horizontal : _vertical)(); 34585 34586 if (pinSpacing) { 34587 spacerState = [pinSpacing + direction.os2, change + otherPinOffset + _px]; 34588 spacerState.t = spacer; 34589 i = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0; 34590 i && spacerState.push(direction.d, i + _px); 34591 34592 _setState(spacerState); 34593 34594 useFixedPosition && scrollFunc(prevScroll); 34595 } 34596 34597 if (useFixedPosition) { 34598 override = { 34599 top: bounds.top + (isVertical ? scroll - start : oppositeScroll) + _px, 34600 left: bounds.left + (isVertical ? oppositeScroll : scroll - start) + _px, 34601 boxSizing: "border-box", 34602 position: "fixed" 34603 }; 34604 override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px; 34605 override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px; 34606 override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0"; 34607 override[_padding] = cs[_padding]; 34608 override[_padding + _Top] = cs[_padding + _Top]; 34609 override[_padding + _Right] = cs[_padding + _Right]; 34610 override[_padding + _Bottom] = cs[_padding + _Bottom]; 34611 override[_padding + _Left] = cs[_padding + _Left]; 34612 pinActiveState = _copyState(pinOriginalState, override, pinReparent); 34613 } 34614 34615 if (animation) { 34616 initted = animation._initted; 34617 34618 _suppressOverwrites(1); 34619 34620 animation.render(animation.duration(), true, true); 34621 pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset; 34622 change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2); 34623 animation.render(0, true, true); 34624 initted || animation.invalidate(); 34625 34626 _suppressOverwrites(0); 34627 } else { 34628 pinChange = change; 34629 } 34630 } else if (trigger && scrollFunc() && !containerAnimation) { 34631 bounds = trigger.parentNode; 34632 34633 while (bounds && bounds !== _body) { 34634 if (bounds._pinOffset) { 34635 start -= bounds._pinOffset; 34636 end -= bounds._pinOffset; 34637 } 34638 34639 bounds = bounds.parentNode; 34640 } 34641 } 34642 34643 revertedPins && revertedPins.forEach(function (t) { 34644 return t.revert(false); 34645 }); 34646 self.start = start; 34647 self.end = end; 34648 scroll1 = scroll2 = scrollFunc(); 34649 34650 if (!containerAnimation) { 34651 scroll1 < prevScroll && scrollFunc(prevScroll); 34652 self.scroll.rec = 0; 34653 } 34654 34655 self.revert(false); 34656 _refreshing = 0; 34657 animation && isToggle && animation._initted && animation.progress() !== prevAnimProgress && animation.progress(prevAnimProgress, true).render(animation.time(), true, true); 34658 34659 if (prevProgress !== self.progress) { 34660 animation && !isToggle && animation.totalProgress(prevProgress, true); 34661 self.progress = prevProgress; 34662 self.update(0, 0, 1); 34663 } 34664 34665 pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange)); 34666 onRefresh && onRefresh(self); 34667 }; 34668 34669 self.getVelocity = function () { 34670 return (scrollFunc() - scroll2) / (_getTime() - _time2) * 1000 || 0; 34671 }; 34672 34673 self.endAnimation = function () {
vendor: 8,601 bytes, lines 34674-34912
34674 _endAnimation(self.callbackAnimation); 34675 34676 if (animation) { 34677 scrubTween ? scrubTween.progress(1) : !animation.paused() ? _endAnimation(animation, animation.reversed()) : isToggle || _endAnimation(animation, self.direction < 0, 1); 34678 } 34679 }; 34680 34681 self.getTrailing = function (name) { 34682 var i = _triggers.indexOf(self), 34683 a = self.direction > 0 ? _triggers.slice(0, i).reverse() : _triggers.slice(i + 1); 34684 34685 return _isString(name) ? a.filter(function (t) { 34686 return t.vars.preventOverlaps === name; 34687 }) : a; 34688 }; 34689 34690 self.update = function (reset, recordVelocity, forceFake) { 34691 if (containerAnimation && !forceFake && !reset) { 34692 return; 34693 } 34694 34695 var scroll = self.scroll(), 34696 p = reset ? 0 : (scroll - start) / change, 34697 clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0, 34698 prevProgress = self.progress, 34699 isActive, 34700 wasActive, 34701 toggleState, 34702 action, 34703 stateChanged, 34704 toggled, 34705 isAtMax, 34706 isTakingAction; 34707 34708 if (recordVelocity) { 34709 scroll2 = scroll1; 34710 scroll1 = containerAnimation ? scrollFunc() : scroll; 34711 34712 if (snap) { 34713 snap2 = snap1; 34714 snap1 = animation && !isToggle ? animation.totalProgress() : clipped; 34715 } 34716 } 34717 34718 anticipatePin && !clipped && pin && !_refreshing && !_startup && _lastScrollTime && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001); 34719 34720 if (clipped !== prevProgress && self.enabled) { 34721 isActive = self.isActive = !!clipped && clipped < 1; 34722 wasActive = !!prevProgress && prevProgress < 1; 34723 toggled = isActive !== wasActive; 34724 stateChanged = toggled || !!clipped !== !!prevProgress; 34725 self.direction = clipped > prevProgress ? 1 : -1; 34726 self.progress = clipped; 34727 34728 if (stateChanged && !_refreshing) { 34729 toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3; 34730 34731 if (isToggle) { 34732 action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState]; 34733 isTakingAction = animation && (action === "complete" || action === "reset" || action in animation); 34734 } 34735 } 34736 34737 preventOverlaps && toggled && (isTakingAction || scrub || !animation) && (_isFunction(preventOverlaps) ? preventOverlaps(self) : self.getTrailing(preventOverlaps).forEach(function (t) { 34738 return t.endAnimation(); 34739 })); 34740 34741 if (!isToggle) { 34742 if (scrubTween && !_refreshing && !_startup) { 34743 scrubTween.vars.totalProgress = clipped; 34744 scrubTween.invalidate().restart(); 34745 } else if (animation) { 34746 animation.totalProgress(clipped, !!_refreshing); 34747 } 34748 } 34749 34750 if (pin) { 34751 reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart); 34752 34753 if (!useFixedPosition) { 34754 pinSetter(pinStart + pinChange * clipped); 34755 } else if (stateChanged) { 34756 isAtMax = !reset && clipped > prevProgress && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction); 34757 34758 if (pinReparent) { 34759 if (!reset && (isActive || isAtMax)) { 34760 var bounds = _getBounds(pin, true), 34761 _offset = scroll - start; 34762 34763 _reparent(pin, _body, bounds.top + (direction === _vertical ? _offset : 0) + _px, bounds.left + (direction === _vertical ? 0 : _offset) + _px); 34764 } else { 34765 _reparent(pin, spacer); 34766 } 34767 } 34768 34769 _setState(isActive || isAtMax ? pinActiveState : pinState); 34770 34771 pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !isAtMax ? pinChange : 0)); 34772 } 34773 } 34774 34775 snap && !tweenTo.tween && !_refreshing && !_startup && snapDelayedCall.restart(true); 34776 toggleClass && (toggled || once && clipped && (clipped < 1 || !_limitCallbacks)) && _toArray(toggleClass.targets).forEach(function (el) { 34777 return el.classList[isActive || once ? "add" : "remove"](toggleClass.className); 34778 }); 34779 onUpdate && !isToggle && !reset && onUpdate(self); 34780 34781 if (stateChanged && !_refreshing) { 34782 if (isToggle) { 34783 if (isTakingAction) { 34784 if (action === "complete") { 34785 animation.pause().totalProgress(1); 34786 } else if (action === "reset") { 34787 animation.restart(true).pause(); 34788 } else if (action === "restart") { 34789 animation.restart(true); 34790 } else { 34791 animation[action](); 34792 } 34793 } 34794 34795 onUpdate && onUpdate(self); 34796 } 34797 34798 if (toggled || !_limitCallbacks) { 34799 onToggle && toggled && _callback(self, onToggle); 34800 callbacks[toggleState] && _callback(self, callbacks[toggleState]); 34801 once && (clipped === 1 ? self.kill(false, 1) : callbacks[toggleState] = 0); 34802 34803 if (!toggled) { 34804 toggleState = clipped === 1 ? 1 : 3; 34805 callbacks[toggleState] && _callback(self, callbacks[toggleState]); 34806 } 34807 } 34808 34809 if (fastScrollEnd && !isActive && Math.abs(self.getVelocity()) > (_isNumber(fastScrollEnd) ? fastScrollEnd : 2500)) { 34810 _endAnimation(self.callbackAnimation); 34811 34812 scrubTween ? scrubTween.progress(1) : _endAnimation(animation, !clipped, 1); 34813 } 34814 } else if (isToggle && onUpdate && !_refreshing) { 34815 onUpdate(self); 34816 } 34817 } 34818 34819 if (markerEndSetter) { 34820 var n = containerAnimation ? scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0) : scroll; 34821 markerStartSetter(n + (markerStartTrigger._isFlipped ? 1 : 0)); 34822 markerEndSetter(n); 34823 } 34824 34825 caMarkerSetter && caMarkerSetter(-scroll / containerAnimation.duration() * (containerAnimation._caScrollDist || 0)); 34826 }; 34827 34828 self.enable = function (reset, refresh) { 34829 if (!self.enabled) { 34830 self.enabled = true; 34831 34832 _addListener(scroller, "resize", _onResize); 34833 34834 _addListener(scroller, "scroll", _onScroll); 34835 34836 onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit); 34837 34838 if (reset !== false) { 34839 self.progress = prevProgress = 0; 34840 scroll1 = scroll2 = lastSnap = scrollFunc(); 34841 } 34842 34843 refresh !== false && self.refresh(); 34844 } 34845 }; 34846 34847 self.getTween = function (snap) { 34848 return snap && tweenTo ? tweenTo.tween : scrubTween; 34849 }; 34850 34851 self.disable = function (reset, allowAnimation) { 34852 if (self.enabled) { 34853 reset !== false && self.revert(); 34854 self.enabled = self.isActive = false; 34855 allowAnimation || scrubTween && scrubTween.pause(); 34856 prevScroll = 0; 34857 pinCache && (pinCache.uncache = 1); 34858 onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit); 34859 34860 if (snapDelayedCall) { 34861 snapDelayedCall.pause(); 34862 tweenTo.tween && tweenTo.tween.kill() && (tweenTo.tween = 0); 34863 } 34864 34865 if (!isViewport) { 34866 var i = _triggers.length; 34867 34868 while (i--) { 34869 if (_triggers[i].scroller === scroller && _triggers[i] !== self) { 34870 return; 34871 } 34872 } 34873 34874 _removeListener(scroller, "resize", _onResize); 34875 34876 _removeListener(scroller, "scroll", _onScroll); 34877 } 34878 } 34879 }; 34880 34881 self.kill = function (revert, allowAnimation) { 34882 self.disable(revert, allowAnimation); 34883 scrubTween && scrubTween.kill(); 34884 id && delete _ids[id]; 34885 34886 var i = _triggers.indexOf(self); 34887 34888 _triggers.splice(i, 1); 34889 34890 i === _i && _direction > 0 && _i--; 34891 i = 0; 34892 34893 _triggers.forEach(function (t) { 34894 return t.scroller === self.scroller && (i = 1); 34895 }); 34896 34897 i || (self.scroll.rec = 0); 34898 34899 if (animation) { 34900 animation.scrollTrigger = null; 34901 revert && animation.render(-1); 34902 allowAnimation || animation.kill(); 34903 } 34904 34905 markerStart && [markerStart, markerEnd, markerStartTrigger, markerEndTrigger].forEach(function (m) { 34906 return m.parentNode && m.parentNode.removeChild(m); 34907 }); 34908 34909 if (pin) { 34910 pinCache && (pinCache.uncache = 1); 34911 i = 0; 34912
34913 _triggers.forEach(function (t) { 34914 return t.pin === pin && i++; 34915 }); 34916 34917 i || (pinCache.spacer = 0); 34918 } 34919 }; 34920 34921 self.enable(false, false); 34922 !animation || !animation.add || change ? self.refresh() : gsap.delayedCall(0.01, function () { 34923 return start || end || self.refresh(); 34924 }) && (change = 0.01) && (start = end = 0); 34925 }; 34926 34927 ScrollTrigger.register = function register(core) { 34928 if (!_coreInitted) { 34929 gsap = core || _getGSAP(); 34930 34931 if (_windowExists() && window.document) { 34932 _win = window; 34933 _doc = document; 34934 _docEl = _doc.documentElement; 34935 _body = _doc.body; 34936 } 34937 34938 if (gsap) { 34939 _toArray = gsap.utils.toArray; 34940 _clamp = gsap.utils.clamp; 34941 _suppressOverwrites = gsap.core.suppressOverwrites || _passThrough; 34942 gsap.core.globals("ScrollTrigger", ScrollTrigger); 34943 34944 if (_body) { 34945 _raf = _win.requestAnimationFrame || function (f) { 34946 return setTimeout(f, 16); 34947 }; 34948 34949 _addListener(_win, "wheel", _onScroll); 34950 34951 _root = [_win, _doc, _docEl, _body]; 34952 34953 _addListener(_doc, "scroll", _onScroll); 34954 34955 var bodyStyle = _body.style, 34956 border = bodyStyle.borderTopStyle, 34957 bounds; 34958 bodyStyle.borderTopStyle = "solid"; 34959 bounds = _getBounds(_body); 34960 _vertical.m = Math.round(bounds.top + _vertical.sc()) || 0; 34961 _horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0; 34962 border ? bodyStyle.borderTopStyle = border : bodyStyle.removeProperty("border-top-style"); 34963 _syncInterval = setInterval(_sync, 200); 34964 gsap.delayedCall(0.5, function () { 34965 return _startup = 0; 34966 }); 34967 34968 _addListener(_doc, "touchcancel", _passThrough); 34969 34970 _addListener(_body, "touchstart", _passThrough); 34971 34972 _multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () { 34973 return _pointerIsDown = 1; 34974 }); 34975 34976 _multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () { 34977 return _pointerIsDown = 0; 34978 }); 34979 34980 _transformProp = gsap.utils.checkPrefix("transform"); 34981 34982 _stateProps.push(_transformProp); 34983 34984 _coreInitted = _getTime(); 34985 _resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause(); 34986 _autoRefresh = [_doc, "visibilitychange", function () { 34987 var w = _win.innerWidth, 34988 h = _win.innerHeight; 34989 34990 if (_doc.hidden) { 34991 _prevWidth = w; 34992 _prevHeight = h; 34993 } else if (_prevWidth !== w || _prevHeight !== h) { 34994 _onResize(); 34995 } 34996 }, _doc, "DOMContentLoaded", _refreshAll, _win, "load", function () { 34997 return _lastScrollTime || _refreshAll(); 34998 }, _win, "resize", _onResize]; 34999 35000 _iterateAutoRefresh(_addListener); 35001 } 35002 } 35003 } 35004 35005 return _coreInitted; 35006 }; 35007 35008 ScrollTrigger.defaults = function defaults(config) { 35009 for (var p in config) { 35010 _defaults[p] = config[p]; 35011 } 35012 }; 35013 35014 ScrollTrigger.kill = function kill() { 35015 _enabled = 0; 35016 35017 _triggers.slice(0).forEach(function (trigger) { 35018 return trigger.kill(1); 35019 }); 35020 }; 35021 35022 ScrollTrigger.config = function config(vars) { 35023 "limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks); 35024 var ms = vars.syncInterval; 35025 ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms); 35026 35027 if ("autoRefreshEvents" in vars) { 35028 _iterateAutoRefresh(_removeListener) || _iterateAutoRefresh(_addListener, vars.autoRefreshEvents || "none"); 35029 _ignoreResize = (vars.autoRefreshEvents + "").indexOf("resize") === -1; 35030 } 35031 }; 35032 35033 ScrollTrigger.scrollerProxy = function scrollerProxy(target, vars) { 35034 var t = _getTarget(target), 35035 i = _scrollers.indexOf(t), 35036 isViewport = _isViewport(t); 35037 35038 if (~i) { 35039 _scrollers.splice(i, isViewport ? 6 : 2); 35040 } 35041 35042 isViewport ? _proxies.unshift(_win, vars, _body, vars, _docEl, vars) : _proxies.unshift(t, vars); 35043 }; 35044 35045 ScrollTrigger.matchMedia = function matchMedia(vars) { 35046 var mq, p, i, func, result; 35047 35048 for (p in vars) { 35049 i = _media.indexOf(p); 35050 func = vars[p]; 35051 _creatingMedia = p; 35052 35053 if (p === "all") { 35054 func(); 35055 } else { 35056 mq = _win.matchMedia(p); 35057 35058 if (mq) { 35059 mq.matches && (result = func()); 35060 35061 if (~i) { 35062 _media[i + 1] = _combineFunc(_media[i + 1], func); 35063 _media[i + 2] = _combineFunc(_media[i + 2], result); 35064 } else { 35065 i = _media.length; 35066 35067 _media.push(p, func, result); 35068 35069 mq.addListener ? mq.addListener(_onMediaChange) : mq.addEventListener("change", _onMediaChange); 35070 } 35071 35072 _media[i + 3] = mq.matches; 35073 } 35074 } 35075 35076 _creatingMedia = 0; 35077 } 35078 35079 return _media; 35080 }; 35081 35082 ScrollTrigger.clearMatchMedia = function clearMatchMedia(query) { 35083 query || (_media.length = 0); 35084 query = _media.indexOf(query); 35085 query >= 0 && _media.splice(query, 4); 35086 }; 35087 35088 ScrollTrigger.isInViewport = function isInViewport(element, ratio, horizontal) { 35089 var bounds = (_isString(element) ? _getTarget(element) : element).getBoundingClientRect(), 35090 offset = bounds[horizontal ? _width : _height] * ratio || 0; 35091 return horizontal ? bounds.right - offset > 0 && bounds.left + offset < _win.innerWidth : bounds.bottom - offset > 0 && bounds.top + offset < _win.innerHeight; 35092 }; 35093 35094 ScrollTrigger.positionInViewport = function positionInViewport(element, referencePoint, horizontal) { 35095 _isString(element) && (element = _getTarget(element)); 35096 var bounds = element.getBoundingClientRect(), 35097 size = bounds[horizontal ? _width : _height], 35098 offset = referencePoint == null ? size / 2 : referencePoint in _keywords ? _keywords[referencePoint] * size : ~referencePoint.indexOf("%") ? parseFloat(referencePoint) * size / 100 : parseFloat(referencePoint) || 0; 35099 return horizontal ? (bounds.left + offset) / _win.innerWidth : (bounds.top + offset) / _win.innerHeight; 35100 }; 35101 35102 return ScrollTrigger; 35103 }(); 35104 ScrollTrigger.version = "3.8.0"; 35105 35106 ScrollTrigger.saveStyles = function (targets) {
35107 return targets ? _toArray(targets).forEach(function (target) { 35108 if (target && target.style) { 35109 var i = _savedStyles.indexOf(target); 35110 35111 i >= 0 && _savedStyles.splice(i, 5); 35112 35113 _savedStyles.push(target, target.style.cssText, target.getBBox && target.getAttribute("transform"), gsap.core.getCache(target), _creatingMedia); 35114 } 35115 }) : _savedStyles; 35116 }; 35117 35118 ScrollTrigger.revert = function (soft, media) { 35119 return _revertAll(!soft, media); 35120 }; 35121 35122 ScrollTrigger.create = function (vars, animation) { 35123 return new ScrollTrigger(vars, animation); 35124 }; 35125 35126 ScrollTrigger.refresh = function (safe) { 35127 return safe ? _onResize() : (_coreInitted || ScrollTrigger.register()) && _refreshAll(true); 35128 }; 35129 35130 ScrollTrigger.update = _updateAll; 35131 ScrollTrigger.clearScrollMemory = _clearScrollMemory; 35132 35133 ScrollTrigger.maxScroll = function (element, horizontal) { 35134 return _maxScroll(element, horizontal ? _horizontal : _vertical); 35135 }; 35136 35137 ScrollTrigger.getScrollFunc = function (element, horizontal) { 35138 return _getScrollFunc(_getTarget(element), horizontal ? _horizontal : _vertical); 35139 }; 35140 35141 ScrollTrigger.getById = function (id) { 35142 return _ids[id]; 35143 }; 35144 35145 ScrollTrigger.getAll = function () { 35146 return _triggers.slice(0); 35147 }; 35148 35149 ScrollTrigger.isScrolling = function () { 35150 return !!_lastScrollTime; 35151 }; 35152 35153 ScrollTrigger.snapDirectional = _snapDirectional; 35154 35155 ScrollTrigger.addEventListener = function (type, callback) { 35156 var a = _listeners[type] || (_listeners[type] = []); 35157 ~a.indexOf(callback) || a.push(callback); 35158 }; 35159 35160 ScrollTrigger.removeEventListener = function (type, callback) { 35161 var a = _listeners[type], 35162 i = a && a.indexOf(callback); 35163 i >= 0 && a.splice(i, 1); 35164 }; 35165 35166 ScrollTrigger.batch = function (targets, vars) { 35167 var result = [], 35168 varsCopy = {}, 35169 interval = vars.interval || 0.016, 35170 batchMax = vars.batchMax || 1e9, 35171 proxyCallback = function proxyCallback(type, callback) { 35172 var elements = [], 35173 triggers = [], 35174 delay = gsap.delayedCall(interval, function () { 35175 callback(elements, triggers); 35176 elements = []; 35177 triggers = []; 35178 }).pause(); 35179 return function (self) { 35180 elements.length || delay.restart(true); 35181 elements.push(self.trigger); 35182 triggers.push(self); 35183 batchMax <= elements.length && delay.progress(1); 35184 }; 35185 }, 35186 p; 35187 35188 for (p in vars) { 35189 varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p]; 35190 } 35191 35192 if (_isFunction(batchMax)) { 35193 batchMax = batchMax(); 35194 35195 _addListener(ScrollTrigger, "refresh", function () { 35196 return batchMax = vars.batchMax(); 35197 }); 35198 } 35199 35200 _toArray(targets).forEach(function (target) { 35201 var config = {}; 35202 35203 for (p in varsCopy) { 35204 config[p] = varsCopy[p]; 35205 } 35206 35207 config.trigger = target; 35208 result.push(ScrollTrigger.create(config)); 35209 }); 35210 35211 return result; 35212 }; 35213 35214 ScrollTrigger.sort = function (func) { 35215 return _triggers.sort(func || function (a, b) { 35216 return (a.vars.refreshPriority || 0) * -1e6 + a.start - (b.start + (b.vars.refreshPriority || 0) * -1e6); 35217 }); 35218 }; 35219 35220 _getGSAP() && gsap.registerPlugin(ScrollTrigger); 35221 35222 exports.ScrollTrigger = ScrollTrigger; 35223 exports.default = ScrollTrigger; 35224 35225 Object.defineProperty(exports, '__esModule', { value: true }); 35226 35227}))); 35228 35229/* ======================================================================== 35230 * Bootstrap: collapse.js v3.1.1 35231 * http://getbootstrap.com/javascript/#collapse 35232 * ======================================================================== 35233 * Copyright 2011-2014 Twitter, Inc. 35234 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 35235 * ======================================================================== */ 35236 35237 35238+function ($) { 35239 'use strict'; 35240 35241 // COLLAPSE PUBLIC CLASS DEFINITION 35242 // ================================ 35243 35244 var Collapse = function (element, options) { 35245 this.$element = $(element) 35246 this.options = $.extend({}, Collapse.DEFAULTS, options) 35247 this.transitioning = null 35248 35249 if (this.options.parent) this.$parent = $(this.options.parent) 35250 if (this.options.toggle) this.toggle() 35251 } 35252 35253 Collapse.DEFAULTS = { 35254 toggle: true 35255 } 35256 35257 Collapse.prototype.dimension = function () { 35258 var hasWidth = this.$element.hasClass('width') 35259 return hasWidth ? 'width' : 'height' 35260 } 35261 35262 Collapse.prototype.show = function () { 35263 if (this.transitioning || this.$element.hasClass('in')) return 35264 35265 var startEvent = $.Event('show.bs.collapse') 35266 this.$element.trigger(startEvent) 35267 if (startEvent.isDefaultPrevented()) return 35268 35269 var actives = this.$parent && this.$parent.find('> .panel > .in') 35270 35271 if (actives && actives.length) { 35272 var hasData = actives.data('bs.collapse') 35273 if (hasData && hasData.transitioning) return 35274 actives.collapse('hide') 35275 hasData || actives.data('bs.collapse', null) 35276 } 35277 35278 var dimension = this.dimension() 35279 35280 this.$element 35281 .removeClass('collapse') 35282 .addClass('collapsing')[dimension](0) 35283 35284 this.transitioning = 1 35285 35286 var complete = function (e) { 35287 if (e && e.target != this.$element[0]) return 35288 this.$element 35289 .removeClass('collapsing') 35290 .addClass('collapse in')[dimension]('auto') 35291 this.transitioning = 0 35292 this.$element.trigger('shown.bs.collapse') 35293 } 35294 35295 if (!$.support.transition) return complete.call(this) 35296 35297 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 35298 35299 this.$element 35300 .one($.support.transition.end, $.proxy(complete, this)) 35301 .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) 35302 } 35303 35304 Collapse.prototype.hide = function () { 35305 if (this.transitioning || !this.$element.hasClass('in')) return 35306 35307 var startEvent = $.Event('hide.bs.collapse') 35308 this.$element.trigger(startEvent) 35309 if (startEvent.isDefaultPrevented()) return 35310 35311 var dimension = this.dimension() 35312 35313 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 35314 35315 this.$element 35316 .addClass('collapsing') 35317 .removeClass('collapse') 35318 .removeClass('in') 35319 35320 this.transitioning = 1 35321 35322 var complete = function (e) { 35323 if (e && e.target != this.$element[0]) return 35324 this.transitioning = 0 35325 this.$element 35326 .trigger('hidden.bs.collapse') 35327 .removeClass('collapsing') 35328 .addClass('collapse') 35329 } 35330 35331 if (!$.support.transition) return complete.call(this) 35332 35333 this.$element 35334 [dimension](0) 35335 .one($.support.transition.end, $.proxy(complete, this)) 35336 .emulateTransitionEnd(350) 35337 } 35338 35339 Collapse.prototype.toggle = function () { 35340 this[this.$element.hasClass('in') ? 'hide' : 'show']() 35341 } 35342 35343 35344 // COLLAPSE PLUGIN DEFINITION 35345 // ========================== 35346 35347 var old = $.fn.collapse 35348 35349 $.fn.collapse = function (option) { 35350 return this.each(function () { 35351 var $this = $(this) 35352 var data = $this.data('bs.collapse') 35353 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 35354 35355 if (!data && options.toggle && option == 'show') option = !option 35356 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 35357 if (typeof option == 'string') data[option]() 35358 }) 35359 } 35360 35361 $.fn.collapse.Constructor = Collapse 35362 35363 35364 // COLLAPSE NO CONFLICT 35365 // ==================== 35366 35367 $.fn.collapse.noConflict = function () { 35368 $.fn.collapse = old 35369 return this 35370 } 35371 35372 35373 // COLLAPSE DATA-API 35374 // ================= 35375 35376 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 35377 var $this = $(this), href 35378 var target = $this.attr('data-target') 35379 || e.preventDefault() 35380 || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 35381 //Edited by Uncode to replace ID in panel [START] 35382 var _target = href.replace(/^#/, ""); 35383 if ( $('[data-id="' + _target + '"]').length ) { 35384 var $target = $('[data-id="' + _target + '"]') 35385 } else { 35386 var $target = $(target) 35387 } 35388 //Edited by Uncode to replace ID in panel [END] 35389 var data = $target.data('bs.collapse') 35390 var option = data ? 'toggle' : $this.data() 35391 var parent = $this.attr('data-parent') 35392 var $parent = parent && $(parent) 35393 35394 if (!data || !data.transitioning) { 35395 if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') 35396 $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') 35397 } 35398 35399 $target.collapse(option) 35400 }) 35401 35402}(jQuery); 35403 35404/* ======================================================================== 35405 * Bootstrap: tab.js v3.1.1 35406 * http://getbootstrap.com/javascript/#tabs 35407 * ======================================================================== 35408 * Copyright 2011-2014 Twitter, Inc. 35409 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 35410 * ======================================================================== */ 35411 35412 35413+function ($) { 35414 'use strict'; 35415 35416 // TAB CLASS DEFINITION 35417 // ==================== 35418 35419 var Tab = function (element) { 35420 this.element = $(element) 35421 } 35422 35423 Tab.prototype.show = function () { 35424 var $this = this.element 35425 var $ul = $this.closest('ul:not(.dropdown-menu)') 35426 var selector = $this.data('target') 35427 35428 if (!selector) { 35429 selector = $this.attr('href') 35430 selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 35431 } 35432 35433 if ($this.parent('li').hasClass('active')) return 35434 35435 var previous = $ul.find('.active:last a')[0] 35436 var e = $.Event('show.bs.tab', { 35437 relatedTarget: previous 35438 }) 35439 35440 $this.trigger(e) 35441 35442 if (e.isDefaultPrevented()) return 35443 35444 //Edited by Uncode to replace ID in panel [START] 35445 var _target = selector.replace(/^#/, ""); 35446 if ( $('[data-id="' + _target + '"]').length ) 35447 var $target = $('[data-id="' + _target + '"]') 35448 else 35449 var $target = $(selector) 35450 //Edited by Uncode to replace ID in panel [END] 35451 35452 this.activate($this.parent('li'), $ul) 35453 this.activate($target, $target.parent(), function () { 35454 $this.trigger({ 35455 type: 'shown.bs.tab', 35456 relatedTarget: previous 35457 }) 35458 }) 35459 } 35460 35461 Tab.prototype.activate = function (element, container, callback) { 35462 var $active = container.find('> .active') 35463 var transition = callback 35464 && $.support.transition 35465 && $active.hasClass('fade') 35466 35467 function next() { 35468 $active 35469 .removeClass('active') 35470 .find('> .dropdown-menu > .active') 35471 .removeClass('active') 35472 35473 element.addClass('active') 35474 35475 if (transition) { 35476 element[0].offsetWidth // reflow for transition 35477 element.addClass('in') 35478 } else { 35479 element.removeClass('fade') 35480 } 35481 35482 if (element.parent('.dropdown-menu')) { 35483 element.closest('li.dropdown').addClass('active') 35484 } 35485 35486 callback && callback() 35487 } 35488 35489 transition ? 35490 $active 35491 .one($.support.transition.end, next) 35492 .emulateTransitionEnd(150) : 35493 next() 35494 35495 $active.removeClass('in') 35496 } 35497 35498 35499 // TAB PLUGIN DEFINITION 35500 // ===================== 35501 35502 var old = $.fn.tab 35503 35504 $.fn.tab = function ( option ) { 35505 return this.each(function () { 35506 var $this = $(this) 35507 var data = $this.data('bs.tab') 35508 35509 if (!data) $this.data('bs.tab', (data = new Tab(this))) 35510 if (typeof option == 'string') data[option]() 35511 }) 35512 } 35513 35514 $.fn.tab.Constructor = Tab 35515 35516 35517 // TAB NO CONFLICT 35518 // =============== 35519 35520 $.fn.tab.noConflict = function () { 35521 $.fn.tab = old 35522 return this 35523 } 35524 35525 35526 // TAB DATA-API 35527 // ============ 35528 35529 $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { 35530 e.preventDefault() 35531 $(this).tab('show') 35532 }) 35533 35534}(jQuery); 35535 35536/* ======================================================================== 35537 * Bootstrap: tooltip.js v3.1.1 35538 * http://getbootstrap.com/javascript/#tooltip 35539 * Inspired by the original jQuery.tipsy by Jason Frame 35540 * ======================================================================== 35541 * Copyright 2011-2014 Twitter, Inc. 35542 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 35543 * ======================================================================== */ 35544 35545 35546+function ($) { 35547 'use strict'; 35548 35549 // TOOLTIP PUBLIC CLASS DEFINITION 35550 // =============================== 35551 35552 var Tooltip = function (element, options) { 35553 this.type = 35554 this.options = 35555 this.enabled = 35556 this.timeout = 35557 this.hoverState = 35558 this.$element = null 35559 35560 this.init('tooltip', element, options) 35561 } 35562 35563 Tooltip.DEFAULTS = { 35564 animation: true, 35565 placement: 'top', 35566 selector: false, 35567 template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', 35568 trigger: 'hover focus', 35569 title: '', 35570 delay: 0, 35571 html: false, 35572 container: false, 35573 viewport: { 35574 selector: 'body', 35575 padding: 0 35576 } 35577 } 35578 35579 Tooltip.prototype.init = function (type, element, options) { 35580 this.enabled = true 35581 this.type = type 35582 this.$element = $(element) 35583 this.options = this.getOptions(options) 35584 this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) 35585 35586 var triggers = this.options.trigger.split(' ') 35587 35588 for (var i = triggers.length; i--;) { 35589 var trigger = triggers[i] 35590 35591 if (trigger == 'click') { 35592 this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) 35593 } else if (trigger != 'manual') { 35594 var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' 35595 var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' 35596 35597 this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) 35598 this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) 35599 } 35600 } 35601 35602 this.options.selector ? 35603 (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : 35604 this.fixTitle() 35605 } 35606 35607 Tooltip.prototype.getDefaults = function () { 35608 return Tooltip.DEFAULTS 35609 } 35610 35611 Tooltip.prototype.getOptions = function (options) { 35612 options = $.extend({}, this.getDefaults(), this.$element.data(), options) 35613 35614 if (options.delay && typeof options.delay == 'number') { 35615 options.delay = { 35616 show: options.delay, 35617 hide: options.delay 35618 } 35619 } 35620 35621 return options 35622 } 35623 35624 Tooltip.prototype.getDelegateOptions = function () { 35625 var options = {} 35626 var defaults = this.getDefaults() 35627 35628 this._options && $.each(this._options, function (key, value) { 35629 if (defaults[key] != value) options[key] = value 35630 }) 35631 35632 return options 35633 } 35634 35635 Tooltip.prototype.enter = function (obj) { 35636 var self = obj instanceof this.constructor ? 35637 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 35638 35639 clearTimeout(self.timeout) 35640 35641 self.hoverState = 'in' 35642 35643 if (!self.options.delay || !self.options.delay.show) return self.show() 35644 35645 self.timeout = setTimeout(function () { 35646 if (self.hoverState == 'in') self.show() 35647 }, self.options.delay.show) 35648 } 35649 35650 Tooltip.prototype.leave = function (obj) { 35651 var self = obj instanceof this.constructor ? 35652 obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) 35653 35654 clearTimeout(self.timeout) 35655 35656 self.hoverState = 'out' 35657 35658 if (!self.options.delay || !self.options.delay.hide) return self.hide() 35659 35660 self.timeout = setTimeout(function () { 35661 if (self.hoverState == 'out') self.hide() 35662 }, self.options.delay.hide) 35663 } 35664 35665 Tooltip.prototype.show = function () { 35666 var e = $.Event('show.bs.' + this.type) 35667 35668 if (this.hasContent() && this.enabled) { 35669 this.$element.trigger(e) 35670 35671 if (e.isDefaultPrevented()) return 35672 var that = this; 35673 35674 var $tip = this.tip() 35675 35676 this.setContent() 35677 35678 if (this.options.animation) $tip.addClass('fade') 35679 35680 var placement = typeof this.options.placement == 'function' ? 35681 this.options.placement.call(this, $tip[0], this.$element[0]) : 35682 this.options.placement 35683 35684 var autoToken = /\s?auto?\s?/i 35685 var autoPlace = autoToken.test(placement) 35686 if (autoPlace) placement = placement.replace(autoToken, '') || 'top' 35687 35688 $tip 35689 .detach() 35690 .css({ top: 0, left: 0, display: 'block' }) 35691 .addClass(placement) 35692 35693 this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element) 35694 35695 var pos = this.getPosition() 35696 var actualWidth = $tip[0].offsetWidth 35697 var act
35697ualHeight = $tip[0].offsetHeight 35698 35699 if (autoPlace) { 35700 var orgPlacement = placement 35701 var $parent = this.$element.parent() 35702 var parentDim = this.getPosition($parent) 35703 35704 placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : 35705 placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : 35706 placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : 35707 placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : 35708 placement 35709 35710 $tip 35711 .removeClass(orgPlacement) 35712 .addClass(placement) 35713 } 35714 35715 var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) 35716 35717 this.applyPlacement(calculatedOffset, placement) 35718 this.hoverState = null 35719 35720 var complete = function() { 35721 that.$element.trigger('shown.bs.' + that.type) 35722 } 35723 35724 $.support.transition && this.$tip.hasClass('fade') ? 35725 $tip 35726 .one($.support.transition.end, complete) 35727 .emulateTransitionEnd(150) : 35728 complete() 35729 } 35730 } 35731 35732 Tooltip.prototype.applyPlacement = function (offset, placement) { 35733 var $tip = this.tip() 35734 var width = $tip[0].offsetWidth 35735 var height = $tip[0].offsetHeight 35736 35737 // manually read margins because getBoundingClientRect includes difference 35738 var marginTop = parseInt($tip.css('margin-top'), 10) 35739 var marginLeft = parseInt($tip.css('margin-left'), 10) 35740 35741 // we must check for NaN for ie 8/9 35742 if (isNaN(marginTop)) marginTop = 0 35743 if (isNaN(marginLeft)) marginLeft = 0 35744 35745 offset.top = offset.top + marginTop 35746 offset.left = offset.left + marginLeft 35747 35748 // $.fn.offset doesn't round pixel values 35749 // so we use setOffset directly with our own function B-0 35750 $.offset.setOffset($tip[0], $.extend({ 35751 using: function (props) { 35752 $tip.css({ 35753 top: Math.round(props.top), 35754 left: Math.round(props.left) 35755 }) 35756 } 35757 }, offset), 0) 35758 35759 $tip.addClass('in') 35760 35761 // check to see if placing tip in new offset caused the tip to resize itself 35762 var actualWidth = $tip[0].offsetWidth 35763 var actualHeight = $tip[0].offsetHeight 35764 35765 if (placement == 'top' && actualHeight != height) { 35766 offset.top = offset.top + height - actualHeight 35767 } 35768 35769 var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) 35770 35771 if (delta.left) offset.left += delta.left 35772 else offset.top += delta.top 35773 35774 var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight 35775 var arrowPosition = delta.left ? 'left' : 'top' 35776 var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' 35777 35778 $tip.offset(offset) 35779 this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) 35780 } 35781 35782 Tooltip.prototype.replaceArrow = function (delta, dimension, position) { 35783 this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') 35784 } 35785 35786 Tooltip.prototype.setContent = function () { 35787 var $tip = this.tip() 35788 var title = this.getTitle() 35789 35790 $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) 35791 $tip.removeClass('fade in top bottom left right') 35792 } 35793 35794 Tooltip.prototype.hide = function () { 35795 var that = this 35796 var $tip = this.tip() 35797 var e = $.Event('hide.bs.' + this.type) 35798 35799 function complete() { 35800 if (that.hoverState != 'in') $tip.detach() 35801 that.$element.trigger('hidden.bs.' + that.type) 35802 } 35803 35804 this.$element.trigger(e) 35805 35806 if (e.isDefaultPrevented()) return 35807 35808 $tip.removeClass('in') 35809 35810 $.support.transition && this.$tip.hasClass('fade') ? 35811 $tip 35812 .one($.support.transition.end, complete) 35813 .emulateTransitionEnd(150) : 35814 complete() 35815 35816 this.hoverState = null 35817 35818 return this 35819 } 35820 35821 Tooltip.prototype.fixTitle = function () { 35822 var $e = this.$element 35823 if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { 35824 $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') 35825 } 35826 } 35827 35828 Tooltip.prototype.hasContent = function () { 35829 return this.getTitle() 35830 } 35831 35832 Tooltip.prototype.getPosition = function ($element) { 35833 $element = $element || this.$element 35834 var el = $element[0] 35835 var isBody = el.tagName == 'BODY' 35836 return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { 35837 scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), 35838 width: isBody ? $(window).width() : $element.outerWidth(), 35839 height: isBody ? $(window).height() : $element.outerHeight() 35840 }, isBody ? {top: 0, left: 0} : $element.offset()) 35841 } 35842 35843 Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { 35844 return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : 35845 placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : 35846 placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : 35847 /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } 35848 35849 } 35850 35851 Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { 35852 var delta = { top: 0, left: 0 } 35853 if (!this.$viewport) return delta 35854 35855 var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 35856 var viewportDimensions = this.getPosition(this.$viewport) 35857 35858 if (/right|left/.test(placement)) { 35859 var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll 35860 var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight 35861 if (topEdgeOffset < viewportDimensions.top) { // top overflow 35862 delta.top = viewportDimensions.top - topEdgeOffset 35863 } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow 35864 delta.top = viewportDimensions.top + viewportDimensions.height - bottom
35864EdgeOffset 35865 } 35866 } else { 35867 var leftEdgeOffset = pos.left - viewportPadding 35868 var rightEdgeOffset = pos.left + viewportPadding + actualWidth 35869 if (leftEdgeOffset < viewportDimensions.left) { // left overflow 35870 delta.left = viewportDimensions.left - leftEdgeOffset 35871 } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow 35872 delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset 35873 } 35874 } 35875 35876 return delta 35877 } 35878 35879 Tooltip.prototype.getTitle = function () { 35880 var title 35881 var $e = this.$element 35882 var o = this.options 35883 35884 title = $e.attr('data-original-title') 35885 || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) 35886 35887 return title 35888 } 35889 35890 Tooltip.prototype.tip = function () { 35891 return this.$tip = this.$tip || $(this.options.template) 35892 } 35893 35894 Tooltip.prototype.arrow = function () { 35895 return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') 35896 } 35897 35898 Tooltip.prototype.validate = function () { 35899 if (!this.$element[0].parentNode) { 35900 this.hide() 35901 this.$element = null 35902 this.options = null 35903 } 35904 } 35905 35906 Tooltip.prototype.enable = function () { 35907 this.enabled = true 35908 } 35909 35910 Tooltip.prototype.disable = function () { 35911 this.enabled = false 35912 } 35913 35914 Tooltip.prototype.toggleEnabled = function () { 35915 this.enabled = !this.enabled 35916 } 35917 35918 Tooltip.prototype.toggle = function (e) { 35919 var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this 35920 self.tip().hasClass('in') ? self.leave(self) : self.enter(self) 35921 } 35922 35923 Tooltip.prototype.destroy = function () { 35924 clearTimeout(this.timeout) 35925 this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) 35926 } 35927 35928 35929 // TOOLTIP PLUGIN DEFINITION 35930 // ========================= 35931 35932 var old = $.fn.tooltip 35933 35934 $.fn.tooltip = function (option) { 35935 return this.each(function () { 35936 var $this = $(this) 35937 var data = $this.data('bs.tooltip') 35938 var options = typeof option == 'object' && option 35939 35940 if (!data && option == 'destroy') return 35941 if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) 35942 if (typeof option == 'string') data[option]() 35943 }) 35944 } 35945 35946 $.fn.tooltip.Constructor = Tooltip 35947 35948 35949 // TOOLTIP NO CONFLICT 35950 // =================== 35951 35952 $.fn.tooltip.noConflict = function () { 35953 $.fn.tooltip = old 35954 return this 35955 } 35956 35957}(jQuery); 35958 35959/* ======================================================================== 35960 * Bootstrap: transition.js v3.1.1 35961 * http://getbootstrap.com/javascript/#transitions 35962 * ======================================================================== 35963 * Copyright 2011-2014 Twitter, Inc. 35964 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 35965 * ======================================================================== */ 35966 35967 35968+function ($) { 35969 'use strict'; 35970 35971 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 35972 // ============================================================ 35973 35974 function transitionEnd() { 35975 var el = document.createElement('bootstrap') 35976 35977 var transEndEventNames = { 35978 WebkitTransition : 'webkitTransitionEnd', 35979 MozTransition : 'transitionend', 35980 OTransition : 'oTransitionEnd otransitionend', 35981 transition : 'transitionend' 35982 } 35983 35984 for (var name in transEndEventNames) { 35985 if (el.style[name] !== undefined) { 35986 return { end: transEndEventNames[name] } 35987 } 35988 } 35989 35990 return false // explicit for ie8 ( ._.) 35991 } 35992 35993 // http://blog.alexmaccaw.com/css-transitions 35994 $.fn.emulateTransitionEnd = function (duration) { 35995 var called = false, $el = this 35996 $(this).one($.support.transition.end, function () { called = true }) 35997 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 35998 setTimeout(callback, duration) 35999 return this 36000 } 36001 36002 $(function () { 36003 $.support.transition = transitionEnd() 36004 }) 36005 36006}(jQuery); 36007 36008 36009// ------------------------------------------ 36010// Rellax.js 36011// Buttery smooth parallax library 36012// Copyright (c) 2016 Moe Amaya (@moeamaya) 36013// MIT license 36014// 36015// Thanks to Paraxify.js and Jaime Cabllero 36016// for parallax concepts 36017// ------------------------------------------ 36018 36019(function (root, factory) { 36020 if (typeof define === 'function' && define.amd) { 36021 // AMD. Register as an anonymous module. 36022 define([], factory); 36023 } else if (typeof module === 'object' && module.exports) { 36024 // Node. Does not work with strict CommonJS, but 36025 // only CommonJS-like environments that support module.exports, 36026 // like Node. 36027 module.exports = factory(); 36028 } else { 36029 // Browser globals (root is window) 36030 root.Rellax = factory(); 36031 } 36032}(typeof window !== "undefined" ? window : global, function () { 36033 var Rellax = function(el, options){ 36034 "use strict"; 36035 36036 var self = Object.create(Rellax.prototype); 36037 36038 var posY = 0; 36039 var screenY = 0; 36040 var posX = 0; 36041 var screenX = 0; 36042 var blocks = []; 36043 var pause = true; 36044 36045 // check what requestAnimationFrame to use, and if 36046 // it's not supported, use the onscroll event 36047 var loop = window.requestAnimationFrame || 36048 window.webkitRequestAnimationFrame || 36049 window.mozRequestAnimationFrame || 36050 window.msRequestAnimationFrame || 36051 window.oRequestAnimationFrame || 36052 function(callback){ return setTimeout(callback, 1000 / 60); }; 36053 36054 // store the id for later use 36055 var loopId = null; 36056 36057 // Test via a getter in the options object to see if the passive property is accessed 36058 var supportsPassive = false;
vendor: 10,724 bytes, lines 36059-36360
36059 try { 36060 var opts = Object.defineProperty({}, 'passive', { 36061 get: function() { 36062 supportsPassive = true; 36063 } 36064 }); 36065 window.addEventListener("testPassive", null, opts); 36066 window.removeEventListener("testPassive", null, opts); 36067 } catch (e) {} 36068 36069 // check what cancelAnimation method to use 36070 var clearLoop = window.cancelAnimationFrame || window.mozCancelAnimationFrame || clearTimeout; 36071 36072 // check which transform property to use 36073 var transformProp = window.transformProp || (function(){ 36074 var testEl = document.createElement('div'); 36075 if (testEl.style.transform === null) { 36076 var vendors = ['Webkit', 'Moz', 'ms']; 36077 for (var vendor in vendors) { 36078 if (testEl.style[ vendors[vendor] + 'Transform' ] !== undefined) { 36079 return vendors[vendor] + 'Transform'; 36080 } 36081 } 36082 } 36083 return 'transform'; 36084 })(); 36085 36086 // Default Settings 36087 self.options = { 36088 speed: -2, 36089 verticalSpeed: null, 36090 horizontalSpeed: null, 36091 breakpoints: [576, 768, 1201], 36092 center: false, 36093 wrapper: null, 36094 relativeToWrapper: false, 36095 round: true, 36096 vertical: true, 36097 horizontal: false, 36098 verticalScrollAxis: "y", 36099 horizontalScrollAxis: "x", 36100 callback: function() {}, 36101 }; 36102 36103 // User defined options (might have more in the future) 36104 if (options){ 36105 Object.keys(options).forEach(function(key){ 36106 self.options[key] = options[key]; 36107 }); 36108 } 36109 36110 function validateCustomBreakpoints () { 36111 if (self.options.breakpoints.length === 3 && Array.isArray(self.options.breakpoints)) { 36112 var isAscending = true; 36113 var isNumerical = true; 36114 var lastVal; 36115 self.options.breakpoints.forEach(function (i) { 36116 if (typeof i !== 'number') isNumerical = false; 36117 if (lastVal !== null) { 36118 if (i < lastVal) isAscending = false; 36119 } 36120 lastVal = i; 36121 }); 36122 if (isAscending && isNumerical) return; 36123 } 36124 // revert defaults if set incorrectly 36125 self.options.breakpoints = [576, 768, 1201]; 36126 console.warn("Rellax: You must pass an array of 3 numbers in ascending order to the breakpoints option. Defaults reverted"); 36127 } 36128 36129 if (options && options.breakpoints) { 36130 validateCustomBreakpoints(); 36131 } 36132 36133 // By default, rellax class 36134 if (!el) { 36135 el = '.rellax'; 36136 } 36137 36138 // check if el is a className or a node 36139 var elements = typeof el === 'string' ? document.querySelectorAll(el) : [el]; 36140 36141 // Now query selector 36142 if (elements.length > 0) { 36143 self.elems = elements; 36144 } 36145 36146 // The elements don't exist 36147 else { 36148 console.warn("Rellax: The elements you're trying to select don't exist."); 36149 return; 36150 } 36151 36152 // Has a wrapper and it exists 36153 if (self.options.wrapper) { 36154 if (!self.options.wrapper.nodeType) { 36155 var wrapper = document.querySelector(self.options.wrapper); 36156 36157 if (wrapper) { 36158 self.options.wrapper = wrapper; 36159 } else { 36160 console.warn("Rellax: The wrapper you're trying to use doesn't exist."); 36161 return; 36162 } 36163 } 36164 } 36165 36166 // set a placeholder for the current breakpoint 36167 var currentBreakpoint; 36168 36169 // helper to determine current breakpoint 36170 var getCurrentBreakpoint = function (w) { 36171 var bp = self.options.breakpoints; 36172 if (w < bp[0]) return 'xs'; 36173 if (w >= bp[0] && w < bp[1]) return 'sm'; 36174 if (w >= bp[1] && w < bp[2]) return 'md'; 36175 return 'lg'; 36176 }; 36177 36178 // Get and cache initial position of all elements 36179 var cacheBlocks = function() { 36180 for (var i = 0; i < self.elems.length; i++){ 36181 var block = createBlock(self.elems[i]); 36182 blocks.push(block); 36183 } 36184 }; 36185 36186 36187 // Let's kick this script off 36188 // Build array for cached element values 36189 var init = function() { 36190 for (var i = 0; i < blocks.length; i++){ 36191 self.elems[i].style.cssText = blocks[i].style; 36192 } 36193 36194 blocks = []; 36195 36196 screenY = window.innerHeight; 36197 screenX = window.innerWidth; 36198 currentBreakpoint = getCurrentBreakpoint(screenX); 36199 36200 setPosition(); 36201 36202 cacheBlocks(); 36203 36204 animate(); 36205 36206 // If paused, unpause and set listener for window resizing events 36207 if (pause) { 36208 window.addEventListener('resize', init); 36209 pause = false; 36210 // Start the loop 36211 update(); 36212 } 36213 }; 36214 36215 // We want to cache the parallax blocks' 36216 // values: base, top, height, speed 36217 // el: is dom object, return: el cache values 36218 var createBlock = function(el) { 36219 var dataPercentage = el.getAttribute( 'data-rellax-percentage' ); 36220 var dataSpeed = el.getAttribute( 'data-rellax-speed' ); 36221 var dataXsSpeed = el.getAttribute( 'data-rellax-xs-speed' ); 36222 var dataMobileSpeed = el.getAttribute( 'data-rellax-mobile-speed' ); 36223 var dataTabletSpeed = el.getAttribute( 'data-rellax-tablet-speed' ); 36224 var dataDesktopSpeed = el.getAttribute( 'data-rellax-desktop-speed' ); 36225 var dataVerticalSpeed = el.getAttribute('data-rellax-vertical-speed'); 36226 var dataHorizontalSpeed = el.getAttribute('data-rellax-horizontal-speed'); 36227 var dataVericalScrollAxis = el.getAttribute('data-rellax-vertical-scroll-axis'); 36228 var dataHorizontalScrollAxis = el.getAttribute('data-rellax-horizontal-scroll-axis'); 36229 var dataZindex = el.getAttribute( 'data-rellax-zindex' ) || 0; 36230 var dataMin = el.getAttribute( 'data-rellax-min' ); 36231 var dataMax = el.getAttribute( 'data-rellax-max' ); 36232 var dataMinX = el.getAttribute('data-rellax-min-x'); 36233 var dataMaxX = el.getAttribute('data-rellax-max-x'); 36234 var dataMinY = el.getAttribute('data-rellax-min-y'); 36235 var dataMaxY = el.getAttribute('data-rellax-max-y'); 36236 var mapBreakpoints; 36237 var breakpoints = true; 36238 36239 if (!dataXsSpeed && !dataMobileSpeed && !dataTabletSpeed && !dataDesktopSpeed) { 36240 breakpoints = false; 36241 } else { 36242 mapBreakpoints = { 36243 'xs': dataXsSpeed, 36244 'sm': dataMobileSpeed, 36245 'md': dataTabletSpeed, 36246 'lg': dataDesktopSpeed 36247 }; 36248 } 36249 36250 // initializing at scrollY = 0 (top of browser), scrollX = 0 (left of browser) 36251 // ensures elements are positioned based on HTML layout. 36252 // 36253 // If the element has the percentage attribute, the posY and posX needs to be 36254 // the current scroll position's value, so that the elements are still positioned based on HTML layout 36255 var wrapperPosY = self.options.wrapper ? self.options.wrapper.scrollTop : (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 36256 // If the option relativeToWrapper is true, use the wrappers offset to top, subtracted from the current page scroll. 36257 if (self.options.relativeToWrapper) { 36258 var scrollPosY = (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); 36259 wrapperPosY = scrollPosY - self.options.wrapper.offsetTop; 36260 } 36261 var posY = self.options.vertical ? ( dataPercentage || self.options.center ? wrapperPosY : 0 ) : 0; 36262 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; 36263 36264 var blockTop = posY + el.getBoundingClientRect().top; 36265 var blockHeight = el.clientHeight || el.offsetHeight || el.scrollHeight; 36266 36267 var blockLeft = posX + el.getBoundingClientRect().left; 36268 var blockWidth = el.clientWidth || el.offsetWidth || el.scrollWidth; 36269 36270 // apparently parallax equation everyone uses 36271 var percentageY = dataPercentage ? dataPercentage : (posY - blockTop + screenY) / (blockHeight + screenY); 36272 var percentageX = dataPercentage ? dataPercentage : (posX - blockLeft + screenX) / (blockWidth + screenX); 36273 if(self.options.center){ percentageX = 0.5; percentageY = 0.5; } 36274 36275 // Optional individual block speed as data attr, otherwise global speed 36276 var speed = (breakpoints && mapBreakpoints[currentBreakpoint] !== null) ? Number(mapBreakpoints[currentBreakpoint]) : (dataSpeed ? dataSpeed : self.options.speed); 36277 var verticalSpeed = dataVerticalSpeed ? dataVerticalSpeed : self.options.verticalSpeed; 36278 var horizontalSpeed = dataHorizontalSpeed ? dataHorizontalSpeed : self.options.horizontalSpeed; 36279 36280 // Optional individual block movement axis direction as data attr, otherwise global movement direction 36281 var verticalScrollAxis = dataVericalScrollAxis ? dataVericalScrollAxis : self.options.verticalScrollAxis; 36282 var horizontalScrollAxis = dataHorizontalScrollAxis ? dataHorizontalScrollAxis : self.options.horizontalScrollAxis; 36283 36284 var bases = updatePosition(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed); 36285 36286 // ~~Store non-translate3d transforms~~ 36287 // Store inline styles and extract transforms 36288 var style = el.style.cssText; 36289 var transform = ''; 36290 36291 // Check if there's an inline styled transform 36292 var searchResult = /transform\s*:/i.exec(style); 36293 if (searchResult) { 36294 // Get the index of the transform 36295 var index = searchResult.index; 36296 36297 // Trim the style to the transform point and get the following semi-colon index 36298 var trimmedStyle = style.slice(index); 36299 var delimiter = trimmedStyle.indexOf(';'); 36300 36301 // Remove "transform" string and save the attribute 36302 if (delimiter) { 36303 transform = " " + trimmedStyle.slice(11, delimiter).replace(/\s/g,''); 36304 } else { 36305 transform = " " + trimmedStyle.slice(11).replace(/\s/g,''); 36306 } 36307 } 36308 36309 return { 36310 baseX: bases.x, 36311 baseY: bases.y, 36312 top: blockTop, 36313 left: blockLeft, 36314 height: blockHeight, 36315 width: blockWidth, 36316 speed: speed, 36317 verticalSpeed: verticalSpeed, 36318 horizontalSpeed: horizontalSpeed, 36319 verticalScrollAxis: verticalScrollAxis, 36320 horizontalScrollAxis: horizontalScrollAxis, 36321 style: style, 36322 transform: transform, 36323 zindex: dataZindex, 36324 min: dataMin, 36325 max: dataMax, 36326 minX: dataMinX, 36327 maxX: dataMaxX, 36328 minY: dataMinY, 36329 maxY: dataMaxY 36330 }; 36331 }; 36332 36333 // set scroll position (posY, posX) 36334 // side effect method is not ideal, but okay for now 36335 // returns true if the scroll changed, false if nothing happened 36336 var setPosition = function() { 36337 var oldY = posY; 36338 var oldX = posX; 36339 36340 posY = self.options.wrapper ? self.options.wrapper.scrollTop : (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 36341 posX = self.options.wrapper ? self.options.wrapper.scrollLeft : (document.documentElement || document.body.parentNode || document.body).scrollLeft || window.pageXOffset; 36342 // If option relativeToWrapper is true, use relative wrapper value instead. 36343 if (self.options.relativeToWrapper) { 36344 var scrollPosY = (document.documentElement || document.body.parentNode || document.body).scrollTop || window.pageYOffset; 36345 posY = scrollPosY - self.options.wrapper.offsetTop; 36346 } 36347 36348 36349 if (oldY != posY && self.options.vertical) { 36350 // scroll changed, return true 36351 return true; 36352 } 36353 36354 if (oldX != posX && self.options.horizontal) { 36355 // scroll changed, return true 36356 return true; 36357 } 36358 36359 // scroll did not change 36360 return false;
36361 }; 36362 36363 // Ahh a pure function, gets new transform value 36364 // based on scrollPosition and speed 36365 // Allow for decimal pixel values 36366 var updatePosition = function(percentageX, percentageY, speed, verticalSpeed, horizontalSpeed) { 36367 var result = {}; 36368 var valueX = ((horizontalSpeed ? horizontalSpeed : speed) * (100 * (1 - percentageX))); 36369 var valueY = ((verticalSpeed ? verticalSpeed : speed) * (100 * (1 - percentageY))); 36370 36371 result.x = self.options.round ? Math.round(valueX) : Math.round(valueX * 100) / 100; 36372 result.y = self.options.round ? Math.round(valueY) : Math.round(valueY * 100) / 100; 36373 36374 return result; 36375 }; 36376 36377 // Remove event listeners and loop again 36378 var deferredUpdate = function() { 36379 window.removeEventListener('resize', deferredUpdate); 36380 window.removeEventListener('orientationchange', deferredUpdate); 36381 (self.options.wrapper ? self.options.wrapper : window).removeEventListener('scroll', deferredUpdate); 36382 (self.options.wrapper ? self.options.wrapper : document).removeEventListener('touchmove', deferredUpdate); 36383 36384 // loop again 36385 loopId = loop(update); 36386 }; 36387 36388 // Loop 36389 var update = function() { 36390 if (setPosition() && pause === false) { 36391 animate(); 36392 36393 // loop again 36394 loopId = loop(update); 36395 } else { 36396 loopId = null; 36397 36398 // Don't animate until we get a position updating event 36399 window.addEventListener('resize', deferredUpdate); 36400 window.addEventListener('orientationchange', deferredUpdate); 36401 (self.options.wrapper ? self.options.wrapper : window).addEventListener('scroll', deferredUpdate, supportsPassive ? { passive: true } : false); 36402 (self.options.wrapper ? self.options.wrapper : document).addEventListener('touchmove', deferredUpdate, supportsPassive ? { passive: true } : false); 36403 } 36404 }; 36405 36406 // Transform3d on parallax element 36407 var animate = function() { 36408 var positions; 36409 for (var i = 0; i < self.elems.length; i++){ 36410 // Determine relevant movement directions 36411 var verticalScrollAxis = blocks[i].verticalScrollAxis.toLowerCase(); 36412 var horizontalScrollAxis = blocks[i].horizontalScrollAxis.toLowerCase(); 36413 var verticalScrollX = verticalScrollAxis.indexOf("x") != -1 ? posY : 0; 36414 var verticalScrollY = verticalScrollAxis.indexOf("y") != -1 ? posY : 0; 36415 var horizontalScrollX = horizontalScrollAxis.indexOf("x") != -1 ? posX : 0; 36416 var horizontalScrollY = horizontalScrollAxis.indexOf("y") != -1 ? posX : 0; 36417 36418 var percentageY = ((verticalScrollY + horizontalScrollY - blocks[i].top + screenY) / (blocks[i].height + screenY)); 36419 var percentageX = ((verticalScrollX + horizontalScrollX - blocks[i].left + screenX) / (blocks[i].width + screenX)); 36420 36421 // Subtracting initialize value, so element stays in same spot as HTML 36422 positions = updatePosition(percentageX, percentageY, blocks[i].speed, blocks[i].verticalSpeed, blocks[i].horizontalSpeed); 36423 var positionY = positions.y - blocks[i].baseY; 36424 var positionX = positions.x - blocks[i].baseX; 36425 36426 // The next two "if" blocks go like this: 36427 // Check if a limit is defined (first "min", then "max"); 36428 // Check if we need to change the Y or the X 36429 // (Currently working only if just one of the axes is enabled) 36430 // Then, check if the new position is inside the allowed limit 36431 // If so, use new position. If not, set position to limit. 36432 36433 // Check if a min limit is defined 36434 if (blocks[i].min !== null) { 36435 if (self.options.vertical && !self.options.horizontal) { 36436 positionY = positionY <= blocks[i].min ? blocks[i].min : positionY; 36437 } 36438 if (self.options.horizontal && !self.options.vertical) { 36439 positionX = positionX <= blocks[i].min ? blocks[i].min : positionX; 36440 } 36441 } 36442 36443 // Check if directional min limits are defined 36444 if (blocks[i].minY != null) { 36445 positionY = positionY <= blocks[i].minY ? blocks[i].minY : positionY; 36446 } 36447 if (blocks[i].minX != null) { 36448 positionX = positionX <= blocks[i].minX ? blocks[i].minX : positionX; 36449 } 36450 36451 // Check if a max limit is defined 36452 if (blocks[i].max !== null) { 36453 if (self.options.vertical && !self.options.horizontal) { 36454 positionY = positionY >= blocks[i].max ? blocks[i].max : positionY; 36455 } 36456 if (self.options.horizontal && !self.options.vertical) { 36457 positionX = positionX >= blocks[i].max ? blocks[i].max : positionX; 36458 } 36459 } 36460 36461 // Check if directional max limits are defined 36462 if (blocks[i].maxY != null) { 36463 positionY = positionY >= blocks[i].maxY ? blocks[i].maxY : positionY; 36464 } 36465 if (blocks[i].maxX != null) { 36466 positionX = positionX >= blocks[i].maxX ? blocks[i].maxX : positionX; 36467 } 36468 36469 var zindex = blocks[i].zindex; 36470 36471 // Move that element 36472 // (Set the new translation and append initial inline transforms.) 36473 var translate = 'translate3d(' + (self.options.horizontal ? positionX : '0') + 'px,' + (self.options.vertical ? positionY : '0') + 'px,' + zindex + 'px) ' + blocks[i].transform; 36474 self.elems[i].style[transformProp] = translate; 36475 } 36476 self.options.callback(positions); 36477 }; 36478 36479 self.destroy = function() { 36480 for (var i = 0; i < self.elems.length; i++){ 36481 self.elems[i].style.cssText = blocks[i].style; 36482 } 36483 36484 // Remove resize event listener if not pause, and pause 36485 if (!pause) { 36486 window.removeEventListener('resize', init); 36487 pause = true; 36488 } 36489 36490 // Clear the animation loop to prevent possible memory leak 36491 clearLoop(loopId); 36492 loopId = null; 36493 }; 36494 36495 // Init 36496 init(); 36497 36498 // Allow to recalculate the initial values whenever we want 36499 self.refresh = init; 36500 36501 return self; 36502 }; 36503 return Rellax; 36504})); 36505 36506/* 36507 * OKVideo by OKFocus v2.3.2 36508 * http://okfoc.us 36509 * 36510 * Copyright 2014, OKFocus 36511 * Licensed under the MIT license. 36512 * 36513 */ 36514var player, OKEvents, options, videoWidth, videoHeight, YTplayers, youtubePlayers = new Array(); 36515// youtube player ready 36516function onYouTubeIframeAPIReady() { 36517 YTplayers = new Array(); 36518 jQuery('.no-touch .uncode-video-container.video').each(function() { 36519 var playerY; 36520 if (jQuery(this).attr('data-provider') == 'youtube') { 36521 var id = jQuery(this).attr('data-id'); 36522 options = jQuery(window).data('okoptions-' + id); 36523 options.time = jQuery(this).attr('data-t'); 36524 playerY = new YT.Player('okplayer-' + id, { 36525 videoId: options.video ? options.video.id : null, 36526 playerVars: { 36527 'autohide': 1, 36528 'autoplay': 0, //options.autoplay, 36529 'disablekb': 1, 36530 'cc_load_policy': options.captions, 36531 'controls': 0, 36532 'enablejsapi': 1, 36533 'fs': 0, 36534 'modestbranding': 1, 36535 'origin': window.location.origin || (window.location.protocol + '//' + window.location.hostname), 36536 'iv_load_policy': options.annotations, 36537 'loop': options.loop, 36538 'showinfo': 0, 36539 'rel': 0, 36540 'wmode': 'opaque', 36541 'hd': options.hd, 36542 'mute': 1 36543 }, 36544 events: { 36545 'onReady': OKEvents.yt.ready, 36546 'onStateChange': OKEvents.yt.onStateChange, 36547 'onError': OKEvents.yt.error 36548 } 36549 }); 36550 YTplayers[id] = playerY; 36551 playerY.videoId = id; 36552 } 36553 36554 }); 36555} 36556// vimeo player ready 36557function vimeoPlayerReady(id) { 36558 options = jQuery(window).data('okoptions-' + id); 36559 var jIframe = options.jobject, 36560 iframe = jIframe[0]; 36561 36562 jIframe.attr('src', jIframe.data('src')); 36563 var playerV = $f(iframe); // `$f` is froogaloop, assumed is loaded 36564 // hide player until Vimeo hides controls... 36565 playerV.addEvent('ready', function(e) { 36566 OKEvents.v.onReady(iframe); 36567 var carouselContainer = jQuery(iframe).closest('.owl-carousel'); 36568 if (carouselContainer.length) { 36569 UNCODE.owlPlayVideo(carouselContainer); 36570 } 36571 // "Do not try to add listeners or call functions before receiving this event." 36572 if (OKEvents.utils.isMobile()) { 36573 // mobile devices cannot listen for play event 36574 OKEvents.v.onPlay(playerV); 36575 } else { 36576 playerV.addEvent('play', OKEvents.v.onPlay(playerV)); 36577 playerV.addEvent('pause', OKEvents.v.onPause); 36578 playerV.addEvent('finish', OKEvents.v.onFinish); 36579 } 36580 if (options.time != null) { 36581 var optsTimeStr = (options.time).replace('t=', ''), 36582 timeV = ''; 36583 36584 if ( /[a-zA-Z]/g.test(optsTimeStr) ) { 36585 var timeArr = optsTimeStr.split(/([^\d.-])/); 36586 for ( var i = 0; i < timeArr.length; i++ ) { 36587 if ( timeArr[i] === 'h' ) { 36588 timeV += parseFloat(timeArr[i-1]) * 3600; 36589 } else if ( timeArr[i] === 'm' ) { 36590 timeV += parseFloat(timeArr[i-1]) * 60; 36591 } else if ( timeArr[i] === 's' ) { 36592 timeV += parseFloat(timeArr[i-1]); 36593 } 36594 } 36595 } else { 36596 timeV = optsTimeStr; 36597 } 36598 36599 playerV.api('seekTo', timeV); 36600 } 36601 36602 playerV.api('play'); 36603 jQuery(iframe).css({ 36604 visibility: 'visible', 36605 opacity: 1 36606 }); 36607 jQuery(iframe).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 36608 jQuery(iframe).closest('#page-header').addClass('video-started'); 36609 jQuery(iframe).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 36610 36611 }); 36612} 36613OKEvents = { 36614 yt: { 36615 ready: function(event) { 36616 var id = event.target.videoId; 36617 youtubePlayers[id] = event.target; 36618 event.target.setVolume(options.volume); 36619 if (options.autoplay === 1) { 36620 if (options.playlist.list) { 36621 player.loadPlaylist(options.playlist.list, options.playlist.index, options.playlist.startSeconds, options.playlist.suggestedQuality); 36622 } else { 36623 var inCarousel = jQuery('#okplayer-' + id).closest('.owl-item'); 36624 if (!inCarousel.length || (inCarousel.length && inCarousel.hasClass('active'))) { 36625 if (options.time != null) { 36626 event.target.seekTo(parseInt(options.time)); 36627 } 36628 event.target.playVideo(); 36629 } else { 36630 event.target.pauseVideo(); 36631 } 36632 } 36633 } 36634 OKEvents.utils.isFunction(options.onReady) && options.onReady(event.target); 36635 36636 jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-resume', function(){ 36637 if (options.time != null) { 36638 event.target.seekTo(parseInt(options.time)).playVideo(); 36639 } else { 36640 event.target.seekTo(0).playVideo(); 36641 } 36642 }); 36643 36644 jQuery('#okplayer-' + id).closest('[data-provider]').on('uncode-pause', function(){ 36645 if (options.time != null) { 36646 event.target.seekTo(parseInt(options.time)).pauseVideo(); 36647 } else { 36648 event.target.seekTo(0).pauseVideo(); 36649 } 36650 }); 36651 }, 36652 onStateChange: function(event) { 36653 var id = event.target.videoId; 36654 switch (event.data) { 36655 case -1: 36656 OKEvents.utils.isFunction(options.unstarted) && options.unstarted(); 36657 break; 36658 case 0: 36659 OKEvents.utils.isFunction(options.onFinished) && options.onFinished(); 36660 options.loop && event.target.playVideo(); 36661 break; 36662 case 1: 36663 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 36664 setTimeout(function() { 36665 UNCODE.initVideoComponent(document.body, '.uncode-video-container.video:not(.drop-move), .uncode-video-container.self-video:not(.drop-move)'); 36666 jQuery('#okplayer-' + id).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 36667 jQuery('#okplayer-' + id).closest('#page-header').addClass('video-started'); 36668 jQuery('#okplayer-' + id).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 36669 }, 300); 36670 break; 36671 case 2: 36672 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 36673 break; 36674 case 3: 36675 OKEvents.utils.isFunction(options.buffering) && options.buffering(); 36676 break; 36677 case 5: 36678 OKEvents.utils.isFunction(options.cued) && options.cued(); 36679 break; 36680 default:
36681 throw "OKVideo: received invalid data from YT player."; 36682 } 36683 }, 36684 error: function(event) { 36685 throw event; 36686 } 36687 }, 36688 v: { 36689 onReady: function(target) { 36690 OKEvents.utils.isFunction(options.onReady) && options.onReady(target); 36691 }, 36692 onPlay: function(player) { 36693 if (!OKEvents.utils.isMobile()) player.api('setVolume', options.volume); 36694 OKEvents.utils.isFunction(options.onPlay) && options.onPlay(); 36695 jQuery(player.element).closest('.uncode-video-container:not(.t-entry-drop)').css('opacity', '1'); 36696 jQuery(player.element).closest('#page-header').addClass('video-started'); 36697 jQuery(player.element).closest('.background-wrapper').find('.block-bg-blend-mode.not-ie').css('opacity', '1'); 36698 }, 36699 onPause: function() { 36700 OKEvents.utils.isFunction(options.onPause) && options.onPause(); 36701 }, 36702 onFinish: function() { 36703 OKEvents.utils.isFunction(options.onFinish) && options.onFinish(); 36704 } 36705 }, 36706 utils: { 36707 isFunction: function(func) { 36708 if (typeof func === 'function') { 36709 return true; 36710 } else { 36711 return false; 36712 } 36713 }, 36714 isMobile: function() { 36715 if (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/)) { 36716 return true; 36717 } else { 36718 return false; 36719 } 36720 } 36721 } 36722}; 36723 36724/** 36725 * vivus - JavaScript library to make drawing animation on SVG 36726 * @version v0.4.4 36727 * @link https://github.com/maxwellito/vivus 36728 * @license MIT 36729 */ 36730 36731'use strict'; 36732 36733(function () { 36734 36735 'use strict'; 36736 36737/** 36738 * Pathformer 36739 * Beta version 36740 * 36741 * Take any SVG version 1.1 and transform 36742 * child elements to 'path' elements 36743 * 36744 * This code is purely forked from 36745 * https://github.com/Waest/SVGPathConverter 36746 */ 36747 36748/** 36749 * Class constructor 36750 * 36751 * @param {DOM|String} element Dom element of the SVG or id of it 36752 */ 36753function Pathformer(element) { 36754 // Test params 36755 if (typeof element === 'undefined') { 36756 throw new Error('Pathformer [constructor]: "element" parameter is required'); 36757 } 36758 36759 // Set the element 36760 if (element.constructor === String) { 36761 element = document.getElementById(element); 36762 if (!element) { 36763 throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID'); 36764 } 36765 } 36766 if (element instanceof window.SVGElement || 36767 element instanceof window.SVGGElement || 36768 /^svg$/i.test(element.nodeName)) { 36769 this.el = element; 36770 } else { 36771 throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement'); 36772 } 36773 36774 // Start 36775 this.scan(element); 36776} 36777 36778/** 36779 * List of tags which can be transformed 36780 * to path elements 36781 * 36782 * @type {Array} 36783 */ 36784Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect']; 36785 36786/** 36787 * List of attribute names which contain 36788 * data. This array list them to check if 36789 * they contain bad values, like percentage. 36790 * 36791 * @type {Array} 36792 */ 36793Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', '
vendor: 24,640 bytes, lines 36793-37591
36793y1', 'y2']; 36794 36795/** 36796 * Finds the elements compatible for transform 36797 * and apply the liked method 36798 * 36799 * @param {object} options Object from the constructor 36800 */ 36801Pathformer.prototype.scan = function (svg) { 36802 var fn, element, pathData, pathDom, 36803 elements = svg.querySelectorAll(this.TYPES.join(',')); 36804 36805 for (var i = 0; i < elements.length; i++) { 36806 element = elements[i]; 36807 fn = this[element.tagName.toLowerCase() + 'ToPath']; 36808 pathData = fn(this.parseAttr(element.attributes)); 36809 pathDom = this.pathMaker(element, pathData); 36810 element.parentNode.replaceChild(pathDom, element); 36811 } 36812}; 36813 36814 36815/** 36816 * Read `line` element to extract and transform 36817 * data, to make it ready for a `path` object. 36818 * 36819 * @param {DOMelement} element Line element to transform 36820 * @return {object} Data for a `path` element 36821 */ 36822Pathformer.prototype.lineToPath = function (element) { 36823 var newElement = {}, 36824 x1 = element.x1 || 0, 36825 y1 = element.y1 || 0, 36826 x2 = element.x2 || 0, 36827 y2 = element.y2 || 0; 36828 36829 newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2; 36830 return newElement; 36831}; 36832 36833/** 36834 * Read `rect` element to extract and transform 36835 * data, to make it ready for a `path` object. 36836 * The radius-border is not taken in charge yet. 36837 * (your help is more than welcomed) 36838 * 36839 * @param {DOMelement} element Rect element to transform 36840 * @return {object} Data for a `path` element 36841 */ 36842Pathformer.prototype.rectToPath = function (element) { 36843 var newElement = {}, 36844 x = parseFloat(element.x) || 0, 36845 y = parseFloat(element.y) || 0, 36846 width = parseFloat(element.width) || 0, 36847 height = parseFloat(element.height) || 0; 36848 36849 if (element.rx || element.ry) { 36850 var rx = parseInt(element.rx, 10) || -1, 36851 ry = parseInt(element.ry, 10) || -1; 36852 rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2); 36853 ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2); 36854 36855 newElement.d = 'M ' + (x + rx) + ',' + y + ' ' + 36856 'L ' + (x + width - rx) + ',' + y + ' ' + 36857 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' + 36858 'L ' + (x + width) + ',' + (y + height - ry) + ' ' + 36859 'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' + 36860 'L ' + (x + rx) + ',' + (y + height) + ' ' + 36861 'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' + 36862 'L ' + x + ',' + (y + ry) + ' ' + 36863 'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y; 36864 } 36865 else { 36866 newElement.d = 'M' + x + ' ' + y + ' ' + 36867 'L' + (x + width) + ' ' + y + ' ' + 36868 'L' + (x + width) + ' ' + (y + height) + ' ' + 36869 'L' + x + ' ' + (y + height) + ' Z'; 36870 } 36871 return newElement; 36872}; 36873 36874/** 36875 * Read `polyline` element to extract and transform 36876 * data, to make it ready for a `path` object. 36877 * 36878 * @param {DOMelement} element Polyline element to transform 36879 * @return {object} Data for a `path` element 36880 */ 36881Pathformer.prototype.polylineToPath = function (element) { 36882 var newElement = {}, 36883 points = element.points.trim().split(' '), 36884 i, path; 36885 36886 // Reformatting if points are defined without commas 36887 if (element.points.indexOf(',') === -1) { 36888 var formattedPoints = []; 36889 for (i = 0; i < points.length; i+=2) { 36890 formattedPoints.push(points[i] + ',' + points[i+1]); 36891 } 36892 points = formattedPoints; 36893 } 36894 36895 // Generate the path.d value 36896 path = 'M' + points[0]; 36897 for(i = 1; i < points.length; i++) { 36898 if (points[i].indexOf(',') !== -1) { 36899 path += 'L' + points[i]; 36900 } 36901 } 36902 newElement.d = path; 36903 return newElement; 36904}; 36905 36906/** 36907 * Read `polygon` element to extract and transform 36908 * data, to make it ready for a `path` object. 36909 * This method rely on polylineToPath, because the 36910 * logic is similar. The path created is just closed, 36911 * so it needs an 'Z' at the end. 36912 * 36913 * @param {DOMelement} element Polygon element to transform 36914 * @return {object} Data for a `path` element 36915 */ 36916Pathformer.prototype.polygonToPath = function (element) { 36917 var newElement = Pathformer.prototype.polylineToPath(element); 36918 36919 newElement.d += 'Z'; 36920 return newElement; 36921}; 36922 36923/** 36924 * Read `ellipse` element to extract and transform 36925 * data, to make it ready for a `path` object. 36926 * 36927 * @param {DOMelement} element ellipse element to transform 36928 * @return {object} Data for a `path` element 36929 */ 36930Pathformer.prototype.ellipseToPath = function (element) { 36931 var newElement = {}, 36932 rx = parseFloat(element.rx) || 0, 36933 ry = parseFloat(element.ry) || 0, 36934 cx = parseFloat(element.cx) || 0, 36935 cy = parseFloat(element.cy) || 0, 36936 startX = cx - rx, 36937 startY = cy, 36938 endX = parseFloat(cx) + parseFloat(rx), 36939 endY = cy; 36940 36941 newElement.d = 'M' + startX + ',' + startY + 36942 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY + 36943 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY; 36944 return newElement; 36945}; 36946 36947/** 36948 * Read `circle` element to extract and transform 36949 * data, to make it ready for a `path` object. 36950 * 36951 * @param {DOMelement} element Circle element to transform 36952 * @return {object} Data for a `path` element 36953 */ 36954Pathformer.prototype.circleToPath = function (element) { 36955 var newElement = {}, 36956 r = parseFloat(element.r) || 0, 36957 cx = parseFloat(element.cx) || 0, 36958 cy = parseFloat(element.cy) || 0, 36959 startX = cx - r, 36960 startY = cy, 36961 endX = parseFloat(cx) + parseFloat(r), 36962 endY = cy; 36963 36964 newElement.d = 'M' + startX + ',' + startY + 36965 'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY + 36966 'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY; 36967 return newElement; 36968}; 36969 36970/** 36971 * Create `path` elements form original element 36972 * and prepared objects 36973 * 36974 * @param {DOMelement} element Original element to transform 36975 * @param {object} pathData Path data (from `toPath` methods) 36976 * @return {DOMelement} Path element 36977 */ 36978Pathformer.prototype.pathMaker = function (element, pathData) { 36979 var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path'); 36980 for(i = 0; i < element.attributes.length; i++) { 36981 attr = element.attributes[i]; 36982 if (this.ATTR_WATCH.indexOf(attr.name) === -1) { 36983 pathTag.setAttribute(attr.name, attr.value); 36984 } 36985 } 36986 for(i in pathData) { 36987 pathTag.setAttribute(i, pathData[i]); 36988 } 36989 return pathTag; 36990}; 36991 36992/** 36993 * Parse attributes of a DOM element to 36994 * get an object of attribute => value 36995 * 36996 * @param {NamedNodeMap} attributes Attributes object from DOM element to parse 36997 * @return {object} Object of attributes 36998 */ 36999Pathformer.prototype.parseAttr = function (element) { 37000 var attr, output = {}; 37001 for (var i = 0; i < element.length; i++) { 37002 attr = element[i]; 37003 // Check if no data attribute contains '%', or the transformation is impossible 37004 if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) { 37005 throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.'); 37006 } 37007 output[attr.name] = attr.value; 37008 } 37009 return output; 37010}; 37011 37012 'use strict'; 37013 37014var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt; 37015 37016/** 37017 * Vivus 37018 * Beta version 37019 * 37020 * Take any SVG and make the animation 37021 * to give give the impression of live drawing 37022 * 37023 * This in more than just inspired from codrops 37024 * At that point, it's a pure fork. 37025 */ 37026 37027/** 37028 * Class constructor 37029 * option structure 37030 * type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed) 37031 * duration: <int> (in frames) 37032 * start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport) 37033 * delay: <int> (delay between the drawing of first and last path) 37034 * dashGap <integer> whitespace extra margin between dashes 37035 * pathTimingFunction <function> timing animation function for each path element of the SVG 37036 * animTimingFunction <function> timing animation function for the complete SVG 37037 * forceRender <boolean> force the browser to re-render all updated path items 37038 * selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original 37039 * 37040 * The attribute 'type' is by default on 'delayed'. 37041 * - 'delayed' 37042 * all paths are draw at the same time but with a 37043 * little delay between them before start 37044 * - 'sync' 37045 * all path are start and finish at the same time 37046 * - 'oneByOne' 37047 * only one path is draw at the time 37048 * the end of the first one will trigger the draw 37049 * of the next one 37050 * 37051 * All these values can be overwritten individually 37052 * for each path item in the SVG 37053 * The value of frames will always take the advantage of 37054 * the duration value. 37055 * If you fail somewhere, an error will be thrown. 37056 * Good luck. 37057 * 37058 * @constructor 37059 * @this {Vivus} 37060 * @param {DOM|String} element Dom element of the SVG or id of it 37061 * @param {Object} options Options about the animation 37062 * @param {Function} callback Callback for the end of the animation 37063 */ 37064function Vivus (element, options, callback) { 37065 37066 setupEnv(); 37067 37068 // Setup 37069 this.isReady = false; 37070 this.setElement(element, options); 37071 this.setOptions(options); 37072 this.setCallback(callback); 37073 37074 if (this.isReady) { 37075 this.init(); 37076 } 37077} 37078 37079/** 37080 * Timing functions 37081 ************************************** 37082 * 37083 * Default functions to help developers. 37084 * It always take a number as parameter (between 0 to 1) then 37085 * return a number (between 0 and 1) 37086 */ 37087Vivus.LINEAR = function (x) {return x;}; 37088Vivus.EASE = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;}; 37089Vivus.EASE_OUT = function (x) {return 1 - Math.pow(1-x, 3);}; 37090Vivus.EASE_IN = function (x) {return Math.pow(x, 3);}; 37091Vivus.EASE_OUT_BOUNCE = function (x) { 37092 var base = -Math.cos(x * (0.5 * Math.PI)) + 1, 37093 rate = Math.pow(base,1.5), 37094 rateR = Math.pow(1 - x, 2), 37095 progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1; 37096 return (1- rateR) + (progress * rateR); 37097}; 37098 37099 37100/** 37101 * Setters 37102 ************************************** 37103 */ 37104 37105/** 37106 * Check and set the element in the instance 37107 * The method will not return anything, but will throw an 37108 * error if the parameter is invalid 37109 * 37110 * @param {DOM|String} element SVG Dom element or id of it 37111 */ 37112Vivus.prototype.setElement = function (element, options) { 37113 var onLoad, self; 37114 37115 // Basic check 37116 if (typeof element === 'undefined') { 37117 throw new Error('Vivus [constructor]: "element" parameter is required'); 37118 } 37119 37120 // Set the element 37121 if (element.constructor === String) { 37122 element = document.getElementById(element); 37123 if (!element) { 37124 throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID'); 37125 } 37126 } 37127 this.parentEl = element; 37128 37129 // Load the SVG with XMLHttpRequest and extract the SVG 37130 if (options && options.file) { 37131 var self = this; 37132 onLoad = function (e) { 37133 var domSandbox = document.createElement('div'); 37134 domSandbox.innerHTML = this.responseText; 37135 37136 var svgTag = domSandbox.querySelector('svg'); 37137 if (!svgTag) { 37138 throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file); 37139 } 37140 37141 self.el = svgTag 37142 self.el.setAttribute('width', '100%'); 37143 self.el.setAttribute('height', '100%'); 37144 self.parentEl.appendChild(self.el) 37145 self.isReady = true; 37146 self.init(); 37147 self = null; 37148 } 37149 37150 var oReq = new window.XMLHttpRequest(); 37151 oReq.addEventListener('load', onLoad); 37152 oReq.open('GET', options.file); 37153 oReq.send(); 37154 return; 37155 } 37156 37157 switch (element.constructor) { 37158 case window.SVGSVGElement: 37159 case window.SVGElement: 37160 case window.SVGGElement: 37161 this.el = element; 37162 this.isReady = true; 37163 break; 37164 37165 case window.HTMLObjectElement: 37166 self = this; 37167 onLoad = function (e) { 37168 if (self.isReady) { 37169 return; 37170 } 37171 self.el = element.contentDocument && element.contentDocument.querySelector('svg'); 37172 if (!self.el && e) { 37173 throw new Error('Vivus [constructor]: object loaded does not contain any SVG'); 37174 } 37175 else if (self.el) { 37176 if (element.getAttribute('built-by-vivus')) { 37177 self.parentEl.insertBefore(self.el, element); 37178 self.parentEl.removeChild(element); 37179 self.el.setAttribute('width', '100%'); 37180 self.el.setAttribute('height', '100%'); 37181 } 37182 self.isReady = true; 37183 self.init(); 37184 self = null; 37185 } 37186 }; 37187 37188 if (!onLoad()) { 37189 element.addEventListener('load', onLoad); 37190 } 37191 break; 37192 37193 default: 37194 throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)'); 37195 } 37196}; 37197 37198/** 37199 * Set up user option to the instance 37200 * The method will not return anything, but will throw an 37201 * error if the parameter is invalid 37202 * 37203 * @param {object} options Object from the constructor 37204 */ 37205Vivus.prototype.setOptions = function (options) { 37206 var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync']; 37207 var allowedStarts = ['inViewport', 'manual', 'autostart']; 37208 37209 // Basic check 37210 if (options !== undefined && options.constructor !== Object) { 37211 throw new Error('Vivus [constructor]: "options" parameter must be an object'); 37212 } 37213 else { 37214 options = options || {}; 37215 } 37216 37217 // Set the animation type 37218 if (options.type && allowedTypes.indexOf(options.type) === -1) { 37219 throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`'); 37220 } 37221 else { 37222 this.type = options.type || allowedTypes[0]; 37223 } 37224 37225 // Set the start type 37226 if (options.start && allowedStarts.indexOf(options.start) === -1) { 37227 throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option'); 37228 } 37229 else { 37230 this.start = options.start || allowedStarts[0]; 37231 } 37232 37233 this.isIE = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 ); 37234 this.duration = parsePositiveInt(options.duration, 120); 37235 this.delay = parsePositiveInt(options.delay, null); 37236 //Uncode addition 37237 this.delayStart = parsePositiveInt(options.delayStart, null); 37238 //#END 37239 this.dashGap = parsePositiveInt(options.dashGap, 1); 37240 this.forceRender = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE; 37241 this.reverseStack = !!options.reverseStack; 37242 this.selfDestroy = !!options.selfDestroy; 37243 this.onReady = options.onReady; 37244 this.map = []; 37245 this.frameLength = this.currentFrame = this.delayUnit = this.speed = this.handle = null; 37246 37247 this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false; 37248 37249 this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR; 37250 this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR; 37251 37252 if (this.delay >= this.duration) { 37253 throw new Error('Vivus [constructor]: delay must be shorter than duration'); 37254 } 37255}; 37256 37257/** 37258 * Set up callback to the instance 37259 * The method will not return enything, but will throw an 37260 * error if the parameter is invalid 37261 * 37262 * @param {Function} callback Callback for the animation end 37263 */ 37264Vivus.prototype.setCallback = function (callback) { 37265 // Basic check 37266 if (!!callback && callback.constructor !== Function) { 37267 throw new Error('Vivus [constructor]: "callback" parameter must be a function'); 37268 } 37269 this.callback = callback || function () {}; 37270}; 37271 37272 37273/** 37274 * Core 37275 ************************************** 37276 */ 37277 37278/** 37279 * Map the svg, path by path. 37280 * The method return nothing, it just fill the 37281 * `map` array. Each item in this array represent 37282 * a path element from the SVG, with informations for 37283 * the animation. 37284 * 37285 * ``` 37286 * [ 37287 * { 37288 * el: <DOMobj> the path element 37289 * length: <number> length of the path line 37290 * startAt: <number> time start of the path animation (in frames) 37291 * duration: <number> path animation duration (in frames) 37292 * }, 37293 * ... 37294 * ] 37295 * ``` 37296 * 37297 */ 37298Vivus.prototype.mapping = function () { 37299 var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint; 37300 timePoint = totalLength = lengthMeter = 0; 37301 paths = this.el.querySelectorAll('path'); 37302 37303 for (i = 0; i < paths.length; i++) { 37304 path = paths[i]; 37305 if (this.isInvisible(path)) { 37306 continue; 37307 } 37308 pathObj = { 37309 el: path, 37310 length: Math.ceil(path.getTotalLength()) 37311 }; 37312 // Test if the path length is correct 37313 if (isNaN(pathObj.length)) { 37314 if (window.console && console.warn) { 37315 console.warn('Vivus [mapping]: cannot retrieve a path element length', path); 37316 } 37317 continue; 37318 } 37319 this.map.push(pathObj); 37320 path.style.strokeDasharray = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2); 37321 path.style.strokeDashoffset = pathObj.length + this.dashGap; 37322 pathObj.length += this.dashGap; 37323 totalLength += pathObj.length; 37324 37325 this.renderPath(i); 37326 } 37327 37328 totalLength = totalLength === 0 ? 1 : totalLength; 37329 this.delay = this.delay === null ? this.duration / 3 : this.delay; 37330 this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1); 37331 37332 // Reverse stack if asked 37333 if (this.reverseStack) { 37334 this.map.reverse(); 37335 } 37336 37337 for (i = 0; i < this.map.length; i++) { 37338 pathObj = this.map[i]; 37339 37340 switch (this.type) { 37341 case 'delayed': 37342 pathObj.startAt = this.delayUnit * i; 37343 pathObj.duration = this.duration - this.delay; 37344 break; 37345 37346 case 'oneByOne': 37347 pathObj.startAt = lengthMeter / totalLength * this.duration; 37348 pathObj.duration = pathObj.length / totalLength * this.duration; 37349 break; 37350 37351 case 'sync': 37352 case 'async': 37353 case 'nsync': 37354 pathObj.startAt = 0; 37355 pathObj.duration = this.duration; 37356 break; 37357 37358 case 'scenario-sync': 37359 path = pathObj.el; 37360 pAttrs = this.parseAttr(path); 37361 pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0); 37362 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 37363 timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration; 37364 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 37365 break; 37366 37367 case 'scenario': 37368 path = pathObj.el; 37369 pAttrs = this.parseAttr(path); 37370 pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0; 37371 pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration); 37372 this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration)); 37373 break; 37374 } 37375 lengthMeter += pathObj.length; 37376 this.frameLength = this.frameLength || this.duration; 37377 } 37378}; 37379 37380/** 37381 * Interval method to draw the SVG from current 37382 * position of the animation. It update the value of 37383 * `currentFrame` and re-trace the SVG. 37384 * 37385 * It use this.handle to store the requestAnimationFrame 37386 * and clear it one the animation is stopped. So this 37387 * attribute can be used to know if the animation is 37388 * playing. 37389 * 37390 * Once the animation at the end, this method will 37391 * trigger the Vivus callback. 37392 * 37393 */ 37394Vivus.prototype.drawer = function () { 37395 var self = this; 37396 this.currentFrame += this.speed; 37397 37398 if (this.currentFrame <= 0) { 37399 this.stop(); 37400 this.reset(); 37401 } else if (this.currentFrame >= this.frameLength) { 37402 this.stop(); 37403 this.currentFrame = this.frameLength; 37404 this.trace(); 37405 if (this.selfDestroy) { 37406 this.destroy(); 37407 } 37408 } else { 37409 this.trace(); 37410 this.handle = requestAnimFrame(function () { 37411 self.drawer(); 37412 }); 37413 return; 37414 } 37415 37416 this.callback(this); 37417 if (this.instanceCallback) { 37418 this.instanceCallback(this); 37419 this.instanceCallback = null; 37420 } 37421}; 37422 37423/** 37424 * Draw the SVG at the current instant from the 37425 * `currentFrame` value. Here is where most of the magic is. 37426 * The trick is to use the `strokeDashoffset` style property. 37427 * 37428 * For optimisation reasons, a new property called `progress` 37429 * is added in each item of `map`. This one contain the current 37430 * progress of the path element. Only if the new value is different 37431 * the new value will be applied to the DOM element. This 37432 * method save a lot of resources to re-render the SVG. And could 37433 * be improved if the animation couldn't be played forward. 37434 * 37435 */ 37436Vivus.prototype.trace = function () { 37437 var i, progress, path, currentFrame; 37438 currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength; 37439 for (i = 0; i < this.map.length; i++) { 37440 path = this.map[i]; 37441 progress = (currentFrame - path.startAt) / path.duration; 37442 progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress))); 37443 if (path.progress !== progress) { 37444 path.progress = progress; 37445 path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress)); 37446 this.renderPath(i); 37447 } 37448 } 37449}; 37450 37451/** 37452 * Method forcing the browser to re-render a path element 37453 * from it's index in the map. Depending on the `forceRender` 37454 * value. 37455 * The trick is to replace the path element by it's clone. 37456 * This practice is not recommended because it's asking more 37457 * ressources, too much DOM manupulation.. 37458 * but it's the only way to let the magic happen on IE. 37459 * By default, this fallback is only applied on IE. 37460 * 37461 * @param {Number} index Path index 37462 */ 37463Vivus.prototype.renderPath = function (index) { 37464 if (this.forceRender && this.map && this.map[index]) { 37465 var pathObj = this.map[index], 37466 newPath = pathObj.el.cloneNode(true); 37467 pathObj.el.parentNode.replaceChild(newPath, pathObj.el); 37468 pathObj.el = newPath; 37469 } 37470}; 37471 37472/** 37473 * When the SVG object is loaded and ready, 37474 * this method will continue the initialisation. 37475 * 37476 * This this mainly due to the case of passing an 37477 * object tag in the constructor. It will wait 37478 * the end of the loading to initialise. 37479 * 37480 */ 37481Vivus.prototype.init = function () { 37482 // Set object variables 37483 this.frameLength = 0; 37484 this.currentFrame = 0; 37485 this.map = []; 37486 37487 // Start 37488 new Pathformer(this.el); 37489 this.mapping(); 37490 this.starter(); 37491 37492 if (this.onReady) { 37493 this.onReady(this); 37494 } 37495}; 37496 37497/** 37498 * Trigger to start of the animation. 37499 * Depending on the `start` value, a different script 37500 * will be applied. 37501 * 37502 * If the `start` value is not valid, an error will be thrown. 37503 * Even if technically, this is impossible. 37504 * 37505 */ 37506Vivus.prototype.starter = function () { 37507 switch (this.start) { 37508 case 'manual': 37509 return; 37510 37511 case 'autostart': 37512 this.play(); 37513 break; 37514 37515 case 'inViewport': 37516 var self = this, 37517 listener = function () { 37518 if (self.isInViewport(self.parentEl, 1)) { 37519 self.play(); 37520 window.removeEventListener('scroll', listener); 37521 //Uncode addition 37522 window.removeEventListener('fp-slide-changed', listener); 37523 window.removeEventListener('fp-slide-scroll', listener); 37524 //#END 37525 } 37526 }; 37527 window.addEventListener('scroll', listener); 37528 //Uncode addition 37529 window.addEventListener('fp-slide-changed', listener); 37530 window.addEventListener('fp-slide-scroll', listener); 37531 //#END 37532 listener(); 37533 break; 37534 } 37535}; 37536 37537 37538/** 37539 * Controls 37540 ************************************** 37541 */ 37542 37543/** 37544 * Get the current status of the animation between 37545 * three different states: 'start', 'progress', 'end'. 37546 * @return {string} Instance status 37547 */ 37548Vivus.prototype.getStatus = function () { 37549 return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress'; 37550}; 37551 37552/** 37553 * Reset the instance to the initial state : undraw 37554 * Be careful, it just reset the animation, if you're 37555 * playing the animation, this won't stop it. But just 37556 * make it start from start. 37557 * 37558 */ 37559Vivus.prototype.reset = function () { 37560 return this.setFrameProgress(0); 37561}; 37562 37563/** 37564 * Set the instance to the final state : drawn 37565 * Be careful, it just set the animation, if you're 37566 * playing the animation on rewind, this won't stop it. 37567 * But just make it start from the end. 37568 * 37569 */ 37570Vivus.prototype.finish = function () { 37571 return this.setFrameProgress(1); 37572}; 37573 37574/** 37575 * Set the level of progress of the drawing. 37576 * 37577 * @param {number} progress Level of progress to set 37578 */ 37579Vivus.prototype.setFrameProgress = function (progress) { 37580 progress = Math.min(1, Math.max(0, progress)); 37581 this.currentFrame = Math.round(this.frameLength * progress); 37582 this.trace(); 37583 return this; 37584}; 37585 37586/** 37587 * Play the animation at the desired speed. 37588 * Speed must be a valid number (no zero). 37589 * By default, the speed value is 1. 37590 * But a negative value is accepted to go forward. 37591 *
37592 * And works with float too. 37593 * But don't forget we are in JavaScript, se be nice 37594 * with him and give him a 1/2^x value. 37595 * 37596 * @param {number} speed Animation speed [optional] 37597 */ 37598Vivus.prototype.play = function (speed, callback) { 37599 this.instanceCallback = null; 37600 37601 if (speed && typeof speed === 'function') { 37602 this.instanceCallback = speed; // first parameter is actually the callback function 37603 speed = null; 37604 } 37605 else if (speed && typeof speed !== 'number') { 37606 throw new Error('Vivus [play]: invalid speed'); 37607 } 37608 // if the first parameter wasn't the callback, check if the seconds was 37609 if (callback && typeof(callback) === 'function' && !this.instanceCallback) { 37610 this.instanceCallback = callback; 37611 } 37612 37613 37614 this.speed = speed || 1; 37615 //Uncode addition 37616 if (!this.handle) { 37617 var $this = this, 37618 delay = (this.delayStart != null) ? this.delayStart : 0; 37619 setTimeout(function() { 37620 $this.drawer(); 37621 }, delay); 37622 } 37623 //#END 37624 return this; 37625}; 37626 37627/** 37628 * Stop the current animation, if on progress. 37629 * Should not trigger any error. 37630 * 37631 */ 37632Vivus.prototype.stop = function () { 37633 if (this.handle) { 37634 cancelAnimFrame(this.handle); 37635 this.handle = null; 37636 } 37637 return this; 37638}; 37639 37640/** 37641 * Destroy the instance. 37642 * Remove all bad styling attributes on all 37643 * path tags 37644 * 37645 */ 37646Vivus.prototype.destroy = function () { 37647 this.stop(); 37648 var i, path; 37649 for (i = 0; i < this.map.length; i++) { 37650 path = this.map[i]; 37651 path.el.style.strokeDashoffset = null; 37652 path.el.style.strokeDasharray = null; 37653 this.renderPath(i); 37654 } 37655}; 37656 37657 37658/** 37659 * Utils methods 37660 * include methods from Codrops 37661 ************************************** 37662 */ 37663 37664/** 37665 * Method to best guess if a path should added into 37666 * the animation or not. 37667 * 37668 * 1. Use the `data-vivus-ignore` attribute if set 37669 * 2. Check if the instance must ignore invisible paths 37670 * 3. Check if the path is visible 37671 * 37672 * For now the visibility checking is unstable. 37673 * It will be used for a beta phase. 37674 * 37675 * Other improvments are planned. Like detecting 37676 * is the path got a stroke or a valid opacity. 37677 */ 37678Vivus.prototype.isInvisible = function (el) { 37679 var rect, 37680 ignoreAttr = el.getAttribute('data-ignore'); 37681 37682 if (ignoreAttr !== null) { 37683 return ignoreAttr !== 'false'; 37684 } 37685 37686 if (this.ignoreInvisible) { 37687 rect = el.getBoundingClientRect(); 37688 return !rect.width && !rect.height; 37689 } 37690 else { 37691 return false; 37692 } 37693}; 37694 37695/** 37696 * Parse attributes of a DOM element to 37697 * get an object of {attributeName => attributeValue} 37698 * 37699 * @param {object} element DOM element to parse 37700 * @return {object} Object of attributes 37701 */ 37702Vivus.prototype.parseAttr = function (element) { 37703 var attr, output = {}; 37704 if (element && element.attributes) { 37705 for (var i = 0; i < element.attributes.length; i++) { 37706 attr = element.attributes[i]; 37707 output[attr.name] = attr.value; 37708 } 37709 } 37710 return output; 37711}; 37712 37713/** 37714 * Reply if an element is in the page viewport 37715 * 37716 * @param {object} el Element to observe 37717 * @param {number} h Percentage of height 37718 * @return {boolean} 37719 */ 37720Vivus.prototype.isInViewport = function (el, h) { 37721 var scrolled = this.scrollY(), 37722 viewed = scrolled + this.getViewportH(), 37723 elBCR = el.getBoundingClientRect(), 37724 elHeight = elBCR.height, 37725 elTop = scrolled + elBCR.top, 37726 elBottom = elTop + elHeight; 37727 37728 // if 0, the element is considered in the viewport as soon as it enters. 37729 // if 1, the element is considered in the viewport only when it's fully inside 37730 // value in percentage (1 >= h >= 0) 37731 h = h || 0; 37732 37733 return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled; 37734}; 37735 37736 37737/** 37738 * Get the viewport height in pixels 37739 * 37740 * @return {integer} Viewport height 37741 */ 37742Vivus.prototype.getViewportH = function () { 37743 var client = this.docElem.clientHeight, 37744 inner = window.innerHeight; 37745 37746 if (client < inner) { 37747 return inner; 37748 } 37749 else { 37750 return client; 37751 } 37752}; 37753 37754/** 37755 * Get the page Y offset 37756 * 37757 * @return {integer} Page Y offset 37758 */ 37759Vivus.prototype.scrollY = function () { 37760 return window.pageYOffset || this.docElem.scrollTop; 37761}; 37762 37763setupEnv = function () { 37764 37765 if (Vivus.prototype.docElem) { 37766 return; 37767 } 37768 37769 /** 37770 * Alias for document element 37771 * 37772 * @type {DOMelement} 37773 */ 37774 Vivus.prototype.docElem = window.document.documentElement; 37775 37776 /** 37777 * Alias for `requestAnimationFrame` or 37778 * `setTimeout` function for deprecated browsers. 37779 * 37780 */ 37781 requestAnimFrame = (function () { 37782 return ( 37783 window.requestAnimationFrame || 37784 window.webkitRequestAnimationFrame || 37785 window.mozRequestAnimationFrame || 37786 window.oRequestAnimationFrame || 37787 window.msRequestAnimationFrame || 37788 function(/* function */ callback){ 37789 return window.setTimeout(callback, 1000 / 60); 37790 } 37791 ); 37792 })(); 37793 37794 /** 37795 * Alias for `cancelAnimationFrame` or 37796 * `cancelTimeout` function for deprecated browsers. 37797 * 37798 */ 37799 cancelAnimFrame = (function () { 37800 return ( 37801 window.cancelAnimationFrame || 37802 window.webkitCancelAnimationFrame || 37803 window.mozCancelAnimationFrame || 37804 window.oCancelAnimationFrame || 37805 window.msCancelAnimationFrame || 37806 function(id){ 37807 return window.clearTimeout(id); 37808 } 37809 ); 37810 })(); 37811}; 37812 37813/** 37814 * Parse string to integer. 37815 * If the number is not positive or null 37816 * the method will return the default value 37817 * or 0 if undefined 37818 * 37819 * @param {string} value String to parse 37820 * @param {*}
37820 defaultValue Value to return if the result parsed is invalid 37821 * @return {number} 37822 * 37823 */ 37824parsePositiveInt = function (value, defaultValue) { 37825 var output = parseInt(value, 10); 37826 return (output >= 0) ? output : defaultValue; 37827}; 37828 37829 37830 if (typeof define === 'function' && define.amd) { 37831 // AMD. Register as an anonymous module. 37832 define([], function() { 37833 return Vivus; 37834 }); 37835 } else if (typeof exports === 'object') { 37836 // Node. Does not work with strict CommonJS, but 37837 // only CommonJS-like environments that support module.exports, 37838 // like Node. 37839 module.exports = Vivus; 37840 } else { 37841 // Browser globals 37842 window.Vivus = Vivus; 37843 } 37844 37845}());
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.